mirror of
https://gitcode.com/gh_mirrors/se/setup-uv.git
synced 2026-07-02 18:17:52 +00:00
58b6d7b303
## Summary - Adds OS name and version (e.g., `ubuntu-22.04`, `macos-14`, `windows-2022`) to cache keys to prevent binary incompatibility when GitHub updates runner images - Fixes issue where cached uv binaries compiled against older glibc/library versions fail on newer runner OS versions ## Changes - Added `getOSNameVersion()` function to `src/utils/platforms.ts` with OS-specific detection for Linux (via `/etc/os-release`), macOS (Darwin kernel version mapping), and Windows - Updated cache key format to include OS version, bumped `CACHE_VERSION` to `"2"` - Added `cache-key` output to expose the generated cache key for debugging - Added `test-cache-key-os-version` job testing across multiple OS versions - Updated `docs/caching.md` with cache key documentation Closes #703
147 lines
3.7 KiB
TypeScript
147 lines
3.7 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");
|
|
|
|
if (id && versionId) {
|
|
return `${id}-${versionId}`;
|
|
}
|
|
} 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]}`;
|
|
}
|