Skip to content

Commit 59f0d6d

Browse files
committed
fix: version compare
Signed-off-by: Umberto Sgueglia <usgueglia@contractor.linuxfoundation.org>
1 parent a8a5b0f commit 59f0d6d

4 files changed

Lines changed: 19 additions & 28 deletions

File tree

services/apps/packages_worker/src/blast-radius/clients/nugetSource.ts

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,8 @@ function codeloadTarballUrl(owner: string, repo: string, ref: string): string {
4747
return `https://codeload.github.com/${owner}/${repo}/tar.gz/${ref}`
4848
}
4949

50-
// .nupkg ships compiled DLLs, not C# source (unlike Maven's -sources.jar), so source
51-
// must come from GitHub. Ordered candidates: the exact commit the nuspec <repository>
52-
// element records (most precise), then a couple of common version-tag conventions
53-
// against the same repo. Only GitHub repos are supported — GitLab/Bitbucket tarballs
54-
// don't share codeload's single-wrapper-directory layout that downloadAndExtractTarball
55-
// (strip: 1) relies on.
50+
// .nupkg has no source (unlike Maven's -sources.jar), so fetch from GitHub repo.
51+
// Try exact commit first, then common version-tag conventions.
5652
async function candidateSourceTarballUrls(packageId: string, version: string): Promise<string[]> {
5753
const nuspec = await fetchNuspec(packageId, version)
5854
if (isNuGetFetchError(nuspec)) return []
@@ -66,11 +62,14 @@ async function candidateSourceTarballUrls(packageId: string, version: string): P
6662
const ownerRepo = githubOwnerRepo(canonical.url)
6763
if (!ownerRepo) return []
6864

69-
const candidates: string[] = []
70-
if (commit) candidates.push(codeloadTarballUrl(ownerRepo.owner, ownerRepo.repo, commit))
71-
candidates.push(codeloadTarballUrl(ownerRepo.owner, ownerRepo.repo, `v${version}`))
72-
candidates.push(codeloadTarballUrl(ownerRepo.owner, ownerRepo.repo, version))
73-
return candidates
65+
// An authoritative commit must never fall through to guessed tags, which could
66+
// resolve to a different revision and produce a verdict from mismatched source.
67+
if (commit) return [codeloadTarballUrl(ownerRepo.owner, ownerRepo.repo, commit)]
68+
69+
return [
70+
codeloadTarballUrl(ownerRepo.owner, ownerRepo.repo, `v${version}`),
71+
codeloadTarballUrl(ownerRepo.owner, ownerRepo.repo, version),
72+
]
7473
}
7574

7675
export async function downloadAndExtractNuGetSource(

services/apps/packages_worker/src/blast-radius/packageIdentifier.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
1-
// Strip query string and fragment from a purl or identifier string.
21
function stripQueryAndFragment(input: string): string {
32
const q = input.indexOf('?')
43
const h = input.indexOf('#')
54
const cut = q === -1 ? h : h === -1 ? q : Math.min(q, h)
65
return cut === -1 ? input : input.slice(0, cut)
76
}
87

9-
// The blast-radius submit endpoint accepts either a bare npm package name
10-
// ("lodash", "@babel/core") or a full purl ("pkg:npm/lodash", "pkg:npm/%40babel/core@4.17.21")
11-
// for the `package` field — see blastRadiusJobRequestSchema. OSV affected-package entries and
12-
// the npm registry only ever use bare names, so a purl must be reduced to that form before
13-
// it's compared against them (raw string equality otherwise never matches a purl input).
8+
// OSV/npm registry use bare names only, so purls must be normalized before comparison.
9+
// See blastRadiusJobRequestSchema for accepted formats.
1410
export function toBareNpmName(input: string): string {
1511
let name = input.trim()
1612

services/apps/packages_worker/src/blast-radius/stages/ecosystemVersions.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,8 @@ import { OsvAffectedPackage } from '../clients/osvClient'
33

44
import { compareNuGetVersion } from './nuget/nugetVersionCompare'
55

6-
// Shared by any ecosystem whose OSV advisories use ECOSYSTEM-typed ranges (ordered via
7-
// compareVersion(ecosystem, …) rather than node-semver) instead of SEMVER-typed ranges —
8-
// currently Maven and NuGet. Parameterized by ecosystem so the two don't duplicate this
9-
// logic; see mavenVersions.ts for the ecosystem-bound wrappers Maven's stage files import.
6+
// Shared range type for Maven and NuGet (ecosystems with ECOSYSTEM-typed OSV ranges).
7+
// Parameterized by ecosystem to avoid duplication; see mavenVersions.ts for wrappers.
108
export interface EcosystemRange {
119
introduced: string | null
1210
fixed: string | null

services/apps/packages_worker/src/blast-radius/stages/selectAdvisoryEntry.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,30 +13,28 @@ export function selectAdvisoryEntry<T extends { package: { name: string } }>(
1313
matchesRequested: (entry: T) => boolean,
1414
advisoryOsvId: string,
1515
): SelectedAdvisoryEntry<T> {
16+
const affectedNames = entries.map((e) => e.package.name)
17+
1618
// `!== null`, not truthiness — an empty string is still an explicit (if malformed)
1719
// request and must go through matching/rejection, not be treated as "none requested".
1820
if (requestedPackageName !== null) {
1921
const entry = entries.find(matchesRequested)
2022
if (!entry) {
21-
const affectedNames = entries.map((e) => e.package.name).join(', ')
2223
throw ApplicationFailure.nonRetryable(
2324
`Requested package ${requestedPackageName} not found in advisory ${advisoryOsvId} ` +
24-
`(affected: ${affectedNames})`,
25+
`(affected: ${affectedNames.join(', ')})`,
2526
'ADVISORY_PACKAGE_NOT_FOUND',
2627
)
2728
}
2829
return {
2930
entry,
30-
relatedAffectedPackages: entries
31-
.map((e) => e.package.name)
32-
.filter((name) => name !== entry.package.name),
31+
relatedAffectedPackages: affectedNames.filter((name) => name !== entry.package.name),
3332
}
3433
}
3534

3635
if (entries.length > 1) {
37-
const affectedNames = entries.map((e) => e.package.name).join(', ')
3836
throw ApplicationFailure.nonRetryable(
39-
`Advisory ${advisoryOsvId} affects ${entries.length} packages (${affectedNames}); ` +
37+
`Advisory ${advisoryOsvId} affects ${entries.length} packages (${affectedNames.join(', ')}); ` +
4038
`advisory-wide analysis is not supported for multi-artifact advisories — specify one via 'package'`,
4139
'ADVISORY_MULTI_ARTIFACT_AMBIGUOUS',
4240
)

0 commit comments

Comments
 (0)