Follow-up to #36, which fixed this repo only. #36's root cause — a documented lint selection that no config file enforced — is not unique to .github. Verified against each repo's default branch on GitHub (not local checkouts):
| Repo |
pyproject.toml |
select |
Lints in CI? |
rems-sync |
yes |
["E","F","I","W"] |
ci.yml |
deck-eval-gen |
yes |
["E","F","I","W"] |
ci.yml |
.github |
no → added by #36 |
— |
ci.yml |
deck-eval-parser |
no |
— |
no — tests.yml runs pytest only, and ruff isn't in requirements.txt or requirements-dev.txt |
officials-admin |
no |
— |
no workflows at all (CI arrives with #12) |
swim-club-tech-survey |
no |
— |
no — only run_survey.yml |
Two distinct problems fall out.
1. Enforcement gap — lints, but with no config
A repo that runs ruff check . without a config uses the installed ruff's defaults, and with ruff>=0.6 those can change under it. That is #36 exactly: main green, next unrelated PR red. .github was the only repo in this state, which is the embarrassing part — the repo that publishes the standard was the one not following it.
2. Coverage gap — doesn't lint at all
deck-eval-parser and swim-club-tech-survey are outside the documented quality gate entirely. CONTRIBUTING.md § Quality gates says "Python repos use ruff", and for these it simply isn't true. deck-eval-parser has real code and its own tests.yml that never calls the shared reusable workflow.
Worth deciding whether that's intended (survey repo may be a scheduled script, not a maintained codebase) or drift. officials-admin is a known-pending case, not drift — #12 adds CI.
Why this can't just be "share the config"
Ruff has no remote config inheritance. extend takes a local path, so there is no way for six repos to point at one file in this one. Options, all with tradeoffs:
- Copy the config into each repo, plus a conformance check.
reconcile-repo-defaults.yml already heals settings drift on a schedule; it could equally assert that every Python repo has a config whose selection matches the documented one. Keeps per-repo autonomy, catches drift, but the config itself is still duplicated.
- Centralize the flag in
reusable-python-ci.yml — add a ruff-select input defaulting to the documented selection, so every consumer is deterministic without touching each repo. Recommended for enforcement. Caveat: a CLI --select overrides file config wholesale, including per-file-ignores, so a repo needing extra rules must pass the input rather than configure locally. No conflict today, since the two repos with config already match the default.
- Ship the config in a pip package and
extend into site-packages. Genuinely shared, and fiddly enough that it probably isn't worth it at six repos.
1 and 2 compose well: 2 makes CI deterministic now, 1 keeps local ruff check . honest for developers, who don't run the workflow.
Acceptance criteria
- Every repo that contains Python either lints with the documented selection or has an explicit, recorded reason not to.
- Local
ruff check . and CI agree — a developer can't be green locally and red in CI, or vice versa.
- A new Python repo created via
scripts/create-repo.sh starts out conformant, rather than relying on someone remembering to copy a config.
CONTRIBUTING.md § Quality gates describes what is actually enforced.
Known instance to fix in passing
officials-admin's requirements-dev.txt (added in swimblocks/officials-admin#16) declares no ruff, because that repo has no lint gate yet. Whatever this issue lands should cover it, or #12 should.
Follow-up to #36, which fixed this repo only. #36's root cause — a documented lint selection that no config file enforced — is not unique to
.github. Verified against each repo's default branch on GitHub (not local checkouts):pyproject.tomlselectrems-sync["E","F","I","W"]ci.ymldeck-eval-gen["E","F","I","W"]ci.yml.githubci.ymldeck-eval-parsertests.ymlrunspytestonly, and ruff isn't inrequirements.txtorrequirements-dev.txtofficials-adminswim-club-tech-surveyrun_survey.ymlTwo distinct problems fall out.
1. Enforcement gap — lints, but with no config
A repo that runs
ruff check .without a config uses the installed ruff's defaults, and withruff>=0.6those can change under it. That is #36 exactly:maingreen, next unrelated PR red..githubwas the only repo in this state, which is the embarrassing part — the repo that publishes the standard was the one not following it.2. Coverage gap — doesn't lint at all
deck-eval-parserandswim-club-tech-surveyare outside the documented quality gate entirely.CONTRIBUTING.md§ Quality gates says "Python repos use ruff", and for these it simply isn't true.deck-eval-parserhas real code and its owntests.ymlthat never calls the shared reusable workflow.Worth deciding whether that's intended (survey repo may be a scheduled script, not a maintained codebase) or drift.
officials-adminis a known-pending case, not drift — #12 adds CI.Why this can't just be "share the config"
Ruff has no remote config inheritance.
extendtakes a local path, so there is no way for six repos to point at one file in this one. Options, all with tradeoffs:reconcile-repo-defaults.ymlalready heals settings drift on a schedule; it could equally assert that every Python repo has a config whose selection matches the documented one. Keeps per-repo autonomy, catches drift, but the config itself is still duplicated.reusable-python-ci.yml— add aruff-selectinput defaulting to the documented selection, so every consumer is deterministic without touching each repo. Recommended for enforcement. Caveat: a CLI--selectoverrides file config wholesale, includingper-file-ignores, so a repo needing extra rules must pass the input rather than configure locally. No conflict today, since the two repos with config already match the default.extendinto site-packages. Genuinely shared, and fiddly enough that it probably isn't worth it at six repos.1 and 2 compose well: 2 makes CI deterministic now, 1 keeps local
ruff check .honest for developers, who don't run the workflow.Acceptance criteria
ruff check .and CI agree — a developer can't be green locally and red in CI, or vice versa.scripts/create-repo.shstarts out conformant, rather than relying on someone remembering to copy a config.CONTRIBUTING.md§ Quality gates describes what is actually enforced.Known instance to fix in passing
officials-admin'srequirements-dev.txt(added in swimblocks/officials-admin#16) declares no ruff, because that repo has no lint gate yet. Whatever this issue lands should cover it, or #12 should.