error NU1004: The package reference Microsoft.NET.ILLink.Tasks version has changed from [8.0.14, ) to [8.0.15, ).
Description
We use nuget locked mode (package lock files).
Our dev team has dotnet SDK 8.0.407 installed currently, and a few days ago, dotnet SDK 8.0.408 (8.0.15) was released.
We see this behaviour
- There is one nuget dependency that seems to make its way into the package.lock.json that is actually supplied by whatever version of the SDK you build the solution with. So in our case - this is the version of the dependency that makes its way into the lock file when the developers build with dotnet SDK
8.0.407:"Microsoft.NET.ILLink.Tasks": { "type": "Direct", "requested": "[8.0.14, )", "resolved": "8.0.14", "contentHash": "4U2fd7PexNKrK5ZqfqIcXZj9/lRRjFsLgA/pxuFQTuGQuLYP/+7yACz/j7EmWbEj/fspOf4mafi/vHIy/rKDzQ==" },
However our CI/CD server installs the sdk based on the global.json in our repo, which allows later patch versions - this means as of the new dotnetr sdk release a few days ago, CI builds use dotnet SDK 8.0.408`
- The build then fails because
error NU1004: The package reference Microsoft.NET.ILLink.Tasks version has changed from [8.0.14, ) to [8.0.15, ).
We have never hit this problem prior to dotnet 8. Having a dependency thats "hard coded" from the dotnet SDK you are restoring with, seems to be at odds with the package lock feature, and a global.json that allows newer dotnet SDK patches to build the solution.
Reproduction Steps
As explained
- create a blazor wasm application project using dotnet SDK
8.0.407and enable nuget package lock feature - build it, and commit the package.lock.json file - on a different machine (or build server) with dotnet SDK
8.0.408installed, restore the solution with locked mode. - you'll hit the error
Expected behavior
I'd expect that for dependencies to be meaningfully captured in a lock file that they would be fixed at the point of build when the lock file is produced. If their are environmental dependencies that sneak into the lock file, and that actually depend on the precise patch version of the SDK that you restore with (8.0.407 vs 8.0.408) this is not obvious to determine at the time, but opens the way for any SDK patch to (perhaps inadvertently in this case?) break all builds accross our organisation and CI / CD servers.. I just didn't expect for a minor patch to the SDK to break package restore.
Actual behavior
As discussed, this new paradigm makes package lock mode more fragile and means that an SDK patch breaks builds - which devalues global.json roll forward feature. The more troublesome issue is it forces that the CI server and all developers must all upgrade to the exact same SDK version together, otherwise they will be in a situation where eachothers dotnet restore will fail.
Regression?
Yes this is a regression, I did not see this behaviour in prior dotnet versions - and we all updated out dotnet SDK's many times, and the CI server also had slightly differing versions as we updated seperately over time - did not see any such issues.
Known Workarounds
SDK has to be aligned accross all local developers and CI servers at the same time should any of them want to roll forward to a new patch version of the SDK and locked mode is being used.
Configuration
No response
Other information
No response
Tagging subscribers to this area: @dotnet/illink See info in area-owners.md if you want to be subscribed.
This looks to be a bug in the SDK. The ILLink.Tasks package is an implict package and shouldn't be included in the lock file.
@nkolev92 @baronfel What is our guidance in cases like this? Should the lock file include implicitly supplied package downloads? Similar to discussions we were having yesterday about lock files.
- @sbomer as well. My understanding was that this was the recommended way to pull in extra resources for publish in the sdk. If it’s not, we could explore another deployment option.
It's the recommended way today, but it is a gap in the overall NuGet lockfile story. Our current recommendation for users that use lock files is to also lock their SDK versions via global.json with no rollforward, so they their entire toolchain stays in lockstep.
I just now realized I started a comment and never finished it.
We have a tracking issue for PackageDownload in https://github.com/nuget/home/issues/7724.
I think the Microsoft.NET.ILLink.Tasks is marked as a PackageReference in this case.
The current design for lock files is that auto referenced packages are part of the lock file. The idea was that the repeatability of the build is dependent on using the same tooling. (what @baronfel said :) )
Ah yeah - ILLink is special amongst many of the other implicit packages because we rely on loading the props/targets from it to overwrite some of the defaults that the SDK ships with. Everything else can be a PackageDownload because we just need access to the bits.
ILLink could become a PackageDownload as well, if we did some additional computing of paths to do the Imports ourselves in the SDK.
What is the current status of this? Can we expect a fix soon? Or is there maybe a workaround?
This is currently preventing us from using lock files. 😞
@tnotheis Given that Microsoft.NET.ILLink.Tasks is being automatically added as a PackageReference, at this point you need to use the same .NET SDK version locally and on the CI.
It's the recommended way today, but it is a gap in the overall NuGet lockfile story. Our current recommendation for users that use lock files is to also lock their SDK versions via global.json with no rollforward, so they their entire toolchain stays in lockstep.
This was news to me. I don't think that recommendation is present in the docs for lock files. Could it be added there?