This commit is contained in:
Zanie Blue
2026-01-22 07:57:07 -06:00
parent 0a4c5102bd
commit 8bd9170ab9
9 changed files with 106 additions and 272 deletions
+20 -23
View File
@@ -13,37 +13,34 @@ export async function validateChecksum(
version: string,
ndjsonChecksum?: string,
): Promise<void> {
let isValid: boolean | undefined;
let checksumUsed: string | undefined;
// Priority: user-provided checksum > KNOWN_CHECKSUMS > NDJSON fallback
const key = `${arch}-${platform}-${version}`;
let checksumToUse: string | undefined;
let source: string;
if (checkSum !== undefined && checkSum !== "") {
checksumUsed = checkSum;
core.debug("Using user-provided checksum.");
isValid = await validateFileCheckSum(downloadPath, checkSum);
checksumToUse = checkSum;
source = "user-provided";
} else if (key in KNOWN_CHECKSUMS) {
checksumToUse = KNOWN_CHECKSUMS[key];
source = `known checksum for ${key}`;
} else if (ndjsonChecksum !== undefined && ndjsonChecksum !== "") {
checksumToUse = ndjsonChecksum;
source = "NDJSON version data";
} else {
const key = `${arch}-${platform}-${version}`;
if (key in KNOWN_CHECKSUMS) {
checksumUsed = KNOWN_CHECKSUMS[key];
core.debug(`Using known checksum for ${key}.`);
isValid = await validateFileCheckSum(downloadPath, checksumUsed);
} else if (ndjsonChecksum !== undefined && ndjsonChecksum !== "") {
checksumUsed = ndjsonChecksum;
core.debug("Using checksum from NDJSON version data.");
isValid = await validateFileCheckSum(downloadPath, ndjsonChecksum);
} else {
core.debug(`No checksum found for ${key}.`);
}
core.debug(`No checksum found for ${key}.`);
return;
}
if (isValid === false) {
core.debug(`Using ${source}.`);
const isValid = await validateFileCheckSum(downloadPath, checksumToUse);
if (!isValid) {
throw new Error(
`Checksum for ${downloadPath} did not match ${checksumUsed}.`,
`Checksum for ${downloadPath} did not match ${checksumToUse}.`,
);
}
if (isValid === true) {
core.debug(`Checksum for ${downloadPath} is valid.`);
}
core.debug(`Checksum for ${downloadPath} is valid.`);
}
async function validateFileCheckSum(
+9 -31
View File
@@ -8,11 +8,10 @@ import { OWNER, REPO, TOOL_CACHE_NAME } from "../utils/constants";
import type { Architecture, Platform } from "../utils/platforms";
import { validateChecksum } from "./checksum/checksum";
import {
getDownloadUrl,
getLatestKnownVersion as getLatestVersionInManifest,
getDownloadUrl as getManifestDownloadUrl,
} from "./version-manifest";
import {
type ArtifactResult,
getAllVersions,
getArtifact,
getLatestVersion as getLatestVersionFromNdjson,
@@ -33,7 +32,7 @@ export function tryGetFromToolCache(
return { installedPath, version: resolvedVersion };
}
export async function downloadVersionFromGithub(
export async function downloadVersionFromNdjson(
platform: Platform,
arch: Architecture,
version: string,
@@ -43,13 +42,8 @@ export async function downloadVersionFromGithub(
const artifact = `uv-${arch}-${platform}`;
const extension = getExtension(platform);
// Try to get artifact info from NDJSON (includes checksum)
let artifactInfo: ArtifactResult | undefined;
try {
artifactInfo = await getArtifact(version, arch, platform);
} catch (err) {
core.debug(`Failed to get artifact from NDJSON: ${(err as Error).message}`);
}
// Get artifact info from NDJSON (includes URL and checksum)
const artifactInfo = await getArtifact(version, arch, platform);
const downloadUrl =
artifactInfo?.url ??
@@ -68,39 +62,23 @@ export async function downloadVersionFromGithub(
}
export async function downloadVersionFromManifest(
manifestUrl: string | undefined,
manifestUrl: string,
platform: Platform,
arch: Architecture,
version: string,
checkSum: string | undefined,
githubToken: string,
): Promise<{ version: string; cachedToolDir: string }> {
const downloadUrl = await getDownloadUrl(
const downloadUrl = await getManifestDownloadUrl(
manifestUrl,
version,
arch,
platform,
);
if (!downloadUrl) {
core.info(
`manifest-file does not contain version ${version}, arch ${arch}, platform ${platform}. Falling back to GitHub releases.`,
throw new Error(
`manifest-file does not contain version ${version}, arch ${arch}, platform ${platform}.`,
);
return await downloadVersionFromGithub(
platform,
arch,
version,
checkSum,
githubToken,
);
}
// Try to get checksum from NDJSON for manifest downloads too
let ndjsonChecksum: string | undefined;
try {
const artifactInfo = await getArtifact(version, arch, platform);
ndjsonChecksum = artifactInfo?.sha256;
} catch (err) {
core.debug(`Failed to get artifact from NDJSON: ${(err as Error).message}`);
}
return await downloadVersion(
@@ -111,7 +89,7 @@ export async function downloadVersionFromManifest(
version,
checkSum,
githubToken,
ndjsonChecksum,
undefined, // No NDJSON checksum for manifest downloads
);
}
+7 -34
View File
@@ -31,46 +31,19 @@ export async function fetchVersionData(): Promise<NdjsonVersion[]> {
);
}
const body = await response.text();
const versions: NdjsonVersion[] = [];
if (!response.body) {
throw new Error("Response body is null");
}
// Stream and parse NDJSON line by line
const decoder = new TextDecoder();
let buffer = "";
for await (const chunk of response.body) {
buffer += decoder.decode(chunk, { stream: true });
// Process complete lines
const lines = buffer.split("\n");
// Keep the last potentially incomplete line in buffer
buffer = lines.pop() ?? "";
for (const line of lines) {
const trimmed = line.trim();
if (trimmed === "") {
continue;
}
try {
const version = JSON.parse(trimmed) as NdjsonVersion;
versions.push(version);
} catch {
core.debug(`Failed to parse NDJSON line: ${trimmed}`);
}
for (const line of body.split("\n")) {
const trimmed = line.trim();
if (trimmed === "") {
continue;
}
}
// Process any remaining content in buffer
const remaining = buffer.trim();
if (remaining !== "") {
try {
const version = JSON.parse(remaining) as NdjsonVersion;
const version = JSON.parse(trimmed) as NdjsonVersion;
versions.push(version);
} catch {
core.debug(`Failed to parse NDJSON line: ${remaining}`);
core.debug(`Failed to parse NDJSON line: ${trimmed}`);
}
}
+18 -8
View File
@@ -5,6 +5,7 @@ import * as exec from "@actions/exec";
import { restoreCache } from "./cache/restore-cache";
import {
downloadVersionFromManifest,
downloadVersionFromNdjson,
resolveVersion,
tryGetFromToolCache,
} from "./download/download-version";
@@ -138,14 +139,23 @@ async function setupUv(
};
}
const downloadVersionResult = await downloadVersionFromManifest(
manifestFile,
platform,
arch,
resolvedVersion,
checkSum,
githubToken,
);
// Use the same source for download as we used for version resolution
const downloadVersionResult = manifestFile
? await downloadVersionFromManifest(
manifestFile,
platform,
arch,
resolvedVersion,
checkSum,
githubToken,
)
: await downloadVersionFromNdjson(
platform,
arch,
resolvedVersion,
checkSum,
githubToken,
);
return {
uvDir: downloadVersionResult.cachedToolDir,
+1 -2
View File
@@ -1,3 +1,4 @@
import { promises as fs } from "node:fs";
import * as core from "@actions/core";
import * as semver from "semver";
import { updateChecksums } from "./download/checksum/update-known-checksums";
@@ -100,8 +101,6 @@ async function updateVersionManifestFromEntries(
filePath: string,
entries: ArtifactEntry[],
): Promise<void> {
const { promises: fs } = await import("node:fs");
const manifest = entries.map((entry) => ({
arch: entry.arch,
artifactName: entry.artifactName,