Files
setup-uv/src/setup-uv.ts
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

225 lines
6.3 KiB
TypeScript
Raw Normal View History

2024-09-05 08:06:45 -04:00
import * as core from "@actions/core";
import * as path from "node:path";
2024-09-05 08:06:45 -04:00
import {
tryGetFromToolCache,
resolveVersion,
2025-06-18 22:33:20 +02:00
downloadVersionFromGithub,
downloadVersionFromManifest,
2024-09-05 08:06:45 -04:00
} from "./download/download-version";
import { restoreCache } from "./cache/restore-cache";
2024-08-23 23:58:26 +02:00
2024-09-05 08:06:45 -04:00
import {
type Architecture,
2024-09-05 08:06:45 -04:00
getArch,
getPlatform,
type Platform,
2024-09-05 08:06:45 -04:00
} from "./utils/platforms";
2024-08-23 23:58:26 +02:00
import {
activateEnvironment as activateEnvironmentInput,
2024-08-23 23:58:26 +02:00
cacheLocalPath,
checkSum,
2025-03-16 22:15:17 +01:00
ignoreEmptyWorkdir,
2024-08-23 23:58:26 +02:00
enableCache,
githubToken,
2024-11-28 21:41:37 +01:00
pythonVersion,
2024-09-21 10:14:36 +02:00
toolBinDir,
toolDir,
version as versionInput,
workingDirectory,
2025-05-21 01:36:07 +08:00
serverUrl,
2025-06-18 22:33:20 +02:00
manifestFile,
2024-09-05 08:06:45 -04:00
} from "./utils/inputs";
import * as exec from "@actions/exec";
import fs from "node:fs";
import { getUvVersionFromConfigFile } from "./utils/config-file";
2024-08-23 23:58:26 +02:00
async function run(): Promise<void> {
2025-03-16 22:15:17 +01:00
detectEmptyWorkdir();
2025-02-17 10:32:34 +01:00
const platform = await getPlatform();
2024-09-05 08:06:45 -04:00
const arch = getArch();
2024-08-23 23:58:26 +02:00
try {
if (platform === undefined) {
2024-09-05 08:06:45 -04:00
throw new Error(`Unsupported platform: ${process.platform}`);
2024-08-23 23:58:26 +02:00
}
if (arch === undefined) {
2024-09-05 08:06:45 -04:00
throw new Error(`Unsupported architecture: ${process.arch}`);
2024-08-23 23:58:26 +02:00
}
const setupResult = await setupUv(platform, arch, checkSum, githubToken);
2024-08-23 23:58:26 +02:00
2024-09-21 10:14:36 +02:00
addToolBinToPath();
addUvToPathAndOutput(setupResult.uvDir);
2024-09-21 10:14:36 +02:00
setToolDir();
setupPython();
await activateEnvironment();
2024-09-05 08:06:45 -04:00
addMatchers();
setCacheDir(cacheLocalPath);
2024-08-23 23:58:26 +02:00
2024-11-28 21:41:37 +01:00
core.setOutput("uv-version", setupResult.version);
core.info(`Successfully installed uv version ${setupResult.version}`);
2024-08-23 23:58:26 +02:00
if (enableCache) {
2024-12-22 12:12:29 +01:00
await restoreCache();
2024-08-23 23:58:26 +02:00
}
2024-09-18 11:29:09 +02:00
process.exit(0);
2024-08-23 23:58:26 +02:00
} catch (err) {
2024-09-05 08:06:45 -04:00
core.setFailed((err as Error).message);
2024-08-23 23:58:26 +02:00
}
}
2025-03-16 22:15:17 +01:00
function detectEmptyWorkdir(): void {
if (fs.readdirSync(".").length === 0) {
if (ignoreEmptyWorkdir) {
core.info(
"Empty workdir detected. Ignoring because ignore-empty-workdir is enabled",
);
} else {
core.warning(
"Empty workdir detected. This may cause unexpected behavior. You can enable ignore-empty-workdir to mute this warning.",
);
}
}
}
2024-08-23 23:58:26 +02:00
async function setupUv(
platform: Platform,
arch: Architecture,
checkSum: string | undefined,
2024-09-18 11:29:09 +02:00
githubToken: string,
2024-09-05 08:06:45 -04:00
): Promise<{ uvDir: string; version: string }> {
const resolvedVersion = await determineVersion(manifestFile);
const toolCacheResult = tryGetFromToolCache(arch, resolvedVersion);
if (toolCacheResult.installedPath) {
core.info(`Found uv in tool-cache for ${toolCacheResult.version}`);
return {
uvDir: toolCacheResult.installedPath,
version: toolCacheResult.version,
};
2024-08-23 23:58:26 +02:00
}
2025-06-18 22:33:20 +02:00
let downloadVersionResult: { version: string; cachedToolDir: string };
if (serverUrl !== "https://github.com") {
core.warning(
"The input server-url is deprecated. Please use manifest-file instead.",
);
downloadVersionResult = await downloadVersionFromGithub(
serverUrl,
platform,
arch,
resolvedVersion,
checkSum,
githubToken,
);
} else {
downloadVersionResult = await downloadVersionFromManifest(
manifestFile,
platform,
arch,
resolvedVersion,
checkSum,
githubToken,
);
}
return {
uvDir: downloadVersionResult.cachedToolDir,
version: downloadVersionResult.version,
};
2024-08-23 23:58:26 +02:00
}
async function determineVersion(
manifestFile: string | undefined,
): Promise<string> {
if (versionInput !== "") {
return await resolveVersion(versionInput, manifestFile, githubToken);
}
const versionFromUvToml = getUvVersionFromConfigFile(
`${workingDirectory}${path.sep}uv.toml`,
);
const versionFromPyproject = getUvVersionFromConfigFile(
`${workingDirectory}${path.sep}pyproject.toml`,
);
if (versionFromUvToml === undefined && versionFromPyproject === undefined) {
core.info(
"Could not determine uv version from uv.toml or pyproject.toml. Falling back to latest.",
);
}
return await resolveVersion(
versionFromUvToml || versionFromPyproject || "latest",
manifestFile,
githubToken,
);
}
2025-03-21 13:44:23 +01:00
function addUvToPathAndOutput(cachedPath: string): void {
core.setOutput("uv-path", `${cachedPath}${path.sep}uv`);
core.setOutput("uvx-path", `${cachedPath}${path.sep}uvx`);
2024-09-05 08:06:45 -04:00
core.addPath(cachedPath);
core.info(`Added ${cachedPath} to the path`);
2024-08-23 23:58:26 +02:00
}
2024-09-21 10:14:36 +02:00
function addToolBinToPath(): void {
if (toolBinDir !== undefined) {
core.exportVariable("UV_TOOL_BIN_DIR", toolBinDir);
core.info(`Set UV_TOOL_BIN_DIR to ${toolBinDir}`);
core.addPath(toolBinDir);
core.info(`Added ${toolBinDir} to the path`);
} else {
if (process.env.XDG_BIN_HOME !== undefined) {
core.addPath(process.env.XDG_BIN_HOME);
core.info(`Added ${process.env.XDG_BIN_HOME} to the path`);
} else if (process.env.XDG_DATA_HOME !== undefined) {
core.addPath(`${process.env.XDG_DATA_HOME}/../bin`);
core.info(`Added ${process.env.XDG_DATA_HOME}/../bin to the path`);
} else {
core.addPath(`${process.env.HOME}/.local/bin`);
core.info(`Added ${process.env.HOME}/.local/bin to the path`);
}
}
}
function setToolDir(): void {
if (toolDir !== undefined) {
core.exportVariable("UV_TOOL_DIR", toolDir);
core.info(`Set UV_TOOL_DIR to ${toolDir}`);
}
}
function setupPython(): void {
2024-11-28 21:41:37 +01:00
if (pythonVersion !== "") {
core.exportVariable("UV_PYTHON", pythonVersion);
core.info(`Set UV_PYTHON to ${pythonVersion}`);
}
}
async function activateEnvironment(): Promise<void> {
if (activateEnvironmentInput) {
const execArgs = ["venv", ".venv", "--directory", workingDirectory];
core.info("Activating python venv...");
2025-04-17 21:02:21 +02:00
await exec.exec("uv", execArgs);
let venvBinPath = `${workingDirectory}${path.sep}.venv${path.sep}bin`;
if (process.platform === "win32") {
venvBinPath = `${workingDirectory}${path.sep}.venv${path.sep}Scripts`;
}
core.addPath(path.resolve(venvBinPath));
core.exportVariable(
"VIRTUAL_ENV",
path.resolve(`${workingDirectory}${path.sep}.venv`),
);
2024-11-28 21:41:37 +01:00
}
}
2024-08-23 23:58:26 +02:00
function setCacheDir(cacheLocalPath: string): void {
2024-09-05 08:06:45 -04:00
core.exportVariable("UV_CACHE_DIR", cacheLocalPath);
core.info(`Set UV_CACHE_DIR to ${cacheLocalPath}`);
2024-08-23 23:58:26 +02:00
}
function addMatchers(): void {
2024-09-05 08:06:45 -04:00
const matchersPath = path.join(__dirname, `..${path.sep}..`, ".github");
core.info(`##[add-matcher]${path.join(matchersPath, "python.json")}`);
2024-08-23 23:58:26 +02:00
}
2024-09-05 08:06:45 -04:00
run();