NuGet Package Hierarchical Versioning

This post discusses an auto-versioning strategy for interdependent NuGet packages.

The new project system

The new project system introduced with Visual Studio 2017 is a huge improvement on what’s gone before.  One of the best features is aggregation of several configuration files into a single project file.  Previously, a typical C# project might include these:

  • <project>.csproj – The project file, which typically lists every file included in the project.
  • Properties/AssemblyInfo.cs – Metadata compiled into the assembly, including version numbers.
  • packages.config – A list of referenced NuGet package versions.
  • <project>.nuspec – NuGet package configuration file (optional; used for creating NuGet packages).

With the new project system, most stuff you’ll need is in the .csproj file.  For many projects this just means less clutter, and a project file you’re happy to edit manually.  If you’re building NuGet packages, it gets even better.

Building NuGet packages

Let’s say you’re building Package A and Package B, and Package B requires Package A.  You make an API change in Package A and increment its version number.  Since you’ve not changed Package B, its latest version continues to reference the old version of Package A.

What if Package B is the primary package you want most users to use, and Package A is just one of several dependencies?  If you want users to have the latest code but not have to reference Package A directly, you need to increment Package B’s version number too.  With the old project system you also need to update Package B’s .nuspec file with Package A’s new version number.

Automated versioning

Because the new project system brings everything we need into the .csproj file, it makes automating the versioning process much easier.  Here’s something I’ve been using that works pretty well:

Given a root folder, it’ll recursively identify local changes that haven’t been committed to git yet (using the ngit package).  It then determines which projects reference projects that contain those changes.  At the end it’ll suggest new version numbers for all affected projects.  If the “writeChanges” flag is set, it’ll modify the project version numbers for you.

Because it’s comparing against the last commit, it’s safe to run multiple times or manually update version numbers if you prefer.

 

2 Comments

Leave a comment