ci: fail loudly on stale uv.lock and pin one ruff repo-wide (#280) - #281
Merged
Conversation
CI ran `uv sync` without `--locked`, so a stale lockfile silently re-resolved at run time instead of failing. Local machines and CI could install different dependency sets for the same commit - which is exactly what burned a debugging cycle on #279, where `ruff format --check` passed locally and failed in CI because each side resolved a different ruff. The unpinned `uv tool install ruff` was the same class of defect from the other direction: any new ruff release could turn CI red with no code change. It already had - ruff 0.16.0 flags BLE001/S110 on the plugin hook handlers, whose fail-open `except Exception: pass` is required by design and enforced by the plugin-validate job. Changes: - `uv sync --locked` at all four call sites (qa.yml x3, build-workspace-images.yml) - Regenerate the stale agentic_logging and consumer_contracts locks - Pin ruff==0.16.0 and mypy==2.3.0 exactly in every pyproject that declares them - New `ruff-version-consistency` job: RUFF_VERSION in qa.yml is the single source of truth, and every pyproject must pin that exact version - Root ruff.toml ignoring BLE001/S110 for plugin hook handlers, with the rationale recorded - `just python-lock-check` / `python-lock-update` for local parity, wired into `just qa` and `just ci`; `python_qa.py sync` now uses --locked too Fallout from moving every package onto ruff 0.16.0, all verified locally: - agentic_events: `Recording(str, Enum)` -> `StrEnum` (UP042) - agentic_logging: README code blocks reformatted Closes #280
The ruff/mypy pin touched plugins/research/tools/firecrawl/pyproject.toml, which plugin-version-check counts as plugin content. Bumping rather than dropping the pin: the ruff-version-consistency guard requires every pyproject that declares ruff to pin RUFF_VERSION, and carving out an exception would reintroduce the drift this PR closes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #280.
Problem
uv syncran without--locked, so a staleuv.locksilently re-resolved at run time instead of failing. CI and a developer machine could install different dependency sets for the same commit.This already cost a debugging cycle on #279:
ruff format --checkpassed locally and failed in CI on the same commit, because each side resolved a different ruff. The symptom looked like a formatting bug in unrelated code.The unpinned
uv tool install ruffwas the same defect from the other direction - any new ruff release could turn CI red with no code change, and it already had. Onmaintoday, ruff resolves to 0.16.0 for the hook check, which flags 20 BLE001/S110 violations on the plugin hook handlers.Two locks were stale on
mainwhen this branch was cut:lib/python/agentic_loggingandtests/consumer_contracts.Changes
Fail loud on stale locks
uv sync --lockedat all four call sites (qa.ymlx3,build-workspace-images.yml)One ruff for the whole repo
RUFF_VERSION: "0.16.0"as a workflow-level env inqa.yml, used byuv tool install ruff==${RUFF_VERSION}ruff==0.16.0/mypy==2.3.0pinned exactly in everypyproject.tomlthat declares themruff-version-consistencyjob asserts everypyproject.tomlpins exactlyRUFF_VERSION, so the hook check and the per-package checks can never format against different ruff releases. It also fails if it finds zero declarations, so the guard can't silently stop guarding. Wired intoqa-success.Root
ruff.tomlplugins/*/hooks/are exempted from BLE001 and S110. Their fail-openexcept Exception: passis required by design -plugin-validateactively enforces that every handler has a top-level exception handler. Without an owning project these files inherited whatever the default rule set of the day happened to be; now that's pinned and the rationale is recorded in the file.Local parity
just python-lock-checkandjust python-lock-update, wired intojust qaandjust cipython_qa.py syncnow uses--lockedtoo, so the local sync path matches CIFallout from moving every package onto ruff 0.16.0
Both verified locally:
agentic_events:Recording(str, Enum)->StrEnum(UP042). 163 tests pass.agentic_logging: README code blocks reformatted.Verification
Run locally against the branch:
uv lock --check(all 6 projects)Acceptance criteria from #280, checked by hand:
ruff==0.16.0->0.15.10in a pyproject) makesuv sync --lockedfail withThe lockfile at uv.lock needs to be updated, but --locked was provided.ruff-version-consistencyguard fail, naming the offending file and both versions.Not included
The issue also floats a periodic job that regenerates locks and opens a PR. Left out to keep this reviewable - happy to file a follow-up.