ci: gate Ruff with a baseline of the existing findings - #281
Merged
Conversation
Ruff has been configured in pyproject.toml for a while but never ran anywhere. Turning it on as-is would fail immediately: 442 findings in 29 files, and 29 files the formatter has never touched. Both jobs run over the whole repository rather than a list of directories, so `pyi_entrypoint.py`, which the release build uses, `utils/` and the docs config are covered too, and a new top-level file cannot slip past. Rather than switch the rules off globally, pin what each file already breaks. A global ignore list would be an amnesty: a new violation of the same rule would then pass anywhere, including in files written from scratch. With `per-file-ignores` a new file, and a rule a file does not already break, both still fail. The one thing this does not catch is another violation of a rule already listed for that same file — `per-file-ignores` keys on file and rule, not on individual findings. Ruff has no native baseline for that yet. `ruff format` is gated the same way, through `[tool.ruff.format].exclude`. That leaves the 25 legacy files alone while every new file is checked from the start, and avoids a 1400-line reformat that would collide with the eight external pull requests still open. The three test files added in #280 were not in that state for long, so they are formatted here instead of listed. Ruff itself is pinned. The enabled rule families pull in new stable rules on an upgrade, which would turn the gate red without anyone touching the code. Both run as separate jobs so a failure names which one, without the Python matrix the tests need. Shrinking this is the point: fix a rule in a file, drop its code from the list, or run `ruff format` on one file and remove it from the exclude list. 197 of the findings are safe autofixes, which is the obvious next step.
mkb79
added a commit
that referenced
this pull request
Aug 7, 2026
The baseline added with #281 recorded 442 findings. 219 of them Ruff can fix on its own without changing behaviour, so this applies them and shrinks the baseline accordingly. Fully gone, 23 rules: the type annotation modernization the project's own target-version already implies (UP006/UP007/UP045, 98 findings), import sorting (I001), docstring formatting (D2xx/D4xx), quote style (Q000), redundant f-strings and conversions (F541, RUF010), and a handful of one-off simplifications (UP009, UP015, UP025, UP032, UP034, UP035, PLR5501, RUF021, RUF022, RUF100). 442 findings -> 230 168 file/rule pairs in the baseline -> 75 29 files with findings -> 23 Nothing was fixed with --unsafe-fixes; those 109 remain untouched because they can change behaviour and deserve to be read one by one. `ruff check --fix` reorders imports, which left `src/audible_cli/__init__.py` unformatted even though it had been clean. It is formatted here and dropped from the formatter's exclude list. The remainder is dominated by G004 (78 f-strings in logging calls), D415 (60 docstring endings) and W291 (24 trailing whitespace), none of which Ruff will fix on its own.
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.
Ruff has been configured in
pyproject.tomlfor a while but never ran anywhere. Turning it on as-is fails immediately: 442 findings across 29 files, and 29 files the formatter has never touched.Not a blanket ignore
A global ignore list would be an amnesty — a new violation of the same rule would then pass anywhere, including in files written from scratch, and among the 48 rules involved are members of
B,S,ASYNCandRUFwhere a single hit can be a real defect. Instead each file's existing findings are pinned inper-file-ignores.What that catches and what it does not:
That last row is inherent:
per-file-ignoreskeys on file and rule, not on individual findings, and Ruff has no native baseline yet (astral-sh/ruff#1149). The alternative that closes it isruff check --add-noqa, which writes 442# noqacomments into the source. That seemed the worse trade here, but it is a one-command switch if you disagree. The limitation is spelled out in the config comment rather than left for someone to discover.Format without the churn
[tool.ruff.format].excludelists the 29 files the formatter has never seen.ruff format --checkis therefore blocking from day one, every new file is checked, and the legacy files leave the list one at a time. This avoids a ~1400-line reformat that would collide with the eight external pull requests still open.The three test files from #280 were only unformatted for a day, so they are formatted here rather than added to the list.
Scope
Both jobs run over the whole repository rather than a list of directories, so
pyi_entrypoint.py— which the release build uses — plusutils/and the docs config are covered, and a new top-level file cannot slip past. Ruff skips.venvand.noxon its own.audible.specstays out: it is Python but not.py, so it would need an extension mapping. That is a separate decision.Pinned on purpose
ruff==0.16.2in the dev group. The enabled rule families pull in new stable rules on an upgrade, which would turn the gate red without anyone touching the code. Dependabot will propose bumps; a red bump PR is then the signal to deal with the new rules deliberately.Verified
ruff check .andruff format --check .both pass, 56 tests still greenS101inconfig.py— whereS101is not listed — fails as it shouldG004passes inmodels.py, whereG004is listed, and fails intests/, where it is notNext
197 of the findings are safe autofixes. Applying them, then dropping the corresponding codes from the baseline, is the obvious follow-up — deliberately not in this PR, so the gate lands first and the mechanical churn stays reviewable on its own.