ci: add uv lock --locked check to lint job (closes #60)#61
Conversation
Catches the v0.3.0-style regression where a release commit bumps pyproject.toml `version` without re-running `uv lock`, leaving uv.lock's self-version block on the previous release. PR #59 papered over the drift after the fact; this prevents recurrence. The new step runs `uv lock --locked` early in the lint job and fails fast on any pyproject.toml-vs-lockfile inconsistency. Does not check lockfile-vs-PyPI freshness — that remains the weekly uv-lock-refresh.yml cron's job. Verified locally on branch: passes on consistent state, exits 1 when pyproject.toml version is mutated to mismatch.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
cmeans
left a comment
There was a problem hiding this comment.
QA review — round 1: PASS
PR head: 67d9e23 · branch: chore/version-parity-check · closes #60
Verification (in /tmp worktree off origin/chore/version-parity-check)
| Check | Result |
|---|---|
uv lock --locked (positive — synced state) |
exit 0, "Resolved 47 packages" |
uv lock --locked (negative — mutated pyproject.toml version to 0.4.0) |
exit 1, "The lockfile at `uv.lock` needs to be updated, but `--locked` was provided" — restored after |
uv sync --frozen --extra dev |
clean |
uv run pytest |
88/88 pass |
uv run ruff check . |
clean |
uv run ruff format --check . |
11 files already formatted |
uv run mypy src/pypi_winnow_downloads/ |
clean (CI invocation) |
CI status on 67d9e23 |
all green (lint, typecheck, test 3.11/3.12/3.13, deploy-smoke) |
Issue scope check
Issue #60 was about the v0.3.0 release commit failing to bump uv.lock's self-version. The original suggestions were release-flow changes (option A) or cron-side guards (option B). This PR takes a structurally stronger approach — a CI gate that fails any PR with pyproject.toml ↔ uv.lock drift, including the kind that originally caused #60. Closure is well-justified: the v0.3.0-style regression cannot recur because the release PR itself would now fail lint before merge.
Workflow surface check
Grepped .github/workflows/*.yml for uv sync / uv pip:
ci.yml— gets the new check ✓publish.yml,test-publish.yml— post-merge release-time workflows; gating inci.ymlalready prevents drift from reaching themuv-lock-refresh.yml— cron that regeneratesuv.lock; doesn't consume--locked
ci.yml's lint job is the only correct surface to add this; PR is appropriately scoped.
Step placement
New step sits between Set up Python and Install dependencies, so failure happens on the cheap-to-run consistency check before the expensive uv sync. Comment block in the workflow file usefully cross-references issue #60 and the boundary with uv-lock-refresh.yml.
CHANGELOG
## [Unreleased] → ### Added — KaC ordering preserved (Added now leads, Changed follows). Bullet honestly describes both what the new step does and what it does NOT do (no PyPI freshness check). References #60.
Verdict
Ready for QA Signoff. Negative case verified by hand, all CI green, scope right.
No follow-up tickets.
Awaiting maintainer QA Approved.
|
Audit: round 1 verification on |
Summary
Adds a
uv lock --lockedstep to thelintjob in.github/workflows/ci.yml. Closes #60.The v0.3.0 release commit (
fdd4fc3) bumpedpyproject.tomlversion = "0.2.0" → "0.3.0"but did not re-runuv lock, souv.lock's self-version block stayed at0.2.0. The drift was picked up days later by the weeklyuv-lock-refresh.ymlcron, which opened PR #59 with mis-framed CHANGELOG copy. PR #59 fixed the symptom; this PR prevents recurrence.uv lock --lockedexits 1 with"The lockfile at uv.lock needs to be updated, but --locked was provided"wheneverpyproject.tomlanduv.lockare not in agreement. With this step in place, a release commit that forgets the lockfile bump would have failed CI on its own PR before merge — structurally enforced rather than convention-enforced.What this does NOT do
uv.lockis fresh against current PyPI. That remainsuv-lock-refresh.yml's job (weekly Thursday cron).uv lock --lockedonly validatespyproject.toml-vs-lockfile consistency, so transitive churn upstream does not produce false positives here.pyproject.toml, runuv lock, stamp CHANGELOG, commit, tag, push. The new check is the safety net that catches a forgottenuv lockstep.Diff stat
Test plan
uv lock --lockedpasses locally on this branch (no drift).uv lock --lockedexits 1 locally whenpyproject.tomlversionis mutated to mismatch (negative case verified before reverting).uv sync --frozen --extra dev && uv run pytestpasses (88 tests).uv run ruff checkanduv run ruff format --check src/ tests/clean.