Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exclude prereleases in upper version limit #16260

Closed

Conversation

ronaldbarendse
Copy link
Contributor

@ronaldbarendse ronaldbarendse commented May 10, 2024

Prerequisites

  • I have added steps to test this contribution in the description below

Description

Version 13 added a version range on project references by automatically adding the next major version, e.g. [13.4.0, 14.0.0) (see #14719). This prevents users from installing CMS components/packages of different major versions and/or for transitive dependencies to upgrade them.

However, this NuGet version range doesn't exclude prereleases in the upper version limit. Most of the time this isn't an issue, because packages won't have a dependency on a CMS prerelease and NuGet won't update transitive dependencies to prerelease versions. With packages that target a new major CMS version though, this issue does become apparent, as mentioned in warrenbuckley/Examine-Peek#4: you can install this v14-only package on a v13 site, which will upgrade some transitive CMS packages to the v14 prerelease (resulting in compilation errors).

The standard Semver range >= 13.0.0 <14.0.0 does exclude pre-preleases, but NuGet uses its own syntax and implementation that doesn't exclude pre-releases when [13.0.0, 14.0.0) is used:

Comparing Semver and NuGet.Versioning

This can be fixed by appending -0 to the upper version limit (the lowest possible prerelease version), which is a nicer solution to using x.999999 like we did in v8:

<!--
note: dependencies are specified as [x.y.z,x.999999) eg [2.1.0,2.999999) and NOT [2.1.0,3.0.0) because
the latter would pick anything below 3.0.0 and that includes prereleases such as 3.0.0-alpha, and we do
not want this to happen as the alpha of the next major is, really, the next major already.
-->
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.3, 2.999999)" />

With this applied, the version range excludes any prerelease version and thereby prevents you from installing any mixed CMS major version in a project:

NuGet.Versioning updated version range

If packages use a similar version range to limit the CMS version you can install it on, they should use the same syntax. So to only allow your package to be installed on a version 13 site, you should use: [13.0.0, 14.0.0-0).

The only downside to this approach is that the NuGet build target will raise a NU5104 warning about using a prerelease dependency when building a stable version of your own package. This is a false-positive, as it's not pulling in a prerelease version, but actually preventing you from installing it... I've added this to the NoWarn property to ignore it, although this might actually remove the warning for dependencies that are actually pulling in prereleases. We currently don't fail the build on these kind of warnings and the build contains too many warnings to be noticeable, so I think this is a fine trade-off to not add any more warnings.

Testing can be done by checking the NuGet packages in the build output and verifying whether the dependencies contain the -0 postfix on the upper version limit. Additionally, you can upgrade a v13 project using this build output and check if you now get a NU1107 error if ExaminePeek 1.0.0 (depending on v14.0.0-rc3) is installed:

❯ dotnet build
MSBuild version 17.9.8+b34f75857 for .NET
  Determining projects to restore...
Umbraco 13_4_0.csproj : error NU1107: Version conflict detected for Umbraco.Cms.Web.Common. Install/reference Umbraco.Cms.Web.Common 14.0.0-rc1 directly to project Umbraco 13_4_0 to resolve this issue.
Umbraco 13_4_0.csproj : error NU1107:  Umbraco 13_4_0 -> ExaminePeek 1.0.0 -> Umbraco.Cms.Web.Website 14.0.0-rc1 -> Umbraco.Cms.Web.Common (>= 14.0.0-rc1 && < 15.0.0)
Umbraco 13_4_0.csproj : error NU1107:  Umbraco 13_4_0 -> Umbraco.Cms 13.4.0--preview.6.gbc46017 -> Umbraco.Cms.Imaging.ImageSharp 13.4.0--preview.6.gbc46017 -> Umbraco.Cms.Web.Common (>= 13.4.0--preview.6.gbc46017 && < 14.0.0-0).
  Failed to restore Umbraco 13_4_0.csproj (in 746 ms).

Build FAILED.

@ronaldbarendse
Copy link
Contributor Author

After applying this to some prereleases of our products, everything seemed fine (including pushing to our MyGet prerelease feed), until the NuGet package was being pushed to the public NuGet.org feed 🤯 Apparently NuGet.org validates the versions for legacy clients and that disallows using numeric-only prerelease labels (like -0), which is also discussed here: NuGet/NuGetGallery#6948.

So we're now in the situation that NuGet uses version ranges that aren't adhering to the spec (since it includes prereleases in upper version limits), but also prevents us from pushing a package that tries to work around that by adding the lowest possible prerelease label 🙃 Yes, we can use -a or -alpha instead, but that makes the version range slightly confusing, as it then includes a more readable/understandable prerelease tag.

So for now, I'll close this PR and leave it up to the user to not install prereleases of the next major into an existing project 😒

@ronaldbarendse ronaldbarendse deleted the v13/bugfix/exclude-prereleases-upper-version branch May 29, 2024 14:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant