Skip to content

[Feature]: Allow overriding a centrally defined package version #11516

Description

@jeffkl

NuGet Product(s) Involved

NuGet.exe, MSBuild.exe, dotnet.exe

The Elevator Pitch

Central Package Management (CPM) allows users to specify versions for their packages in one place. However, there are edge cases where a project might want to use a different version. For example, a prototype project could need a newer version than a repo is using so it would opt into newer versions.

There is an existing implementation, Microsoft.Build.CentralPackageVersions, which uses a VersionOverride attribute to indicate that a <PackageReference /> should use a different version than is centrally defined.

This design has a few advantages:

  1. Makes it obvious when a project is using its own package version(s)
  2. Ideally, an entire repo would use the same package version which is why users would define it in one place. Users who want to use a different version would need to fully understand the ramifications of specifying the VersionOverride attribute.
  3. Migration from Microsoft.Build.CentralPackageVersions would be easier.

Other options for users that would still be possible are:

  1. Specify a <PackageVersion /> in a project
  2. Define an MSBuild property that represents the package version and set it in a project

Since MSBuild essentially lets users do anything they want, the built-in mechanism for overriding a package version should be simple and well documented.

Design

A user would specify package versions in Directory.Packages.props:

<Project>
  <ItemGroup>
    <PackageVersion Include="PackageA" Version="1.0.0" />
    <PackageVersion Include="PackageB" Version="2.0.0" />
  </ItemGroup>
<Project>

A project would override the version with the VersionOverride metadata on a <PackageReference /> item:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="PackageA" VersionOverride="3.0.0" />
  </ItemGroup>
<Project>

In this case, the project's restore graph would resolve PackageA to version 3.0.0. Any project that references it would also get that version and a user would be responsible for handling an unresolved conflicts.

Finally, a repo owner should be able to disable the ability for developers to override package version. This would be used for instance if someone wanted to ensure that all package versions are unified. This would be possible by setting the MSBuild property EnablePackageVersionOverride to false in a project or import like Directory.Build.props:

<Project>
  <PropertyGroup>
    <EnablePackageVersionOverride>false</EnablePackageVersionOverride>
  </PropertyGroup>
<Project>

When this is disabled, specifying a VersionOverride on a <PackageReference /> would result in a restore error indicating that he feature is disabled.

Additional Context and Details

No response

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions