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

fix(nuget): Sort api response before picking projectUrl #23090

Merged
Original file line number Diff line number Diff line change
@@ -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>
Original file line number Diff line number Diff line change
@@ -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"
}
]
}
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
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)) {
rarkins marked this conversation as resolved.
Show resolved Hide resolved
latestStable = removeBuildMeta(version);
homepage = projectUrl ? massageUrl(projectUrl) : homepage;
}
Expand Down