Files
setup-uv/src/utils/platforms.ts
T
Hans Gaiser ed73b5df24
Release Drafter / ✏️ Draft release (push) Waiting to run
test / test-tool-install (macos-14) (push) Waiting to run
test / test-tool-install (macos-latest) (push) Waiting to run
test / test-default-version (macos-latest) (push) Waiting to run
test / test-default-version (windows-latest) (push) Waiting to run
test / test-tool-install (windows-latest) (push) Waiting to run
test / test-default-version (macos-14) (push) Waiting to run
test / test-checksum (map[checksum:a70cbfbf3bb5c08b2f84963b4f12c94e08fbb2468ba418a3bfe1066fbe9e7218 os:macos-latest]) (push) Waiting to run
test / test-python-version (macos-latest) (push) Waiting to run
test / test-python-version (windows-latest) (push) Waiting to run
test / test-activate-environment (macos-latest) (push) Waiting to run
test / test-activate-environment (windows-latest) (push) Waiting to run
test / test-activate-environment-custom-path (macos-latest) (push) Waiting to run
test / test-activate-environment-custom-path (windows-latest) (push) Waiting to run
test / test-cache-key-os-version (macos-14, macos-14) (push) Waiting to run
test / test-cache-key-os-version (macos-15, macos-15) (push) Waiting to run
test / test-cache-key-os-version (ubuntu-24.04, ubuntu-24.04) (push) Waiting to run
test / test-cache-key-os-version (windows-2022, windows-2022) (push) Waiting to run
test / test-cache-key-os-version (windows-2025, windows-2025) (push) Waiting to run
test / test-setup-cache (auto, windows-latest) (push) Waiting to run
test / test-setup-cache (false, windows-latest) (push) Waiting to run
test / test-setup-cache (true, windows-latest) (push) Waiting to run
test / test-restore-cache (auto, ubuntu-latest) (push) Blocked by required conditions
test / test-restore-cache (auto, windows-latest) (push) Blocked by required conditions
test / test-restore-cache (false, ubuntu-latest) (push) Blocked by required conditions
test / test-restore-cache (false, windows-latest) (push) Blocked by required conditions
test / test-restore-cache (true, ubuntu-latest) (push) Blocked by required conditions
test / test-restore-cache (true, windows-latest) (push) Blocked by required conditions
test / test-cache-local (map[expected-cache-dir:D:\a\_temp\setup-uv-cache os:windows-latest]) (push) Waiting to run
test / test-python-install-dir (map[expected-python-dir:D:\a\_temp\uv-python-dir os:windows-latest]) (push) Waiting to run
test / all-tests-passed (push) Blocked by required conditions
test / test-specific-version (map[expected-version:0.3.0 version-input:0.3.0]) (push) Failing after 1m7s
test / test-specific-version (map[expected-version:0.1.45 resolution-strategy:highest version-input:>=0.1,<0.2]) (push) Failing after 1m8s
test / test-uv-no-modify-path (push) Failing after 1m10s
test / test-specific-version (map[expected-version:0.1.0 resolution-strategy:lowest version-input:>=0.1.0,<0.2]) (push) Failing after 1m13s
test / test-default-version (ubuntu-latest) (push) Failing after 1m18s
test / test-specific-version (map[expected-version:0.3.2 version-input:0.3.2]) (push) Failing after 1m19s
test / test-specific-version (map[expected-version:0.3.5 version-input:0.3.x]) (push) Failing after 1m19s
test / test-malformed-pyproject-file-fallback (push) Failing after 1m16s
test / test-specific-version (map[expected-version:0.4.25 resolution-strategy:lowest version-input:>=0.4.25,<0.5]) (push) Failing after 1m20s
test / test-specific-version (map[expected-version:0.3.5 version-input:0.3]) (push) Failing after 1m20s
test / test-specific-version (map[expected-version:0.4.30 version-input:>=0.4.25,<0.5]) (push) Failing after 1m22s
test / test-specific-version (map[expected-version:0.4.25 resolution-strategy:lowest version-input:>=0.4.25]) (push) Failing after 1m23s
test / test-latest-version (>=0.8) (push) Failing after 1m18s
test / test-latest-version (latest) (push) Failing after 1m23s
test / test-from-working-directory-version (map[expected-version:0.5.14 working-directory:__tests__/fixtures/pyproject-toml-project]) (push) Failing after 1m23s
test / test-from-working-directory-version (map[expected-version:0.5.15 working-directory:__tests__/fixtures/uv-toml-project]) (push) Failing after 1m20s
test / test-version-file-version (map[expected-version:0.5.15 version-file:__tests__/fixtures/.tool-versions]) (push) Failing after 1m17s
test / test-with-explicit-token (push) Failing after 1m13s
test / test-debian-unstable (push) Failing after 3s
test / test-version-file-version (map[expected-version:0.8.3 version-file:__tests__/fixtures/uv-in-requirements-hash-txt-project/requirements.txt]) (push) Failing after 1m19s
test / test-uvx (push) Failing after 1m15s
test / test-checksum (map[checksum:4d9279ad5ca596b1e2d703901d508430eb07564dc4d8837de9e2fca9c90f8ecd os:ubuntu-latest]) (push) Failing after 1m20s
test / test-musl (push) Failing after 6s
test / test-version-file-version (map[expected-version:0.6.17 version-file:__tests__/fixtures/uv-in-requirements-txt-project/requirements.txt]) (push) Failing after 1m21s
test / test-tool-install (ubuntu-latest) (push) Failing after 35s
test / test-python-version (ubuntu-latest) (push) Failing after 20s
test / test-activate-environment-custom-path (ubuntu-latest) (push) Failing after 17s
test / test-activate-environment (ubuntu-latest) (push) Failing after 18s
test / test-activate-environment-no-project (push) Failing after 50s
CodeQL / Analyze (TypeScript) (push) Failing after 3m28s
test / test-setup-cache (auto, ubuntu-latest) (push) Failing after 53s
test / test-setup-cache (false, ubuntu-latest) (push) Failing after 53s
test / test-setup-cache (true, ubuntu-latest) (push) Failing after 53s
test / test-restore-cache-restore-cache-false (push) Has been skipped
test / test-setup-cache-restore-cache-false (push) Failing after 50s
test / test-setup-cache-requirements-txt (push) Failing after 54s
test / test-restore-cache-requirements-txt (push) Has been skipped
test / test-setup-cache-dependency-glob (push) Failing after 54s
test / test-restore-cache-dependency-glob (push) Has been skipped
test / test-setup-cache-save-cache-false (push) Failing after 54s
test / test-restore-cache-save-cache-false (push) Has been skipped
test / test-cache-local (map[expected-cache-dir:/home/runner/work/_temp/setup-uv-cache os:ubuntu-latest]) (push) Failing after 54s
test / test-cache-local-cache-disabled (push) Failing after 52s
test / test-cache-local-cache-disabled-but-explicit-path (push) Failing after 49s
test / test-cache-key-os-version (ubuntu-22.04, ubuntu-22.04) (push) Failing after 1m3s
test / test-no-python-version (push) Failing after 56s
test / test-custom-manifest-file (push) Failing after 22s
test / test-download-from-astral-mirror-false (push) Failing after 23s
test / test-absolute-path (push) Failing after 27s
test / test-cache-python-missing-managed-install-dir (push) Failing after 40s
test / test-cache-prune-force (push) Failing after 43s
test / test-python-install-dir (map[expected-python-dir:/home/runner/work/_temp/uv-python-dir os:ubuntu-latest]) (push) Failing after 42s
test / test-act (push) Failing after 42s
test / test-cache-dir-from-file (push) Failing after 48s
test / test-cache-python-installs (push) Failing after 47s
test / test-restore-python-installs (push) Has been skipped
test / test-relative-path (push) Failing after 52s
test / validate-typings (push) Failing after 3m37s
test / lint (push) Failing after 30m3s
fix: use BUILD_ID as backup for determining os version (#912)
On Arch Linux based runners, the setup fails with because
`/etc/os-release` does not contain `VERSION_ID` or `VERSION_CODENAME`.
It does contain a `BUILD_ID` which is set to `rolling`:

```sh
$ cat /etc/os-release
NAME="Arch Linux"
PRETTY_NAME="Arch Linux"
ID=arch
BUILD_ID=rolling
ANSI_COLOR="38;2;23;147;209"
HOME_URL="https://archlinux.org/"
DOCUMENTATION_URL="https://wiki.archlinux.org/"
SUPPORT_URL="https://bbs.archlinux.org/"
BUG_REPORT_URL="https://gitlab.archlinux.org/groups/archlinux/-/issues"
PRIVACY_POLICY_URL="https://terms.archlinux.org/docs/privacy-policy/"
LOGO=archlinux-logo
```

This PR makes `getLinuxOSNameVersion` return `arch-rolling`.

There is no update from arch that would change the returned value, so
the same cache will always be used. Is this an issue? I'm not sure. At
least it's better than crashing because `os-release` does not contain
the expected values :).
2026-06-09 13:12:37 +02:00

159 lines
4.2 KiB
TypeScript

import fs from "node:fs";
import os from "node:os";
import * as core from "@actions/core";
import * as exec from "@actions/exec";
export type Platform =
| "unknown-linux-gnu"
| "unknown-linux-musl"
| "unknown-linux-musleabihf"
| "apple-darwin"
| "pc-windows-msvc";
export type Architecture =
| "i686"
| "x86_64"
| "aarch64"
| "s390x"
| "riscv64gc"
| "powerpc64le";
export function getArch(): Architecture | undefined {
const arch = process.arch;
const archMapping: { [key: string]: Architecture } = {
arm64: "aarch64",
ia32: "i686",
ppc64: "powerpc64le",
riscv64: "riscv64gc",
s390x: "s390x",
x64: "x86_64",
};
if (arch in archMapping) {
return archMapping[arch];
}
}
export async function getPlatform(): Promise<Platform | undefined> {
const processPlatform = process.platform;
const platformMapping: { [key: string]: Platform } = {
darwin: "apple-darwin",
linux: "unknown-linux-gnu",
win32: "pc-windows-msvc",
};
if (processPlatform in platformMapping) {
const platform = platformMapping[processPlatform];
if (platform === "unknown-linux-gnu") {
const isMusl = await isMuslOs();
return isMusl ? "unknown-linux-musl" : platform;
}
return platform;
}
}
async function isMuslOs(): Promise<boolean> {
let stdOutput = "";
let errOutput = "";
const options: exec.ExecOptions = {
ignoreReturnCode: true,
listeners: {
stderr: (data: Buffer) => {
errOutput += data.toString();
},
stdout: (data: Buffer) => {
stdOutput += data.toString();
},
},
silent: !core.isDebug(),
};
try {
const execArgs = ["--version"];
await exec.exec("ldd", execArgs, options);
return stdOutput.includes("musl") || errOutput.includes("musl");
} catch (error) {
const err = error as Error;
core.warning(
`Failed to determine glibc or musl. Falling back to glibc. Error: ${err.message}`,
);
return false;
}
}
/**
* Returns OS name and version for cache key differentiation.
* Examples: "ubuntu-22.04", "macos-14", "windows-2022"
* Throws if OS detection fails.
*/
export function getOSNameVersion(): string {
const platform = process.platform;
if (platform === "linux") {
return getLinuxOSNameVersion();
}
if (platform === "darwin") {
return getMacOSNameVersion();
}
if (platform === "win32") {
return getWindowsNameVersion();
}
throw new Error(`Unsupported platform: ${platform}`);
}
function getLinuxOSNameVersion(): string {
const files = ["/etc/os-release", "/usr/lib/os-release"];
for (const file of files) {
try {
const content = fs.readFileSync(file, "utf8");
const id = parseOsReleaseValue(content, "ID");
const versionId = parseOsReleaseValue(content, "VERSION_ID");
// Fallback for rolling releases (debian:unstable/testing, arch, etc.)
// that don't have VERSION_ID but have VERSION_CODENAME or BUILD_ID
const versionCodename = parseOsReleaseValue(content, "VERSION_CODENAME");
const buildId = parseOsReleaseValue(content, "BUILD_ID");
if (id && versionId) {
return `${id}-${versionId}`;
}
if (id && versionCodename) {
return `${id}-${versionCodename}`;
}
if (id && buildId) {
return `${id}-${buildId}`;
}
} catch {
// Try next file
}
}
throw new Error(
"Failed to determine Linux distribution. " +
"Could not read /etc/os-release or /usr/lib/os-release",
);
}
function parseOsReleaseValue(content: string, key: string): string | undefined {
const regex = new RegExp(`^${key}=["']?([^"'\\n]*)["']?$`, "m");
const match = content.match(regex);
return match?.[1];
}
function getMacOSNameVersion(): string {
const darwinVersion = Number.parseInt(os.release().split(".")[0], 10);
if (Number.isNaN(darwinVersion)) {
throw new Error(`Failed to parse macOS version from: ${os.release()}`);
}
const macosVersion = darwinVersion - 9;
return `macos-${macosVersion}`;
}
function getWindowsNameVersion(): string {
const version = os.version();
const match = version.match(/Windows(?: Server)? (\d+)/);
if (!match) {
throw new Error(`Failed to parse Windows version from: ${version}`);
}
return `windows-${match[1]}`;
}