Constrain PackageReference upgrade version when update-package run
Asked Answered
D

3

7

Under .NET's older packages.config system for NuGet, I could constrain the possible versions of a package that are considered when packages are updated by using the allowedVersions attribute on the Package element

<package id="Newtonsoft.Json" version="10.0.3" allowedVersions="[10.0.3]" />

When update-package is run within Visual studio for a project including the above, no update will occur for Newtonsoft.Json because I've pinned to 10.0.3 using the allowedVersions attribute.

How can I achieve this under PackageReference? Applying semver syntax to the Version attribute only affects the version restored - it doesn't constrain updates. So if I specify the below PackageReference and run update-package, I will for example be upgraded to 11.0.1 if 11.0.1 is in my NuGet repository.

<PackageReference Include="Newtonsoft.Json" Version="[10.0.3]" />

Background

We rely on command line tooling to update packages because we have both fast moving internal packages (updated multiple times a day) and more stable low moving packages (eg: ASP.NET). On large codebases updating each dependency by hand in .csproj files is simply not scalable for us (and error prone). Under packages.config we can 'pin' the third party packages which we don't want upgraded and also update to the latest fast moving dependencies.

Dell answered 21/3, 2018 at 5:10 Comment(0)
C
2

This has now been implemented as of https://github.com/NuGet/NuGet.Client/pull/2201. If you are using any version of NuGet 5, PackageReference semver constraints should now work as expected.

Clubby answered 3/10, 2019 at 12:27 Comment(0)
A
3

From this answer:

At the moment, this is not possible. See this GitHub issue for tracking.

The cli commands for adding references however support updating single packages in a project by re-running dotnet add package The.Package.Id.

From GitHub Issue 4358:

There is no PackageReference replacement for update yet, the command to modify references is only in dotnet.

You might want to weigh in on the open feature request GitHub issue 4103 about this (4358 was closed as a duplicate). Microsoft hasn't put a high priority on this feature (it was originally opened in October, 2016).

Possible Workarounds

Option 1

It is possible to "update" a dependency by removing and adding the reference. According to this post, specifying the version explicitly with the command will install the exact version, not the latest version. I have also confirmed you can add version constraints with the command:

dotnet remove NewCsproj.csproj package Newtonsoft.Json
dotnet add NewCsproj.csproj package Newtonsoft.Json -v [10.0.3]

What you could do with these commands:

  1. Keep version numbers of packages around in a text file (perhaps just keep it named packages.config).
  2. Use a script to create your own "update" command that reads the text file and processes each dependency in a loop using the above 2 commands. The script could be setup to be passed a .sln file to process each of the projects within it.

Option 2

Use MSBuild to "import" dependencies from a common MSBuild file, where you can update the versions in one place.

You can define your own <IncludeDependencies> element to include specific dependencies to each project.

SomeProject.csproj

<Project Sdk="Microsoft.NET.Sdk">

    <IncludeDependencies>Newtonsoft.Json;FastMoving</IncludeDependencies>
    <Import Project="..\..\..\Dependencies.proj" />
  
    ...
  
</Project>

Dependencies.proj

<Project>

    <ItemGroup>
        <PackageReference Condition="$(IncludeDependencies.Contains('Newtonsoft.Json'))" Include="Newtonsoft.Json" Version="[10.0.3]" />
        <PackageReference Condition="$(IncludeDependencies.Contains('FastMoving'))" Include="FastMoving" Version="3.332.0" />
    </ItemGroup>
  
</Project>
Anemochore answered 21/3, 2018 at 6:42 Comment(2)
Thanks for your reply. We rely on command line tooling to update packages because we have both fast moving internal packages (updated multiple times a day) and more stable low moving packages (eg: ASPNET). On large codebases updating each dependency by hand in csproj files is simply not scalable for us (and error prone). Under packages.config we can 'pin' the third party packages which we don't want upgraded and also update to the latest fast moving dependencies.Dell
Thanks. I have updated my answer with a couple of possible options if you don't want to wait around for Microsoft to implement this.Anemochore
C
2

This has now been implemented as of https://github.com/NuGet/NuGet.Client/pull/2201. If you are using any version of NuGet 5, PackageReference semver constraints should now work as expected.

Clubby answered 3/10, 2019 at 12:27 Comment(0)
F
0

Pinning - Yet another workaround

This doesn't prevent the update but triggers a build error if one did and update. It won't help much with the use case of automated updates but it may help others that do manual updates and need some way of pinning.

<ItemGroup>
    <PackageReference Include="MongoDB.Driver" Version="2.13.*" GeneratePathProperty="true" />
</ItemGroup>

<Target Name="CheckPkgVersions" AfterTargets="AfterBuild">
    <Error Condition="!$(PkgMongoDB_Driver.Contains('2.13.'))" Text="MongoDB.Driver must remain at version 2.13.* to be compatible with MongoDB 3.4.21" />
</Target>
Funds answered 24/5, 2022 at 12:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.