Skip to content

Add custom nuget version sorter

Moaz Khalifa requested to merge 407395-fix-nuget-version-sorting into master

What does this MR do and why?

The ordering of NuGet versions with mixed alphanumeric identifiers in the pre-release part of the version string is incorrect and can lead to Package ... is not found in the following primary source(s): error while trying to install a package.

The error happens because installing a package command would hit the package metadata endpoint and check if the version-to-be-installed is in between the "lower" & "upper" fields returned from the metadata endpoint. Those fields are generated by sorting the versions and returning the first & last versions as lower & upper bounds.

We use the version_sorter gem for version sorting, which apparently fails to handle the NuGet version specifics. That's why a new custom sorting function is introduced in this MR. It considers the version comparison rules followed by NuGet to correctly sort an array of version strings.

This tool was used to verify the correct ordering while implementing the custom sorting function.

How to set up and validate locally

- To verify the discrepancy between the version_sorter gem behavior and the custom sorting function, you can check how each is ordering differently in the rails console:

include Packages::Nuget::VersionHelpers
versions = ['1.0.0-a1b', '1.0.0-abb', '1.0.0-a11']
VersionSorter.sort(versions) # should output ["1.0.0-a1b", "1.0.0-a11", "1.0.0-abb"] which is wrong
sort_versions(versions) # should output ["1.0.0-a11", "1.0.0-a1b", "1.0.0-abb"] which is correct

- To verify it fixes the Package ... is not found in the following primary source(s): error while trying to install a package:

  1. Ensure you have the NuGet CLI installed (see nuget docs for links to installation pages).

  2. In a new directory, run nuget spec.

  3. Update the version in the Package.nuspec file to 1.0.0-a1b.

  4. Run nuget pack in the same directory, you should find a generated file named Package.1.0.0-a1b.nupkg.

  5. Add a project as your NuGet source:

    nuget source Add -Name localhost -Source "http://gdk.test:3000/api/v4/projects/<project_id>/packages/nuget/index.json" -UserName <gitlab_username> -Password <personal_access_token>
  6. Push the package to your project:

    nuget push Package.1.0.0-a1b.nupkg -Source localhost
  7. Change the version to 1.0.0-a11 in 3. and publish the new package version.

  8. Change the version to 1.0.0-abb in 3. and publish the new package version.

  9. Now you should have the 3 package versions 1.0.0-a1b, 1.0.0-a11 & 1.0.0-abb published.

  10. Try to install version 1.0.0-a11 by running the following command:

  nuget install Package -Version 1.0.0-a11 -Source localhost
  1. The package should be installed successfully.
  2. When switching to the master branch and trying to install the same version, it should fail. (P.S. Don't forget to clear Nuget cache before trying to reinstall the same version: nuget locals all -clear)

MR acceptance checklist

This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.

Related to #407395 (closed)

Edited by Moaz Khalifa

Merge request reports

Loading