ci: guard against stray uv.lock changes in PRs#351
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a CI safeguard to detect and fail pull requests that change uv.lock without also changing pyproject.toml, preventing accidental lockfile drift from bot-generated docs/plan PRs.
Changes:
- Introduces a new “Lockfile Guard” job in CI to reject PRs with a lone
uv.lockchange and provide remediation instructions.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| && ! printf '%s\n' "$changed" | grep -qx 'pyproject.toml'; then | ||
| echo "::error::uv.lock changed without a corresponding pyproject.toml change." | ||
| echo "Plan/docs PRs must not carry a uv.lock update. Restore it with:" | ||
| echo " git checkout origin/${GITHUB_BASE_REF} -- uv.lock && git commit uv.lock" |
There was a problem hiding this comment.
Applied in e74eabd — switched the hint to git checkout $BASE_SHA -- uv.lock && git commit -m 'restore uv.lock' uv.lock. The base SHA is unambiguous and the -m avoids the editor, so both points are addressed.
One note on the rationale: the fork-remote concern does not really apply here. This guard exists for the in-repo bot branches (bot-plan-* / bot-implement-*), where origin is correct — and a bare SHA is not actually more fork-safe anyway, since a fork contributor would need to fetch upstream to have that SHA locally either way. Took the change because the SHA + -m is simply a cleaner hint, not for fork safety.
Bot-generated plan/docs PRs have repeatedly carried a stale
uv.lockfrom an old base. It is invisible until it fails the Dependency Audit (vulnerable transitive pins on #309/#317/#346) or conflicts withmainon merge (#309). A real dependency change always touchespyproject.toml, so a loneuv.lockchange is the drift signal.Adds a
Lockfile Guardjob: PRs that modifyuv.lockwithoutpyproject.tomlfail with instructions to restore the lockfile. Legit dependency bumps (which touch both) and code/docs PRs are unaffected.Note: the duplicate-module defect from #349 is already caught by ruff F811 in
Lint & Format, so no separate check is added here.