Description
Our policy since 1.0.0 has been to always cascade version updates in the packages we own. e.g. if Logging has a product change in 2.1.x, then Kestrel, EF Core, Mvc, etc also re-ship with the updated Logging dependency. This has been done for a variety of reasons:
- NuGet does not show updates for transitive dependencies, only direct ones
- NuGet does resolves the lowest compatible transitive dependencies
- ASP.NET Core ships to both .NET Framework (where transitive dependency version matters) and .NET Core (where it matters less if you use the shared framework)
While transitive dependencies is still an important scenario, this practice of always patching has led to bigger issues.
- High probability users will unintentionally upgrade out of the shared framework: Remove the PackageReference to Microsoft.AspNetCore.App/All from project files for netcoreapp2.x #3307
- Conflicts with metapackages that attempt to use exact version constraints: Packages that share dependencies with Microsoft.AspNetCore.App cannot reference patch versions aspnet/Universe#1180
- A quality perception issue: the high volume of new versions in servicing updates with only metadata changes has created the impression that new versions of packages may not be very important. It's also made it appear like there are more issues product than there really are.
- High volume of packages changing with only metadata changes. Of the last 301 packages published in a servicing update, only 11 contained actual changes to the implementation assemblies. (3.5%)
Proposal
Change 1
Stop cascading versions for every servicing patch.
For example, after 2.2.0 is finished, patching Logging to 2.2.1 would not necessarily mean Kestrel, Mvc, and SignalR need a 2.2.1 release.
Exceptions
This is the general rule, but there may arise important scenarios when the transitive version matters. When these occur, we will make manual updates. Examples may include:
- security issues
- high-impact functional changes in patches
- (unlikely to happen -- in theory) API additions or changes in a patch
Implementation plan
We'll start by implementing this within ASP.NET Core on a repo by repo basis. Doing this from package to package within a repo is currently prohibitively expensive due to the way we use ProjectReference and nuspec generation.
Change 2
Work with NuGet to provide better tooling for finding and updating out of date transitive references. Some proposals currently in the incubation: NuGet/Home#5762, NuGet/Home#2867
Not changing
Metapackages, such as Microsoft.AspNetCore, AspNetCore.App, and AspNetCore.All will continue to cascade versions. These provide the best way for users to get the latest set of things, without hoisting dozens of transitive dependencies to be direct dependencies.