mirror of
https://github.com/astral-sh/setup-uv.git
synced 2026-07-22 20:20:23 +00:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 39734b1941 | |||
| c6081965dd | |||
| c771a70e62 | |||
| 2f537ca87c | |||
| 2269552d54 | |||
| 47a7f4fb2e | |||
| 71966eff34 | |||
| f12b1f0a84 | |||
| ecd24dd710 | |||
| 6a19136684 | |||
| 11f9893b08 | |||
| f798556032 | |||
| e80544d808 |
@@ -47,7 +47,7 @@ jobs:
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
|
||||
uses: github/codeql-action/init@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
source-root: src
|
||||
@@ -59,7 +59,7 @@ jobs:
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
|
||||
uses: github/codeql-action/autobuild@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
@@ -73,4 +73,4 @@ jobs:
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
|
||||
uses: github/codeql-action/analyze@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
|
||||
|
||||
@@ -27,8 +27,8 @@ jobs:
|
||||
- name: Actionlint
|
||||
uses: eifinger/actionlint-action@1fc89649be682d16ec5cf65ea16e269eb88d3982 # v1.10.2
|
||||
- name: Run zizmor
|
||||
uses: zizmorcore/zizmor-action@5f14fd08f7cf1cb1609c1e344975f152c7ee938d # v0.5.6
|
||||
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
uses: zizmorcore/zizmor-action@6599ee8b7a49aef6a770f63d261d214911a7ce02 # v0.6.0
|
||||
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
||||
with:
|
||||
node-version-file: .nvmrc
|
||||
cache: npm
|
||||
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: true
|
||||
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
||||
with:
|
||||
node-version-file: .nvmrc
|
||||
cache: npm
|
||||
|
||||
@@ -26,7 +26,7 @@ Set up your GitHub Actions workflow with a specific version of [uv](https://docs
|
||||
|
||||
```yaml
|
||||
- name: Install the latest version of uv
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
```
|
||||
|
||||
If you do not specify a version, this action will look for a [required-version](https://docs.astral.sh/uv/reference/settings/#required-version)
|
||||
@@ -42,7 +42,7 @@ Have a look under [Advanced Configuration](#advanced-configuration) for detailed
|
||||
|
||||
```yaml
|
||||
- name: Install uv with all available options
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
# The version of uv to install (default: searches for version in config files, then latest)
|
||||
version: ""
|
||||
@@ -100,7 +100,7 @@ Have a look under [Advanced Configuration](#advanced-configuration) for detailed
|
||||
cache-local-path: ""
|
||||
|
||||
# Prune cache before saving
|
||||
prune-cache: "true"
|
||||
prune-cache: "false"
|
||||
|
||||
# Upload managed Python installations to the GitHub Actions cache
|
||||
cache-python: "false"
|
||||
@@ -148,7 +148,7 @@ This will override any python version specifications in `pyproject.toml` and `.p
|
||||
|
||||
```yaml
|
||||
- name: Install the latest version of uv and set the python version to 3.13t
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
python-version: 3.13t
|
||||
- run: uv pip install --python=3.13t pip
|
||||
@@ -166,7 +166,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Install the latest version of uv and set the python version
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Test with python ${{ matrix.python-version }}
|
||||
@@ -183,7 +183,7 @@ It also controls where [the venv gets created](#activate-environment), unless `v
|
||||
|
||||
```yaml
|
||||
- name: Install uv based on the config files in the working-directory
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
working-directory: my/subproject/dir
|
||||
```
|
||||
@@ -225,7 +225,7 @@ For example:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@main
|
||||
- name: Install the latest version of uv
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
enable-cache: true
|
||||
- name: Test
|
||||
@@ -237,7 +237,7 @@ To install a specific version of Python, use
|
||||
|
||||
```yaml
|
||||
- name: Install the latest version of uv
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
enable-cache: true
|
||||
- name: Install Python 3.12
|
||||
@@ -256,7 +256,7 @@ output:
|
||||
uses: actions/checkout@main
|
||||
- name: Install the default version of uv
|
||||
id: setup-uv
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
- name: Print the installed version
|
||||
run: echo "Installed uv version is ${{ steps.setup-uv.outputs.uv-version }}"
|
||||
```
|
||||
|
||||
+2
-2
@@ -62,13 +62,13 @@ describe("restoreCache", () => {
|
||||
expect(cacheKey).toContain("-tests-3.10%2C3.11");
|
||||
});
|
||||
|
||||
it("keeps cache keys unchanged for exact Python versions and simple suffixes", async () => {
|
||||
it("uses an unpruned cache key by default", async () => {
|
||||
const inputs = createSetupInputs({ cacheSuffix: "tests-3.11" });
|
||||
|
||||
await restoreCache(inputs, "3.11");
|
||||
|
||||
expect(cacheKeyOutput()).toBe(
|
||||
"setup-uv-2-x86_64-unknown-linux-gnu-ubuntu-24.04-3.11-pruned-dependencyhash-tests-3.11",
|
||||
"setup-uv-2-x86_64-unknown-linux-gnu-ubuntu-24.04-3.11-dependencyhash-tests-3.11",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { beforeEach, describe, expect, it, jest } from "@jest/globals";
|
||||
import * as semver from "semver";
|
||||
import { VERSIONS_MANIFEST_URL } from "../../src/utils/constants";
|
||||
|
||||
const mockInfo = jest.fn();
|
||||
const mockWarning = jest.fn();
|
||||
@@ -36,11 +37,14 @@ const mockGetLatestVersion = jest.fn<any>();
|
||||
// biome-ignore lint/suspicious/noExplicitAny: Mock requires flexible typing in tests.
|
||||
const mockGetAllVersions = jest.fn<any>();
|
||||
// biome-ignore lint/suspicious/noExplicitAny: Mock requires flexible typing in tests.
|
||||
const mockGetFirstMatchingVersion = jest.fn<any>();
|
||||
// biome-ignore lint/suspicious/noExplicitAny: Mock requires flexible typing in tests.
|
||||
const mockGetArtifact = jest.fn<any>();
|
||||
|
||||
jest.unstable_mockModule("../../src/download/manifest", () => ({
|
||||
getAllVersions: mockGetAllVersions,
|
||||
getArtifact: mockGetArtifact,
|
||||
getFirstMatchingVersion: mockGetFirstMatchingVersion,
|
||||
getLatestVersion: mockGetLatestVersion,
|
||||
}));
|
||||
|
||||
@@ -65,6 +69,7 @@ describe("download-version", () => {
|
||||
mockCacheDir.mockReset();
|
||||
mockGetLatestVersion.mockReset();
|
||||
mockGetAllVersions.mockReset();
|
||||
mockGetFirstMatchingVersion.mockReset();
|
||||
mockGetArtifact.mockReset();
|
||||
mockValidateChecksum.mockReset();
|
||||
|
||||
@@ -85,14 +90,43 @@ describe("download-version", () => {
|
||||
expect(mockGetLatestVersion).toHaveBeenCalledWith(undefined);
|
||||
});
|
||||
|
||||
it("uses the default manifest to resolve available versions", async () => {
|
||||
mockGetAllVersions.mockResolvedValue(["0.9.26", "0.9.25"]);
|
||||
it("stops at the first matching version in the default manifest", async () => {
|
||||
mockGetFirstMatchingVersion.mockImplementation(
|
||||
(predicate: (version: string) => boolean) =>
|
||||
["0.9.26", "0.9.25"].find(predicate),
|
||||
);
|
||||
|
||||
const version = await resolveVersion("^0.9.0", undefined);
|
||||
|
||||
expect(version).toBe("0.9.26");
|
||||
expect(mockGetAllVersions).toHaveBeenCalledTimes(1);
|
||||
expect(mockGetAllVersions).toHaveBeenCalledWith(undefined);
|
||||
expect(mockGetFirstMatchingVersion).toHaveBeenCalledTimes(1);
|
||||
expect(mockGetAllVersions).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("streams ranges when the default manifest URL is explicit", async () => {
|
||||
mockGetFirstMatchingVersion.mockImplementation(
|
||||
(predicate: (version: string) => boolean) =>
|
||||
["0.9.26", "0.9.25"].find(predicate),
|
||||
);
|
||||
|
||||
const version = await resolveVersion("^0.9.0", VERSIONS_MANIFEST_URL);
|
||||
|
||||
expect(version).toBe("0.9.26");
|
||||
expect(mockGetFirstMatchingVersion).toHaveBeenCalledTimes(1);
|
||||
expect(mockGetAllVersions).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("streams PEP 440 ranges from the default manifest", async () => {
|
||||
mockGetFirstMatchingVersion.mockImplementation(
|
||||
(predicate: (version: string) => boolean) =>
|
||||
["0.9.26", "0.9.25"].find(predicate),
|
||||
);
|
||||
|
||||
const version = await resolveVersion("!=0.9.26", undefined);
|
||||
|
||||
expect(version).toBe("0.9.25");
|
||||
expect(mockGetFirstMatchingVersion).toHaveBeenCalledTimes(1);
|
||||
expect(mockGetAllVersions).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("treats == exact pins as explicit versions", async () => {
|
||||
|
||||
@@ -17,6 +17,7 @@ const {
|
||||
fetchManifest,
|
||||
getAllVersions,
|
||||
getArtifact,
|
||||
getFirstMatchingVersion,
|
||||
getLatestVersion,
|
||||
parseManifest,
|
||||
} = await import("../../src/download/manifest");
|
||||
@@ -33,6 +34,7 @@ function createMockResponse(
|
||||
data: string,
|
||||
) {
|
||||
return {
|
||||
body: null,
|
||||
ok,
|
||||
status,
|
||||
statusText,
|
||||
@@ -40,6 +42,31 @@ function createMockResponse(
|
||||
};
|
||||
}
|
||||
|
||||
function createStreamingMockResponse(
|
||||
chunks: string[],
|
||||
cancel: () => void | Promise<void> = () => {},
|
||||
close = false,
|
||||
) {
|
||||
const encoder = new TextEncoder();
|
||||
return {
|
||||
body: new ReadableStream<Uint8Array>({
|
||||
cancel,
|
||||
start(controller) {
|
||||
for (const chunk of chunks) {
|
||||
controller.enqueue(encoder.encode(chunk));
|
||||
}
|
||||
if (close) {
|
||||
controller.close();
|
||||
}
|
||||
},
|
||||
}),
|
||||
ok: true,
|
||||
status: 200,
|
||||
statusText: "OK",
|
||||
text: async () => chunks.join(""),
|
||||
};
|
||||
}
|
||||
|
||||
describe("manifest", () => {
|
||||
beforeEach(() => {
|
||||
clearManifestCache();
|
||||
@@ -105,6 +132,75 @@ describe("manifest", () => {
|
||||
getLatestVersion("https://example.com/custom.ndjson"),
|
||||
).resolves.toBe("0.9.26");
|
||||
});
|
||||
|
||||
it("stops reading the default manifest after the first record", async () => {
|
||||
const [latestVersion] = sampleManifestResponse.split("\n");
|
||||
const cancel = jest.fn();
|
||||
mockFetch.mockResolvedValue(
|
||||
createStreamingMockResponse(
|
||||
[
|
||||
latestVersion.slice(0, 100),
|
||||
`${latestVersion.slice(100)}\n`,
|
||||
"invalid trailing data\n",
|
||||
],
|
||||
cancel,
|
||||
),
|
||||
);
|
||||
|
||||
await expect(getLatestVersion()).resolves.toBe("0.9.26");
|
||||
await expect(
|
||||
getArtifact("0.9.26", "aarch64", "apple-darwin"),
|
||||
).resolves.toBeDefined();
|
||||
|
||||
expect(cancel).toHaveBeenCalledTimes(1);
|
||||
expect(mockFetch).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("does not fail when canceling the remaining response fails", async () => {
|
||||
const [latestVersion] = sampleManifestResponse.split("\n");
|
||||
mockFetch.mockResolvedValue(
|
||||
createStreamingMockResponse([`${latestVersion}\n`], () =>
|
||||
Promise.reject(new Error("cancel failed")),
|
||||
),
|
||||
);
|
||||
|
||||
await expect(getLatestVersion()).resolves.toBe("0.9.26");
|
||||
});
|
||||
});
|
||||
|
||||
describe("getFirstMatchingVersion", () => {
|
||||
it("stops at the first matching record", async () => {
|
||||
const cancel = jest.fn();
|
||||
mockFetch.mockResolvedValue(
|
||||
createStreamingMockResponse(
|
||||
[`${sampleManifestResponse}\n`, "invalid trailing data\n"],
|
||||
cancel,
|
||||
),
|
||||
);
|
||||
|
||||
await expect(
|
||||
getFirstMatchingVersion((version) => version === "0.9.25"),
|
||||
).resolves.toBe("0.9.25");
|
||||
|
||||
expect(cancel).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("caches a fully consumed response stream", async () => {
|
||||
mockFetch.mockResolvedValue(
|
||||
createStreamingMockResponse(
|
||||
[`${sampleManifestResponse}\n`],
|
||||
undefined,
|
||||
true,
|
||||
),
|
||||
);
|
||||
|
||||
await expect(
|
||||
getFirstMatchingVersion((version) => version === "0.0.1"),
|
||||
).resolves.toBeUndefined();
|
||||
await expect(getLatestVersion()).resolves.toBe("0.9.26");
|
||||
|
||||
expect(mockFetch).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getArtifact", () => {
|
||||
@@ -168,6 +264,60 @@ describe("manifest", () => {
|
||||
|
||||
expect(artifact).toBeUndefined();
|
||||
});
|
||||
|
||||
it("does not cache records from a failed stream read", async () => {
|
||||
const [latestVersion] = sampleManifestResponse.split("\n");
|
||||
mockFetch
|
||||
.mockResolvedValueOnce(
|
||||
createStreamingMockResponse([
|
||||
`${latestVersion}\n`,
|
||||
"invalid manifest record\n",
|
||||
]),
|
||||
)
|
||||
.mockResolvedValueOnce(
|
||||
createMockResponse(true, 200, "OK", sampleManifestResponse),
|
||||
);
|
||||
|
||||
await expect(
|
||||
getArtifact("0.0.1", "aarch64", "apple-darwin"),
|
||||
).rejects.toThrow("Failed to parse manifest data");
|
||||
await expect(getLatestVersion()).resolves.toBe("0.9.26");
|
||||
|
||||
expect(mockFetch).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it("does not cache records when the response stream fails", async () => {
|
||||
const [latestVersion] = sampleManifestResponse.split("\n");
|
||||
const encoder = new TextEncoder();
|
||||
let sentVersion = false;
|
||||
const body = new ReadableStream<Uint8Array>({
|
||||
pull(controller) {
|
||||
if (!sentVersion) {
|
||||
sentVersion = true;
|
||||
controller.enqueue(encoder.encode(`${latestVersion}\n`));
|
||||
return;
|
||||
}
|
||||
controller.error(new Error("response stream failed"));
|
||||
},
|
||||
});
|
||||
mockFetch
|
||||
.mockResolvedValueOnce({
|
||||
body,
|
||||
ok: true,
|
||||
status: 200,
|
||||
statusText: "OK",
|
||||
})
|
||||
.mockResolvedValueOnce(
|
||||
createMockResponse(true, 200, "OK", sampleManifestResponse),
|
||||
);
|
||||
|
||||
await expect(
|
||||
getArtifact("0.0.1", "aarch64", "apple-darwin"),
|
||||
).rejects.toThrow("response stream failed");
|
||||
await expect(getLatestVersion()).resolves.toBe("0.9.26");
|
||||
|
||||
expect(mockFetch).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe("parseManifest", () => {
|
||||
|
||||
@@ -20,7 +20,7 @@ export function createSetupInputs(
|
||||
ignoreEmptyWorkdir: false,
|
||||
ignoreNothingToCache: false,
|
||||
noProject: false,
|
||||
pruneCache: true,
|
||||
pruneCache: false,
|
||||
pythonDir: "/tmp/uv-python-dir",
|
||||
pythonVersion: "",
|
||||
quiet: false,
|
||||
|
||||
+1
-1
@@ -61,7 +61,7 @@ inputs:
|
||||
default: ""
|
||||
prune-cache:
|
||||
description: "Prune cache before saving."
|
||||
default: "true"
|
||||
default: "false"
|
||||
cache-python:
|
||||
description: "Upload managed Python installations to the Github Actions cache."
|
||||
default: "false"
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"$schema": "https://biomejs.dev/schemas/2.4.16/schema.json",
|
||||
"$schema": "https://biomejs.dev/schemas/2.5.1/schema.json",
|
||||
"assist": {
|
||||
"actions": {
|
||||
"source": {
|
||||
@@ -34,7 +34,7 @@
|
||||
"linter": {
|
||||
"enabled": true,
|
||||
"rules": {
|
||||
"recommended": true
|
||||
"preset": "recommended"
|
||||
}
|
||||
},
|
||||
"vcs": {
|
||||
|
||||
+225
-210
@@ -6,7 +6,11 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __getProtoOf = Object.getPrototypeOf;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __commonJS = (cb, mod) => function __require() {
|
||||
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
||||
try {
|
||||
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
||||
} catch (e) {
|
||||
throw mod = 0, e;
|
||||
}
|
||||
};
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
@@ -22687,7 +22691,7 @@ var require_package = __commonJS({
|
||||
"node_modules/@actions/cache/package.json"(exports2, module2) {
|
||||
module2.exports = {
|
||||
name: "@actions/cache",
|
||||
version: "6.0.1",
|
||||
version: "6.1.0",
|
||||
description: "Actions cache lib",
|
||||
keywords: [
|
||||
"github",
|
||||
@@ -61406,6 +61410,14 @@ var ReserveCacheError = class _ReserveCacheError extends Error {
|
||||
Object.setPrototypeOf(this, _ReserveCacheError.prototype);
|
||||
}
|
||||
};
|
||||
var CACHE_WRITE_DENIED_PREFIX = "cache write denied:";
|
||||
var CacheWriteDeniedError = class _CacheWriteDeniedError extends ReserveCacheError {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = "CacheWriteDeniedError";
|
||||
Object.setPrototypeOf(this, _CacheWriteDeniedError.prototype);
|
||||
}
|
||||
};
|
||||
var FinalizeCacheError = class _FinalizeCacheError extends Error {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
@@ -61444,7 +61456,7 @@ function saveCache2(paths_1, key_1, options_1) {
|
||||
}
|
||||
function saveCacheV1(paths_1, key_1, options_1) {
|
||||
return __awaiter16(this, arguments, void 0, function* (paths, key, options, enableCrossOsArchive = false) {
|
||||
var _a, _b, _c, _d, _e;
|
||||
var _a, _b, _c, _d, _e, _f;
|
||||
const compressionMethod = yield getCompressionMethod();
|
||||
let cacheId = -1;
|
||||
const cachePaths = yield resolvePaths(paths);
|
||||
@@ -61478,7 +61490,11 @@ function saveCacheV1(paths_1, key_1, options_1) {
|
||||
} else if ((reserveCacheResponse === null || reserveCacheResponse === void 0 ? void 0 : reserveCacheResponse.statusCode) === 400) {
|
||||
throw new Error((_d = (_c = reserveCacheResponse === null || reserveCacheResponse === void 0 ? void 0 : reserveCacheResponse.error) === null || _c === void 0 ? void 0 : _c.message) !== null && _d !== void 0 ? _d : `Cache size of ~${Math.round(archiveFileSize / (1024 * 1024))} MB (${archiveFileSize} B) is over the data cap limit, not saving cache.`);
|
||||
} else {
|
||||
throw new ReserveCacheError(`Unable to reserve cache with key ${key}, another job may be creating this cache. More details: ${(_e = reserveCacheResponse === null || reserveCacheResponse === void 0 ? void 0 : reserveCacheResponse.error) === null || _e === void 0 ? void 0 : _e.message}`);
|
||||
const detailMessage = (_e = reserveCacheResponse === null || reserveCacheResponse === void 0 ? void 0 : reserveCacheResponse.error) === null || _e === void 0 ? void 0 : _e.message;
|
||||
if (detailMessage === null || detailMessage === void 0 ? void 0 : detailMessage.startsWith(CACHE_WRITE_DENIED_PREFIX)) {
|
||||
throw new CacheWriteDeniedError(`Unable to reserve cache with key ${key}. More details: ${detailMessage}`);
|
||||
}
|
||||
throw new ReserveCacheError(`Unable to reserve cache with key ${key}, another job may be creating this cache. More details: ${(_f = reserveCacheResponse === null || reserveCacheResponse === void 0 ? void 0 : reserveCacheResponse.error) === null || _f === void 0 ? void 0 : _f.message}`);
|
||||
}
|
||||
debug(`Saving Cache (ID: ${cacheId})`);
|
||||
yield saveCache(cacheId, archivePath, "", options);
|
||||
@@ -61486,6 +61502,8 @@ function saveCacheV1(paths_1, key_1, options_1) {
|
||||
const typedError = error2;
|
||||
if (typedError.name === ValidationError.name) {
|
||||
throw error2;
|
||||
} else if (typedError.name === CacheWriteDeniedError.name) {
|
||||
warning(`Failed to save: ${typedError.message}`);
|
||||
} else if (typedError.name === ReserveCacheError.name) {
|
||||
info(`Failed to save: ${typedError.message}`);
|
||||
} else {
|
||||
@@ -61507,6 +61525,7 @@ function saveCacheV1(paths_1, key_1, options_1) {
|
||||
}
|
||||
function saveCacheV2(paths_1, key_1, options_1) {
|
||||
return __awaiter16(this, arguments, void 0, function* (paths, key, options, enableCrossOsArchive = false) {
|
||||
var _a;
|
||||
options = Object.assign(Object.assign({}, options), { uploadChunkSize: 64 * 1024 * 1024, uploadConcurrency: 8, useAzureSdk: true });
|
||||
const compressionMethod = yield getCompressionMethod();
|
||||
const twirpClient = internalCacheTwirpClient();
|
||||
@@ -61538,7 +61557,7 @@ function saveCacheV2(paths_1, key_1, options_1) {
|
||||
try {
|
||||
const response = yield twirpClient.CreateCacheEntry(request);
|
||||
if (!response.ok) {
|
||||
if (response.message) {
|
||||
if (response.message && !response.message.startsWith(CACHE_WRITE_DENIED_PREFIX)) {
|
||||
warning(`Cache reservation failed: ${response.message}`);
|
||||
}
|
||||
throw new Error(response.message || "Response was not ok");
|
||||
@@ -61546,6 +61565,10 @@ function saveCacheV2(paths_1, key_1, options_1) {
|
||||
signedUploadUrl = response.signedUploadUrl;
|
||||
} catch (error2) {
|
||||
debug(`Failed to reserve cache: ${error2}`);
|
||||
const errorMessage = (_a = error2 === null || error2 === void 0 ? void 0 : error2.message) !== null && _a !== void 0 ? _a : "";
|
||||
if (errorMessage.startsWith(CACHE_WRITE_DENIED_PREFIX)) {
|
||||
throw new CacheWriteDeniedError(`Unable to reserve cache with key ${key}. More details: ${errorMessage}`);
|
||||
}
|
||||
throw new ReserveCacheError(`Unable to reserve cache with key ${key}, another job may be creating this cache.`);
|
||||
}
|
||||
debug(`Attempting to upload cache located at: ${archivePath}`);
|
||||
@@ -61568,6 +61591,8 @@ function saveCacheV2(paths_1, key_1, options_1) {
|
||||
const typedError = error2;
|
||||
if (typedError.name === ValidationError.name) {
|
||||
throw error2;
|
||||
} else if (typedError.name === CacheWriteDeniedError.name) {
|
||||
warning(`Failed to save: ${typedError.message}`);
|
||||
} else if (typedError.name === ReserveCacheError.name) {
|
||||
info(`Failed to save: ${typedError.message}`);
|
||||
} else if (typedError.name === FinalizeCacheError.name) {
|
||||
@@ -61814,125 +61839,6 @@ var import_node_path = __toESM(require("node:path"), 1);
|
||||
// src/utils/config-file.ts
|
||||
var import_node_fs2 = __toESM(require("node:fs"), 1);
|
||||
|
||||
// node_modules/smol-toml/dist/error.js
|
||||
function getLineColFromPtr(string, ptr) {
|
||||
let lines = string.slice(0, ptr).split(/\r\n|\n|\r/g);
|
||||
return [lines.length, lines.pop().length + 1];
|
||||
}
|
||||
function makeCodeBlock(string, line, column) {
|
||||
let lines = string.split(/\r\n|\n|\r/g);
|
||||
let codeblock = "";
|
||||
let numberLen = (Math.log10(line + 1) | 0) + 1;
|
||||
for (let i = line - 1; i <= line + 1; i++) {
|
||||
let l = lines[i - 1];
|
||||
if (!l)
|
||||
continue;
|
||||
codeblock += i.toString().padEnd(numberLen, " ");
|
||||
codeblock += ": ";
|
||||
codeblock += l;
|
||||
codeblock += "\n";
|
||||
if (i === line) {
|
||||
codeblock += " ".repeat(numberLen + column + 2);
|
||||
codeblock += "^\n";
|
||||
}
|
||||
}
|
||||
return codeblock;
|
||||
}
|
||||
var TomlError = class extends Error {
|
||||
line;
|
||||
column;
|
||||
codeblock;
|
||||
constructor(message, options) {
|
||||
const [line, column] = getLineColFromPtr(options.toml, options.ptr);
|
||||
const codeblock = makeCodeBlock(options.toml, line, column);
|
||||
super(`Invalid TOML document: ${message}
|
||||
|
||||
${codeblock}`, options);
|
||||
this.line = line;
|
||||
this.column = column;
|
||||
this.codeblock = codeblock;
|
||||
}
|
||||
};
|
||||
|
||||
// node_modules/smol-toml/dist/util.js
|
||||
function isEscaped(str, ptr) {
|
||||
let i = 0;
|
||||
while (str[ptr - ++i] === "\\")
|
||||
;
|
||||
return --i && i % 2;
|
||||
}
|
||||
function indexOfNewline(str, start = 0, end = str.length) {
|
||||
let idx = str.indexOf("\n", start);
|
||||
if (str[idx - 1] === "\r")
|
||||
idx--;
|
||||
return idx <= end ? idx : -1;
|
||||
}
|
||||
function skipComment(str, ptr) {
|
||||
for (let i = ptr; i < str.length; i++) {
|
||||
let c = str[i];
|
||||
if (c === "\n")
|
||||
return i;
|
||||
if (c === "\r" && str[i + 1] === "\n")
|
||||
return i + 1;
|
||||
if (c < " " && c !== " " || c === "\x7F") {
|
||||
throw new TomlError("control characters are not allowed in comments", {
|
||||
toml: str,
|
||||
ptr
|
||||
});
|
||||
}
|
||||
}
|
||||
return str.length;
|
||||
}
|
||||
function skipVoid(str, ptr, banNewLines, banComments) {
|
||||
let c;
|
||||
while (1) {
|
||||
while ((c = str[ptr]) === " " || c === " " || !banNewLines && (c === "\n" || c === "\r" && str[ptr + 1] === "\n"))
|
||||
ptr++;
|
||||
if (banComments || c !== "#")
|
||||
break;
|
||||
ptr = skipComment(str, ptr);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
function skipUntil(str, ptr, sep7, end, banNewLines = false) {
|
||||
if (!end) {
|
||||
ptr = indexOfNewline(str, ptr);
|
||||
return ptr < 0 ? str.length : ptr;
|
||||
}
|
||||
for (let i = ptr; i < str.length; i++) {
|
||||
let c = str[i];
|
||||
if (c === "#") {
|
||||
i = indexOfNewline(str, i);
|
||||
} else if (c === sep7) {
|
||||
return i + 1;
|
||||
} else if (c === end || banNewLines && (c === "\n" || c === "\r" && str[i + 1] === "\n")) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
throw new TomlError("cannot find end of structure", {
|
||||
toml: str,
|
||||
ptr
|
||||
});
|
||||
}
|
||||
function getStringEnd(str, seek) {
|
||||
let first = str[seek];
|
||||
let target = first === str[seek + 1] && str[seek + 1] === str[seek + 2] ? str.slice(seek, seek + 3) : first;
|
||||
seek += target.length - 1;
|
||||
do
|
||||
seek = str.indexOf(target, ++seek);
|
||||
while (seek > -1 && first !== "'" && isEscaped(str, seek));
|
||||
if (seek > -1) {
|
||||
seek += target.length;
|
||||
if (target.length > 1) {
|
||||
if (str[seek] === first)
|
||||
seek++;
|
||||
if (str[seek] === first)
|
||||
seek++;
|
||||
}
|
||||
}
|
||||
return seek;
|
||||
}
|
||||
|
||||
// node_modules/smol-toml/dist/date.js
|
||||
var DATE_TIME_RE = /^(\d{4}-\d{2}-\d{2})?[T ]?(?:(\d{2}):\d{2}(?::\d{2}(?:\.\d+)?)?)?(Z|[-+]\d{2}:\d{2})?$/i;
|
||||
var TomlDate = class _TomlDate extends Date {
|
||||
@@ -62025,93 +61931,153 @@ var TomlDate = class _TomlDate extends Date {
|
||||
}
|
||||
};
|
||||
|
||||
// node_modules/smol-toml/dist/error.js
|
||||
function getLineColFromPtr(string, ptr) {
|
||||
let lines = string.slice(0, ptr).split(/\r\n|\n|\r/g);
|
||||
return [lines.length, lines.pop().length + 1];
|
||||
}
|
||||
function makeCodeBlock(string, line, column) {
|
||||
let lines = string.split(/\r\n|\n|\r/g);
|
||||
let codeblock = "";
|
||||
let numberLen = (Math.log10(line + 1) | 0) + 1;
|
||||
for (let i = line - 1; i <= line + 1; i++) {
|
||||
let l = lines[i - 1];
|
||||
if (!l)
|
||||
continue;
|
||||
codeblock += i.toString().padEnd(numberLen, " ");
|
||||
codeblock += ": ";
|
||||
codeblock += l;
|
||||
codeblock += "\n";
|
||||
if (i === line) {
|
||||
codeblock += " ".repeat(numberLen + column + 2);
|
||||
codeblock += "^\n";
|
||||
}
|
||||
}
|
||||
return codeblock;
|
||||
}
|
||||
var TomlError = class extends Error {
|
||||
line;
|
||||
column;
|
||||
codeblock;
|
||||
constructor(message, options) {
|
||||
const [line, column] = getLineColFromPtr(options.toml, options.ptr);
|
||||
const codeblock = makeCodeBlock(options.toml, line, column);
|
||||
super(`Invalid TOML document: ${message}
|
||||
|
||||
${codeblock}`, options);
|
||||
this.line = line;
|
||||
this.column = column;
|
||||
this.codeblock = codeblock;
|
||||
}
|
||||
};
|
||||
|
||||
// node_modules/smol-toml/dist/primitive.js
|
||||
var INT_REGEX = /^((0x[0-9a-fA-F](_?[0-9a-fA-F])*)|(([+-]|0[ob])?\d(_?\d)*))$/;
|
||||
var FLOAT_REGEX = /^[+-]?\d(_?\d)*(\.\d(_?\d)*)?([eE][+-]?\d(_?\d)*)?$/;
|
||||
var LEADING_ZERO = /^[+-]?0[0-9_]/;
|
||||
var ESCAPE_REGEX = /^[0-9a-f]{2,8}$/i;
|
||||
var ESC_MAP = {
|
||||
b: "\b",
|
||||
t: " ",
|
||||
n: "\n",
|
||||
f: "\f",
|
||||
r: "\r",
|
||||
e: "\x1B",
|
||||
'"': '"',
|
||||
"\\": "\\"
|
||||
};
|
||||
function parseString(str, ptr = 0, endPtr = str.length) {
|
||||
let isLiteral = str[ptr] === "'";
|
||||
let isMultiline = str[ptr++] === str[ptr] && str[ptr] === str[ptr + 1];
|
||||
function parseString(str, ptr) {
|
||||
let c = str[ptr++];
|
||||
let first = c;
|
||||
let isLiteral = c === "'";
|
||||
let isMultiline = c === str[ptr] && c === str[ptr + 1];
|
||||
if (isMultiline) {
|
||||
endPtr -= 2;
|
||||
if (str[ptr += 2] === "\r")
|
||||
ptr++;
|
||||
if (str[ptr] === "\n")
|
||||
if (str[ptr += 2] === "\n")
|
||||
ptr++;
|
||||
else if (str[ptr] === "\r" && str[ptr + 1] === "\n")
|
||||
ptr += 2;
|
||||
}
|
||||
let tmp = 0;
|
||||
let isEscape;
|
||||
let parsed = "";
|
||||
let sliceStart = ptr;
|
||||
while (ptr < endPtr - 1) {
|
||||
let c = str[ptr++];
|
||||
if (c === "\n" || c === "\r" && str[ptr] === "\n") {
|
||||
if (!isMultiline) {
|
||||
throw new TomlError("newlines are not allowed in strings", {
|
||||
toml: str,
|
||||
ptr: ptr - 1
|
||||
});
|
||||
}
|
||||
let state3 = 0;
|
||||
for (let i = ptr; i < str.length; i++) {
|
||||
c = str[i];
|
||||
if (isMultiline && (c === "\n" || c === "\r" && str[i + 1] === "\n")) {
|
||||
state3 = state3 && 3;
|
||||
} else if (c < " " && c !== " " || c === "\x7F") {
|
||||
throw new TomlError("control characters are not allowed in strings", {
|
||||
toml: str,
|
||||
ptr: ptr - 1
|
||||
ptr: i
|
||||
});
|
||||
}
|
||||
if (isEscape) {
|
||||
isEscape = false;
|
||||
} else if ((!state3 || state3 === 3) && c === first && (!isMultiline || str[i + 1] === first && str[i + 2] === first)) {
|
||||
if (isMultiline) {
|
||||
if (str[i + 3] === first)
|
||||
i++;
|
||||
if (str[i + 3] === first)
|
||||
i++;
|
||||
}
|
||||
return [
|
||||
// If we're in a newline escape still, then there's nothing to add.
|
||||
// Also try to avoid concat if there's nothing to add to parsed, or nothing has been added to parsed.
|
||||
state3 ? parsed : parsed + str.slice(sliceStart, i),
|
||||
i + (isMultiline ? 3 : 1)
|
||||
];
|
||||
} else if (!state3) {
|
||||
if (!isLiteral && c === "\\") {
|
||||
parsed += str.slice(sliceStart, sliceStart = i);
|
||||
state3 = 1;
|
||||
}
|
||||
} else if (state3 === 1) {
|
||||
if (c === "x" || c === "u" || c === "U") {
|
||||
let code = str.slice(ptr, ptr += c === "x" ? 2 : c === "u" ? 4 : 8);
|
||||
if (!ESCAPE_REGEX.test(code)) {
|
||||
throw new TomlError("invalid unicode escape", {
|
||||
toml: str,
|
||||
ptr: tmp
|
||||
});
|
||||
let value = 0;
|
||||
let len = c === "x" ? 2 : c === "u" ? 4 : 8;
|
||||
for (let j = 0; j < len; j++, i++) {
|
||||
let hex = str.charCodeAt(i + 1);
|
||||
let digit = (
|
||||
/* 0-9 */
|
||||
hex >= 48 && hex <= 57 ? hex - 48 : (
|
||||
/* A-F */
|
||||
hex >= 65 && hex <= 70 ? hex - 65 + 10 : (
|
||||
/* a-f */
|
||||
hex >= 97 && hex <= 102 ? hex - 97 + 10 : -1
|
||||
)
|
||||
)
|
||||
);
|
||||
if (digit < 0)
|
||||
throw new TomlError("invalid non-hex character in unicode escape", { toml: str, ptr: i + 1 });
|
||||
value = value << 4 | digit;
|
||||
}
|
||||
try {
|
||||
parsed += String.fromCodePoint(parseInt(code, 16));
|
||||
} catch {
|
||||
throw new TomlError("invalid unicode escape", {
|
||||
toml: str,
|
||||
ptr: tmp
|
||||
});
|
||||
if (value < 0 || value > 1114111 || value >= 55296 && value <= 57343) {
|
||||
throw new TomlError("invalid unicode escape", { toml: str, ptr: i });
|
||||
}
|
||||
} else if (isMultiline && (c === "\n" || c === " " || c === " " || c === "\r")) {
|
||||
ptr = skipVoid(str, ptr - 1, true);
|
||||
if (str[ptr] !== "\n" && str[ptr] !== "\r") {
|
||||
throw new TomlError("invalid escape: only line-ending whitespace may be escaped", {
|
||||
toml: str,
|
||||
ptr: tmp
|
||||
});
|
||||
}
|
||||
ptr = skipVoid(str, ptr);
|
||||
} else if (c in ESC_MAP) {
|
||||
parsed += ESC_MAP[c];
|
||||
parsed += String.fromCodePoint(value);
|
||||
sliceStart = i + 1;
|
||||
state3 = 0;
|
||||
} else if (c === " " || c === " ") {
|
||||
state3 = 2;
|
||||
} else {
|
||||
throw new TomlError("unrecognized escape sequence", {
|
||||
if (c === "b")
|
||||
parsed += "\b";
|
||||
else if (c === "t")
|
||||
parsed += " ";
|
||||
else if (c === "n")
|
||||
parsed += "\n";
|
||||
else if (c === "f")
|
||||
parsed += "\f";
|
||||
else if (c === "r")
|
||||
parsed += "\r";
|
||||
else if (c === "e")
|
||||
parsed += "\x1B";
|
||||
else if (c === '"')
|
||||
parsed += '"';
|
||||
else if (c === "\\")
|
||||
parsed += "\\";
|
||||
else
|
||||
throw new TomlError("unrecognized escape sequence", { toml: str, ptr: i });
|
||||
sliceStart = i + 1;
|
||||
state3 = 0;
|
||||
}
|
||||
} else if (c !== " " && c !== " ") {
|
||||
if (state3 === 2) {
|
||||
throw new TomlError("invalid escape: only line-ending whitespace may be escaped", {
|
||||
toml: str,
|
||||
ptr: tmp
|
||||
ptr: sliceStart
|
||||
});
|
||||
}
|
||||
sliceStart = ptr;
|
||||
} else if (!isLiteral && c === "\\") {
|
||||
tmp = ptr - 1;
|
||||
isEscape = true;
|
||||
parsed += str.slice(sliceStart, tmp);
|
||||
state3 = !isLiteral && c === "\\" ? 1 : 0;
|
||||
sliceStart = i;
|
||||
}
|
||||
}
|
||||
return parsed + str.slice(sliceStart, endPtr - 1);
|
||||
throw new TomlError("unfinished string", { toml: str, ptr });
|
||||
}
|
||||
function parseValue2(value, toml, ptr, integersAsBigInt) {
|
||||
if (value === "true")
|
||||
@@ -62164,6 +62130,61 @@ function parseValue2(value, toml, ptr, integersAsBigInt) {
|
||||
return date;
|
||||
}
|
||||
|
||||
// node_modules/smol-toml/dist/util.js
|
||||
function indexOfNewline(str, start = 0, end = str.length) {
|
||||
let idx = str.indexOf("\n", start);
|
||||
if (str[idx - 1] === "\r")
|
||||
idx--;
|
||||
return idx <= end ? idx : -1;
|
||||
}
|
||||
function skipComment(str, ptr) {
|
||||
for (let i = ptr; i < str.length; i++) {
|
||||
let c = str[i];
|
||||
if (c === "\n")
|
||||
return i;
|
||||
if (c === "\r" && str[i + 1] === "\n")
|
||||
return i + 1;
|
||||
if (c < " " && c !== " " || c === "\x7F") {
|
||||
throw new TomlError("control characters are not allowed in comments", {
|
||||
toml: str,
|
||||
ptr
|
||||
});
|
||||
}
|
||||
}
|
||||
return str.length;
|
||||
}
|
||||
function skipVoid(str, ptr, banNewLines, banComments) {
|
||||
let c;
|
||||
while (1) {
|
||||
while ((c = str[ptr]) === " " || c === " " || !banNewLines && (c === "\n" || c === "\r" && str[ptr + 1] === "\n"))
|
||||
ptr++;
|
||||
if (banComments || c !== "#")
|
||||
break;
|
||||
ptr = skipComment(str, ptr);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
function skipUntil(str, ptr, sep7, end, banNewLines = false) {
|
||||
if (!end) {
|
||||
ptr = indexOfNewline(str, ptr);
|
||||
return ptr < 0 ? str.length : ptr;
|
||||
}
|
||||
for (let i = ptr; i < str.length; i++) {
|
||||
let c = str[i];
|
||||
if (c === "#") {
|
||||
i = indexOfNewline(str, i);
|
||||
} else if (c === sep7) {
|
||||
return i + 1;
|
||||
} else if (c === end || banNewLines && (c === "\n" || c === "\r" && str[i + 1] === "\n")) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
throw new TomlError("cannot find end of structure", {
|
||||
toml: str,
|
||||
ptr
|
||||
});
|
||||
}
|
||||
|
||||
// node_modules/smol-toml/dist/extract.js
|
||||
function sliceAndTrimEndOf(str, startPtr, endPtr) {
|
||||
let value = str.slice(startPtr, endPtr);
|
||||
@@ -62197,24 +62218,23 @@ function extractValue(str, ptr, end, depth, integersAsBigInt) {
|
||||
}
|
||||
return [value, endPtr2];
|
||||
}
|
||||
let endPtr;
|
||||
if (c === '"' || c === "'") {
|
||||
endPtr = getStringEnd(str, ptr);
|
||||
let parsed = parseString(str, ptr, endPtr);
|
||||
let [parsed, endPtr2] = parseString(str, ptr);
|
||||
if (end) {
|
||||
endPtr = skipVoid(str, endPtr);
|
||||
if (str[endPtr] && str[endPtr] !== "," && str[endPtr] !== end && str[endPtr] !== "\n" && str[endPtr] !== "\r") {
|
||||
endPtr2 = skipVoid(str, endPtr2);
|
||||
if (str[endPtr2] && str[endPtr2] !== "," && str[endPtr2] !== end && str[endPtr2] !== "\n" && str[endPtr2] !== "\r") {
|
||||
throw new TomlError("unexpected character encountered", {
|
||||
toml: str,
|
||||
ptr: endPtr
|
||||
ptr: endPtr2
|
||||
});
|
||||
}
|
||||
endPtr += +(str[endPtr] === ",");
|
||||
if (str[endPtr2] === ",")
|
||||
endPtr2++;
|
||||
}
|
||||
return [parsed, endPtr];
|
||||
return [parsed, endPtr2];
|
||||
}
|
||||
endPtr = skipUntil(str, ptr, ",", end);
|
||||
let slice = sliceAndTrimEndOf(str, ptr, endPtr - +(str[endPtr - 1] === ","));
|
||||
let endPtr = skipUntil(str, ptr, ",", end);
|
||||
let slice = sliceAndTrimEndOf(str, ptr, endPtr - (str[endPtr - 1] === "," ? 1 : 0));
|
||||
if (!slice[0]) {
|
||||
throw new TomlError("incomplete key-value declaration: no value specified", {
|
||||
toml: str,
|
||||
@@ -62223,7 +62243,8 @@ function extractValue(str, ptr, end, depth, integersAsBigInt) {
|
||||
}
|
||||
if (end && slice[1] > -1) {
|
||||
endPtr = skipVoid(str, ptr + slice[1]);
|
||||
endPtr += +(str[endPtr] === ",");
|
||||
if (str[endPtr] === ",")
|
||||
endPtr++;
|
||||
}
|
||||
return [
|
||||
parseValue2(slice[0], str, ptr, integersAsBigInt),
|
||||
@@ -62253,13 +62274,7 @@ function parseKey(str, ptr, end = "=") {
|
||||
ptr
|
||||
});
|
||||
}
|
||||
let eos = getStringEnd(str, ptr);
|
||||
if (eos < 0) {
|
||||
throw new TomlError("unfinished string encountered", {
|
||||
toml: str,
|
||||
ptr
|
||||
});
|
||||
}
|
||||
let [part, eos] = parseString(str, ptr);
|
||||
dot = str.indexOf(".", eos);
|
||||
let strEnd = str.slice(eos, dot < 0 || dot > endPtr ? endPtr : dot);
|
||||
let newLine = indexOfNewline(strEnd);
|
||||
@@ -62284,7 +62299,7 @@ function parseKey(str, ptr, end = "=") {
|
||||
});
|
||||
}
|
||||
}
|
||||
parsed.push(parseString(str, ptr, eos));
|
||||
parsed.push(part);
|
||||
} else {
|
||||
dot = str.indexOf(".", ptr);
|
||||
let part = str.slice(ptr, dot < 0 || dot > endPtr ? endPtr : dot);
|
||||
@@ -62910,10 +62925,10 @@ undici/lib/web/fetch/body.js:
|
||||
undici/lib/web/websocket/frame.js:
|
||||
(*! ws. MIT License. Einar Otto Stangvik <einaros@gmail.com> *)
|
||||
|
||||
smol-toml/dist/error.js:
|
||||
smol-toml/dist/util.js:
|
||||
smol-toml/dist/date.js:
|
||||
smol-toml/dist/error.js:
|
||||
smol-toml/dist/primitive.js:
|
||||
smol-toml/dist/util.js:
|
||||
smol-toml/dist/extract.js:
|
||||
smol-toml/dist/struct.js:
|
||||
smol-toml/dist/parse.js:
|
||||
|
||||
+468
-306
File diff suppressed because it is too large
Load Diff
+182
-52
@@ -6,7 +6,11 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __getProtoOf = Object.getPrototypeOf;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __commonJS = (cb, mod) => function __require() {
|
||||
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
||||
try {
|
||||
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
||||
} catch (e) {
|
||||
throw mod = 0, e;
|
||||
}
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
@@ -9157,7 +9161,7 @@ var require_readable = __commonJS({
|
||||
"node_modules/@actions/http-client/node_modules/undici/lib/api/readable.js"(exports2, module2) {
|
||||
"use strict";
|
||||
var assert = require("node:assert");
|
||||
var { Readable } = require("node:stream");
|
||||
var { Readable: Readable2 } = require("node:stream");
|
||||
var { RequestAbortedError, NotSupportedError, InvalidArgumentError, AbortError } = require_errors();
|
||||
var util = require_util();
|
||||
var { ReadableStreamFrom } = require_util();
|
||||
@@ -9169,7 +9173,7 @@ var require_readable = __commonJS({
|
||||
var kContentLength = /* @__PURE__ */ Symbol("kContentLength");
|
||||
var noop = () => {
|
||||
};
|
||||
var BodyReadable = class extends Readable {
|
||||
var BodyReadable = class extends Readable2 {
|
||||
constructor({
|
||||
resume,
|
||||
abort,
|
||||
@@ -9511,7 +9515,7 @@ var require_api_request = __commonJS({
|
||||
"node_modules/@actions/http-client/node_modules/undici/lib/api/api-request.js"(exports2, module2) {
|
||||
"use strict";
|
||||
var assert = require("node:assert");
|
||||
var { Readable } = require_readable();
|
||||
var { Readable: Readable2 } = require_readable();
|
||||
var { InvalidArgumentError, RequestAbortedError } = require_errors();
|
||||
var util = require_util();
|
||||
var { getResolveErrorBodyCallback } = require_util3();
|
||||
@@ -9606,7 +9610,7 @@ var require_api_request = __commonJS({
|
||||
const parsedHeaders = responseHeaders === "raw" ? util.parseHeaders(rawHeaders) : headers;
|
||||
const contentType = parsedHeaders["content-type"];
|
||||
const contentLength = parsedHeaders["content-length"];
|
||||
const res = new Readable({
|
||||
const res = new Readable2({
|
||||
resume,
|
||||
abort,
|
||||
contentType,
|
||||
@@ -9921,7 +9925,7 @@ var require_api_pipeline = __commonJS({
|
||||
"node_modules/@actions/http-client/node_modules/undici/lib/api/api-pipeline.js"(exports2, module2) {
|
||||
"use strict";
|
||||
var {
|
||||
Readable,
|
||||
Readable: Readable2,
|
||||
Duplex,
|
||||
PassThrough
|
||||
} = require("node:stream");
|
||||
@@ -9935,7 +9939,7 @@ var require_api_pipeline = __commonJS({
|
||||
var { addSignal, removeSignal } = require_abort_signal();
|
||||
var assert = require("node:assert");
|
||||
var kResume = /* @__PURE__ */ Symbol("resume");
|
||||
var PipelineRequest = class extends Readable {
|
||||
var PipelineRequest = class extends Readable2 {
|
||||
constructor() {
|
||||
super({ autoDestroy: true });
|
||||
this[kResume] = null;
|
||||
@@ -9952,7 +9956,7 @@ var require_api_pipeline = __commonJS({
|
||||
callback(err);
|
||||
}
|
||||
};
|
||||
var PipelineResponse = class extends Readable {
|
||||
var PipelineResponse = class extends Readable2 {
|
||||
constructor(resume) {
|
||||
super({ autoDestroy: true });
|
||||
this[kResume] = resume;
|
||||
@@ -13277,7 +13281,7 @@ var require_fetch = __commonJS({
|
||||
subresourceSet
|
||||
} = require_constants3();
|
||||
var EE = require("node:events");
|
||||
var { Readable, pipeline, finished } = require("node:stream");
|
||||
var { Readable: Readable2, pipeline, finished } = require("node:stream");
|
||||
var { addAbortListener, isErrored, isReadable, bufferToLowerCasedHeaderName } = require_util();
|
||||
var { dataURLProcessor, serializeAMimeType, minimizeSupportedMimeType } = require_data_url();
|
||||
var { getGlobalDispatcher } = require_global2();
|
||||
@@ -14178,7 +14182,7 @@ var require_fetch = __commonJS({
|
||||
headersList.append(bufferToLowerCasedHeaderName(rawHeaders[i]), rawHeaders[i + 1].toString("latin1"), true);
|
||||
}
|
||||
location = headersList.get("location", true);
|
||||
this.body = new Readable({ read: resume });
|
||||
this.body = new Readable2({ read: resume });
|
||||
const decoders = [];
|
||||
const willFollow = location && request.redirect === "follow" && redirectStatusSet.has(status);
|
||||
if (request.method !== "HEAD" && request.method !== "CONNECT" && !nullBodyStatus.includes(status) && !willFollow) {
|
||||
@@ -31244,7 +31248,7 @@ var require_readable2 = __commonJS({
|
||||
"use strict";
|
||||
var assert = require("node:assert");
|
||||
var { addAbortListener } = require("node:events");
|
||||
var { Readable } = require("node:stream");
|
||||
var { Readable: Readable2 } = require("node:stream");
|
||||
var { RequestAbortedError, NotSupportedError, InvalidArgumentError, AbortError } = require_errors2();
|
||||
var util = require_util9();
|
||||
var { ReadableStreamFrom } = require_util9();
|
||||
@@ -31258,7 +31262,7 @@ var require_readable2 = __commonJS({
|
||||
var kBytesRead = /* @__PURE__ */ Symbol("kBytesRead");
|
||||
var noop = () => {
|
||||
};
|
||||
var BodyReadable = class extends Readable {
|
||||
var BodyReadable = class extends Readable2 {
|
||||
/**
|
||||
* @param {object} opts
|
||||
* @param {(this: Readable, size: number) => void} opts.resume
|
||||
@@ -31647,7 +31651,7 @@ var require_api_request2 = __commonJS({
|
||||
"use strict";
|
||||
var assert = require("node:assert");
|
||||
var { AsyncResource } = require("node:async_hooks");
|
||||
var { Readable } = require_readable2();
|
||||
var { Readable: Readable2 } = require_readable2();
|
||||
var { InvalidArgumentError, RequestAbortedError } = require_errors2();
|
||||
var util = require_util9();
|
||||
function noop() {
|
||||
@@ -31731,7 +31735,7 @@ var require_api_request2 = __commonJS({
|
||||
const parsedHeaders = headers;
|
||||
const contentType = parsedHeaders?.["content-type"];
|
||||
const contentLength = parsedHeaders?.["content-length"];
|
||||
const res = new Readable({
|
||||
const res = new Readable2({
|
||||
resume: () => controller.resume(),
|
||||
abort: (reason) => controller.abort(reason),
|
||||
contentType,
|
||||
@@ -32107,7 +32111,7 @@ var require_api_pipeline2 = __commonJS({
|
||||
"node_modules/undici/lib/api/api-pipeline.js"(exports2, module2) {
|
||||
"use strict";
|
||||
var {
|
||||
Readable,
|
||||
Readable: Readable2,
|
||||
Duplex,
|
||||
PassThrough
|
||||
} = require("node:stream");
|
||||
@@ -32124,7 +32128,7 @@ var require_api_pipeline2 = __commonJS({
|
||||
function noop() {
|
||||
}
|
||||
var kResume = /* @__PURE__ */ Symbol("resume");
|
||||
var PipelineRequest = class extends Readable {
|
||||
var PipelineRequest = class extends Readable2 {
|
||||
constructor() {
|
||||
super({ autoDestroy: true });
|
||||
this[kResume] = null;
|
||||
@@ -32142,7 +32146,7 @@ var require_api_pipeline2 = __commonJS({
|
||||
callback(err);
|
||||
}
|
||||
};
|
||||
var PipelineResponse = class extends Readable {
|
||||
var PipelineResponse = class extends Readable2 {
|
||||
constructor(resume) {
|
||||
super({ autoDestroy: true });
|
||||
this[kResume] = resume;
|
||||
@@ -36759,7 +36763,7 @@ var require_cache3 = __commonJS({
|
||||
"node_modules/undici/lib/interceptor/cache.js"(exports2, module2) {
|
||||
"use strict";
|
||||
var assert = require("node:assert");
|
||||
var { Readable } = require("node:stream");
|
||||
var { Readable: Readable2 } = require("node:stream");
|
||||
var util = require_util9();
|
||||
var CacheHandler = require_cache_handler();
|
||||
var MemoryCacheStore = require_memory_cache_store();
|
||||
@@ -36855,7 +36859,7 @@ var require_cache3 = __commonJS({
|
||||
return dispatch(opts, new CacheHandler(globalOpts, cacheKey, handler));
|
||||
}
|
||||
function sendCachedValue(handler, opts, result, age, context, isStale2) {
|
||||
const stream = util.isStream(result.body) ? result.body : Readable.from(result.body ?? []);
|
||||
const stream = util.isStream(result.body) ? result.body : Readable2.from(result.body ?? []);
|
||||
assert(!stream.destroyed, "stream should not be destroyed");
|
||||
assert(!stream.readableDidRead, "stream should not be readableDidRead");
|
||||
const controller = {
|
||||
@@ -39978,7 +39982,7 @@ var require_fetch2 = __commonJS({
|
||||
subresourceSet
|
||||
} = require_constants8();
|
||||
var EE = require("node:events");
|
||||
var { Readable, pipeline, finished, isErrored, isReadable } = require("node:stream");
|
||||
var { Readable: Readable2, pipeline, finished, isErrored, isReadable } = require("node:stream");
|
||||
var { addAbortListener, bufferToLowerCasedHeaderName } = require_util9();
|
||||
var { dataURLProcessor, serializeAMimeType, minimizeSupportedMimeType } = require_data_url2();
|
||||
var { getGlobalDispatcher } = require_global4();
|
||||
@@ -40940,7 +40944,7 @@ var require_fetch2 = __commonJS({
|
||||
const headersList = new HeadersList();
|
||||
appendHeadersListFromResponseHeaders(headersList, headers, rawHeaders);
|
||||
const location = headersList.get("location", true);
|
||||
this.body = new Readable({ read: () => controller.resume() });
|
||||
this.body = new Readable2({ read: () => controller.resume() });
|
||||
const willFollow = location && request.redirect === "follow" && redirectStatusSet.has(status);
|
||||
const decoders = [];
|
||||
if (request.method !== "HEAD" && request.method !== "CONNECT" && !nullBodyStatus.includes(status) && !willFollow) {
|
||||
@@ -45701,6 +45705,60 @@ var semver = __toESM(require_semver(), 1);
|
||||
|
||||
// src/download/checksum/known-checksums.ts
|
||||
var KNOWN_CHECKSUMS = {
|
||||
"aarch64-apple-darwin-0.11.30": "9bed3567d496d8dab84ecf7a1247551ac94ef1baaebb7b65df008dd93e9dc357",
|
||||
"aarch64-pc-windows-msvc-0.11.30": "0edc44e7f23668bce7985facd96b2fe04a4d8ea8edfc7e53294afd8993e960fc",
|
||||
"aarch64-unknown-linux-gnu-0.11.30": "8c11d90f5f66d232930cf8ae3a085c39877690d409e10878234802b028b20e2a",
|
||||
"aarch64-unknown-linux-musl-0.11.30": "7562a40e4e08b1bfd566bd6aeca55a16ee5ac45211554543e8cdb3c395b47416",
|
||||
"arm-unknown-linux-musleabihf-0.11.30": "58967610a6f14f2785e3be3b1b47553b5ff92c3d51bc0f1d9d90d83dc224f0db",
|
||||
"armv7-unknown-linux-gnueabihf-0.11.30": "8e2d2ab63a37af47c1b4126c5871ee191b983a10670af91d8ef0bee198292931",
|
||||
"armv7-unknown-linux-musleabihf-0.11.30": "33b515887e04c79d4d5de5967b8278b9dac1853cc8d657bf77052bab16a6629f",
|
||||
"i686-pc-windows-msvc-0.11.30": "8ceaa74889e30d64adf55d7ad7acce6ed101fb036155bf2d7613715c9d9533c1",
|
||||
"i686-unknown-linux-gnu-0.11.30": "e53221602d83b03c63a5e262bfcbf0f5f6e5972e93847498418bdb42005f04e7",
|
||||
"i686-unknown-linux-musl-0.11.30": "f66898852a6a745a8c0ab0a26e046857ee77c9f24e4a3b64cb078753490b3978",
|
||||
"powerpc64le-unknown-linux-gnu-0.11.30": "81a71fa495239c372b3b0c1bb2509167da00cf307323a2d2a39cbc92f0c6d5d1",
|
||||
"riscv64gc-unknown-linux-gnu-0.11.30": "e2d65822d8f668f6d055679dba4937e386764b9561f9d1269d3bc9e7140f7491",
|
||||
"riscv64gc-unknown-linux-musl-0.11.30": "3d75e26ace5e679e5de26106a71ee775af5c7f7ad872cd04f33b4d53c523a707",
|
||||
"s390x-unknown-linux-gnu-0.11.30": "a30f253aca1291dbcdbb7f76c754235f268ff84d106a595f7d1abf337ab22ac1",
|
||||
"x86_64-apple-darwin-0.11.30": "ce285fbbfbe294b1e1bc6c87c8b59d9622b85383b88b2b132a2df5c73e83d7c1",
|
||||
"x86_64-pc-windows-msvc-0.11.30": "be8d78c992312212e5cc05e9f9de3fa996db73b7c86a186dfb9231eb9f91d33e",
|
||||
"x86_64-unknown-linux-gnu-0.11.30": "04bc7d180d6138bf6dc08387acf507a823f397a98fea55da36b0ccc7fbce3b68",
|
||||
"x86_64-unknown-linux-musl-0.11.30": "023fdd3b59fccfb67b365c69fb34182aaaed1d685d367a57571e3c1468a4c70c",
|
||||
"aarch64-apple-darwin-0.11.29": "61c04acc52a33ef0f331e494bdfbedcdb6c26c6970c022ed3699e5860f8930e3",
|
||||
"aarch64-pc-windows-msvc-0.11.29": "55b597ae81bc29531a7c352a1431a8a73cc2755d7a5b9ec454580cbe02e5154f",
|
||||
"aarch64-unknown-linux-gnu-0.11.29": "94500fb064ae3c971a873cba64d94694c50677e0a4dbf78735c80509e7429919",
|
||||
"aarch64-unknown-linux-musl-0.11.29": "593d79a797ece3f1dfaaf3e0a973263422a135d9262c7dbc6cd75d9c11acc0b4",
|
||||
"arm-unknown-linux-musleabihf-0.11.29": "b160d7eb7dc45af378b3c9dd2cd6b07d64c65b509f2da673434e8e5dc996e5b1",
|
||||
"armv7-unknown-linux-gnueabihf-0.11.29": "7b5717ae304fbb1e94104699fb8c08b32d1537fedc90dd8fcf87768d818951ed",
|
||||
"armv7-unknown-linux-musleabihf-0.11.29": "bfd05286a80b39bd4708bbbb4450fe09f07fea86eea60d31ea2de0b5e816ef54",
|
||||
"i686-pc-windows-msvc-0.11.29": "c173af6f6e125d65214b55d6b75fcf1a32d5e1c3a656938740fe0b2379cd4bcc",
|
||||
"i686-unknown-linux-gnu-0.11.29": "c62af324951ae6f31f9453280e077176c96b6e31897d8133c00411a91a20878f",
|
||||
"i686-unknown-linux-musl-0.11.29": "368dd75d030cae0512631ba0d50604e8471275ec2d9f02836edb91e4c82ad36a",
|
||||
"powerpc64le-unknown-linux-gnu-0.11.29": "641b15637de9fedc7e738b0e4716b2233c792ba6dca722ba0484381749e1a9fd",
|
||||
"riscv64gc-unknown-linux-gnu-0.11.29": "5c1229cc0309ebc6872ee847b8fc75564b3b7688edeb09e19427203e2dbc0ea7",
|
||||
"riscv64gc-unknown-linux-musl-0.11.29": "d4708d913ba88fad9fe1d81da3e13aecadde7a3190cc095a7f2af2fa5c8caa8f",
|
||||
"s390x-unknown-linux-gnu-0.11.29": "fa029183f550a3b00b89c06529fabfa11e0c69c097ccd397a8e7eae46f397348",
|
||||
"x86_64-apple-darwin-0.11.29": "c4c4de482da9ccdd076dc4fb5cfe7b740609029385c72f58606be3153602387d",
|
||||
"x86_64-pc-windows-msvc-0.11.29": "a047d55651bc3e0ca24595b25ec4cfcb10f9dca9fb56514e661269b37d4fae68",
|
||||
"x86_64-unknown-linux-gnu-0.11.29": "04f8b82f5d47f0512dcd32c67a4a6f16a0ea27c81537c338fd0ad6b23cebe829",
|
||||
"x86_64-unknown-linux-musl-0.11.29": "46711858adb2a3acaa9cee00f9060688ad1fd5706aecc005b96a6a7f285a00b7",
|
||||
"aarch64-apple-darwin-0.11.28": "33540eb7c883ab857eff79bd5ac2aa31fe27b595abecb4a9c003a2c998447232",
|
||||
"aarch64-pc-windows-msvc-0.11.28": "3248109afad3ec59baad299d324ff53de17e2d9a3b3e21580ffd26744b11e036",
|
||||
"aarch64-unknown-linux-gnu-0.11.28": "03e9fe0a81b0718d0bc84625de3885df6cc3f89a8b6af6121d6b9f6113fb6533",
|
||||
"aarch64-unknown-linux-musl-0.11.28": "da10cdfa7d92212b7acb62021a0fd61bcf8580c58c3632ec915d10c3a1a7906b",
|
||||
"arm-unknown-linux-musleabihf-0.11.28": "955f9697d4781cf4dfc62d9442a49f3e57861f19405a981ffe9fdc0d18e0a31a",
|
||||
"armv7-unknown-linux-gnueabihf-0.11.28": "b7cddaad27cd531096e88e64de863f7e37c6fedde11c97595060e6503544d120",
|
||||
"armv7-unknown-linux-musleabihf-0.11.28": "eb00e0f246d278133df6a55b5d3534a49f051a7dfc276f640b66504c091167f6",
|
||||
"i686-pc-windows-msvc-0.11.28": "01975deb06072edfc1f18435c25737d8d378dc849b918cd580768ab3b7641e85",
|
||||
"i686-unknown-linux-gnu-0.11.28": "f8d01e918dd4d5eabdd4caee78e8adbc3993a70f3b82395fa6b23fcf791925d9",
|
||||
"i686-unknown-linux-musl-0.11.28": "c869415e44e13000d9daae15cec7bcfaf0735915a8d6e66402d459f6bed35710",
|
||||
"powerpc64le-unknown-linux-gnu-0.11.28": "b634b6f26a036d112914c2d6d7ae1944bf8f4a6dfed6e19a22b35e5d91f168fb",
|
||||
"riscv64gc-unknown-linux-gnu-0.11.28": "be7473dc29ee88bd260e30642faa5ba6dccd7d4493012077873b293c377ab546",
|
||||
"riscv64gc-unknown-linux-musl-0.11.28": "4a9e553d8a62c42600d5c2874b7c2f728c03d4310d72ed7351edbee8ed6a71b4",
|
||||
"s390x-unknown-linux-gnu-0.11.28": "f5ed9d2aed566e11ffc3f1f7ab5b4049dfbfcb04c326ce2ed5bbf42069d62b27",
|
||||
"x86_64-apple-darwin-0.11.28": "2ad79983127ffca7d77b77ce6a24278d7e4f7b817a1acf72fea5f8124b4aac5e",
|
||||
"x86_64-pc-windows-msvc-0.11.28": "0a23463216d09c6a72ff80ef5dc5a795f07dc1575cb84d24596c2f124a441b7b",
|
||||
"x86_64-unknown-linux-gnu-0.11.28": "e490a6464492183c5d4534a5527fb4440f7f2bb2f228162ad7e4afe076dc0224",
|
||||
"x86_64-unknown-linux-musl-0.11.28": "f02146b371c35c287d860f003ece7345c86e358a3fd70a9b63700cd141ee7fb4",
|
||||
"aarch64-apple-darwin-0.11.27": "34e63cc0de0aebbc8d424767c588c31b685479f045f9ced9e5ef43ff9e0e8d63",
|
||||
"aarch64-pc-windows-msvc-0.11.27": "7566a80fe96ee84e6938621a1b704f44b0db546672bf43025905784b2507b7fe",
|
||||
"aarch64-unknown-linux-gnu-0.11.27": "321580b9a7069d0cdbd8db9482a5fb62b4f1285110f847746e3b495408e3a08c",
|
||||
@@ -50665,6 +50723,10 @@ async function updateChecksums(filePath, checksumEntries) {
|
||||
await import_node_fs.promises.writeFile(filePath, content);
|
||||
}
|
||||
|
||||
// src/download/manifest.ts
|
||||
var import_node_readline = require("node:readline");
|
||||
var import_node_stream = require("node:stream");
|
||||
|
||||
// src/utils/constants.ts
|
||||
var VERSIONS_MANIFEST_URL = "https://raw.githubusercontent.com/astral-sh/versions/main/v1/uv.ndjson";
|
||||
|
||||
@@ -50709,21 +50771,15 @@ function info2(msg) {
|
||||
// src/download/manifest.ts
|
||||
var cachedManifestData = /* @__PURE__ */ new Map();
|
||||
async function fetchManifest(manifestUrl = VERSIONS_MANIFEST_URL) {
|
||||
const cachedVersions = cachedManifestData.get(manifestUrl);
|
||||
if (cachedVersions !== void 0) {
|
||||
const cachedManifest = cachedManifestData.get(manifestUrl);
|
||||
if (cachedManifest?.complete === true) {
|
||||
debug(`Using cached manifest data from ${manifestUrl}`);
|
||||
return cachedVersions;
|
||||
}
|
||||
info2(`Fetching manifest data from ${manifestUrl} ...`);
|
||||
const response = await fetch(manifestUrl, {});
|
||||
if (!response.ok) {
|
||||
throw new Error(
|
||||
`Failed to fetch manifest data: ${response.status} ${response.statusText}`
|
||||
);
|
||||
return cachedManifest.versions;
|
||||
}
|
||||
const response = await fetchManifestResponse(manifestUrl);
|
||||
const body = await response.text();
|
||||
const versions = parseManifest(body, manifestUrl);
|
||||
cachedManifestData.set(manifestUrl, versions);
|
||||
cachedManifestData.set(manifestUrl, { complete: true, versions });
|
||||
return versions;
|
||||
}
|
||||
function parseManifest(data, sourceDescription) {
|
||||
@@ -50731,31 +50787,14 @@ function parseManifest(data, sourceDescription) {
|
||||
if (trimmed === "") {
|
||||
throw new Error(`Manifest at ${sourceDescription} is empty.`);
|
||||
}
|
||||
if (trimmed.startsWith("[")) {
|
||||
throw new Error(
|
||||
`Legacy JSON array manifests are no longer supported in ${sourceDescription}. Use the astral-sh/versions manifest format instead.`
|
||||
);
|
||||
}
|
||||
rejectLegacyManifest(trimmed, sourceDescription);
|
||||
const versions = [];
|
||||
for (const [index, line] of data.split("\n").entries()) {
|
||||
const record = line.trim();
|
||||
if (record === "") {
|
||||
continue;
|
||||
}
|
||||
let parsed;
|
||||
try {
|
||||
parsed = JSON.parse(record);
|
||||
} catch (error2) {
|
||||
throw new Error(
|
||||
`Failed to parse manifest data from ${sourceDescription} at line ${index + 1}: ${error2.message}`
|
||||
);
|
||||
}
|
||||
if (!isManifestVersion(parsed)) {
|
||||
throw new Error(
|
||||
`Invalid manifest record in ${sourceDescription} at line ${index + 1}.`
|
||||
);
|
||||
}
|
||||
versions.push(parsed);
|
||||
versions.push(parseManifestRecord(record, sourceDescription, index + 1));
|
||||
}
|
||||
if (versions.length === 0) {
|
||||
throw new Error(`No manifest data found in ${sourceDescription}.`);
|
||||
@@ -50763,13 +50802,104 @@ function parseManifest(data, sourceDescription) {
|
||||
return versions;
|
||||
}
|
||||
async function getLatestVersion(manifestUrl = VERSIONS_MANIFEST_URL) {
|
||||
const latestVersion = (await fetchManifest(manifestUrl))[0]?.version;
|
||||
const latestVersion = manifestUrl === VERSIONS_MANIFEST_URL ? (await findManifestVersion(() => true))?.version : (await fetchManifest(manifestUrl))[0]?.version;
|
||||
if (latestVersion === void 0) {
|
||||
throw new Error("No versions found in manifest data");
|
||||
}
|
||||
debug(`Latest version from manifest: ${latestVersion}`);
|
||||
return latestVersion;
|
||||
}
|
||||
async function fetchManifestResponse(manifestUrl) {
|
||||
info2(`Fetching manifest data from ${manifestUrl} ...`);
|
||||
const response = await fetch(manifestUrl, {});
|
||||
if (!response.ok) {
|
||||
throw new Error(
|
||||
`Failed to fetch manifest data: ${response.status} ${response.statusText}`
|
||||
);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
async function findManifestVersion(predicate) {
|
||||
const cachedManifest = cachedManifestData.get(VERSIONS_MANIFEST_URL);
|
||||
const cachedVersion = cachedManifest?.versions.find(predicate);
|
||||
if (cachedVersion !== void 0 || cachedManifest?.complete === true) {
|
||||
return cachedVersion;
|
||||
}
|
||||
const response = await fetchManifestResponse(VERSIONS_MANIFEST_URL);
|
||||
if (response.body === null) {
|
||||
const versions2 = parseManifest(
|
||||
await response.text(),
|
||||
VERSIONS_MANIFEST_URL
|
||||
);
|
||||
cachedManifestData.set(VERSIONS_MANIFEST_URL, {
|
||||
complete: true,
|
||||
versions: versions2
|
||||
});
|
||||
return versions2.find(predicate);
|
||||
}
|
||||
const input = import_node_stream.Readable.fromWeb(response.body);
|
||||
const lines = (0, import_node_readline.createInterface)({ crlfDelay: Number.POSITIVE_INFINITY, input });
|
||||
const versions = [];
|
||||
let complete = false;
|
||||
let lineNumber = 0;
|
||||
let matchedVersion;
|
||||
try {
|
||||
for await (const line of lines) {
|
||||
lineNumber += 1;
|
||||
const record = line.trim();
|
||||
if (record === "") {
|
||||
continue;
|
||||
}
|
||||
if (versions.length === 0) {
|
||||
rejectLegacyManifest(record, VERSIONS_MANIFEST_URL);
|
||||
}
|
||||
const versionData = parseManifestRecord(
|
||||
record,
|
||||
VERSIONS_MANIFEST_URL,
|
||||
lineNumber
|
||||
);
|
||||
versions.push(versionData);
|
||||
if (predicate(versionData)) {
|
||||
matchedVersion = versionData;
|
||||
break;
|
||||
}
|
||||
}
|
||||
complete = matchedVersion === void 0;
|
||||
} finally {
|
||||
lines.close();
|
||||
if (!complete) {
|
||||
input.destroy();
|
||||
}
|
||||
}
|
||||
if (versions.length === 0) {
|
||||
throw new Error(`Manifest at ${VERSIONS_MANIFEST_URL} is empty.`);
|
||||
}
|
||||
cachedManifestData.set(VERSIONS_MANIFEST_URL, { complete, versions });
|
||||
return matchedVersion;
|
||||
}
|
||||
function parseManifestRecord(record, sourceDescription, lineNumber) {
|
||||
let parsed;
|
||||
try {
|
||||
parsed = JSON.parse(record);
|
||||
} catch (error2) {
|
||||
throw new Error(
|
||||
`Failed to parse manifest data from ${sourceDescription} at line ${lineNumber}: ${error2.message}`
|
||||
);
|
||||
}
|
||||
if (!isManifestVersion(parsed)) {
|
||||
throw new Error(
|
||||
`Invalid manifest record in ${sourceDescription} at line ${lineNumber}.`
|
||||
);
|
||||
}
|
||||
return parsed;
|
||||
}
|
||||
function rejectLegacyManifest(data, sourceDescription) {
|
||||
if (data.startsWith("[")) {
|
||||
throw new Error(
|
||||
`Legacy JSON array manifests are no longer supported in ${sourceDescription}. Use the astral-sh/versions manifest format instead.`
|
||||
);
|
||||
}
|
||||
}
|
||||
function isManifestVersion(value) {
|
||||
if (!isRecord(value)) {
|
||||
return false;
|
||||
|
||||
@@ -6,7 +6,7 @@ This document covers advanced options for configuring which version of uv to ins
|
||||
|
||||
```yaml
|
||||
- name: Install the latest version of uv
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
version: "latest"
|
||||
```
|
||||
@@ -15,7 +15,7 @@ This document covers advanced options for configuring which version of uv to ins
|
||||
|
||||
```yaml
|
||||
- name: Install a specific version of uv
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
version: "0.4.4"
|
||||
```
|
||||
@@ -28,21 +28,21 @@ to install the latest version that satisfies the range.
|
||||
|
||||
```yaml
|
||||
- name: Install a semver range of uv
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
version: ">=0.4.0"
|
||||
```
|
||||
|
||||
```yaml
|
||||
- name: Pinning a minor version of uv
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
version: "0.4.x"
|
||||
```
|
||||
|
||||
```yaml
|
||||
- name: Install a pep440-specifier-satisfying version of uv
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
version: ">=0.4.25,<0.5"
|
||||
```
|
||||
@@ -54,7 +54,7 @@ You can change this behavior using the `resolution-strategy` input:
|
||||
|
||||
```yaml
|
||||
- name: Install the lowest compatible version of uv
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
version: ">=0.4.0"
|
||||
resolution-strategy: "lowest"
|
||||
@@ -76,7 +76,7 @@ uv defined as a dependency in `pyproject.toml` or `requirements.txt`.
|
||||
|
||||
```yaml
|
||||
- name: Install uv based on the version defined in pyproject.toml
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
version-file: "pyproject.toml"
|
||||
```
|
||||
@@ -87,7 +87,7 @@ silently picking up a newer uv until the lockfile is updated.
|
||||
|
||||
```yaml
|
||||
- name: Install uv based on the version locked in uv.lock
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
version-file: "uv.lock"
|
||||
```
|
||||
|
||||
+25
-26
@@ -23,7 +23,7 @@ The computed cache key is available as the `cache-key` output:
|
||||
```yaml
|
||||
- name: Setup uv
|
||||
id: setup-uv
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
enable-cache: true
|
||||
- name: Print cache key
|
||||
@@ -33,8 +33,8 @@ The computed cache key is available as the `cache-key` output:
|
||||
## Enable caching
|
||||
|
||||
> [!NOTE]
|
||||
> The cache is pruned before it is uploaded to the GitHub Actions cache. This can lead to
|
||||
> a small or empty cache. See [Disable cache pruning](#disable-cache-pruning) for more details.
|
||||
> The entire uv cache is uploaded to the GitHub Actions cache by default. To reduce the cache size,
|
||||
> see [Enable cache pruning](#enable-cache-pruning).
|
||||
|
||||
If you enable caching, the [uv cache](https://docs.astral.sh/uv/concepts/cache/) will be uploaded to
|
||||
the GitHub Actions cache. This can speed up runs that reuse the cache by several minutes.
|
||||
@@ -50,7 +50,7 @@ You can optionally define a custom cache key suffix.
|
||||
```yaml
|
||||
- name: Enable caching and define a custom cache key suffix
|
||||
id: setup-uv
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-suffix: "optional-suffix"
|
||||
@@ -89,7 +89,7 @@ changes. If you use relative paths, they are relative to the working directory.
|
||||
|
||||
```yaml
|
||||
- name: Define a cache dependency glob
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-dependency-glob: "**/pyproject.toml"
|
||||
@@ -97,7 +97,7 @@ changes. If you use relative paths, they are relative to the working directory.
|
||||
|
||||
```yaml
|
||||
- name: Define a list of cache dependency globs
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
@@ -107,7 +107,7 @@ changes. If you use relative paths, they are relative to the working directory.
|
||||
|
||||
```yaml
|
||||
- name: Define an absolute cache dependency glob
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-dependency-glob: "/tmp/my-folder/requirements*.txt"
|
||||
@@ -115,7 +115,7 @@ changes. If you use relative paths, they are relative to the working directory.
|
||||
|
||||
```yaml
|
||||
- name: Never invalidate the cache
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-dependency-glob: ""
|
||||
@@ -128,7 +128,7 @@ By default, the cache will be restored.
|
||||
|
||||
```yaml
|
||||
- name: Don't restore an existing cache
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
enable-cache: true
|
||||
restore-cache: false
|
||||
@@ -142,7 +142,7 @@ By default, the cache will be saved.
|
||||
|
||||
```yaml
|
||||
- name: Don't save the cache after the run
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
enable-cache: true
|
||||
save-cache: false
|
||||
@@ -168,35 +168,34 @@ It defaults to `setup-uv-cache` in the `TMP` dir, `D:\a\_temp\setup-uv-cache` on
|
||||
|
||||
```yaml
|
||||
- name: Define a custom uv cache path
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
cache-local-path: "/path/to/cache"
|
||||
```
|
||||
|
||||
## Disable cache pruning
|
||||
## Enable cache pruning
|
||||
|
||||
By default, the uv cache is pruned after every run, removing pre-built wheels, but retaining any
|
||||
wheels that were built from source. On GitHub-hosted runners, it's typically faster to omit those
|
||||
pre-built wheels from the cache (and instead re-download them from the registry on each run).
|
||||
However, on self-hosted or local runners, preserving the cache may be more efficient. See
|
||||
the [documentation](https://docs.astral.sh/uv/concepts/cache/#caching-in-continuous-integration) for
|
||||
more information.
|
||||
By default, the entire uv cache is persisted across runs. On GitHub-hosted runners, it's typically
|
||||
faster to prune the cache before saving it, removing pre-built wheels, but retaining any wheels that
|
||||
were built from source. The pre-built wheels are then re-downloaded from the registry on each run.
|
||||
See the [documentation](https://docs.astral.sh/uv/concepts/cache/#caching-in-continuous-integration)
|
||||
for more information.
|
||||
|
||||
If you want to persist the entire cache across runs, disable cache pruning with the `prune-cache`
|
||||
input.
|
||||
If you want to prune the cache before saving it, enable cache pruning with the `prune-cache` input.
|
||||
|
||||
```yaml
|
||||
- name: Don't prune the cache before saving it
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
- name: Prune the cache before saving it
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
enable-cache: true
|
||||
prune-cache: false
|
||||
prune-cache: true
|
||||
```
|
||||
|
||||
## Cache Python installs
|
||||
|
||||
By default, the Python install dir (`uv python dir` / `UV_PYTHON_INSTALL_DIR`) is not cached,
|
||||
for the same reason that the dependency cache is pruned.
|
||||
for the same reason that pruning the dependency cache can improve performance on GitHub-hosted
|
||||
runners.
|
||||
If you want to cache Python installs along with your dependencies, set the `cache-python` input to `true`.
|
||||
|
||||
Note that this only caches Python versions that uv actually installs into `UV_PYTHON_INSTALL_DIR`
|
||||
@@ -205,7 +204,7 @@ To force managed Python installs, set `UV_PYTHON_PREFERENCE=only-managed`.
|
||||
|
||||
```yaml
|
||||
- name: Cache Python installs
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-python: true
|
||||
@@ -223,7 +222,7 @@ If you want to ignore this, set the `ignore-nothing-to-cache` input to `true`.
|
||||
|
||||
```yaml
|
||||
- name: Ignore nothing to cache
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
enable-cache: true
|
||||
ignore-nothing-to-cache: true
|
||||
|
||||
@@ -10,7 +10,7 @@ are automatically verified by this action. The sha256 hashes can be found on the
|
||||
|
||||
```yaml
|
||||
- name: Install a specific version and validate the checksum
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
version: "0.3.1"
|
||||
checksum: "e11b01402ab645392c7ad6044db63d37e4fd1e745e015306993b07695ea5f9f8"
|
||||
@@ -39,7 +39,7 @@ The `archive_format` field is currently ignored.
|
||||
|
||||
```yaml
|
||||
- name: Use a custom manifest file
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
manifest-file: "https://example.com/my-custom-manifest.ndjson"
|
||||
```
|
||||
@@ -58,7 +58,7 @@ You can disable this by setting the `add-problem-matchers` input to `false`.
|
||||
|
||||
```yaml
|
||||
- name: Install the latest version of uv without problem matchers
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
add-problem-matchers: false
|
||||
```
|
||||
|
||||
@@ -9,7 +9,7 @@ This allows directly using it in later steps:
|
||||
|
||||
```yaml
|
||||
- name: Install the latest version of uv and activate the environment
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
activate-environment: true
|
||||
- run: uv pip install pip
|
||||
@@ -20,7 +20,7 @@ By default, the venv is created at `.venv` inside the `working-directory`.
|
||||
You can customize the venv location with `venv-path`, for example to place it in the runner temp directory:
|
||||
|
||||
```yaml
|
||||
- uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
- uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
activate-environment: true
|
||||
venv-path: ${{ runner.temp }}/custom-venv
|
||||
@@ -51,7 +51,7 @@ are not sufficient, you can provide a custom GitHub token with the necessary per
|
||||
|
||||
```yaml
|
||||
- name: Install the latest version of uv with a custom GitHub token
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
github-token: ${{ secrets.CUSTOM_GITHUB_TOKEN }}
|
||||
```
|
||||
@@ -69,7 +69,7 @@ input:
|
||||
|
||||
```yaml
|
||||
- name: Install the latest version of uv with a custom tool dir
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
tool-dir: "/path/to/tool/dir"
|
||||
```
|
||||
@@ -88,7 +88,7 @@ If you want to change this behaviour (especially on self-hosted runners) you can
|
||||
|
||||
```yaml
|
||||
- name: Install the latest version of uv with a custom tool bin dir
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
tool-bin-dir: "/path/to/tool-bin/dir"
|
||||
```
|
||||
@@ -105,7 +105,7 @@ This action supports expanding the `~` character to the user's home directory fo
|
||||
|
||||
```yaml
|
||||
- name: Expand the tilde character
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
cache-local-path: "~/path/to/cache"
|
||||
tool-dir: "~/path/to/tool/dir"
|
||||
@@ -122,7 +122,7 @@ If you want to ignore this, set the `ignore-empty-workdir` input to `true`.
|
||||
|
||||
```yaml
|
||||
- name: Ignore empty workdir
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
ignore-empty-workdir: true
|
||||
```
|
||||
@@ -145,7 +145,7 @@ This action sets several environment variables that influence uv's behavior and
|
||||
|
||||
```yaml
|
||||
- name: Example using environment variables
|
||||
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
python-version: "3.12"
|
||||
tool-dir: "/custom/tool/dir"
|
||||
|
||||
Generated
+340
-330
File diff suppressed because it is too large
Load Diff
+7
-7
@@ -28,25 +28,25 @@
|
||||
"author": "@eifinger",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/cache": "^6.0.1",
|
||||
"@actions/cache": "^6.1.0",
|
||||
"@actions/core": "^3.0.0",
|
||||
"@actions/exec": "^3.0.0",
|
||||
"@actions/glob": "^0.6.1",
|
||||
"@actions/io": "^3.0.2",
|
||||
"@actions/tool-cache": "^4.0.0",
|
||||
"@renovatebot/pep440": "^5.0.0",
|
||||
"smol-toml": "^1.6.1",
|
||||
"smol-toml": "^1.7.0",
|
||||
"undici": "^8.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "^2.4.16",
|
||||
"@biomejs/biome": "^2.5.1",
|
||||
"@types/js-yaml": "^4.0.9",
|
||||
"@types/node": "^25.5.0",
|
||||
"@types/node": "^26.1.1",
|
||||
"@types/semver": "^7.7.1",
|
||||
"@vercel/ncc": "^0.38.4",
|
||||
"esbuild": "^0.28.0",
|
||||
"@vercel/ncc": "^0.44.1",
|
||||
"esbuild": "^0.28.1",
|
||||
"jest": "^30.4.2",
|
||||
"js-yaml": "^4.1.1",
|
||||
"js-yaml": "^5.2.1",
|
||||
"ts-jest": "^29.4.11",
|
||||
"typescript": "^6.0.3"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,113 @@
|
||||
// AUTOGENERATED_DO_NOT_EDIT
|
||||
export const KNOWN_CHECKSUMS: { [key: string]: string } = {
|
||||
"aarch64-apple-darwin-0.11.30":
|
||||
"9bed3567d496d8dab84ecf7a1247551ac94ef1baaebb7b65df008dd93e9dc357",
|
||||
"aarch64-pc-windows-msvc-0.11.30":
|
||||
"0edc44e7f23668bce7985facd96b2fe04a4d8ea8edfc7e53294afd8993e960fc",
|
||||
"aarch64-unknown-linux-gnu-0.11.30":
|
||||
"8c11d90f5f66d232930cf8ae3a085c39877690d409e10878234802b028b20e2a",
|
||||
"aarch64-unknown-linux-musl-0.11.30":
|
||||
"7562a40e4e08b1bfd566bd6aeca55a16ee5ac45211554543e8cdb3c395b47416",
|
||||
"arm-unknown-linux-musleabihf-0.11.30":
|
||||
"58967610a6f14f2785e3be3b1b47553b5ff92c3d51bc0f1d9d90d83dc224f0db",
|
||||
"armv7-unknown-linux-gnueabihf-0.11.30":
|
||||
"8e2d2ab63a37af47c1b4126c5871ee191b983a10670af91d8ef0bee198292931",
|
||||
"armv7-unknown-linux-musleabihf-0.11.30":
|
||||
"33b515887e04c79d4d5de5967b8278b9dac1853cc8d657bf77052bab16a6629f",
|
||||
"i686-pc-windows-msvc-0.11.30":
|
||||
"8ceaa74889e30d64adf55d7ad7acce6ed101fb036155bf2d7613715c9d9533c1",
|
||||
"i686-unknown-linux-gnu-0.11.30":
|
||||
"e53221602d83b03c63a5e262bfcbf0f5f6e5972e93847498418bdb42005f04e7",
|
||||
"i686-unknown-linux-musl-0.11.30":
|
||||
"f66898852a6a745a8c0ab0a26e046857ee77c9f24e4a3b64cb078753490b3978",
|
||||
"powerpc64le-unknown-linux-gnu-0.11.30":
|
||||
"81a71fa495239c372b3b0c1bb2509167da00cf307323a2d2a39cbc92f0c6d5d1",
|
||||
"riscv64gc-unknown-linux-gnu-0.11.30":
|
||||
"e2d65822d8f668f6d055679dba4937e386764b9561f9d1269d3bc9e7140f7491",
|
||||
"riscv64gc-unknown-linux-musl-0.11.30":
|
||||
"3d75e26ace5e679e5de26106a71ee775af5c7f7ad872cd04f33b4d53c523a707",
|
||||
"s390x-unknown-linux-gnu-0.11.30":
|
||||
"a30f253aca1291dbcdbb7f76c754235f268ff84d106a595f7d1abf337ab22ac1",
|
||||
"x86_64-apple-darwin-0.11.30":
|
||||
"ce285fbbfbe294b1e1bc6c87c8b59d9622b85383b88b2b132a2df5c73e83d7c1",
|
||||
"x86_64-pc-windows-msvc-0.11.30":
|
||||
"be8d78c992312212e5cc05e9f9de3fa996db73b7c86a186dfb9231eb9f91d33e",
|
||||
"x86_64-unknown-linux-gnu-0.11.30":
|
||||
"04bc7d180d6138bf6dc08387acf507a823f397a98fea55da36b0ccc7fbce3b68",
|
||||
"x86_64-unknown-linux-musl-0.11.30":
|
||||
"023fdd3b59fccfb67b365c69fb34182aaaed1d685d367a57571e3c1468a4c70c",
|
||||
"aarch64-apple-darwin-0.11.29":
|
||||
"61c04acc52a33ef0f331e494bdfbedcdb6c26c6970c022ed3699e5860f8930e3",
|
||||
"aarch64-pc-windows-msvc-0.11.29":
|
||||
"55b597ae81bc29531a7c352a1431a8a73cc2755d7a5b9ec454580cbe02e5154f",
|
||||
"aarch64-unknown-linux-gnu-0.11.29":
|
||||
"94500fb064ae3c971a873cba64d94694c50677e0a4dbf78735c80509e7429919",
|
||||
"aarch64-unknown-linux-musl-0.11.29":
|
||||
"593d79a797ece3f1dfaaf3e0a973263422a135d9262c7dbc6cd75d9c11acc0b4",
|
||||
"arm-unknown-linux-musleabihf-0.11.29":
|
||||
"b160d7eb7dc45af378b3c9dd2cd6b07d64c65b509f2da673434e8e5dc996e5b1",
|
||||
"armv7-unknown-linux-gnueabihf-0.11.29":
|
||||
"7b5717ae304fbb1e94104699fb8c08b32d1537fedc90dd8fcf87768d818951ed",
|
||||
"armv7-unknown-linux-musleabihf-0.11.29":
|
||||
"bfd05286a80b39bd4708bbbb4450fe09f07fea86eea60d31ea2de0b5e816ef54",
|
||||
"i686-pc-windows-msvc-0.11.29":
|
||||
"c173af6f6e125d65214b55d6b75fcf1a32d5e1c3a656938740fe0b2379cd4bcc",
|
||||
"i686-unknown-linux-gnu-0.11.29":
|
||||
"c62af324951ae6f31f9453280e077176c96b6e31897d8133c00411a91a20878f",
|
||||
"i686-unknown-linux-musl-0.11.29":
|
||||
"368dd75d030cae0512631ba0d50604e8471275ec2d9f02836edb91e4c82ad36a",
|
||||
"powerpc64le-unknown-linux-gnu-0.11.29":
|
||||
"641b15637de9fedc7e738b0e4716b2233c792ba6dca722ba0484381749e1a9fd",
|
||||
"riscv64gc-unknown-linux-gnu-0.11.29":
|
||||
"5c1229cc0309ebc6872ee847b8fc75564b3b7688edeb09e19427203e2dbc0ea7",
|
||||
"riscv64gc-unknown-linux-musl-0.11.29":
|
||||
"d4708d913ba88fad9fe1d81da3e13aecadde7a3190cc095a7f2af2fa5c8caa8f",
|
||||
"s390x-unknown-linux-gnu-0.11.29":
|
||||
"fa029183f550a3b00b89c06529fabfa11e0c69c097ccd397a8e7eae46f397348",
|
||||
"x86_64-apple-darwin-0.11.29":
|
||||
"c4c4de482da9ccdd076dc4fb5cfe7b740609029385c72f58606be3153602387d",
|
||||
"x86_64-pc-windows-msvc-0.11.29":
|
||||
"a047d55651bc3e0ca24595b25ec4cfcb10f9dca9fb56514e661269b37d4fae68",
|
||||
"x86_64-unknown-linux-gnu-0.11.29":
|
||||
"04f8b82f5d47f0512dcd32c67a4a6f16a0ea27c81537c338fd0ad6b23cebe829",
|
||||
"x86_64-unknown-linux-musl-0.11.29":
|
||||
"46711858adb2a3acaa9cee00f9060688ad1fd5706aecc005b96a6a7f285a00b7",
|
||||
"aarch64-apple-darwin-0.11.28":
|
||||
"33540eb7c883ab857eff79bd5ac2aa31fe27b595abecb4a9c003a2c998447232",
|
||||
"aarch64-pc-windows-msvc-0.11.28":
|
||||
"3248109afad3ec59baad299d324ff53de17e2d9a3b3e21580ffd26744b11e036",
|
||||
"aarch64-unknown-linux-gnu-0.11.28":
|
||||
"03e9fe0a81b0718d0bc84625de3885df6cc3f89a8b6af6121d6b9f6113fb6533",
|
||||
"aarch64-unknown-linux-musl-0.11.28":
|
||||
"da10cdfa7d92212b7acb62021a0fd61bcf8580c58c3632ec915d10c3a1a7906b",
|
||||
"arm-unknown-linux-musleabihf-0.11.28":
|
||||
"955f9697d4781cf4dfc62d9442a49f3e57861f19405a981ffe9fdc0d18e0a31a",
|
||||
"armv7-unknown-linux-gnueabihf-0.11.28":
|
||||
"b7cddaad27cd531096e88e64de863f7e37c6fedde11c97595060e6503544d120",
|
||||
"armv7-unknown-linux-musleabihf-0.11.28":
|
||||
"eb00e0f246d278133df6a55b5d3534a49f051a7dfc276f640b66504c091167f6",
|
||||
"i686-pc-windows-msvc-0.11.28":
|
||||
"01975deb06072edfc1f18435c25737d8d378dc849b918cd580768ab3b7641e85",
|
||||
"i686-unknown-linux-gnu-0.11.28":
|
||||
"f8d01e918dd4d5eabdd4caee78e8adbc3993a70f3b82395fa6b23fcf791925d9",
|
||||
"i686-unknown-linux-musl-0.11.28":
|
||||
"c869415e44e13000d9daae15cec7bcfaf0735915a8d6e66402d459f6bed35710",
|
||||
"powerpc64le-unknown-linux-gnu-0.11.28":
|
||||
"b634b6f26a036d112914c2d6d7ae1944bf8f4a6dfed6e19a22b35e5d91f168fb",
|
||||
"riscv64gc-unknown-linux-gnu-0.11.28":
|
||||
"be7473dc29ee88bd260e30642faa5ba6dccd7d4493012077873b293c377ab546",
|
||||
"riscv64gc-unknown-linux-musl-0.11.28":
|
||||
"4a9e553d8a62c42600d5c2874b7c2f728c03d4310d72ed7351edbee8ed6a71b4",
|
||||
"s390x-unknown-linux-gnu-0.11.28":
|
||||
"f5ed9d2aed566e11ffc3f1f7ab5b4049dfbfcb04c326ce2ed5bbf42069d62b27",
|
||||
"x86_64-apple-darwin-0.11.28":
|
||||
"2ad79983127ffca7d77b77ce6a24278d7e4f7b817a1acf72fea5f8124b4aac5e",
|
||||
"x86_64-pc-windows-msvc-0.11.28":
|
||||
"0a23463216d09c6a72ff80ef5dc5a795f07dc1575cb84d24596c2f124a441b7b",
|
||||
"x86_64-unknown-linux-gnu-0.11.28":
|
||||
"e490a6464492183c5d4534a5527fb4440f7f2bb2f228162ad7e4afe076dc0224",
|
||||
"x86_64-unknown-linux-musl-0.11.28":
|
||||
"f02146b371c35c287d860f003ece7345c86e358a3fd70a9b63700cd141ee7fb4",
|
||||
"aarch64-apple-darwin-0.11.27":
|
||||
"34e63cc0de0aebbc8d424767c588c31b685479f045f9ced9e5ef43ff9e0e8d63",
|
||||
"aarch64-pc-windows-msvc-0.11.27":
|
||||
|
||||
+147
-39
@@ -1,3 +1,5 @@
|
||||
import { createInterface } from "node:readline";
|
||||
import { Readable } from "node:stream";
|
||||
import * as core from "@actions/core";
|
||||
import { VERSIONS_MANIFEST_URL } from "../utils/constants";
|
||||
import { fetch } from "../utils/fetch";
|
||||
@@ -23,28 +25,26 @@ export interface ArtifactResult {
|
||||
downloadUrl: string;
|
||||
}
|
||||
|
||||
const cachedManifestData = new Map<string, ManifestVersion[]>();
|
||||
interface CachedManifest {
|
||||
complete: boolean;
|
||||
versions: ManifestVersion[];
|
||||
}
|
||||
|
||||
const cachedManifestData = new Map<string, CachedManifest>();
|
||||
|
||||
export async function fetchManifest(
|
||||
manifestUrl: string = VERSIONS_MANIFEST_URL,
|
||||
): Promise<ManifestVersion[]> {
|
||||
const cachedVersions = cachedManifestData.get(manifestUrl);
|
||||
if (cachedVersions !== undefined) {
|
||||
const cachedManifest = cachedManifestData.get(manifestUrl);
|
||||
if (cachedManifest?.complete === true) {
|
||||
core.debug(`Using cached manifest data from ${manifestUrl}`);
|
||||
return cachedVersions;
|
||||
}
|
||||
|
||||
log.info(`Fetching manifest data from ${manifestUrl} ...`);
|
||||
const response = await fetch(manifestUrl, {});
|
||||
if (!response.ok) {
|
||||
throw new Error(
|
||||
`Failed to fetch manifest data: ${response.status} ${response.statusText}`,
|
||||
);
|
||||
return cachedManifest.versions;
|
||||
}
|
||||
|
||||
const response = await fetchManifestResponse(manifestUrl);
|
||||
const body = await response.text();
|
||||
const versions = parseManifest(body, manifestUrl);
|
||||
cachedManifestData.set(manifestUrl, versions);
|
||||
cachedManifestData.set(manifestUrl, { complete: true, versions });
|
||||
return versions;
|
||||
}
|
||||
|
||||
@@ -57,11 +57,7 @@ export function parseManifest(
|
||||
throw new Error(`Manifest at ${sourceDescription} is empty.`);
|
||||
}
|
||||
|
||||
if (trimmed.startsWith("[")) {
|
||||
throw new Error(
|
||||
`Legacy JSON array manifests are no longer supported in ${sourceDescription}. Use the astral-sh/versions manifest format instead.`,
|
||||
);
|
||||
}
|
||||
rejectLegacyManifest(trimmed, sourceDescription);
|
||||
|
||||
const versions: ManifestVersion[] = [];
|
||||
|
||||
@@ -71,22 +67,7 @@ export function parseManifest(
|
||||
continue;
|
||||
}
|
||||
|
||||
let parsed: unknown;
|
||||
try {
|
||||
parsed = JSON.parse(record);
|
||||
} catch (error) {
|
||||
throw new Error(
|
||||
`Failed to parse manifest data from ${sourceDescription} at line ${index + 1}: ${(error as Error).message}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (!isManifestVersion(parsed)) {
|
||||
throw new Error(
|
||||
`Invalid manifest record in ${sourceDescription} at line ${index + 1}.`,
|
||||
);
|
||||
}
|
||||
|
||||
versions.push(parsed);
|
||||
versions.push(parseManifestRecord(record, sourceDescription, index + 1));
|
||||
}
|
||||
|
||||
if (versions.length === 0) {
|
||||
@@ -99,7 +80,10 @@ export function parseManifest(
|
||||
export async function getLatestVersion(
|
||||
manifestUrl: string = VERSIONS_MANIFEST_URL,
|
||||
): Promise<string> {
|
||||
const latestVersion = (await fetchManifest(manifestUrl))[0]?.version;
|
||||
const latestVersion =
|
||||
manifestUrl === VERSIONS_MANIFEST_URL
|
||||
? (await findManifestVersion(() => true))?.version
|
||||
: (await fetchManifest(manifestUrl))[0]?.version;
|
||||
|
||||
if (latestVersion === undefined) {
|
||||
throw new Error("No versions found in manifest data");
|
||||
@@ -109,6 +93,16 @@ export async function getLatestVersion(
|
||||
return latestVersion;
|
||||
}
|
||||
|
||||
// The default manifest is guaranteed to be ordered newest-first:
|
||||
// https://github.com/astral-sh/versions#format
|
||||
export async function getFirstMatchingVersion(
|
||||
predicate: (version: string) => boolean,
|
||||
): Promise<string | undefined> {
|
||||
return (
|
||||
await findManifestVersion((versionData) => predicate(versionData.version))
|
||||
)?.version;
|
||||
}
|
||||
|
||||
export async function getAllVersions(
|
||||
manifestUrl: string = VERSIONS_MANIFEST_URL,
|
||||
): Promise<string[]> {
|
||||
@@ -125,10 +119,12 @@ export async function getArtifact(
|
||||
platform: string,
|
||||
manifestUrl: string = VERSIONS_MANIFEST_URL,
|
||||
): Promise<ArtifactResult | undefined> {
|
||||
const versions = await fetchManifest(manifestUrl);
|
||||
const versionData = versions.find(
|
||||
(candidate) => candidate.version === version,
|
||||
);
|
||||
const versionData =
|
||||
manifestUrl === VERSIONS_MANIFEST_URL
|
||||
? await findManifestVersion((candidate) => candidate.version === version)
|
||||
: (await fetchManifest(manifestUrl)).find(
|
||||
(candidate) => candidate.version === version,
|
||||
);
|
||||
if (!versionData) {
|
||||
core.debug(`Version ${version} not found in manifest ${manifestUrl}`);
|
||||
return undefined;
|
||||
@@ -169,6 +165,87 @@ export function clearManifestCache(manifestUrl?: string): void {
|
||||
cachedManifestData.delete(manifestUrl);
|
||||
}
|
||||
|
||||
async function fetchManifestResponse(manifestUrl: string) {
|
||||
log.info(`Fetching manifest data from ${manifestUrl} ...`);
|
||||
const response = await fetch(manifestUrl, {});
|
||||
if (!response.ok) {
|
||||
throw new Error(
|
||||
`Failed to fetch manifest data: ${response.status} ${response.statusText}`,
|
||||
);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
async function findManifestVersion(
|
||||
predicate: (versionData: ManifestVersion) => boolean,
|
||||
): Promise<ManifestVersion | undefined> {
|
||||
const cachedManifest = cachedManifestData.get(VERSIONS_MANIFEST_URL);
|
||||
const cachedVersion = cachedManifest?.versions.find(predicate);
|
||||
if (cachedVersion !== undefined || cachedManifest?.complete === true) {
|
||||
return cachedVersion;
|
||||
}
|
||||
|
||||
const response = await fetchManifestResponse(VERSIONS_MANIFEST_URL);
|
||||
if (response.body === null) {
|
||||
const versions = parseManifest(
|
||||
await response.text(),
|
||||
VERSIONS_MANIFEST_URL,
|
||||
);
|
||||
cachedManifestData.set(VERSIONS_MANIFEST_URL, {
|
||||
complete: true,
|
||||
versions,
|
||||
});
|
||||
return versions.find(predicate);
|
||||
}
|
||||
|
||||
const input = Readable.fromWeb(response.body);
|
||||
const lines = createInterface({ crlfDelay: Number.POSITIVE_INFINITY, input });
|
||||
const versions: ManifestVersion[] = [];
|
||||
let complete = false;
|
||||
let lineNumber = 0;
|
||||
let matchedVersion: ManifestVersion | undefined;
|
||||
|
||||
try {
|
||||
for await (const line of lines) {
|
||||
lineNumber += 1;
|
||||
const record = line.trim();
|
||||
if (record === "") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (versions.length === 0) {
|
||||
rejectLegacyManifest(record, VERSIONS_MANIFEST_URL);
|
||||
}
|
||||
|
||||
const versionData = parseManifestRecord(
|
||||
record,
|
||||
VERSIONS_MANIFEST_URL,
|
||||
lineNumber,
|
||||
);
|
||||
versions.push(versionData);
|
||||
if (predicate(versionData)) {
|
||||
matchedVersion = versionData;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
complete = matchedVersion === undefined;
|
||||
} finally {
|
||||
lines.close();
|
||||
if (!complete) {
|
||||
input.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
if (versions.length === 0) {
|
||||
throw new Error(`Manifest at ${VERSIONS_MANIFEST_URL} is empty.`);
|
||||
}
|
||||
|
||||
cachedManifestData.set(VERSIONS_MANIFEST_URL, { complete, versions });
|
||||
return matchedVersion;
|
||||
}
|
||||
|
||||
function manifestSource(manifestUrl: string): string {
|
||||
if (manifestUrl === VERSIONS_MANIFEST_URL) {
|
||||
return VERSIONS_MANIFEST_URL;
|
||||
@@ -177,6 +254,37 @@ function manifestSource(manifestUrl: string): string {
|
||||
return `manifest-file ${manifestUrl}`;
|
||||
}
|
||||
|
||||
function parseManifestRecord(
|
||||
record: string,
|
||||
sourceDescription: string,
|
||||
lineNumber: number,
|
||||
): ManifestVersion {
|
||||
let parsed: unknown;
|
||||
try {
|
||||
parsed = JSON.parse(record);
|
||||
} catch (error) {
|
||||
throw new Error(
|
||||
`Failed to parse manifest data from ${sourceDescription} at line ${lineNumber}: ${(error as Error).message}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (!isManifestVersion(parsed)) {
|
||||
throw new Error(
|
||||
`Invalid manifest record in ${sourceDescription} at line ${lineNumber}.`,
|
||||
);
|
||||
}
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
function rejectLegacyManifest(data: string, sourceDescription: string): void {
|
||||
if (data.startsWith("[")) {
|
||||
throw new Error(
|
||||
`Legacy JSON array manifests are no longer supported in ${sourceDescription}. Use the astral-sh/versions manifest format instead.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function isManifestVersion(value: unknown): value is ManifestVersion {
|
||||
if (!isRecord(value)) {
|
||||
return false;
|
||||
|
||||
@@ -102,6 +102,7 @@ export function getOSNameVersion(): string {
|
||||
|
||||
function getLinuxOSNameVersion(): string {
|
||||
const files = ["/etc/os-release", "/usr/lib/os-release"];
|
||||
let idWithoutVersion: string | undefined;
|
||||
|
||||
for (const file of files) {
|
||||
try {
|
||||
@@ -122,11 +123,22 @@ function getLinuxOSNameVersion(): string {
|
||||
if (id && buildId) {
|
||||
return `${id}-${buildId}`;
|
||||
}
|
||||
// Remember the ID but keep looking: the next file might still
|
||||
// provide a version field
|
||||
if (id && idWithoutVersion === undefined) {
|
||||
idWithoutVersion = id;
|
||||
}
|
||||
} catch {
|
||||
// Try next file
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback for rolling releases (e.g. void) that have no version
|
||||
// field at all
|
||||
if (idWithoutVersion) {
|
||||
return idWithoutVersion;
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
"Failed to determine Linux distribution. " +
|
||||
"Could not read /etc/os-release or /usr/lib/os-release",
|
||||
|
||||
+55
-8
@@ -2,7 +2,12 @@ import * as core from "@actions/core";
|
||||
import * as tc from "@actions/tool-cache";
|
||||
import * as pep440 from "@renovatebot/pep440";
|
||||
import * as semver from "semver";
|
||||
import { getAllVersions, getLatestVersion } from "../download/manifest";
|
||||
import {
|
||||
getAllVersions,
|
||||
getFirstMatchingVersion,
|
||||
getLatestVersion,
|
||||
} from "../download/manifest";
|
||||
import { VERSIONS_MANIFEST_URL } from "../utils/constants";
|
||||
import type { ResolutionStrategy } from "../utils/inputs";
|
||||
import * as log from "../utils/logging";
|
||||
import {
|
||||
@@ -82,13 +87,26 @@ class RangeVersionResolver implements ConcreteVersionResolver {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const availableVersions = await getAllVersions(context.manifestUrl);
|
||||
core.debug(`Available versions: ${availableVersions}`);
|
||||
|
||||
const resolvedVersion =
|
||||
context.resolutionStrategy === "lowest"
|
||||
? minSatisfying(availableVersions, context.parsedSpecifier.normalized)
|
||||
: maxSatisfying(availableVersions, context.parsedSpecifier.normalized);
|
||||
let resolvedVersion: string | undefined;
|
||||
if (
|
||||
context.resolutionStrategy === "highest" &&
|
||||
(context.manifestUrl === undefined ||
|
||||
context.manifestUrl === VERSIONS_MANIFEST_URL)
|
||||
) {
|
||||
resolvedVersion = await findHighestSatisfyingVersion(
|
||||
context.parsedSpecifier.normalized,
|
||||
);
|
||||
} else {
|
||||
const availableVersions = await getAllVersions(context.manifestUrl);
|
||||
core.debug(`Available versions: ${availableVersions}`);
|
||||
resolvedVersion =
|
||||
context.resolutionStrategy === "lowest"
|
||||
? minSatisfying(availableVersions, context.parsedSpecifier.normalized)
|
||||
: maxSatisfying(
|
||||
availableVersions,
|
||||
context.parsedSpecifier.normalized,
|
||||
);
|
||||
}
|
||||
|
||||
if (resolvedVersion === undefined) {
|
||||
throw new Error(`No version found for ${context.parsedSpecifier.raw}`);
|
||||
@@ -141,6 +159,35 @@ export async function resolveVersion(
|
||||
throw new Error(`No version found for ${versionInput}`);
|
||||
}
|
||||
|
||||
async function findHighestSatisfyingVersion(
|
||||
versionSpecifier: string,
|
||||
): Promise<string | undefined> {
|
||||
// This fast path assumes uv releases are semver-monotonic: newer manifest
|
||||
// entries always have higher versions, with no lower-version backports.
|
||||
const semverRange = semver.validRange(versionSpecifier);
|
||||
if (semverRange !== null) {
|
||||
const semverMatch = await getFirstMatchingVersion((version) =>
|
||||
semver.satisfies(version, semverRange),
|
||||
);
|
||||
if (semverMatch !== undefined) {
|
||||
core.debug(
|
||||
`Found a version that satisfies the semver range: ${semverMatch}`,
|
||||
);
|
||||
return semverMatch;
|
||||
}
|
||||
}
|
||||
|
||||
const pep440Match = await getFirstMatchingVersion((version) =>
|
||||
pep440.satisfies(version, versionSpecifier),
|
||||
);
|
||||
if (pep440Match !== undefined) {
|
||||
core.debug(
|
||||
`Found a version that satisfies the pep440 specifier: ${pep440Match}`,
|
||||
);
|
||||
}
|
||||
return pep440Match;
|
||||
}
|
||||
|
||||
function maxSatisfying(
|
||||
versions: string[],
|
||||
version: string,
|
||||
|
||||
Reference in New Issue
Block a user