mirror of
https://github.com/astral-sh/setup-uv.git
synced 2026-11-05 01:35:32 +00:00
Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
68559e99cc | ||
|
|
0192b69518 | ||
|
|
2f29784424 | ||
|
|
9c7332190c | ||
|
|
80fbe0140c | ||
|
|
36b7b57007 |
Vendored
+87
@@ -0,0 +1,87 @@
|
|||||||
|
import { mkdtempSync, rmSync } from "node:fs";
|
||||||
|
import { tmpdir } from "node:os";
|
||||||
|
import { join } from "node:path";
|
||||||
|
import {
|
||||||
|
afterAll,
|
||||||
|
beforeEach,
|
||||||
|
describe,
|
||||||
|
expect,
|
||||||
|
it,
|
||||||
|
jest,
|
||||||
|
} from "@jest/globals";
|
||||||
|
import { CacheLocalSource, type SetupInputs } from "../../src/utils/inputs";
|
||||||
|
import { createSetupInputs } from "../helpers/setup-inputs";
|
||||||
|
|
||||||
|
const mockSaveCache = jest.fn<() => Promise<number>>();
|
||||||
|
const mockInfo = jest.fn();
|
||||||
|
const mockLoadInputs = jest.fn<() => SetupInputs>(() =>
|
||||||
|
createSetupInputs({ enableCache: false }),
|
||||||
|
);
|
||||||
|
const state: Record<string, string> = {};
|
||||||
|
|
||||||
|
jest.unstable_mockModule("@actions/cache", () => ({
|
||||||
|
saveCache: mockSaveCache,
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.unstable_mockModule("@actions/core", () => ({
|
||||||
|
getState: jest.fn((name: string) => state[name] ?? ""),
|
||||||
|
setFailed: jest.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.unstable_mockModule("../../src/utils/inputs", () => ({
|
||||||
|
loadInputs: mockLoadInputs,
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.unstable_mockModule("../../src/utils/logging", () => ({
|
||||||
|
info: mockInfo,
|
||||||
|
warning: jest.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.spyOn(process, "exit").mockImplementation((() => undefined) as never);
|
||||||
|
|
||||||
|
const { run } = await import("../../src/save-cache");
|
||||||
|
|
||||||
|
const cacheDir = mkdtempSync(join(tmpdir(), "setup-uv-save-cache-"));
|
||||||
|
const cacheKey = "setup-uv-2-x86_64-unknown-linux-gnu-ubuntu-24.04-3.12-hash";
|
||||||
|
|
||||||
|
function infoMessages(): string[] {
|
||||||
|
return mockInfo.mock.calls.map(([msg]) => msg as string);
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
delete process.env.UV_CACHE_DIR;
|
||||||
|
state["cache-key"] = cacheKey;
|
||||||
|
state["cache-matched-key"] = "";
|
||||||
|
mockLoadInputs.mockReturnValue(
|
||||||
|
createSetupInputs({
|
||||||
|
cacheLocalPath: { path: cacheDir, source: CacheLocalSource.Input },
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
rmSync(cacheDir, { force: true, recursive: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("saveCache", () => {
|
||||||
|
it("reports the saved key when the cache is saved", async () => {
|
||||||
|
mockSaveCache.mockResolvedValue(42);
|
||||||
|
|
||||||
|
await run();
|
||||||
|
|
||||||
|
expect(mockSaveCache).toHaveBeenCalledWith([cacheDir], cacheKey);
|
||||||
|
expect(infoMessages()).toContain(`uv cache saved with key: ${cacheKey}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not report the cache as saved when saving fails", async () => {
|
||||||
|
// @actions/cache logs the failure itself and returns -1
|
||||||
|
mockSaveCache.mockResolvedValue(-1);
|
||||||
|
|
||||||
|
await run();
|
||||||
|
|
||||||
|
expect(mockSaveCache).toHaveBeenCalledWith([cacheDir], cacheKey);
|
||||||
|
expect(infoMessages()).not.toContain(
|
||||||
|
`uv cache saved with key: ${cacheKey}`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -146,6 +146,28 @@ describe("download-version", () => {
|
|||||||
expect(mockGetAllVersions).not.toHaveBeenCalled();
|
expect(mockGetAllVersions).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("resolves ~= with PEP 440 compatible release semantics", async () => {
|
||||||
|
mockGetFirstMatchingVersion.mockImplementation(
|
||||||
|
(predicate: (version: string) => boolean) =>
|
||||||
|
["1.0.0", "0.10.2", "0.9.26"].find(predicate),
|
||||||
|
);
|
||||||
|
|
||||||
|
const version = await resolveVersion("~=0.9", undefined);
|
||||||
|
|
||||||
|
expect(version).toBe("0.10.2");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("resolves ~= with PEP 440 compatible release semantics from manifest-file", async () => {
|
||||||
|
mockGetAllVersions.mockResolvedValue(["1.0.0", "0.10.2", "0.9.26"]);
|
||||||
|
|
||||||
|
const version = await resolveVersion(
|
||||||
|
"~=0.9",
|
||||||
|
"https://example.com/custom.ndjson",
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(version).toBe("0.10.2");
|
||||||
|
});
|
||||||
|
|
||||||
it("treats == exact pins as explicit versions", async () => {
|
it("treats == exact pins as explicit versions", async () => {
|
||||||
const version = await resolveVersion("==0.9.26", undefined);
|
const version = await resolveVersion("==0.9.26", undefined);
|
||||||
|
|
||||||
@@ -220,7 +242,7 @@ describe("download-version", () => {
|
|||||||
"token",
|
"token",
|
||||||
),
|
),
|
||||||
).rejects.toThrow(
|
).rejects.toThrow(
|
||||||
"Could not find artifact for version 0.9.26, arch x86_64, platform unknown-linux-gnu in https://raw.githubusercontent.com/astral-sh/versions/main/v1/uv.ndjson .",
|
"Could not find artifact for version 0.9.26, arch x86_64, platform unknown-linux-gnu in https://releases.astral.sh/github/versions/main/v1/uv.ndjson .",
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(mockDownloadTool).not.toHaveBeenCalled();
|
expect(mockDownloadTool).not.toHaveBeenCalled();
|
||||||
|
|||||||
@@ -96,6 +96,78 @@ describe("manifest", () => {
|
|||||||
expect(versions).toHaveLength(2);
|
expect(versions).toHaveLength(2);
|
||||||
expect(versions[0]?.version).toBe("0.9.26");
|
expect(versions[0]?.version).toBe("0.9.26");
|
||||||
expect(versions[1]?.version).toBe("0.9.25");
|
expect(versions[1]?.version).toBe("0.9.25");
|
||||||
|
expect(mockFetch.mock.calls.map(([url]) => url)).toEqual([
|
||||||
|
"https://releases.astral.sh/github/versions/main/v1/uv.ndjson",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("falls back to GitHub after mirror network retries are exhausted", async () => {
|
||||||
|
jest.useFakeTimers();
|
||||||
|
mockFetch
|
||||||
|
.mockRejectedValueOnce(new Error("mirror unavailable"))
|
||||||
|
.mockRejectedValueOnce(new Error("mirror unavailable"))
|
||||||
|
.mockRejectedValueOnce(new Error("mirror unavailable"))
|
||||||
|
.mockResolvedValueOnce(
|
||||||
|
createMockResponse(true, 200, "OK", sampleManifestResponse),
|
||||||
|
);
|
||||||
|
|
||||||
|
const result = fetchManifest();
|
||||||
|
await jest.runAllTimersAsync();
|
||||||
|
|
||||||
|
await expect(result).resolves.toEqual([
|
||||||
|
expect.objectContaining({ version: "0.9.26" }),
|
||||||
|
expect.objectContaining({ version: "0.9.25" }),
|
||||||
|
]);
|
||||||
|
expect(mockFetch.mock.calls.map(([url]) => url)).toEqual([
|
||||||
|
"https://releases.astral.sh/github/versions/main/v1/uv.ndjson",
|
||||||
|
"https://releases.astral.sh/github/versions/main/v1/uv.ndjson",
|
||||||
|
"https://releases.astral.sh/github/versions/main/v1/uv.ndjson",
|
||||||
|
"https://raw.githubusercontent.com/astral-sh/versions/main/v1/uv.ndjson",
|
||||||
|
]);
|
||||||
|
|
||||||
|
await expect(getLatestVersion()).resolves.toBe("0.9.26");
|
||||||
|
expect(mockFetch).toHaveBeenCalledTimes(4);
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each([404, 429, 503])(
|
||||||
|
"falls back to a streaming GitHub manifest on mirror HTTP %s",
|
||||||
|
async (status) => {
|
||||||
|
mockFetch
|
||||||
|
.mockResolvedValueOnce(createMockResponse(false, status, "Error", ""))
|
||||||
|
.mockResolvedValueOnce(
|
||||||
|
createStreamingMockResponse([`${sampleManifestResponse}\n`]),
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect(getLatestVersion()).resolves.toBe("0.9.26");
|
||||||
|
await expect(
|
||||||
|
getArtifact("0.9.26", "aarch64", "apple-darwin"),
|
||||||
|
).resolves.toEqual({
|
||||||
|
archiveFormat: "tar.gz",
|
||||||
|
checksum:
|
||||||
|
"fcf0a9ea6599c6ae28a4c854ac6da76f2c889354d7c36ce136ef071f7ab9721f",
|
||||||
|
downloadUrl:
|
||||||
|
"https://github.com/astral-sh/uv/releases/download/0.9.26/uv-aarch64-apple-darwin.tar.gz",
|
||||||
|
});
|
||||||
|
expect(mockFetch.mock.calls.map(([url]) => url)).toEqual([
|
||||||
|
"https://releases.astral.sh/github/versions/main/v1/uv.ndjson",
|
||||||
|
"https://raw.githubusercontent.com/astral-sh/versions/main/v1/uv.ndjson",
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
it("does not fall back from a custom manifest", async () => {
|
||||||
|
mockFetch.mockResolvedValue(
|
||||||
|
createMockResponse(false, 503, "Service Unavailable", ""),
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
fetchManifest("https://example.com/custom.ndjson"),
|
||||||
|
).rejects.toThrow(
|
||||||
|
"Failed to fetch manifest data: 503 Service Unavailable",
|
||||||
|
);
|
||||||
|
expect(mockFetch.mock.calls.map(([url]) => url)).toEqual([
|
||||||
|
"https://example.com/custom.ndjson",
|
||||||
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("retries network failures", async () => {
|
it("retries network failures", async () => {
|
||||||
@@ -123,7 +195,7 @@ describe("manifest", () => {
|
|||||||
await jest.runAllTimersAsync();
|
await jest.runAllTimersAsync();
|
||||||
|
|
||||||
await result;
|
await result;
|
||||||
expect(mockFetch).toHaveBeenCalledTimes(MANIFEST_FETCH_ATTEMPTS);
|
expect(mockFetch).toHaveBeenCalledTimes(MANIFEST_FETCH_ATTEMPTS * 2);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("throws on a failed fetch", async () => {
|
it("throws on a failed fetch", async () => {
|
||||||
|
|||||||
@@ -35,3 +35,14 @@ test("strips PEP 508 markers from requirements dependencies", () => {
|
|||||||
|
|
||||||
expect(parsedVersion).toBe("==0.11.20");
|
expect(parsedVersion).toBe("==0.11.20");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test.each([
|
||||||
|
["uv >= 0.5.0", ">=0.5.0"],
|
||||||
|
["uv == 0.11.20", "==0.11.20"],
|
||||||
|
["uv>=0.5.0, <0.6.0", ">=0.5.0,<0.6.0"],
|
||||||
|
["uv >= 0.5.0 , < 0.6.0", ">=0.5.0,<0.6.0"],
|
||||||
|
["uv==0.11.20 --hash=sha256:abc", "==0.11.20"],
|
||||||
|
["uv==0.11.20 # pinned for CI", "==0.11.20"],
|
||||||
|
])("allows whitespace in the uv specifier %s", (dependency, expected) => {
|
||||||
|
expect(getUvVersionFromRequirementsText(dependency)).toBe(expected);
|
||||||
|
});
|
||||||
|
|||||||
+4
-2
@@ -66671,8 +66671,10 @@ async function saveCacheToKey(cacheKey, cachePath, stateKey, cacheName) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
info2(`Including ${cacheName} path: ${cachePath}`);
|
info2(`Including ${cacheName} path: ${cachePath}`);
|
||||||
await saveCache2([cachePath], cacheKey);
|
const cacheId = await saveCache2([cachePath], cacheKey);
|
||||||
info2(`${cacheName} saved with key: ${cacheKey}`);
|
if (cacheId !== -1) {
|
||||||
|
info2(`${cacheName} saved with key: ${cacheKey}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
__name(saveCacheToKey, "saveCacheToKey");
|
__name(saveCacheToKey, "saveCacheToKey");
|
||||||
run();
|
run();
|
||||||
|
|||||||
+40
-5
@@ -94499,7 +94499,8 @@ function _getGlobal(key, defaultValue) {
|
|||||||
var TOOL_CACHE_NAME = "uv";
|
var TOOL_CACHE_NAME = "uv";
|
||||||
var STATE_UV_PATH = "uv-path";
|
var STATE_UV_PATH = "uv-path";
|
||||||
var STATE_UV_VERSION = "uv-version";
|
var STATE_UV_VERSION = "uv-version";
|
||||||
var VERSIONS_MANIFEST_URL = "https://raw.githubusercontent.com/astral-sh/versions/main/v1/uv.ndjson";
|
var VERSIONS_MANIFEST_URL = "https://releases.astral.sh/github/versions/main/v1/uv.ndjson";
|
||||||
|
var GITHUB_VERSIONS_MANIFEST_URL = "https://raw.githubusercontent.com/astral-sh/versions/main/v1/uv.ndjson";
|
||||||
var GITHUB_RELEASES_PREFIX = "https://github.com/astral-sh/uv/releases/download/";
|
var GITHUB_RELEASES_PREFIX = "https://github.com/astral-sh/uv/releases/download/";
|
||||||
var ASTRAL_MIRROR_PREFIX = "https://releases.astral.sh/github/uv/releases/download/";
|
var ASTRAL_MIRROR_PREFIX = "https://releases.astral.sh/github/uv/releases/download/";
|
||||||
|
|
||||||
@@ -94509,6 +94510,24 @@ var fs10 = __toESM(require("node:fs"), 1);
|
|||||||
|
|
||||||
// src/download/checksum/known-checksums.json
|
// src/download/checksum/known-checksums.json
|
||||||
var known_checksums_default = {
|
var known_checksums_default = {
|
||||||
|
"aarch64-apple-darwin-0.13.6": "60fbd5c8a1ed681845eea28d9d622fcde03c51e91a43465b64a1e17db1ed3472",
|
||||||
|
"aarch64-pc-windows-msvc-0.13.6": "c2426c0c8e28b53d8c440e47a18d96ad4db51e159866c0e81435b196d7f0081c",
|
||||||
|
"aarch64-unknown-linux-gnu-0.13.6": "229e194255c7958d86d56e8790d969a6f74736592133f0dfd0076f754c642c1d",
|
||||||
|
"aarch64-unknown-linux-musl-0.13.6": "819692e404d23e5aae6bc44c0e260f1f5492fd1910ab4693b2c650f926dbe800",
|
||||||
|
"arm-unknown-linux-musleabihf-0.13.6": "57ac0f7c04deb42c5d686b4eeeef555c442db6ffea16fe4cbd7adb0384403794",
|
||||||
|
"armv7-unknown-linux-gnueabihf-0.13.6": "d00cd4949c4524c934afcfee1aedfa9d337cf4e43be4d6b692ad8d74d0a65562",
|
||||||
|
"armv7-unknown-linux-musleabihf-0.13.6": "b215398c886e8cc2cfa282fe346c02025957f8633b75a3d4fd848e0adda4eddd",
|
||||||
|
"i686-pc-windows-msvc-0.13.6": "32ceb64db231cbedfd499f7654c72e4c0b564f2846f9e76c0a4a7b2d03d7e67c",
|
||||||
|
"i686-unknown-linux-gnu-0.13.6": "665ea831c38d342900950e606beb2ccc37b7ba0fcefc37b814eb4b076305f2b6",
|
||||||
|
"i686-unknown-linux-musl-0.13.6": "de3a015c4b0fce63c178ae4fa95c94c873adfd92fa1e258c6a2a94e529812629",
|
||||||
|
"powerpc64le-unknown-linux-gnu-0.13.6": "3b2847185ec2946fcc928500efef7e3e74c255d3be6f2cb435081a84885d8c6c",
|
||||||
|
"riscv64gc-unknown-linux-gnu-0.13.6": "517052603ed46483b59d8875c9c61a577946b8f493c73e4339e45e7b119171d0",
|
||||||
|
"riscv64gc-unknown-linux-musl-0.13.6": "659a95dc6aee3ecf86742a08d8ca6c6261422121cbd41decc0042f5a71af6305",
|
||||||
|
"s390x-unknown-linux-gnu-0.13.6": "fb56d731308aa5c7718059d71afcb14d9a933a974997cee3d4eb5d06fc462a4b",
|
||||||
|
"x86_64-apple-darwin-0.13.6": "63ba17fdda55ad1a230d4b37fc6017ffa10c23688c83818bd3bfdf914c652a02",
|
||||||
|
"x86_64-pc-windows-msvc-0.13.6": "a2a8820d5eea32f08ef467ef3b7f66883a9b076d5737a2fc2fbb5f458d1bb50f",
|
||||||
|
"x86_64-unknown-linux-gnu-0.13.6": "f29c3e94ffabd7e6f3ba521dba169a9b7ec12100bf3257087f0f24f6123f3645",
|
||||||
|
"x86_64-unknown-linux-musl-0.13.6": "5d61f26b6c7213779eda90edc6971ea6b0b796bfb8d49a574c8ad69b59838548",
|
||||||
"aarch64-apple-darwin-0.13.5": "743f85035a1996ecb350659e01cd9faea9709829be09b1b4b03c73eaf3c9cd73",
|
"aarch64-apple-darwin-0.13.5": "743f85035a1996ecb350659e01cd9faea9709829be09b1b4b03c73eaf3c9cd73",
|
||||||
"aarch64-pc-windows-msvc-0.13.5": "09f47edf90726084a70f9426f6e3ca4f46e9bf7cbf23b1716ec64d60b055fae3",
|
"aarch64-pc-windows-msvc-0.13.5": "09f47edf90726084a70f9426f6e3ca4f46e9bf7cbf23b1716ec64d60b055fae3",
|
||||||
"aarch64-unknown-linux-gnu-0.13.5": "4bb69cf95ed13f23713bb7bc09f241896ea0c75b7c557e615a20604b82f9c403",
|
"aarch64-unknown-linux-gnu-0.13.5": "4bb69cf95ed13f23713bb7bc09f241896ea0c75b7c557e615a20604b82f9c403",
|
||||||
@@ -100287,6 +100306,19 @@ async function getArtifact(version3, arch3, platform2, manifestUrl = VERSIONS_MA
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
async function fetchManifestResponse(manifestUrl) {
|
async function fetchManifestResponse(manifestUrl) {
|
||||||
|
try {
|
||||||
|
return await fetchManifestResponseFromUrl(manifestUrl);
|
||||||
|
} catch (error2) {
|
||||||
|
if (manifestUrl !== VERSIONS_MANIFEST_URL) {
|
||||||
|
throw error2;
|
||||||
|
}
|
||||||
|
info2(
|
||||||
|
`Failed to fetch manifest from Astral mirror, falling back to GitHub: ${error2.message}`
|
||||||
|
);
|
||||||
|
return await fetchManifestResponseFromUrl(GITHUB_VERSIONS_MANIFEST_URL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function fetchManifestResponseFromUrl(manifestUrl) {
|
||||||
let response;
|
let response;
|
||||||
for (let attempt = 1; attempt <= MANIFEST_FETCH_ATTEMPTS; attempt++) {
|
for (let attempt = 1; attempt <= MANIFEST_FETCH_ATTEMPTS; attempt++) {
|
||||||
info2(`Fetching manifest data from ${manifestUrl} ...`);
|
info2(`Fetching manifest data from ${manifestUrl} ...`);
|
||||||
@@ -101579,7 +101611,7 @@ function getUvVersionFromAllDependencies(allDependencies) {
|
|||||||
}
|
}
|
||||||
function getUvVersionFromDependency(dependency) {
|
function getUvVersionFromDependency(dependency) {
|
||||||
const dependencyWithoutMarker = dependency.split(";", 1)[0]?.trim();
|
const dependencyWithoutMarker = dependency.split(";", 1)[0]?.trim();
|
||||||
return dependencyWithoutMarker?.match(/^uv([=<>~!]+\S*)/)?.[1].trim();
|
return dependencyWithoutMarker?.match(/^uv\s*((?:[=<>~!]+\s*[^\s,]+\s*,?\s*)+)/)?.[1].replace(/\s/g, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
// src/version/tool-versions-file.ts
|
// src/version/tool-versions-file.ts
|
||||||
@@ -101937,7 +101969,7 @@ async function resolveVersion(versionInput, manifestUrl, resolutionStrategy = "h
|
|||||||
throw new Error(`No version found for ${versionInput}`);
|
throw new Error(`No version found for ${versionInput}`);
|
||||||
}
|
}
|
||||||
async function findHighestSatisfyingVersion(versionSpecifier) {
|
async function findHighestSatisfyingVersion(versionSpecifier) {
|
||||||
const semverRange = semver5.validRange(versionSpecifier);
|
const semverRange = isCompatibleReleaseSpecifier(versionSpecifier) ? null : semver5.validRange(versionSpecifier);
|
||||||
if (semverRange !== null) {
|
if (semverRange !== null) {
|
||||||
const semverMatch = await getFirstMatchingVersion(
|
const semverMatch = await getFirstMatchingVersion(
|
||||||
(version3) => semver5.satisfies(version3, semverRange)
|
(version3) => semver5.satisfies(version3, semverRange)
|
||||||
@@ -101959,8 +101991,11 @@ async function findHighestSatisfyingVersion(versionSpecifier) {
|
|||||||
}
|
}
|
||||||
return pep440Match;
|
return pep440Match;
|
||||||
}
|
}
|
||||||
|
function isCompatibleReleaseSpecifier(versionSpecifier) {
|
||||||
|
return versionSpecifier.includes("~=");
|
||||||
|
}
|
||||||
function maxSatisfying2(versions, version3) {
|
function maxSatisfying2(versions, version3) {
|
||||||
const maxSemver = evaluateVersions(versions, version3);
|
const maxSemver = isCompatibleReleaseSpecifier(version3) ? "" : evaluateVersions(versions, version3);
|
||||||
if (maxSemver !== "") {
|
if (maxSemver !== "") {
|
||||||
debug(`Found a version that satisfies the semver range: ${maxSemver}`);
|
debug(`Found a version that satisfies the semver range: ${maxSemver}`);
|
||||||
return maxSemver;
|
return maxSemver;
|
||||||
@@ -101975,7 +102010,7 @@ function maxSatisfying2(versions, version3) {
|
|||||||
return void 0;
|
return void 0;
|
||||||
}
|
}
|
||||||
function minSatisfying3(versions, version3) {
|
function minSatisfying3(versions, version3) {
|
||||||
const minSemver = semver5.minSatisfying(versions, version3);
|
const minSemver = isCompatibleReleaseSpecifier(version3) ? null : semver5.minSatisfying(versions, version3);
|
||||||
if (minSemver !== null) {
|
if (minSemver !== null) {
|
||||||
debug(`Found a version that satisfies the semver range: ${minSemver}`);
|
debug(`Found a version that satisfies the semver range: ${minSemver}`);
|
||||||
return minSemver;
|
return minSemver;
|
||||||
|
|||||||
+33
-1
@@ -47182,6 +47182,24 @@ var semver = __toESM(require_semver(), 1);
|
|||||||
|
|
||||||
// src/download/checksum/known-checksums.json
|
// src/download/checksum/known-checksums.json
|
||||||
var known_checksums_default = {
|
var known_checksums_default = {
|
||||||
|
"aarch64-apple-darwin-0.13.6": "60fbd5c8a1ed681845eea28d9d622fcde03c51e91a43465b64a1e17db1ed3472",
|
||||||
|
"aarch64-pc-windows-msvc-0.13.6": "c2426c0c8e28b53d8c440e47a18d96ad4db51e159866c0e81435b196d7f0081c",
|
||||||
|
"aarch64-unknown-linux-gnu-0.13.6": "229e194255c7958d86d56e8790d969a6f74736592133f0dfd0076f754c642c1d",
|
||||||
|
"aarch64-unknown-linux-musl-0.13.6": "819692e404d23e5aae6bc44c0e260f1f5492fd1910ab4693b2c650f926dbe800",
|
||||||
|
"arm-unknown-linux-musleabihf-0.13.6": "57ac0f7c04deb42c5d686b4eeeef555c442db6ffea16fe4cbd7adb0384403794",
|
||||||
|
"armv7-unknown-linux-gnueabihf-0.13.6": "d00cd4949c4524c934afcfee1aedfa9d337cf4e43be4d6b692ad8d74d0a65562",
|
||||||
|
"armv7-unknown-linux-musleabihf-0.13.6": "b215398c886e8cc2cfa282fe346c02025957f8633b75a3d4fd848e0adda4eddd",
|
||||||
|
"i686-pc-windows-msvc-0.13.6": "32ceb64db231cbedfd499f7654c72e4c0b564f2846f9e76c0a4a7b2d03d7e67c",
|
||||||
|
"i686-unknown-linux-gnu-0.13.6": "665ea831c38d342900950e606beb2ccc37b7ba0fcefc37b814eb4b076305f2b6",
|
||||||
|
"i686-unknown-linux-musl-0.13.6": "de3a015c4b0fce63c178ae4fa95c94c873adfd92fa1e258c6a2a94e529812629",
|
||||||
|
"powerpc64le-unknown-linux-gnu-0.13.6": "3b2847185ec2946fcc928500efef7e3e74c255d3be6f2cb435081a84885d8c6c",
|
||||||
|
"riscv64gc-unknown-linux-gnu-0.13.6": "517052603ed46483b59d8875c9c61a577946b8f493c73e4339e45e7b119171d0",
|
||||||
|
"riscv64gc-unknown-linux-musl-0.13.6": "659a95dc6aee3ecf86742a08d8ca6c6261422121cbd41decc0042f5a71af6305",
|
||||||
|
"s390x-unknown-linux-gnu-0.13.6": "fb56d731308aa5c7718059d71afcb14d9a933a974997cee3d4eb5d06fc462a4b",
|
||||||
|
"x86_64-apple-darwin-0.13.6": "63ba17fdda55ad1a230d4b37fc6017ffa10c23688c83818bd3bfdf914c652a02",
|
||||||
|
"x86_64-pc-windows-msvc-0.13.6": "a2a8820d5eea32f08ef467ef3b7f66883a9b076d5737a2fc2fbb5f458d1bb50f",
|
||||||
|
"x86_64-unknown-linux-gnu-0.13.6": "f29c3e94ffabd7e6f3ba521dba169a9b7ec12100bf3257087f0f24f6123f3645",
|
||||||
|
"x86_64-unknown-linux-musl-0.13.6": "5d61f26b6c7213779eda90edc6971ea6b0b796bfb8d49a574c8ad69b59838548",
|
||||||
"aarch64-apple-darwin-0.13.5": "743f85035a1996ecb350659e01cd9faea9709829be09b1b4b03c73eaf3c9cd73",
|
"aarch64-apple-darwin-0.13.5": "743f85035a1996ecb350659e01cd9faea9709829be09b1b4b03c73eaf3c9cd73",
|
||||||
"aarch64-pc-windows-msvc-0.13.5": "09f47edf90726084a70f9426f6e3ca4f46e9bf7cbf23b1716ec64d60b055fae3",
|
"aarch64-pc-windows-msvc-0.13.5": "09f47edf90726084a70f9426f6e3ca4f46e9bf7cbf23b1716ec64d60b055fae3",
|
||||||
"aarch64-unknown-linux-gnu-0.13.5": "4bb69cf95ed13f23713bb7bc09f241896ea0c75b7c557e615a20604b82f9c403",
|
"aarch64-unknown-linux-gnu-0.13.5": "4bb69cf95ed13f23713bb7bc09f241896ea0c75b7c557e615a20604b82f9c403",
|
||||||
@@ -52836,7 +52854,8 @@ var import_node_readline = require("node:readline");
|
|||||||
var import_node_stream = require("node:stream");
|
var import_node_stream = require("node:stream");
|
||||||
|
|
||||||
// src/utils/constants.ts
|
// src/utils/constants.ts
|
||||||
var VERSIONS_MANIFEST_URL = "https://raw.githubusercontent.com/astral-sh/versions/main/v1/uv.ndjson";
|
var VERSIONS_MANIFEST_URL = "https://releases.astral.sh/github/versions/main/v1/uv.ndjson";
|
||||||
|
var GITHUB_VERSIONS_MANIFEST_URL = "https://raw.githubusercontent.com/astral-sh/versions/main/v1/uv.ndjson";
|
||||||
|
|
||||||
// src/utils/fetch.ts
|
// src/utils/fetch.ts
|
||||||
var import_undici2 = __toESM(require_undici2(), 1);
|
var import_undici2 = __toESM(require_undici2(), 1);
|
||||||
@@ -52908,6 +52927,19 @@ async function getLatestVersion(manifestUrl = VERSIONS_MANIFEST_URL) {
|
|||||||
return latestVersion;
|
return latestVersion;
|
||||||
}
|
}
|
||||||
async function fetchManifestResponse(manifestUrl) {
|
async function fetchManifestResponse(manifestUrl) {
|
||||||
|
try {
|
||||||
|
return await fetchManifestResponseFromUrl(manifestUrl);
|
||||||
|
} catch (error2) {
|
||||||
|
if (manifestUrl !== VERSIONS_MANIFEST_URL) {
|
||||||
|
throw error2;
|
||||||
|
}
|
||||||
|
info2(
|
||||||
|
`Failed to fetch manifest from Astral mirror, falling back to GitHub: ${error2.message}`
|
||||||
|
);
|
||||||
|
return await fetchManifestResponseFromUrl(GITHUB_VERSIONS_MANIFEST_URL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function fetchManifestResponseFromUrl(manifestUrl) {
|
||||||
let response;
|
let response;
|
||||||
for (let attempt = 1; attempt <= MANIFEST_FETCH_ATTEMPTS; attempt++) {
|
for (let attempt = 1; attempt <= MANIFEST_FETCH_ATTEMPTS; attempt++) {
|
||||||
info2(`Fetching manifest data from ${manifestUrl} ...`);
|
info2(`Fetching manifest data from ${manifestUrl} ...`);
|
||||||
|
|||||||
@@ -20,10 +20,12 @@ You can specify a checksum to override those values. The sha256 hashes can also
|
|||||||
## Manifest file
|
## Manifest file
|
||||||
|
|
||||||
By default, setup-uv reads version metadata from
|
By default, setup-uv reads version metadata from
|
||||||
[`astral-sh/versions`](https://github.com/astral-sh/versions).
|
the [Astral mirror](https://releases.astral.sh/github/versions/main/v1/uv.ndjson).
|
||||||
|
If the mirror request fails, it falls back to [`astral-sh/versions`](https://github.com/astral-sh/versions).
|
||||||
|
|
||||||
The `manifest-file` input lets you override that source with your own URL, for example to test
|
The `manifest-file` input lets you override that source with your own URL, for example to test
|
||||||
custom uv builds or alternate download locations.
|
custom uv builds or alternate download locations. Custom manifest URLs do not fall back to the
|
||||||
|
default sources.
|
||||||
|
|
||||||
### Format
|
### Format
|
||||||
|
|
||||||
|
|||||||
@@ -50,12 +50,13 @@ You can customize the venv location with `venv-path`, for example to place it in
|
|||||||
|
|
||||||
## GitHub authentication token
|
## GitHub authentication token
|
||||||
|
|
||||||
By default, this action resolves available uv versions from
|
By default, this action fetches version metadata and uv archives from the Astral mirror.
|
||||||
[`astral-sh/versions`](https://github.com/astral-sh/versions), then downloads uv artifacts from
|
If a manifest request fails, it falls back to `raw.githubusercontent.com`. If an archive download
|
||||||
GitHub Releases.
|
fails, it falls back to GitHub Releases.
|
||||||
|
|
||||||
You can provide a token via `github-token` to authenticate those downloads. By default, the
|
You can provide a token via `github-token` to authenticate GitHub Releases downloads. The token
|
||||||
`GITHUB_TOKEN` secret is used, which is automatically provided by GitHub Actions.
|
is not sent to the Astral mirror or used for manifest requests. By default, the `GITHUB_TOKEN`
|
||||||
|
secret is used, which is automatically provided by GitHub Actions.
|
||||||
|
|
||||||
If the default
|
If the default
|
||||||
[permissions for the GitHub token](https://docs.github.com/en/actions/security-for-github-actions/security-guides/automatic-token-authentication#permissions-for-the-github_token)
|
[permissions for the GitHub token](https://docs.github.com/en/actions/security-for-github-actions/security-guides/automatic-token-authentication#permissions-for-the-github_token)
|
||||||
|
|||||||
+18
@@ -1,4 +1,22 @@
|
|||||||
{
|
{
|
||||||
|
"aarch64-apple-darwin-0.13.6": "60fbd5c8a1ed681845eea28d9d622fcde03c51e91a43465b64a1e17db1ed3472",
|
||||||
|
"aarch64-pc-windows-msvc-0.13.6": "c2426c0c8e28b53d8c440e47a18d96ad4db51e159866c0e81435b196d7f0081c",
|
||||||
|
"aarch64-unknown-linux-gnu-0.13.6": "229e194255c7958d86d56e8790d969a6f74736592133f0dfd0076f754c642c1d",
|
||||||
|
"aarch64-unknown-linux-musl-0.13.6": "819692e404d23e5aae6bc44c0e260f1f5492fd1910ab4693b2c650f926dbe800",
|
||||||
|
"arm-unknown-linux-musleabihf-0.13.6": "57ac0f7c04deb42c5d686b4eeeef555c442db6ffea16fe4cbd7adb0384403794",
|
||||||
|
"armv7-unknown-linux-gnueabihf-0.13.6": "d00cd4949c4524c934afcfee1aedfa9d337cf4e43be4d6b692ad8d74d0a65562",
|
||||||
|
"armv7-unknown-linux-musleabihf-0.13.6": "b215398c886e8cc2cfa282fe346c02025957f8633b75a3d4fd848e0adda4eddd",
|
||||||
|
"i686-pc-windows-msvc-0.13.6": "32ceb64db231cbedfd499f7654c72e4c0b564f2846f9e76c0a4a7b2d03d7e67c",
|
||||||
|
"i686-unknown-linux-gnu-0.13.6": "665ea831c38d342900950e606beb2ccc37b7ba0fcefc37b814eb4b076305f2b6",
|
||||||
|
"i686-unknown-linux-musl-0.13.6": "de3a015c4b0fce63c178ae4fa95c94c873adfd92fa1e258c6a2a94e529812629",
|
||||||
|
"powerpc64le-unknown-linux-gnu-0.13.6": "3b2847185ec2946fcc928500efef7e3e74c255d3be6f2cb435081a84885d8c6c",
|
||||||
|
"riscv64gc-unknown-linux-gnu-0.13.6": "517052603ed46483b59d8875c9c61a577946b8f493c73e4339e45e7b119171d0",
|
||||||
|
"riscv64gc-unknown-linux-musl-0.13.6": "659a95dc6aee3ecf86742a08d8ca6c6261422121cbd41decc0042f5a71af6305",
|
||||||
|
"s390x-unknown-linux-gnu-0.13.6": "fb56d731308aa5c7718059d71afcb14d9a933a974997cee3d4eb5d06fc462a4b",
|
||||||
|
"x86_64-apple-darwin-0.13.6": "63ba17fdda55ad1a230d4b37fc6017ffa10c23688c83818bd3bfdf914c652a02",
|
||||||
|
"x86_64-pc-windows-msvc-0.13.6": "a2a8820d5eea32f08ef467ef3b7f66883a9b076d5737a2fc2fbb5f458d1bb50f",
|
||||||
|
"x86_64-unknown-linux-gnu-0.13.6": "f29c3e94ffabd7e6f3ba521dba169a9b7ec12100bf3257087f0f24f6123f3645",
|
||||||
|
"x86_64-unknown-linux-musl-0.13.6": "5d61f26b6c7213779eda90edc6971ea6b0b796bfb8d49a574c8ad69b59838548",
|
||||||
"aarch64-apple-darwin-0.13.5": "743f85035a1996ecb350659e01cd9faea9709829be09b1b4b03c73eaf3c9cd73",
|
"aarch64-apple-darwin-0.13.5": "743f85035a1996ecb350659e01cd9faea9709829be09b1b4b03c73eaf3c9cd73",
|
||||||
"aarch64-pc-windows-msvc-0.13.5": "09f47edf90726084a70f9426f6e3ca4f46e9bf7cbf23b1716ec64d60b055fae3",
|
"aarch64-pc-windows-msvc-0.13.5": "09f47edf90726084a70f9426f6e3ca4f46e9bf7cbf23b1716ec64d60b055fae3",
|
||||||
"aarch64-unknown-linux-gnu-0.13.5": "4bb69cf95ed13f23713bb7bc09f241896ea0c75b7c557e615a20604b82f9c403",
|
"aarch64-unknown-linux-gnu-0.13.5": "4bb69cf95ed13f23713bb7bc09f241896ea0c75b7c557e615a20604b82f9c403",
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
import { createInterface } from "node:readline";
|
import { createInterface } from "node:readline";
|
||||||
import { Readable } from "node:stream";
|
import { Readable } from "node:stream";
|
||||||
import * as core from "@actions/core";
|
import * as core from "@actions/core";
|
||||||
import { VERSIONS_MANIFEST_URL } from "../utils/constants";
|
import {
|
||||||
|
GITHUB_VERSIONS_MANIFEST_URL,
|
||||||
|
VERSIONS_MANIFEST_URL,
|
||||||
|
} from "../utils/constants";
|
||||||
import { fetch } from "../utils/fetch";
|
import { fetch } from "../utils/fetch";
|
||||||
import * as log from "../utils/logging";
|
import * as log from "../utils/logging";
|
||||||
import { selectDefaultVariant } from "./variant-selection";
|
import { selectDefaultVariant } from "./variant-selection";
|
||||||
@@ -167,6 +170,20 @@ export function clearManifestCache(manifestUrl?: string): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function fetchManifestResponse(manifestUrl: string) {
|
async function fetchManifestResponse(manifestUrl: string) {
|
||||||
|
try {
|
||||||
|
return await fetchManifestResponseFromUrl(manifestUrl);
|
||||||
|
} catch (error) {
|
||||||
|
if (manifestUrl !== VERSIONS_MANIFEST_URL) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
log.info(
|
||||||
|
`Failed to fetch manifest from Astral mirror, falling back to GitHub: ${(error as Error).message}`,
|
||||||
|
);
|
||||||
|
return await fetchManifestResponseFromUrl(GITHUB_VERSIONS_MANIFEST_URL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchManifestResponseFromUrl(manifestUrl: string) {
|
||||||
let response: Awaited<ReturnType<typeof fetch>> | undefined;
|
let response: Awaited<ReturnType<typeof fetch>> | undefined;
|
||||||
for (let attempt = 1; attempt <= MANIFEST_FETCH_ATTEMPTS; attempt++) {
|
for (let attempt = 1; attempt <= MANIFEST_FETCH_ATTEMPTS; attempt++) {
|
||||||
log.info(`Fetching manifest data from ${manifestUrl} ...`);
|
log.info(`Fetching manifest data from ${manifestUrl} ...`);
|
||||||
|
|||||||
+4
-2
@@ -159,8 +159,10 @@ async function saveCacheToKey(
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.info(`Including ${cacheName} path: ${cachePath}`);
|
log.info(`Including ${cacheName} path: ${cachePath}`);
|
||||||
await cache.saveCache([cachePath], cacheKey);
|
const cacheId = await cache.saveCache([cachePath], cacheKey);
|
||||||
log.info(`${cacheName} saved with key: ${cacheKey}`);
|
if (cacheId !== -1) {
|
||||||
|
log.info(`${cacheName} saved with key: ${cacheKey}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
run();
|
run();
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ export const TOOL_CACHE_NAME = "uv";
|
|||||||
export const STATE_UV_PATH = "uv-path";
|
export const STATE_UV_PATH = "uv-path";
|
||||||
export const STATE_UV_VERSION = "uv-version";
|
export const STATE_UV_VERSION = "uv-version";
|
||||||
export const VERSIONS_MANIFEST_URL =
|
export const VERSIONS_MANIFEST_URL =
|
||||||
|
"https://releases.astral.sh/github/versions/main/v1/uv.ndjson";
|
||||||
|
export const GITHUB_VERSIONS_MANIFEST_URL =
|
||||||
"https://raw.githubusercontent.com/astral-sh/versions/main/v1/uv.ndjson";
|
"https://raw.githubusercontent.com/astral-sh/versions/main/v1/uv.ndjson";
|
||||||
|
|
||||||
/** GitHub Releases URL prefix for uv artifacts. */
|
/** GitHub Releases URL prefix for uv artifacts. */
|
||||||
|
|||||||
@@ -69,5 +69,7 @@ function getUvVersionFromAllDependencies(
|
|||||||
|
|
||||||
function getUvVersionFromDependency(dependency: string): string | undefined {
|
function getUvVersionFromDependency(dependency: string): string | undefined {
|
||||||
const dependencyWithoutMarker = dependency.split(";", 1)[0]?.trim();
|
const dependencyWithoutMarker = dependency.split(";", 1)[0]?.trim();
|
||||||
return dependencyWithoutMarker?.match(/^uv([=<>~!]+\S*)/)?.[1].trim();
|
return dependencyWithoutMarker
|
||||||
|
?.match(/^uv\s*((?:[=<>~!]+\s*[^\s,]+\s*,?\s*)+)/)?.[1]
|
||||||
|
.replace(/\s/g, "");
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-3
@@ -169,7 +169,9 @@ async function findHighestSatisfyingVersion(
|
|||||||
): Promise<string | undefined> {
|
): Promise<string | undefined> {
|
||||||
// This fast path assumes uv releases are semver-monotonic: newer manifest
|
// This fast path assumes uv releases are semver-monotonic: newer manifest
|
||||||
// entries always have higher versions, with no lower-version backports.
|
// entries always have higher versions, with no lower-version backports.
|
||||||
const semverRange = semver.validRange(versionSpecifier);
|
const semverRange = isCompatibleReleaseSpecifier(versionSpecifier)
|
||||||
|
? null
|
||||||
|
: semver.validRange(versionSpecifier);
|
||||||
if (semverRange !== null) {
|
if (semverRange !== null) {
|
||||||
const semverMatch = await getFirstMatchingVersion((version) =>
|
const semverMatch = await getFirstMatchingVersion((version) =>
|
||||||
semver.satisfies(version, semverRange),
|
semver.satisfies(version, semverRange),
|
||||||
@@ -193,11 +195,22 @@ async function findHighestSatisfyingVersion(
|
|||||||
return pep440Match;
|
return pep440Match;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* `~=` is the PEP 440 compatible release operator. semver accepts it as a
|
||||||
|
* tilde range with a narrower upper bound (`~=0.5` as `<0.6.0` instead of
|
||||||
|
* `<1.0`), so it must only be evaluated as PEP 440.
|
||||||
|
*/
|
||||||
|
function isCompatibleReleaseSpecifier(versionSpecifier: string): boolean {
|
||||||
|
return versionSpecifier.includes("~=");
|
||||||
|
}
|
||||||
|
|
||||||
function maxSatisfying(
|
function maxSatisfying(
|
||||||
versions: string[],
|
versions: string[],
|
||||||
version: string,
|
version: string,
|
||||||
): string | undefined {
|
): string | undefined {
|
||||||
const maxSemver = tc.evaluateVersions(versions, version);
|
const maxSemver = isCompatibleReleaseSpecifier(version)
|
||||||
|
? ""
|
||||||
|
: tc.evaluateVersions(versions, version);
|
||||||
if (maxSemver !== "") {
|
if (maxSemver !== "") {
|
||||||
core.debug(`Found a version that satisfies the semver range: ${maxSemver}`);
|
core.debug(`Found a version that satisfies the semver range: ${maxSemver}`);
|
||||||
return maxSemver;
|
return maxSemver;
|
||||||
@@ -218,7 +231,9 @@ function minSatisfying(
|
|||||||
versions: string[],
|
versions: string[],
|
||||||
version: string,
|
version: string,
|
||||||
): string | undefined {
|
): string | undefined {
|
||||||
const minSemver = semver.minSatisfying(versions, version);
|
const minSemver = isCompatibleReleaseSpecifier(version)
|
||||||
|
? null
|
||||||
|
: semver.minSatisfying(versions, version);
|
||||||
if (minSemver !== null) {
|
if (minSemver !== null) {
|
||||||
core.debug(`Found a version that satisfies the semver range: ${minSemver}`);
|
core.debug(`Found a version that satisfies the semver range: ${minSemver}`);
|
||||||
return minSemver;
|
return minSemver;
|
||||||
|
|||||||
Reference in New Issue
Block a user