Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constrain PackageReference upgrade version when update-package run

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.

like image 371
Dav Evans Avatar asked Mar 21 '18 05:03

Dav Evans


2 Answers

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>
like image 53
NightOwl888 Avatar answered Oct 01 '22 10:10

NightOwl888


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.

like image 20
Ian Kemp Avatar answered Oct 01 '22 11:10

Ian Kemp