Problem
test_ruff_pin_lockstep.py (#339) requires pyproject.toml's ruff== pin and .pre-commit-config.yaml's ruff-pre-commit hook rev to match exactly. Dependabot tracks these via two separate package-ecosystem blocks in .github/dependabot.yml (pip and pre-commit), so every ruff release produces two independent PRs, each bumping only one side of the pair — and each one fails CI on its own by design, since the lockstep test can't pass until both land together.
This isn't hypothetical: it happened on the most recent ruff 0.16.3→0.16.4 bump (patterns#400 for pyproject.toml, patterns#401 for .pre-commit-config.yaml), and had to be resolved manually by combining both into a single PR (patterns#403).
Why the current config doesn't already solve this
.github/dependabot.yml's pip block already has a groups: dev-dependencies entry covering ruff, with a comment on the pre-commit block explicitly acknowledging the lockstep concern:
"keeps the ruff-pre-commit rev in lockstep with the pyproject ruff== pin (the pip ecosystem above only bumps the PyPI dep, so without this the two ruff versions drift apart after every release)"
But Dependabot's groups: feature only groups updates within a single package-ecosystem block — it cannot merge a pip update and a pre-commit update into one PR, since they're different ecosystems entirely. So the comment correctly identifies the risk but the current config has no way to actually prevent the two-PR collision; it can only note that pre-commit needs its own tracking, not unify it with pip's PR.
Impact
Every future ruff release will repeat this exact pattern: two Dependabot PRs, both red, requiring a manual combine PR — unless something changes. Low severity (cheap to fix by hand each time, as done for #403), but a recurring, avoidable maintenance tax.
Possible directions (not prescribing one — needs a decision)
- Accept the two-PR pattern and document the manual-combine procedure (e.g. a short note in
CONTRIBUTING.md or a comment in the lockstep test itself) so whoever handles the next bump doesn't have to rediscover the fix.
- Drop the
pre-commit ecosystem block and self-manage ruff-pre-commit's rev via a script/pre-commit hook that derives it from pyproject.toml's pin at commit/CI time, instead of pinning it independently — trades "one more Dependabot PR to review" for "one less place version drift can originate," but changes the supply-chain-pinning model for that hook.
- Investigate whether a Dependabot custom auto-merge/close automation (e.g. a scheduled GitHub Action that detects "the other half's PR is open" and auto-combines them) is worth the complexity for a once-a-release-or-so annoyance — likely overkill given the low frequency.
Acceptance criteria
Problem
test_ruff_pin_lockstep.py(#339) requirespyproject.toml'sruff==pin and.pre-commit-config.yaml'sruff-pre-commithook rev to match exactly. Dependabot tracks these via two separatepackage-ecosystemblocks in.github/dependabot.yml(pipandpre-commit), so every ruff release produces two independent PRs, each bumping only one side of the pair — and each one fails CI on its own by design, since the lockstep test can't pass until both land together.This isn't hypothetical: it happened on the most recent ruff 0.16.3→0.16.4 bump (patterns#400 for
pyproject.toml, patterns#401 for.pre-commit-config.yaml), and had to be resolved manually by combining both into a single PR (patterns#403).Why the current config doesn't already solve this
.github/dependabot.yml'spipblock already has agroups: dev-dependenciesentry coveringruff, with a comment on thepre-commitblock explicitly acknowledging the lockstep concern:But Dependabot's
groups:feature only groups updates within a singlepackage-ecosystemblock — it cannot merge apipupdate and apre-commitupdate into one PR, since they're different ecosystems entirely. So the comment correctly identifies the risk but the current config has no way to actually prevent the two-PR collision; it can only note that pre-commit needs its own tracking, not unify it with pip's PR.Impact
Every future ruff release will repeat this exact pattern: two Dependabot PRs, both red, requiring a manual combine PR — unless something changes. Low severity (cheap to fix by hand each time, as done for #403), but a recurring, avoidable maintenance tax.
Possible directions (not prescribing one — needs a decision)
CONTRIBUTING.mdor a comment in the lockstep test itself) so whoever handles the next bump doesn't have to rediscover the fix.pre-commitecosystem block and self-manageruff-pre-commit's rev via a script/pre-commit hook that derives it frompyproject.toml's pin at commit/CI time, instead of pinning it independently — trades "one more Dependabot PR to review" for "one less place version drift can originate," but changes the supply-chain-pinning model for that hook.Acceptance criteria