chore: adopt the mechanical portfolio Python standards (dependabot uv, exclude-newer, workflow hardening) - #195
Merged
Conversation
…, exclude-newer, workflow hardening)
The "free, mechanical" first step from the portfolio Python Project Standard.
No behavior change to the CLI, the service, or the release process.
1. Dependabot ecosystem pip -> uv. This repo resolves from the committed
uv.lock, and the pip ecosystem does not update that file — it would bump
pyproject.toml and leave the lock (what CI and the Docker build actually
install from) untouched. This was a live defect, not a style gap.
2. [tool.uv] exclude-newer = "7 days" — the resolver-side twin of the
Dependabot cooldown already configured. Without it a plain `uv sync` still
pulls a just-published transitive dependency that Dependabot would have
waited on. Verified uv 0.12.5 accepts the relative form; `uv lock` records
it as exclude-newer-span = "P7D" and moved no package versions.
3. Top-level least-privilege `permissions:` and a `concurrency:` group on all
ten workflows (previously 4/10 had permissions, 1/10 concurrency, 0/10
both). Every job that elevates keeps its own block, which still overrides.
cancel-in-progress is NOT true everywhere, deliberately. smoke-test.yml
already established the precedent ("Never cancel — would orphan cloud
resources") and it generalizes: smoke-test creates billable EC2 instances,
key pairs, security groups, Hetzner servers and volumes whose destroy steps
run last, so a cancellation leaks them until the 4-hourly cleanup reaps
them; provision/teardown leave half-built or half-destroyed infrastructure;
release desynchronizes tag/Release/PyPI/GHCR; release-please half-amends the
release PR; dev-build discards a wheel someone is waiting on. Only ci,
codeql and dependency-review — pure recomputation on a superseded commit —
get true.
Verified: 2564 passed / 19 skipped, ruff clean, mypy clean over 78 files, and
all ten workflows parse with both keys present.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MzLwS8fijKdrVVh7oj9kNd
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.
Step 1 ("free, mechanical, no design review needed") from the portfolio Python Project Standard. No behavior change to the CLI, the web service, or the release process.
1. Dependabot
pip→uvThis repo resolves from the committed
uv.lock, and thepipecosystem does not update that file — it would bumppyproject.tomland leave the lock, which is what CI and the Docker build actually install from, untouched.This is the one item in the batch that was a live defect rather than a style gap.
2.
[tool.uv] exclude-newer = "7 days"The resolver-side twin of the Dependabot cooldown this repo already configures. Without it, a plain
uv syncstill pulls a just-published transitive dependency that Dependabot would have waited 7 days on.Verified
uv 0.12.5accepts the relative form rather than assuming it:uv lockresolves it to a concrete cutoff and recordsexclude-newer-span = "P7D". No package version moved — the lock diff is 4 added lines recording the option.3.
permissions:+concurrency:on all ten workflowsBefore: 4/10 had top-level
permissions:, 1/10 hadconcurrency:, 0/10 had both. Now all ten have both. Every job that elevates (security-events: write,id-token: write,packages: write,contents: write) keeps its own block, which still overrides the top-level default.cancel-in-progressis deliberately nottrueeverywhereThe standard states the rule as
cancel-in-progress: true, but applying that blanket-wise here would be actively harmful, and this repo already knew it —smoke-test.ymlshipped withcancel-in-progress: false # Never cancel — would orphan cloud resourcesbefore this PR. That precedent generalizes:ci,codeql,dependency-reviewsmoke-testremo … destroysteps run last, so a cancellation leaks them until the 4-hourly cleanup reaps themprovision/teardownsmoke-test-cleanupreleaserelease-pleasedev-buildVerification
uv run pytest— 2564 passed, 19 skippeduv run ruff check src/remo_cli— cleanuv run mypy src/remo_cli— clean, 78 filesNot in this PR
The rest of the standard is deliberately out of scope here:
[dependency-groups], explicit ruffselect, lintingtests/,ruff format --check, pytest--strict-markers/--timeout/asyncio_mode, coverage floor, mypy strictness ratchet,requires-pythonceiling, a task runner +checkverb,hatch-vcsdynamic versioning, and reducingAGENTS.mdto a pointer. Each needs a decision or a reformat commit; none is mechanical.hatch-vcsin particular should be decided before or well after cutting 4.4.0, not during.🤖 Generated with Claude Code
https://claude.ai/code/session_01MzLwS8fijKdrVVh7oj9kNd