mirror of
https://github.com/astral-sh/setup-uv.git
synced 2026-02-17 22:41:45 +00:00
chore: normalize venv-path and warn when unused
- Normalize venv-path and trim trailing separators - Improve activation log message - Warn when venv-path is set without activate-environment - Add test coverage for trailing slash + warning
This commit is contained in:
parent
4b51b416f8
commit
45fe5a27c5
5 changed files with 84 additions and 8 deletions
|
|
@ -5,6 +5,7 @@ jest.mock("@actions/core", () => {
|
||||||
(name: string) => (mockInputs[name] ?? "") === "true",
|
(name: string) => (mockInputs[name] ?? "") === "true",
|
||||||
),
|
),
|
||||||
getInput: jest.fn((name: string) => mockInputs[name] ?? ""),
|
getInput: jest.fn((name: string) => mockInputs[name] ?? ""),
|
||||||
|
warning: jest.fn(),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -24,6 +25,7 @@ const ORIGINAL_HOME = process.env.HOME;
|
||||||
describe("cacheDependencyGlob", () => {
|
describe("cacheDependencyGlob", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.resetModules();
|
jest.resetModules();
|
||||||
|
jest.clearAllMocks();
|
||||||
mockInputs = {};
|
mockInputs = {};
|
||||||
process.env.HOME = "/home/testuser";
|
process.env.HOME = "/home/testuser";
|
||||||
});
|
});
|
||||||
|
|
@ -88,6 +90,7 @@ describe("cacheDependencyGlob", () => {
|
||||||
describe("venvPath", () => {
|
describe("venvPath", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.resetModules();
|
jest.resetModules();
|
||||||
|
jest.clearAllMocks();
|
||||||
mockInputs = {};
|
mockInputs = {};
|
||||||
process.env.HOME = "/home/testuser";
|
process.env.HOME = "/home/testuser";
|
||||||
});
|
});
|
||||||
|
|
@ -104,13 +107,23 @@ describe("venvPath", () => {
|
||||||
|
|
||||||
it("resolves a relative venv-path", async () => {
|
it("resolves a relative venv-path", async () => {
|
||||||
mockInputs["working-directory"] = "/workspace";
|
mockInputs["working-directory"] = "/workspace";
|
||||||
|
mockInputs["activate-environment"] = "true";
|
||||||
mockInputs["venv-path"] = "custom-venv";
|
mockInputs["venv-path"] = "custom-venv";
|
||||||
const { venvPath } = await import("../../src/utils/inputs");
|
const { venvPath } = await import("../../src/utils/inputs");
|
||||||
expect(venvPath).toBe("/workspace/custom-venv");
|
expect(venvPath).toBe("/workspace/custom-venv");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("normalizes venv-path with trailing slash", async () => {
|
||||||
|
mockInputs["working-directory"] = "/workspace";
|
||||||
|
mockInputs["activate-environment"] = "true";
|
||||||
|
mockInputs["venv-path"] = "custom-venv/";
|
||||||
|
const { venvPath } = await import("../../src/utils/inputs");
|
||||||
|
expect(venvPath).toBe("/workspace/custom-venv");
|
||||||
|
});
|
||||||
|
|
||||||
it("keeps an absolute venv-path unchanged", async () => {
|
it("keeps an absolute venv-path unchanged", async () => {
|
||||||
mockInputs["working-directory"] = "/workspace";
|
mockInputs["working-directory"] = "/workspace";
|
||||||
|
mockInputs["activate-environment"] = "true";
|
||||||
mockInputs["venv-path"] = "/tmp/custom-venv";
|
mockInputs["venv-path"] = "/tmp/custom-venv";
|
||||||
const { venvPath } = await import("../../src/utils/inputs");
|
const { venvPath } = await import("../../src/utils/inputs");
|
||||||
expect(venvPath).toBe("/tmp/custom-venv");
|
expect(venvPath).toBe("/tmp/custom-venv");
|
||||||
|
|
@ -118,8 +131,29 @@ describe("venvPath", () => {
|
||||||
|
|
||||||
it("expands tilde in venv-path", async () => {
|
it("expands tilde in venv-path", async () => {
|
||||||
mockInputs["working-directory"] = "/workspace";
|
mockInputs["working-directory"] = "/workspace";
|
||||||
|
mockInputs["activate-environment"] = "true";
|
||||||
mockInputs["venv-path"] = "~/.venv";
|
mockInputs["venv-path"] = "~/.venv";
|
||||||
const { venvPath } = await import("../../src/utils/inputs");
|
const { venvPath } = await import("../../src/utils/inputs");
|
||||||
expect(venvPath).toBe("/home/testuser/.venv");
|
expect(venvPath).toBe("/home/testuser/.venv");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("warns when venv-path is set but activate-environment is false", async () => {
|
||||||
|
mockInputs["working-directory"] = "/workspace";
|
||||||
|
mockInputs["venv-path"] = "custom-venv";
|
||||||
|
|
||||||
|
const { activateEnvironment, venvPath } = await import(
|
||||||
|
"../../src/utils/inputs"
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(activateEnvironment).toBe(false);
|
||||||
|
expect(venvPath).toBe("/workspace/custom-venv");
|
||||||
|
|
||||||
|
const mockedCore = jest.requireMock("@actions/core") as {
|
||||||
|
warning: jest.Mock;
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(mockedCore.warning).toHaveBeenCalledWith(
|
||||||
|
"venv-path is only used when activate-environment is true",
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
17
dist/save-cache/index.js
generated
vendored
17
dist/save-cache/index.js
generated
vendored
|
|
@ -91079,10 +91079,13 @@ function getVersionFile() {
|
||||||
function getVenvPath() {
|
function getVenvPath() {
|
||||||
const venvPathInput = core.getInput("venv-path");
|
const venvPathInput = core.getInput("venv-path");
|
||||||
if (venvPathInput !== "") {
|
if (venvPathInput !== "") {
|
||||||
|
if (!exports.activateEnvironment) {
|
||||||
|
core.warning("venv-path is only used when activate-environment is true");
|
||||||
|
}
|
||||||
const tildeExpanded = expandTilde(venvPathInput);
|
const tildeExpanded = expandTilde(venvPathInput);
|
||||||
return resolveRelativePath(tildeExpanded);
|
return normalizePath(resolveRelativePath(tildeExpanded));
|
||||||
}
|
}
|
||||||
return resolveRelativePath(".venv");
|
return normalizePath(resolveRelativePath(".venv"));
|
||||||
}
|
}
|
||||||
function getEnableCache() {
|
function getEnableCache() {
|
||||||
const enableCacheInput = core.getInput("enable-cache");
|
const enableCacheInput = core.getInput("enable-cache");
|
||||||
|
|
@ -91212,6 +91215,16 @@ function expandTilde(input) {
|
||||||
}
|
}
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
function normalizePath(inputPath) {
|
||||||
|
const normalized = node_path_1.default.normalize(inputPath);
|
||||||
|
const root = node_path_1.default.parse(normalized).root;
|
||||||
|
// Remove any trailing path separators, except when the whole path is the root.
|
||||||
|
let trimmed = normalized;
|
||||||
|
while (trimmed.length > root.length && trimmed.endsWith(node_path_1.default.sep)) {
|
||||||
|
trimmed = trimmed.slice(0, -1);
|
||||||
|
}
|
||||||
|
return trimmed;
|
||||||
|
}
|
||||||
function resolveRelativePath(inputPath) {
|
function resolveRelativePath(inputPath) {
|
||||||
const hasNegation = inputPath.startsWith("!");
|
const hasNegation = inputPath.startsWith("!");
|
||||||
const pathWithoutNegation = hasNegation ? inputPath.substring(1) : inputPath;
|
const pathWithoutNegation = hasNegation ? inputPath.substring(1) : inputPath;
|
||||||
|
|
|
||||||
19
dist/setup/index.js
generated
vendored
19
dist/setup/index.js
generated
vendored
|
|
@ -96532,7 +96532,7 @@ async function activateEnvironment() {
|
||||||
if (process.env.UV_NO_MODIFY_PATH !== undefined) {
|
if (process.env.UV_NO_MODIFY_PATH !== undefined) {
|
||||||
throw new Error("UV_NO_MODIFY_PATH and activate-environment cannot be used together.");
|
throw new Error("UV_NO_MODIFY_PATH and activate-environment cannot be used together.");
|
||||||
}
|
}
|
||||||
core.info(`Activating python venv at ${inputs_1.venvPath}...`);
|
core.info(`Creating and activating python venv at ${inputs_1.venvPath}...`);
|
||||||
await exec.exec("uv", ["venv", inputs_1.venvPath, "--directory", inputs_1.workingDirectory]);
|
await exec.exec("uv", ["venv", inputs_1.venvPath, "--directory", inputs_1.workingDirectory]);
|
||||||
let venvBinPath = `${inputs_1.venvPath}${path.sep}bin`;
|
let venvBinPath = `${inputs_1.venvPath}${path.sep}bin`;
|
||||||
if (process.platform === "win32") {
|
if (process.platform === "win32") {
|
||||||
|
|
@ -96759,10 +96759,13 @@ function getVersionFile() {
|
||||||
function getVenvPath() {
|
function getVenvPath() {
|
||||||
const venvPathInput = core.getInput("venv-path");
|
const venvPathInput = core.getInput("venv-path");
|
||||||
if (venvPathInput !== "") {
|
if (venvPathInput !== "") {
|
||||||
|
if (!exports.activateEnvironment) {
|
||||||
|
core.warning("venv-path is only used when activate-environment is true");
|
||||||
|
}
|
||||||
const tildeExpanded = expandTilde(venvPathInput);
|
const tildeExpanded = expandTilde(venvPathInput);
|
||||||
return resolveRelativePath(tildeExpanded);
|
return normalizePath(resolveRelativePath(tildeExpanded));
|
||||||
}
|
}
|
||||||
return resolveRelativePath(".venv");
|
return normalizePath(resolveRelativePath(".venv"));
|
||||||
}
|
}
|
||||||
function getEnableCache() {
|
function getEnableCache() {
|
||||||
const enableCacheInput = core.getInput("enable-cache");
|
const enableCacheInput = core.getInput("enable-cache");
|
||||||
|
|
@ -96892,6 +96895,16 @@ function expandTilde(input) {
|
||||||
}
|
}
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
function normalizePath(inputPath) {
|
||||||
|
const normalized = node_path_1.default.normalize(inputPath);
|
||||||
|
const root = node_path_1.default.parse(normalized).root;
|
||||||
|
// Remove any trailing path separators, except when the whole path is the root.
|
||||||
|
let trimmed = normalized;
|
||||||
|
while (trimmed.length > root.length && trimmed.endsWith(node_path_1.default.sep)) {
|
||||||
|
trimmed = trimmed.slice(0, -1);
|
||||||
|
}
|
||||||
|
return trimmed;
|
||||||
|
}
|
||||||
function resolveRelativePath(inputPath) {
|
function resolveRelativePath(inputPath) {
|
||||||
const hasNegation = inputPath.startsWith("!");
|
const hasNegation = inputPath.startsWith("!");
|
||||||
const pathWithoutNegation = hasNegation ? inputPath.substring(1) : inputPath;
|
const pathWithoutNegation = hasNegation ? inputPath.substring(1) : inputPath;
|
||||||
|
|
|
||||||
|
|
@ -271,7 +271,7 @@ async function activateEnvironment(): Promise<void> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
core.info(`Activating python venv at ${venvPath}...`);
|
core.info(`Creating and activating python venv at ${venvPath}...`);
|
||||||
await exec.exec("uv", ["venv", venvPath, "--directory", workingDirectory]);
|
await exec.exec("uv", ["venv", venvPath, "--directory", workingDirectory]);
|
||||||
|
|
||||||
let venvBinPath = `${venvPath}${path.sep}bin`;
|
let venvBinPath = `${venvPath}${path.sep}bin`;
|
||||||
|
|
|
||||||
|
|
@ -49,10 +49,13 @@ function getVersionFile(): string {
|
||||||
function getVenvPath(): string {
|
function getVenvPath(): string {
|
||||||
const venvPathInput = core.getInput("venv-path");
|
const venvPathInput = core.getInput("venv-path");
|
||||||
if (venvPathInput !== "") {
|
if (venvPathInput !== "") {
|
||||||
|
if (!activateEnvironment) {
|
||||||
|
core.warning("venv-path is only used when activate-environment is true");
|
||||||
|
}
|
||||||
const tildeExpanded = expandTilde(venvPathInput);
|
const tildeExpanded = expandTilde(venvPathInput);
|
||||||
return resolveRelativePath(tildeExpanded);
|
return normalizePath(resolveRelativePath(tildeExpanded));
|
||||||
}
|
}
|
||||||
return resolveRelativePath(".venv");
|
return normalizePath(resolveRelativePath(".venv"));
|
||||||
}
|
}
|
||||||
|
|
||||||
function getEnableCache(): boolean {
|
function getEnableCache(): boolean {
|
||||||
|
|
@ -204,6 +207,19 @@ function expandTilde(input: string): string {
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizePath(inputPath: string): string {
|
||||||
|
const normalized = path.normalize(inputPath);
|
||||||
|
const root = path.parse(normalized).root;
|
||||||
|
|
||||||
|
// Remove any trailing path separators, except when the whole path is the root.
|
||||||
|
let trimmed = normalized;
|
||||||
|
while (trimmed.length > root.length && trimmed.endsWith(path.sep)) {
|
||||||
|
trimmed = trimmed.slice(0, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return trimmed;
|
||||||
|
}
|
||||||
|
|
||||||
function resolveRelativePath(inputPath: string): string {
|
function resolveRelativePath(inputPath: string): string {
|
||||||
const hasNegation = inputPath.startsWith("!");
|
const hasNegation = inputPath.startsWith("!");
|
||||||
const pathWithoutNegation = hasNegation ? inputPath.substring(1) : inputPath;
|
const pathWithoutNegation = hasNegation ? inputPath.substring(1) : inputPath;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue