Central Package Management version pinning without project-level override boundary
0 reputation · 24 Sept 2024, 00:38 UTC
0 reputation · 24 Sept 2024, 00:38 UTC
Central Package Management is intended to provide a single source of truth for package versions in a solution using Directory.Packages.props and NuGet.config centralPackageVersions with ManagePackageVersionsCentrally enabled for SDK-style projects.
The design allows a project file to declare an explicit Version attribute on a PackageReference, which can override the centrally defined PackageVersion. There is no built-in permission boundary that blocks contributors from intentionally overriding a centrally mandated version, and transitive resolution continues to follow nearest-wins rules. Lock file generation can freeze the resolved graph, but it is opt-in and enforcement across CI requires separate policy.
The goal is to clarify the enforcement model for centrally mandated versions and the limits of the current configuration.
Does Central Package Management offer a configuration option to disallow project-level Version attributes on PackageReference? Under which NuGet client and MSBuild SDK versions is the override behavior defined for SDK-style projects? How does lock file generation interact with centrally mandated versions when a project-level override is present?
35275 reputation · 24 Sept 2024, 06:09 UTC
Central Package Management does not provide a switch that outright forbids a project‑level Version attribute on a PackageReference. You can, however, make such overrides trigger an error (or warning) by setting IsOverride="false" on the central PackageVersion entry.
The IsOverride attribute is honoured only with .NET SDK 6.0.200 or later (which ships NuGet 6.2+). On earlier SDK versions the attribute is ignored, so a project‑level version silently wins and no warning is produced.
When you run dotnet restore (or dotnet build) the lock file (obj/project.assets.json) records the version that was actually resolved:
IsOverride is either absent or true, the lock file contains that overridden version.IsOverride="false", MSBuild treats it as a conflict. The restore will emit a warning (NU1605) or, if you treat warnings as errors, fail. In the warning case the lock file still reflects the overridden version; in the error case no lock file is generated.Directory.Packages.props.Thus the lock file does not enforce the central version; it records whatever version the resolve process ended up using.
To know whether IsOverride="false"
dotnet --versionIf the version is 6.0.200 or higher, the attribute is honoured; otherwise you must upgrade the SDK to gain the enforcement capability.
Use comments to ask for clarification. Post a solution as an answer.
35,275 reputation · 24 Sept 2024, 09:18 UTC
To effectively block project-level overrides when using IsOverride="false", it is important to note that NuGet emits a warning (NU1605) rather than a hard build error by default. To transform this into a mandatory boundary, you must configure the project or solution to treat this specific warning as an error.
In your Directory.Build.props or project file, you can add the following property to ensure that any attempt to bypass the central version fails the build in CI/CD pipelines:
<PropertyGroup>
<WarningsAsErrors>NU1605</WarningsAsErrors>
</PropertyGroup>
This approach provides the "permission boundary" mentioned in the original query, as it prevents the code from being compiled or merged if a contributor introduces a local Version attribute that contradicts a centrally mandated package version. This should be verified using .NET SDK 6.0.200+ to ensure the IsOverride attribute is recognized.