Skip to content

Commit

Permalink
fix(nuget): Sort api response before picking projectUrl (#23090)
Browse files Browse the repository at this point in the history
Co-authored-by: Rhys Arkins <rhys@arkins.net>
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
  • Loading branch information
3 people committed Oct 15, 2023
1 parent d03ef92 commit ac15e23
Show file tree
Hide file tree
Showing 6 changed files with 199 additions and 2 deletions.
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata minClientVersion="2.12">
<id>NUnit</id>
<version>3.13.2</version>
<title>NUnit</title>
<authors>Charlie Poole, Rob Prouse</authors>
<owners>Charlie Poole, Rob Prouse</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<license type="file">LICENSE.txt</license>
<licenseUrl>https://aka.ms/deprecateLicenseUrl</licenseUrl>
<icon>icon.png</icon>
<projectUrl>https://nunit.org/</projectUrl>
<iconUrl>https://cdn.rawgit.com/nunit/resources/master/images/icon/nunit_256.png</iconUrl>
<description></description>
<summary>NUnit is a unit-testing framework for all .NET languages with a strong TDD focus.</summary>
<releaseNotes></releaseNotes>
<copyright>Copyright (c) 2021 Charlie Poole, Rob Prouse</copyright>
<language>en-US</language>
<tags>nunit test testing tdd framework fluent assert theory plugin addin</tags>
<repository type="git" url="https://github.com/nunit/nunit" />
<dependencies>
<group targetFramework=".NETFramework3.5" />
<group targetFramework=".NETFramework4.0" />
<group targetFramework=".NETFramework4.5" />
<group targetFramework=".NETStandard2.0">
<dependency id="NETStandard.Library" version="2.0.0" />
</group>
</dependencies>
</metadata>
</package>
@@ -0,0 +1,56 @@
{
"count": 1,
"items": [
{
"count": 4,
"items": [
{
"@id": "https://pkgs.dev.azure.com/organisationName/_packaging/2745c5e9-610a-4537-9032-978c66527b51/nuget/v3/registrations2/nunit/3.13.2.json",
"@type": "Package",
"catalogEntry": {
"listed": true,
"projectUrl": "https://nunit.org/",
"published": "2021-12-03T03:20:52Z",
"version": "3.13.2"
},
"packageContent": "https://pkgs.dev.azure.com/organisationName/_packaging/2745c5e9-610a-4537-9032-978c66527b51/nuget/v3/flat2/nunit/3.13.2/nunit.3.13.2.nupkg"
},
{
"@id": "https://pkgs.dev.azure.com/organisationName/_packaging/2745c5e9-610a-4537-9032-978c66527b51/nuget/v3/registrations2/nunit/2.7.1.json",
"@type": "Package",
"catalogEntry": {
"listed": true,
"projectUrl": "http://nunitsoftware.com/nunitv2",
"published": "2021-12-03T03:20:52Z",
"version": "2.7.1"
},
"packageContent": "https://pkgs.dev.azure.com/organisationName/_packaging/2745c5e9-610a-4537-9032-978c66527b51/nuget/v3/flat2/nunit/2.7.1/nunit.2.7.1.nupkg"
},
{
"@id": "https://pkgs.dev.azure.com/organisationName/_packaging/2745c5e9-610a-4537-9032-978c66527b51/nuget/v3/registrations2/nunit/2.6.5.json",
"@type": "Package",
"catalogEntry": {
"listed": true,
"projectUrl": "http://nunit.org/",
"published": "2021-12-03T03:20:52Z",
"version": "2.6.5"
},
"packageContent": "https://pkgs.dev.azure.com/organisationName/_packaging/2745c5e9-610a-4537-9032-978c66527b51/nuget/v3/flat2/nunit/2.6.5/nunit.2.6.5.nupkg"
},
{
"@id": "https://pkgs.dev.azure.com/organisationName/_packaging/2745c5e9-610a-4537-9032-978c66527b51/nuget/v3/registrations2/nunit/2.5.7.10213.json",
"@type": "Package",
"catalogEntry": {
"listed": true,
"projectUrl": "",
"published": "2021-12-03T03:20:52Z",
"version": "2.5.7.10213"
},
"packageContent": "https://pkgs.dev.azure.com/organisationName/_packaging/2745c5e9-610a-4537-9032-978c66527b51/nuget/v3/flat2/nunit/2.5.7.10213/nunit.2.5.7.10213.nupkg"
}
],
"lower": "2.5.7.10213",
"upper": "3.13.2"
}
]
}
@@ -0,0 +1,14 @@
{
"resources": [
{
"@id": "https://pkgs.dev.azure.com/organisationName/_packaging/2745c5e9-610a-4537-9032-978c66527b51/nuget/v3/registrations2-semver2/",
"@type": "RegistrationsBaseUrl/3.6.0",
"comment": "This base URL includes SemVer 2.0.0 packages."
},
{
"@id": "https://pkgs.dev.azure.com/organisationName/_packaging/2745c5e9-610a-4537-9032-978c66527b51/nuget/v3/flat2/",
"@type": "PackageBaseAddress/3.0.0"
}
],
"version": "3.0.0-beta"
}
54 changes: 54 additions & 0 deletions lib/modules/datasource/nuget/index.spec.ts
Expand Up @@ -94,6 +94,15 @@ const configV3Multiple = {
],
};

const configV3AzureDevOps = {
datasource,
versioning,
packageName: 'nunit',
registryUrls: [
'https://pkgs.dev.azure.com/organisationName/_packaging/2745c5e9-610a-4537-9032-978c66527b51/nuget/v3/index.json',
],
};

describe('modules/datasource/nuget/index', () => {
describe('parseRegistryUrl', () => {
it('extracts feed version from registry URL hash (v3)', () => {
Expand Down Expand Up @@ -374,6 +383,51 @@ describe('modules/datasource/nuget/index', () => {
expect(res?.sourceUrl).toBeDefined();
});

it('processes real data (v3) feed is azure devops', async () => {
httpMock
.scope('https://pkgs.dev.azure.com')
.get(
'/organisationName/_packaging/2745c5e9-610a-4537-9032-978c66527b51/nuget/v3/index.json'
)
.twice()
.reply(200, Fixtures.get('azure_devops/v3_index.json'))
.get(
'/organisationName/_packaging/2745c5e9-610a-4537-9032-978c66527b51/nuget/v3/registrations2-semver2/nunit/index.json'
)
.reply(200, Fixtures.get('azure_devops/nunit/v3_registration.json'))
.get(
'/organisationName/_packaging/2745c5e9-610a-4537-9032-978c66527b51/nuget/v3/flat2/nunit/3.13.2/nunit.nuspec'
)
.reply(200, Fixtures.get('azure_devops/nunit/nuspec.xml'));
const res = await getPkgReleases({
...configV3AzureDevOps,
});
expect(res).toMatchObject({
homepage: 'https://nunit.org/',
registryUrl:
'https://pkgs.dev.azure.com/organisationName/_packaging/2745c5e9-610a-4537-9032-978c66527b51/nuget/v3/index.json',
releases: [
{
releaseTimestamp: '2021-12-03T03:20:52.000Z',
version: '2.5.7.10213',
},
{
releaseTimestamp: '2021-12-03T03:20:52.000Z',
version: '2.6.5',
},
{
releaseTimestamp: '2021-12-03T03:20:52.000Z',
version: '2.7.1',
},
{
releaseTimestamp: '2021-12-03T03:20:52.000Z',
version: '3.13.2',
},
],
sourceUrl: 'https://github.com/nunit/nunit',
});
});

it('processes real data (v3) for several catalog pages', async () => {
const scope = httpMock
.scope('https://api.nuget.org')
Expand Down
19 changes: 19 additions & 0 deletions lib/modules/datasource/nuget/v3.spec.ts
@@ -0,0 +1,19 @@
import { sortNugetVersions } from './v3';

describe('modules/datasource/nuget/v3', () => {
it.each<{ version: string; other: string; result: number }>`
version | other | result
${'invalid1'} | ${'invalid2'} | ${0}
${'invalid'} | ${'1.0.0'} | ${-1}
${'1.0.0'} | ${'invalid'} | ${1}
${'1.0.0-rc.1'} | ${'1.0.0'} | ${-1}
${'1.0.0'} | ${'1.0.0-rc.1'} | ${1}
${'1.0.0'} | ${'1.0.0'} | ${0}
`(
'sortNugetVersions("$version", "$other") === $result',
({ version, other, result }) => {
const res = sortNugetVersions(version, other);
expect(res).toBe(result);
}
);
});
27 changes: 25 additions & 2 deletions lib/modules/datasource/nuget/v3.ts
Expand Up @@ -8,6 +8,7 @@ import { Http, HttpError } from '../../../util/http';
import * as p from '../../../util/promises';
import { regEx } from '../../../util/regex';
import { ensureTrailingSlash } from '../../../util/url';
import { api as versioning } from '../../versioning/nuget';
import type { Release, ReleaseResult } from '../types';
import { massageUrl, removeBuildMeta } from './common';
import type {
Expand Down Expand Up @@ -110,6 +111,26 @@ async function getCatalogEntry(
return items.map(({ catalogEntry }) => catalogEntry);
}

/**
* Compare two versions. Return:
* - `1` if `a > b` or `b` is invalid
* - `-1` if `a < b` or `a` is invalid
* - `0` if `a == b` or both `a` and `b` are invalid
*/
export function sortNugetVersions(a: string, b: string): number {
if (versioning.isValid(a)) {
if (versioning.isValid(b)) {
return versioning.sortVersions(a, b);
} else {
return 1;
}
} else if (versioning.isValid(b)) {
return -1;
} else {
return 0;
}
}

export async function getReleases(
http: Http,
registryUrl: string,
Expand All @@ -123,7 +144,9 @@ export async function getReleases(
const catalogPagesQueue = catalogPages.map(
(page) => (): Promise<CatalogEntry[]> => getCatalogEntry(http, page)
);
const catalogEntries = (await p.all(catalogPagesQueue)).flat();
const catalogEntries = (await p.all(catalogPagesQueue))
.flat()
.sort((a, b) => sortNugetVersions(a.version, b.version));

let homepage: string | null = null;
let latestStable: string | null = null;
Expand All @@ -133,7 +156,7 @@ export async function getReleases(
if (releaseTimestamp) {
release.releaseTimestamp = releaseTimestamp;
}
if (semver.valid(version) && !semver.prerelease(version)) {
if (versioning.isValid(version) && versioning.isStable(version)) {
latestStable = removeBuildMeta(version);
homepage = projectUrl ? massageUrl(projectUrl) : homepage;
}
Expand Down

0 comments on commit ac15e23

Please sign in to comment.