.netdependenciesnugetversioningbinary-reproducibility

Ensuring reproducible builds using NuGet packages


I have a .NET app called Application.

This application depends on two NuGet packages:

The Database package depends on two additional packages:

Currently, Application uses these concrete package versions: Database version 2.1, Logging version 3.1.

I build my Application, NuGet resolves and downloads the dependencies, so I get DTO version 1.5 and DAL version 4.0. I put my Application into an installation package and deliver to my customer. I tag this release in git with app-1.0.

So my customer gets the following binaries:

One year later, the customer files a bug which I need to thoroughly analyse. To reproduce the issue, I need the same binaries as the customer, so I check out the tag app-1.0 and want to build my application.

Meanwhile, the DAL and the DTO packages were updated on the NuGet feed: latest DTO version is 1.7 and DAL version is 4.5.

My questions are:


Solution

  • NuGet introduced lock files in version 4.9 (Visual Studio 2017, 15.9), .NET Core SDK 2.1.500. The blog post that introduces it is even titled "Enable repeatable package restores using a lock file"

    The blog post only lists one way to enable lock files. One way is to create an empty file named packages.lock.json in the same directory as your project file (csproj), then do a restore. Another way is to run dotnet restore --use-lock-file on the command line. Another way is to set the RestorePackagesWithLockFile MSBuild property to true, which is possible in many ways (property in your project file, property in Directory.Build.props, environment variable, command line argument).

    Once the lock file is created, it will always be used, so you no longer need to explicitly opt-in as you need to the first time. Note that restore will update the lock file by default when it finds changes. If you want to fail restore when it can't restore the exact same packages, you need to opt-in to "locked mode", for example dotnet restore --locked-mode, which you probably want to do on your CI machines.