Skip to content

Instantly share code, notes, and snippets.

@joelverhagen
Last active August 3, 2018 15:37
Show Gist options
  • Save joelverhagen/c87933d306a8744934ebd3953258de39 to your computer and use it in GitHub Desktop.
Save joelverhagen/c87933d306a8744934ebd3953258de39 to your computer and use it in GitHub Desktop.
NuGet Package Version Conventions

NuGet Package Version Conventions

CI packages and release packages

A common pattern for NuGet package versions is producing two sets of .nupkgs for every CI build. That is two sets of functionally equivalent packages produced from the same source. Two sets are:

  1. CI packages: a NuGet package version that is suffixed with a build number. This allows bleeding edge consumption of the latest APIs or fixes. These packages are typically pushed to a development package feed like VSTS or MyGet. Example version numbers: 4.0.0-rc-2046, 3.5.0-rtm-1996, 3.5.0-beta2-1543

  2. Release packages: a NuGet package that has no build number in the version but may still have a prerelease label. This package is intended for official release to NuGet.org or to customers. Example version numbers: 4.0.0-rc, 3.5.0, 3.5.0-beta2

These two sets of packages should be produced by two separate invocations of nuget.exe pack or dotnet pack. At first glance, it is tempting to produce one set of packages based on the other by simply copying the .nupkg and editing the contained .nuspec. This manual approach should be discouraged as it promotes error-prone munging of NuGet's implementation details and likely breaks the upcoming package signing feature. The pack command should be the master of producing .nupkgs.

Finally, it is convenient to produce a set of release-ready packages every time a build runs to minimize the number of infrequently excerised release processes. Any build that passes the necessary quality checks should be able to be shipped by simple selecting the associated set of release packages.

Assembly metadata

It is possible for the assemblies in these two packages to have different assembly metadata. Typically the AssemblyVersion and AssemblyFileVersion share the integer part of the package version and the AssemblyInformationalyVersion matches the NuGet package version verbatim (for simplicity and correlation). The AssemblyFileVersion should include the build number.

Dependency versions

It is not required for all packages produced by a CI build to have the same version number or release label. However, the build number component of a version should match.

When packing a .csproj, a <ProjectReference> should be converted to a <dependency> in the output .nuspec with a version defined in the referenced project's .csproj. dotnet pack does not behave this way today, which is a bug tracked by NuGet/Home#3874.

In general, interdependent packages produced by a single CI build should have matching package and dependency versions so that the set of resulting packages does not have any package dependencies on previous CI builds.

NuGet's own build process

In NuGet client, we use Preview 2 .NET CLI tooling (1.0.0-preview2-003121) to produce our cross-platform packages and nuget.exe (3.5.0-beta2-1520) to produce our Windows-only packages.

For all packages except NuGet.CommandLine, the assembly metadata between the CI and release package does not vary. For NuGet.CommandLine, the AssemblyInformationalVersional must match the package version as part of the nuget update -Self logic.

All of our packages have the same version, release label, and build number (with the one exception of SynchronizationTestApp... which is probably a bug).

Tooling

Version Suffix

There are two styles of how a provided version suffix behaves in tooling:

append: version suffix is appending to version prefix.

Example 1:

  • Version: 1.0.0
  • Version Suffix: rc
  • Result: 1.0.0-rc

Example 2:

  • Version prefix: 1.0.0-beta
  • Version suffix: final
  • Result: 1.0.0-beta-final

replace: version suffix is used as the prerelease label.

Example 1:

  • Version: 1.0.0
  • Version Suffix: rc
  • Result: 1.0.0-rc

Example 2:

  • Version: 1.0.0-beta
  • Version Suffix: rc
  • Result: 1.0.0-rc

Tools

Build operations use the version suffix when constructing the AssemblyInformationalVersion. Pack operations use the version suffix when constructing the NuGet package version.

Tool Release Version suffix style
nuget.exe pack < 3.4.0 not supported
nuget.exe pack ≥ 3.4.0 replace
dotnet pack Preview 2 append *
dotnet pack RTM ** replace
dotnet build Preview 2 append *
dotnet build RTM ** append

* = only happens if there is a version ending in -* in the project.json. Otherwise, the version suffix is ignored.

** = not yet released

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment