nugetnuget-server

Keeping Nuget packages updated in many projects/solutions


If using the same nuget package(s) over multiple solutions, how do I keep them up to date without having to open up every solution and update packages when a new version is released?

Folder structure is typically something like this but over many more projects. Each project has its own packages.config with various package references.

$tfs/
├── Solution One/
│   ├ Solution 1.sln
│   ├   nuget.config (solution item)
│   ├── Packages/
│   ├    ├── Newtonsoft.JSON.12.0.2/
│   ├    ├── Jquery3.1.4/
│   ├── Project one/
│   ├       ── packages.config
│   ├       ── whatever.cs
│   ├       ── folder /
│   ├       ── another folder /
│   ├── Project Two/
│   ├       ── packages.config
│   ├       ── file.cs
│   ├       ── folder/
│   ├       ── another folder/
├── Solution Two/
│   ├ Solution 2.sln
│   ├   nuget.config
│   ├── Packages/
│   ├    ├── Newtonsoft.JSON.11.1.0/
│   ├    ├── Jquery1.3.4/
│   ├── Project one/
│   ├       ── packages.config
│   ├       ── whatever.cs
│   ├       ── folder /
│   ├       ── another folder /
│   ├── Project two/
│   ├       ── packages.config
│   ├       ── file.cs
│   ├       ── folder/
│   ├       ── another folder/

I have tried running this powershell in Package Manager Console but this only applies to one solution at a time:

$packageId = "jquery"
Get-ChildItem *.sln -recurse | %{.\\nuget.exe restore $_.fullname}
Get-ChildItem packages.config -Recurse `
| Where-Object {$_ | Select-String -Pattern $packageId} `
| %{.\\nuget.exe update -Id $packageId $_.FullName}

Do I need to update packages.config in each solution of each project and open them in order to get the updates? I would have thought there would be an easier way to do this. I am using a private nuget server if it makes a difference.

Note: I have looked at this question: Updating nuget packages in all projects in a solution and it is not the same scenario as mine. I'm looking to update packages across multiple solutions, not multiple projects in one solution.


Solution

  • As @imps said in the comments, there's no solution for packages.config projects across solutions. Within a solution you can use the NuGet Package Manager UI's "Manage packages for solution" and the consolidate tab helps makes sure all projects use the same version, but you'll need to repeat this for all solutions.

    If you migrate from packages.config to PackageReference, you could take advantage of MSBuild extensibility and either import a common props file, or if using Visual Studio 2017 or newer, use Directory.Build.Props in the highest common parent directory of all the projects.

    In your props file, you define the versions of the packages you care about, something like this:

    <Project>
      <PropertyGroup>
        <NewtonsoftJsonVersion>12.0.1</NewtonsoftJsonVersion>
      </PropertyGroup>
    </Project>
    

    and then in your csproj files, use <PackageReference Include="Newtonsoft.Json" Version="$(NewtonsoftJsonVersion)" />. The issue with this is that you can no longer use the Package Manager UI or Package Manager Console in VS to upgrade (well you can, but it'll change it in the csproj, not your props file), but you can still use the UI to check for updates. If you add your props file to your solution, then it just takes two clicks and a few taps on your keyboard to update, so it's really not a big deal.

    In your example, the common parent directory would be the TFS root, so $/Directory.Build.props. The problem with this is if you use CI and have a trigger to run the Solution One build on changes to $/Solution One/* and run the Solution Two build on changes to $/Solution Two/*, then they'll both miss changes to $/Directory.Build.props. Or maybe it is possible to configure TFS build triggers to include it, but I don't remember because I haven't used TFVC is such a long time.

    However, the bigger issue is that in your example, it's clear you're using the jQuery package. This uses content, which copies files into your project on install/upgrade. PackageReference doesn't work this way (it's listed as a package compatibility issue) , so unless you want to have a different process for upgrading jQuery and any other js/css in your web projects, you can't migrate ASP.NET projects to PackageReference. Note that ASP.NET Core projects are SDK style which only support PackageReference, not packages.config, and typically use either LibMan or npm to get css and javascript.

    Customers who can migrate to SDK style projects, they could even consider using this SDK for central package management that helps ensure you don't accidently leave a version number in your csproj.