I have a .NET app called Application.
This application depends on two NuGet packages:
Database, version 2.*Logging, version 3.*
The Database package depends on two additional packages:
DTO, version 1.*DAL, version 4.*
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:
Application.exe, version 1.0Database.dll, version 2.1Logging.dll, version 3.1DTO.dll, version 1.5DAL.dll, version 4.0
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:
- When I build my application now, does NuGet resolve the
Databasedependencies to the latest available versions? So do I getDTO 1.7andDAL 4.5instead ofDTO 1.5andDAL 4.0(which were used to buildapp-1.0)? - If yes, how can I ensure the binary reproducibility of my release using NuGet?
- If no, how does NuGet manage to resolve the "right" references?
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.jsonin the same directory as your project file (csproj), then do a restore. Another way is to rundotnet restore --use-lock-fileon the command line. Another way is to set theRestorePackagesWithLockFileMSBuild property totrue, which is possible in many ways (property in your project file, property inDirectory.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.