ci(ruff): pin ruff to the lockfile and stop CI auto-fixing - #704
Merged
Conversation
Two independent problems, both of which let CI diverge from local. 1. Floating ruff. `chartboost/ruff-action@v1` installs the latest ruff on every run, so a release can turn every open PR red with no commit having been made. That is what happened: ruff 0.16.0 stabilised PLR0917 (too-many-positional-arguments) out of preview, and since pyproject selects the whole "PLR" category it was picked up immediately. Ten pre-existing violations on an unmodified main; the pinned 0.14.14 from uv.lock that `poe lint` uses reports none. The workflow now installs uv and runs the locked ruff, mirroring tests.yml. uv.lock becomes the single source of truth. 2. CI could auto-fix. `poe lint` runs `ruff check --fix`, which mutates the checkout and then reports only what is left. Pointing CI at it would mask every auto-fixable violation. Demonstrated with an unsorted import block: `poe lint` exits 0 (having silently fixed it) where `poe lint-ci` exits 1. Adds a `lint-ci` task using `--no-fix`. `poe lint` keeps `--fix` for local ergonomics and is unchanged. Also ignores PLR0917 alongside the PLR0913 already ignored. Kernels, likelihoods and variational families are constructed positionally with defaults; making those arguments keyword-only to satisfy the rule would be a breaking change to public constructors. Verified: ruff 0.16.0 now reports no errors on gpjax, tests and benchmarks. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bj9k5fnAZ8JzD4Rg3HMDMj
thomaspinder
enabled auto-merge (squash)
July 26, 2026 14:16
thomaspinder
temporarily deployed
to
docs-preview
July 26, 2026 14:38 — with
GitHub Actions
Inactive
3 tasks
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.
Checklist
uv run poe formatbefore committing.Description
mainis currently red onruffthrough no change of its own, and #702 / #703 inherit it. Fixing that surfaced a second, quieter problem in the same workflow.1. Ruff was floating, not pinned
chartboost/ruff-action@v1installs the latest ruff on every run. So a ruff release can turn every open PR red without anyone having committed anything — which is exactly what happened. Ruff 0.16.0 stabilisedPLR0917(too-many-positional-arguments) out of preview, and sincepyproject.tomlselects the whole"PLR"category, it was adopted the moment it shipped.Reproduced on an unmodified
main:The workflow now installs uv and runs the locked ruff, mirroring
tests.yml.uv.lockbecomes the single source of truth, so local and CI cannot disagree again.2. CI could have silently auto-fixed violations
The obvious fix is to point CI at
poe lint— but that runsruff check --fix, which mutates the checkout and then reports only what's left. Every auto-fixable violation would be quietly repaired in the ephemeral runner and pass.Not theoretical. Planting an unsorted import block:
So this adds a
lint-citask using--no-fixfor CI.poe lintkeeps--fixfor local ergonomics and is unchanged, as is theall-testssequence.3. PLR0917 ignored alongside PLR0913
PLR0913(too many arguments) was already ignored;PLR0917is its positional-only sibling and wasn't. They flag the same constructors:PLR0913self/clsPLR0917self/cls, anything after*Kernels, likelihoods and variational families are deliberately constructed positionally with defaults —
RBF(active_dims, lengthscale, variance, n_dims, compute_engine)is 6, over the limit of 5. Satisfying the rule properly means inserting*into ten public constructors, which breaks every positional caller. Ignoring it is consistent with the existingPLR0913decision.Verification
The second line is the one that matters: the version that broke CI now passes.
Note on job runtime
The lint job goes from ~11s to a
uv sync --frozen(cached viasetup-uv). That's the price of resolving ruff from the lockfile instead of the network. If it proves too slow, the alternative isastral-sh/ruff-action@v3with an explicitversion:— faster, but reintroduces a second place to keep the ruff version in sync.Merging this unblocks #702 and #703.
🤖 Generated with Claude Code
https://claude.ai/code/session_01Bj9k5fnAZ8JzD4Rg3HMDMj