mirror of
https://github.com/astral-sh/setup-uv.git
synced 2026-03-06 01:16:48 +00:00
Debian unstable and testing don't have VERSION_ID in /etc/os-release. This change falls back to VERSION_CODENAME when VERSION_ID is missing, producing cache keys like 'debian-sid' for unstable. Fixes #773
153 lines
4.0 KiB
TypeScript
153 lines
4.0 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"
|
|
| "powerpc64le";
|
|
|
|
export function getArch(): Architecture | undefined {
|
|
const arch = process.arch;
|
|
const archMapping: { [key: string]: Architecture } = {
|
|
arm64: "aarch64",
|
|
ia32: "i686",
|
|
ppc64: "powerpc64le",
|
|
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
|
|
const versionCodename = parseOsReleaseValue(content, "VERSION_CODENAME");
|
|
|
|
if (id && versionId) {
|
|
return `${id}-${versionId}`;
|
|
}
|
|
if (id && versionCodename) {
|
|
return `${id}-${versionCodename}`;
|
|
}
|
|
} 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]}`;
|
|
}
|