Skip to content

CI: a stale uv.lock fails the release three steps late, as a dirty-tree error that does not name it #424

Description

@eaitbrahim

The 0.10.0 release failed on its first run and the error pointed at the wrong thing: https://github.com/CodeGateSoftware/keel/actions/runs/32316126013

What happened

#422 bumped the version in all seven pyproject.toml files and missed uv.lock, which is tracked. The workflow's "Sync dependencies" step regenerated it, leaving the checkout dirty. "Stamp build info" then stamped from that dirty checkout, and five steps later:

warning: this build is NOT reproducible -- it does not correspond to a commit. Do not run it against live funds.
keel 0.10.0+29464f06ee11 (DIRTY) [release]
::error::artifact reports a dirty tree

Fixed by #423, one uv lock.

Why this is worth a guard rather than a lesson

The failure is correct but the message is misdirecting. "artifact reports a dirty tree" sends a reader to keel/version.py, to _build_info.py, to the stamp step — everywhere except the lockfile, which is the actual cause and is three steps upstream. Nothing in the log says "uv.lock changed". Diagnosing it meant reading version.build_info(), confirming keel/_build_info.py is gitignored so it could not be the culprit, and only then checking whether the lock was tracked and stale.

It costs a full build to find out. Lint, Type-check, Test and Build all ran and passed — several minutes — before the guard fired. A lockfile check is instant.

The class of mistake recurs. Every release bumps seven pyproject.toml files, and the lockfile is the eighth thing that has to move with them. It is not mentioned in RELEASING.md's "Cutting a release" steps, which say only "edit version in pyproject.toml".

Proposal

Add a step immediately after checkout, before anything mutates the tree:

- name: The lockfile must already be current
  run: uv lock --check

uv lock --check exits non-zero when the lockfile is out of date with the manifests, and names the lockfile. It runs in about a second.

Worth doing in two more places:

  • the same check in the ordinary CI workflow, so a version-bump PR fails before it merges rather than at release time;
  • a line in RELEASING.md step 1: the bump is pyproject.toml and uv lock.

Not proposed

Having the workflow run uv lock itself and commit it. RELEASING.md is explicit that CI never writes to main and that the version decision belongs in a reviewed PR; a workflow that quietly fixed the lockfile would be the same principle violated from a different direction.

Metadata

Metadata

Assignees

No one assigned

    Labels

    ciCI/workflows (Docs, CI & tooling)toolingDev/release tooling (Docs, CI & tooling)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions