feat: support uv.lock as a version-file source (#918)

Adds `uv.lock` as a supported `version-file` source. When `uv` is locked
as a
dependency in `uv.lock`, the action now installs the exact pinned
version,
closing the gap reported in #682.

This is useful for deterministic CI: the same uv version is used until
the
lockfile is updated, which avoids "CI worked yesterday, fails today"
drift and
reduces supply-chain exposure from auto-installing the latest release.

The implementation mirrors the existing `version-file` parsers — a new
`uv.lock`
entry in the parser registry reads the `[[package]]` whose `name = "uv"`
and
returns its locked `version`. Scoped to explicit `version-file:
uv.lock`;
workspace auto-detection is left as a possible follow-up to avoid
precedence
ambiguity with `uv.toml` / `pyproject.toml`.

Validation (local, Node 23; dist build is esbuild-deterministic):
- `npm run all` → build clean, biome clean, package clean, jest 77/77
- New tests: 3 unit (`uv-lock-file.test.ts`) + 1 integration — exact pin
resolves
  through the full pipeline (`uv.lock` → `0.8.17`)
- dist rebuilt + committed (single bundle, no spurious churn)

related: #682
This commit is contained in:
somaz
2026-06-19 14:08:57 +09:00
committed by GitHub
parent ca5ddd015e
commit 3faa3174e6
9 changed files with 124 additions and 11 deletions
+24
View File
@@ -0,0 +1,24 @@
import fs from "node:fs";
import * as toml from "smol-toml";
interface UvLockPackage {
name?: string;
version?: string;
}
interface UvLock {
package?: UvLockPackage[];
}
export function getUvVersionFromUvLock(filePath: string): string | undefined {
const fileContent = fs.readFileSync(filePath, "utf-8");
return getUvVersionFromUvLockContent(fileContent);
}
export function getUvVersionFromUvLockContent(
fileContent: string,
): string | undefined {
const parsed = toml.parse(fileContent) as UvLock;
const uvPackage = parsed.package?.find((pkg) => pkg.name === "uv");
return uvPackage?.version;
}