mirror of
https://github.com/astral-sh/setup-uv.git
synced 2025-08-31 17:16:56 +00:00
committed by
GitHub
parent
fce199e243
commit
adeb28643f
17
.github/workflows/test.yml
vendored
17
.github/workflows/test.yml
vendored
@ -187,6 +187,22 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
|
||||
test-tool-versions-file-version:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Install from .tools-versions file
|
||||
id: setup-uv
|
||||
uses: ./
|
||||
with:
|
||||
version-file: "__tests__/fixtures/.tool-versions"
|
||||
- name: Correct version gets installed
|
||||
run: |
|
||||
if [ "$(uv --version)" != "uv 0.5.15" ]; then
|
||||
echo "Wrong uv version: $(uv --version)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
test-checksum:
|
||||
runs-on: ${{ matrix.inputs.os }}
|
||||
strategy:
|
||||
@ -635,6 +651,7 @@ jobs:
|
||||
- test-uv-file-version
|
||||
- test-version-file-version
|
||||
- test-version-file-hash-version
|
||||
- test-tool-versions-file-version
|
||||
- test-checksum
|
||||
- test-with-explicit-token
|
||||
- test-uvx
|
||||
|
@ -100,6 +100,8 @@ You can use the `version-file` input to specify a file that contains the version
|
||||
This can either be a `pyproject.toml` or `uv.toml` file which defines a `required-version` or
|
||||
uv defined as a dependency in `pyproject.toml` or `requirements.txt`.
|
||||
|
||||
[asdf](https://asdf-vm.com/) `.tool-versions` is also supported, but without the `ref` syntax.
|
||||
|
||||
```yaml
|
||||
- name: Install uv based on the version defined in pyproject.toml
|
||||
uses: astral-sh/setup-uv@v6
|
||||
|
1
__tests__/fixtures/.tool-versions
Normal file
1
__tests__/fixtures/.tool-versions
Normal file
@ -0,0 +1 @@
|
||||
uv 0.5.15
|
115
__tests__/version/tool-versions-file.test.ts
Normal file
115
__tests__/version/tool-versions-file.test.ts
Normal file
@ -0,0 +1,115 @@
|
||||
jest.mock("node:fs");
|
||||
jest.mock("@actions/core", () => ({
|
||||
warning: jest.fn(),
|
||||
}));
|
||||
|
||||
import fs from "node:fs";
|
||||
import * as core from "@actions/core";
|
||||
import { beforeEach, describe, expect, it, jest } from "@jest/globals";
|
||||
import { getUvVersionFromToolVersions } from "../../src/version/tool-versions-file";
|
||||
|
||||
const mockedFs = fs as jest.Mocked<typeof fs>;
|
||||
const mockedCore = core as jest.Mocked<typeof core>;
|
||||
|
||||
describe("getUvVersionFromToolVersions", () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it("should return undefined for non-.tool-versions files", () => {
|
||||
const result = getUvVersionFromToolVersions("package.json");
|
||||
expect(result).toBeUndefined();
|
||||
expect(mockedFs.readFileSync).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should return version for valid uv entry", () => {
|
||||
const fileContent = "python 3.11.0\nuv 0.1.0\nnodejs 18.0.0";
|
||||
mockedFs.readFileSync.mockReturnValue(fileContent);
|
||||
|
||||
const result = getUvVersionFromToolVersions(".tool-versions");
|
||||
|
||||
expect(result).toBe("0.1.0");
|
||||
expect(mockedFs.readFileSync).toHaveBeenCalledWith(
|
||||
".tool-versions",
|
||||
"utf8",
|
||||
);
|
||||
});
|
||||
|
||||
it("should return version for uv entry with v prefix", () => {
|
||||
const fileContent = "uv v0.2.0";
|
||||
mockedFs.readFileSync.mockReturnValue(fileContent);
|
||||
|
||||
const result = getUvVersionFromToolVersions(".tool-versions");
|
||||
|
||||
expect(result).toBe("0.2.0");
|
||||
});
|
||||
|
||||
it("should handle whitespace around uv entry", () => {
|
||||
const fileContent = " uv 0.3.0 ";
|
||||
mockedFs.readFileSync.mockReturnValue(fileContent);
|
||||
|
||||
const result = getUvVersionFromToolVersions(".tool-versions");
|
||||
|
||||
expect(result).toBe("0.3.0");
|
||||
});
|
||||
|
||||
it("should skip commented lines", () => {
|
||||
const fileContent = "# uv 0.1.0\npython 3.11.0\nuv 0.2.0";
|
||||
mockedFs.readFileSync.mockReturnValue(fileContent);
|
||||
|
||||
const result = getUvVersionFromToolVersions(".tool-versions");
|
||||
|
||||
expect(result).toBe("0.2.0");
|
||||
});
|
||||
|
||||
it("should return first matching uv version", () => {
|
||||
const fileContent = "uv 0.1.0\npython 3.11.0\nuv 0.2.0";
|
||||
mockedFs.readFileSync.mockReturnValue(fileContent);
|
||||
|
||||
const result = getUvVersionFromToolVersions(".tool-versions");
|
||||
|
||||
expect(result).toBe("0.1.0");
|
||||
});
|
||||
|
||||
it("should return undefined when no uv entry found", () => {
|
||||
const fileContent = "python 3.11.0\nnodejs 18.0.0";
|
||||
mockedFs.readFileSync.mockReturnValue(fileContent);
|
||||
|
||||
const result = getUvVersionFromToolVersions(".tool-versions");
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should return undefined for empty file", () => {
|
||||
mockedFs.readFileSync.mockReturnValue("");
|
||||
|
||||
const result = getUvVersionFromToolVersions(".tool-versions");
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should warn and return undefined for ref syntax", () => {
|
||||
const fileContent = "uv ref:main";
|
||||
mockedFs.readFileSync.mockReturnValue(fileContent);
|
||||
|
||||
const result = getUvVersionFromToolVersions(".tool-versions");
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
expect(mockedCore.warning).toHaveBeenCalledWith(
|
||||
"The ref syntax of .tool-versions is not supported. Please use a released version instead.",
|
||||
);
|
||||
});
|
||||
|
||||
it("should handle file path with .tool-versions extension", () => {
|
||||
const fileContent = "uv 0.1.0";
|
||||
mockedFs.readFileSync.mockReturnValue(fileContent);
|
||||
|
||||
const result = getUvVersionFromToolVersions("path/to/.tool-versions");
|
||||
|
||||
expect(result).toBe("0.1.0");
|
||||
expect(mockedFs.readFileSync).toHaveBeenCalledWith(
|
||||
"path/to/.tool-versions",
|
||||
"utf8",
|
||||
);
|
||||
});
|
||||
});
|
78
dist/setup/index.js
generated
vendored
78
dist/setup/index.js
generated
vendored
@ -127216,6 +127216,7 @@ const node_fs_1 = __importDefault(__nccwpck_require__(73024));
|
||||
const core = __importStar(__nccwpck_require__(37484));
|
||||
const config_file_1 = __nccwpck_require__(9931);
|
||||
const requirements_file_1 = __nccwpck_require__(4569);
|
||||
const tool_versions_file_1 = __nccwpck_require__(4895);
|
||||
function getUvVersionFromFile(filePath) {
|
||||
core.info(`Trying to find version for uv in: ${filePath}`);
|
||||
if (!node_fs_1.default.existsSync(filePath)) {
|
||||
@ -127224,7 +127225,10 @@ function getUvVersionFromFile(filePath) {
|
||||
}
|
||||
let uvVersion;
|
||||
try {
|
||||
uvVersion = (0, config_file_1.getRequiredVersionFromConfigFile)(filePath);
|
||||
uvVersion = (0, tool_versions_file_1.getUvVersionFromToolVersions)(filePath);
|
||||
if (uvVersion === undefined) {
|
||||
uvVersion = (0, config_file_1.getRequiredVersionFromConfigFile)(filePath);
|
||||
}
|
||||
if (uvVersion === undefined) {
|
||||
uvVersion = (0, requirements_file_1.getUvVersionFromRequirementsFile)(filePath);
|
||||
}
|
||||
@ -127244,6 +127248,78 @@ function getUvVersionFromFile(filePath) {
|
||||
}
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 4895:
|
||||
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
||||
|
||||
"use strict";
|
||||
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || (function () {
|
||||
var ownKeys = function(o) {
|
||||
ownKeys = Object.getOwnPropertyNames || function (o) {
|
||||
var ar = [];
|
||||
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
||||
return ar;
|
||||
};
|
||||
return ownKeys(o);
|
||||
};
|
||||
return function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
})();
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.getUvVersionFromToolVersions = getUvVersionFromToolVersions;
|
||||
const node_fs_1 = __importDefault(__nccwpck_require__(73024));
|
||||
const core = __importStar(__nccwpck_require__(37484));
|
||||
function getUvVersionFromToolVersions(filePath) {
|
||||
if (!filePath.endsWith(".tool-versions")) {
|
||||
return undefined;
|
||||
}
|
||||
const fileContents = node_fs_1.default.readFileSync(filePath, "utf8");
|
||||
const lines = fileContents.split("\n");
|
||||
for (const line of lines) {
|
||||
// Skip commented lines
|
||||
if (line.trim().startsWith("#")) {
|
||||
continue;
|
||||
}
|
||||
const match = line.match(/^\s*uv\s*v?\s*(?<version>[^\s]+)\s*$/);
|
||||
if (match) {
|
||||
const matchedVersion = match.groups?.version.trim();
|
||||
if (matchedVersion?.startsWith("ref")) {
|
||||
core.warning("The ref syntax of .tool-versions is not supported. Please use a released version instead.");
|
||||
return undefined;
|
||||
}
|
||||
return matchedVersion;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 42078:
|
||||
|
@ -2,6 +2,7 @@ import fs from "node:fs";
|
||||
import * as core from "@actions/core";
|
||||
import { getRequiredVersionFromConfigFile } from "./config-file";
|
||||
import { getUvVersionFromRequirementsFile } from "./requirements-file";
|
||||
import { getUvVersionFromToolVersions } from "./tool-versions-file";
|
||||
|
||||
export function getUvVersionFromFile(filePath: string): string | undefined {
|
||||
core.info(`Trying to find version for uv in: ${filePath}`);
|
||||
@ -11,7 +12,10 @@ export function getUvVersionFromFile(filePath: string): string | undefined {
|
||||
}
|
||||
let uvVersion: string | undefined;
|
||||
try {
|
||||
uvVersion = getRequiredVersionFromConfigFile(filePath);
|
||||
uvVersion = getUvVersionFromToolVersions(filePath);
|
||||
if (uvVersion === undefined) {
|
||||
uvVersion = getRequiredVersionFromConfigFile(filePath);
|
||||
}
|
||||
if (uvVersion === undefined) {
|
||||
uvVersion = getUvVersionFromRequirementsFile(filePath);
|
||||
}
|
||||
|
31
src/version/tool-versions-file.ts
Normal file
31
src/version/tool-versions-file.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import fs from "node:fs";
|
||||
import * as core from "@actions/core";
|
||||
|
||||
export function getUvVersionFromToolVersions(
|
||||
filePath: string,
|
||||
): string | undefined {
|
||||
if (!filePath.endsWith(".tool-versions")) {
|
||||
return undefined;
|
||||
}
|
||||
const fileContents = fs.readFileSync(filePath, "utf8");
|
||||
const lines = fileContents.split("\n");
|
||||
|
||||
for (const line of lines) {
|
||||
// Skip commented lines
|
||||
if (line.trim().startsWith("#")) {
|
||||
continue;
|
||||
}
|
||||
const match = line.match(/^\s*uv\s*v?\s*(?<version>[^\s]+)\s*$/);
|
||||
if (match) {
|
||||
const matchedVersion = match.groups?.version.trim();
|
||||
if (matchedVersion?.startsWith("ref")) {
|
||||
core.warning(
|
||||
"The ref syntax of .tool-versions is not supported. Please use a released version instead.",
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
return matchedVersion;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
Reference in New Issue
Block a user