Support NuGet version normalization
-
Review changes -
-
Download -
Patches
-
Plain diff
What does this MR do and why?
Problem
Suppose we have a NuGet package named Hello
in our GitLab NuGet Repository with version 1.0.7.0
. If we tried to pull it using NuGet 3.4+, you would get the following error:
Package 'Hello.1.0.7' is not found on source 'https://example.gitlab.com/api/v4/projects/<your_project_id>/packages/nuget/index.json'.
Notice the version in the error message: it's different than the package's version stored in GitLab's NuGet Repository. The reason is that NuGet 3.4+ normalizes the version number and then sends the normalized string to the NuGet Repository. We try to search for the package using the received normalized version and we don't find the package. Makes sense.
Solution
In this MR, the following solution has been introduced:
- Create a new column
normalized_version
in thepackages_nuget_metadata
table - Add Packages::Nuget::NormalizeVersionService to apply normalization rules on the version string.
- When a new package is created, we save the normalized version in
packages_nuget_metadata
'snormalized_version
column using abefore_validation
callback in thePackages::Nuget::Metadatum
model. - Update
Packages::Nuget::PackageFinder
to search for packages usingLOWER(version)
orpackages_nuget_metadata
'snormalized_version
. - Get rid of
ILIKE
fuzzing matching inPackages::Nuget::PackageFinder
in favor of exact matching to enhance the performance. NuGet client always sends the package's full name so exact matching would suffice. - In a subsequent MR, I will introduce a background migration to backfill the
normalized_version
for the existing NuGet Repository packages. - Changes are behind the
nuget_normalized_version
feature flag.
How to set up and validate locally
-
Ensure you have the NuGet CLI installed (see nuget docs for links to installation pages).
-
In a new directory, run
nuget spec
. -
Update the version in the
Package.nuspec
file to1.0.7.0
. -
Run
nuget pack
in the same directory, you should find a generated file namedPackage.1.0.7.nupkg
. -
Notice the NuGet CLI automatically normalized the version to
1.0.7
, we need to update the version manually so that we can push the package with the unnormalized version1.0.7.0
:- Run
unzip Package.1.0.7.nupkg
, and allow the.nuspec
file to be replaced. - Edit the
.nuspec
file and set the version to1.0.7.0
- Compress/zip all of the files in the folder except for
Package.1.0.7.nupkg
. - Rename the zip archive
Package.1.0.7.0.nupkg
.
- Run
-
Add a GitLab 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>
-
In rails console, enable the
nuget_normalized_version
feature flag before publishing the package:
Feature.enable(:nuget_normalized_version, Project.find(<project_id>))
-
Push the package to your project:
nuget push Package.1.0.7.0.nupkg.zip -Source localhost
-
In the UI, navigate to the project, and go to
Packages & Registries -> Package Registry
. You should see the NuGet package published with version1.0.7.0
. -
Create packages.config file in the directory of the published package:
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Package" version="1.0.7.0" />
</packages>
- Execute the command:
nuget restore -PackagesDirectory . -Source localhost
- The package should be pulled successfully.
MR acceptance checklist
This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.
-
I have evaluated the MR acceptance checklist for this MR.
Database analysis
Related to #273697 (closed) & #270976 (closed)
Merge request reports
- version 316774e0df
- version 304319a1b9
- version 2991962b09
- version 28ae2f45c6
- version 279c169f2d
- version 26b88eead6
- version 25111744d6
- version 2472c08ae1
- version 23f5581b03
- version 2255d86957
- version 2187ebed40
- version 204d098694
- version 19b7070a38
- version 18dfecb940
- version 179d9ac9a8
- version 163f733b30
- version 150c544589
- version 143b42065c
- version 139fa8b117
- version 1227e1b821
- version 11677a7c2f
- version 1071945b69
- version 95fa01dc2
- version 8a684ac3a
- version 75b49c3ba
- version 66777f021
- version 58b8b2c60
- version 443f7bd8c
- version 3c1554b8f
- version 29a86ace0
- version 19b6fad1d
- master (base)
- latest version027bf0231 commit,
- version 316774e0df1 commit,
- version 304319a1b91 commit,
- version 2991962b091 commit,
- version 28ae2f45c61 commit,
- version 279c169f2d1 commit,
- version 26b88eead61 commit,
- version 25111744d61 commit,
- version 2472c08ae11 commit,
- version 23f5581b031 commit,
- version 2255d8695720 commits,
- version 2187ebed4020 commits,
- version 204d09869420 commits,
- version 19b7070a3817 commits,
- version 18dfecb94017 commits,
- version 179d9ac9a817 commits,
- version 163f733b3017 commits,
- version 150c54458917 commits,
- version 143b42065c16 commits,
- version 139fa8b11715 commits,
- version 1227e1b82115 commits,
- version 11677a7c2f14 commits,
- version 1071945b6913 commits,
- version 95fa01dc212 commits,
- version 8a684ac3a11 commits,
- version 75b49c3ba10 commits,
- version 66777f0218 commits,
- version 58b8b2c605 commits,
- version 443f7bd8c4 commits,
- version 3c1554b8f3 commits,
- version 29a86ace02 commits,
- version 19b6fad1d1 commit,
- Side-by-side
- Inline
There are no changes yet
No changes between version 10 and version 10