chore: Dependabot PR hygiene (config, auto-CHANGELOG workflow, PR template)#54
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
…plate) Cascades the post-mcp-synology#63 Dependabot-PR-hygiene playbook from the validated cmeans/mcp-clipboard#96 rollout. Five files: - .github/dependabot.yml — pip + github-actions ecosystems, weekly Monday 06:00 America/Chicago, grouped per ecosystem, `chore` prefix with `include: scope` (canonical title shape `chore(deps): bump foo`; doubling to `chore(deps)` would yield `chore(deps)(deps):`). No docker ecosystem because this repo has no Dockerfile. - .github/workflows/dependabot-changelog.yml — `pull_request_target` workflow filtered to `dependabot[bot]` that prepends a Keep-a-Changelog-ordered entry under `[Unreleased] / Changed`. Authenticated via a GitHub App installation token (`actions/create-github-app-token@v3.1.1`, SHA `1b10c78c7865c340bc4f6099eb2f838309f1e8c3`) so the bot's follow-up commit re-fires the QA-Gate-required CI checks (test ubuntu / test macos / smoke-macos). `GITHUB_TOKEN`-authored pushes do NOT trigger downstream `pull_request` workflows (GitHub anti-loop policy), which would block merge under the main-protection ruleset. Uses `dependabot/fetch-metadata@v3.1.0` (SHA `25dd0e34f4fe68f24cc83900b1fe3fe149efef98`) — v2 returns empty `prevVersion`/`newVersion` strings on grouped PRs. Loop guard skips when last commit author is the bot; idempotency guard skips when `(#N)` is already present in CHANGELOG.md. Commits with NUMERIC user id `272174644` in noreply email format (not APP_ID `3223881` — APP_ID breaks `require_last_push_approval` ruleset commit attribution). Includes the post-`mcp-synology#63` Keep-a-Changelog ordering fix in the create-`### Changed`-from-scratch path. - .github/PULL_REQUEST_TEMPLATE.md — auto-fills human-authored PR bodies with Summary / Test plan / CHANGELOG checklist using this repo's commands (`.venv/bin/python -m pytest`, `ruff check`, `bash scripts/smoke-test.sh`). Dependabot bypasses templates and supplies its own body, which is why the workflow above exists. - .github/labels.yml — adds `python` (color 3572A5, linguist Python) and `github-actions` (color 2088FF, GitHub Actions blue) so the Dependabot grouped PRs get their domain labels at open time. Sync via .github/workflows/sync-labels.yml on push to main. - CHANGELOG.md — Unreleased / Added entry recording the change. Operator prereqs: `BOT_APP_ID` and `BOT_APP_PRIVATE_KEY` repo secrets configured (confirmed in-place); GitHub App installed on the repo with `contents:write` and `pull-requests:read`. SHA pins on all three third-party actions verified exact match upstream tags via `gh api repos/<owner>/<repo>/git/refs/tags/v<X>`. Bot user id 272174644 verified via `gh api 'users/cmeans-claude-dev%5Bbot%5D'`. Workflow's CHANGELOG insertion logic dry-run on this repo's current `[Unreleased]` (which has `### Changed` already) produces correct output. YAML parses on all three YAML files; Python heredoc in the compose step parses cleanly. 485 tests pass; ruff clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
9a61909 to
a25d350
Compare
cmeans
left a comment
There was a problem hiding this comment.
QA Round 1 — PR #54
Verdict: QA Failed. One substantive finding (stale test count in PR body). Workflow logic and pins are clean; only doc drift blocks signoff.
Verified
502 / 502 tests passon HEADa25d350(.venv/bin/python -m pytest tests/)ruff check src/ tests/clean- All three YAML files parse (
.github/dependabot.yml,.github/workflows/dependabot-changelog.yml,.github/labels.yml) - Workflow's CHANGELOG insertion logic dry-run against the current
[Unreleased](which has### Changed) inserts at line 31 — after the### Changedheader + blank line, before the existing PEP 639 entry. Correct. - Workflow's from-scratch
### Changedcreation path respects Keep-a-Changelog v1.1.0 ordering — verified on a synthesized[Unreleased]with only### Added+### Fixed; the new### Changedblock lands between them. - All three third-party action SHA pins match upstream tag refs verbatim:
actions/create-github-app-token@v3.1.1→1b10c78c7865c340bc4f6099eb2f838309f1e8c3✓actions/checkout@v6.0.2→de0fac2e4500dabe0009e67214ff5f5447ce83dd✓dependabot/fetch-metadata@v3.1.0→25dd0e34f4fe68f24cc83900b1fe3fe149efef98✓
- Bot user id
272174644resolves tocmeans-claude-dev[bot](type: Bot) ✓ - Repo secrets
BOT_APP_ID+BOT_APP_PRIVATE_KEYpresent (set 2026-04-26) - Loop guard logic sound: bot-authored-last-commit branch and
(#PR_NUMBER)idempotency branch both reachable; first-run path avoids both correctly. Dependabot's recreate cycle drops the bot's commit, so a recreated PR re-fires the workflow cleanly (no orphan entry). - App-token push interaction with the rest of the workflow stack:
pr-labels.yml(usessecrets.GITHUB_TOKENon the resultingsynchronizeevent) will reset toAwaiting CI;ci.ymlreruns on the bot's HEAD SHA because App-token pushes are not subject to GitHub'sGITHUB_TOKENanti-loop policy;pr-labels-ci.ymlthen promotes back toReady for QA. Lifecycle is consistent. - CHANGELOG entry under
[Unreleased] / ### Added— categorized correctly and accurate to scope. python(#3572A5) andgithub-actions(#2088FF) labels added to.github/labels.yml.bash scripts/smoke-test.sh— 19 / 19 checks pass.
Findings
1. (Substantive) PR body test count is stale post-rebase. The Test plan checkbox reads [x] .venv/bin/python -m pytest tests/ — 485 passed, but the actual run on HEAD a25d350 is 502 passed in 44.55s. The branch was rebased after #49 / #50 / #52 / #53 merged (which added 17 tests on main); the diff itself adds zero test files. Update the line to 502 passed so the maintainer reads the count actually verified at merge time.
Notes (non-blocking)
- The post-merge verification gate (sync-labels firing, first real Dependabot weekly PR, populated arrows on the auto-CHANGELOG entry, App-token push re-firing required CI checks) is correctly out-of-scope for pre-merge QA per the playbook.
- The Python heredoc inside
dependabot-changelog.ymlhas non-trivial branching (KaC ordering, idempotency, loop guard) but is only validated end-to-end by the post-merge gate. That's the playbook approach; not a finding.
QA Active is being released; once the test count is corrected, re-apply Ready for QA and I'll re-run round 2.
|
Applying |
|
QA Round 1 finding addressed: PR body test plan updated to |
cmeans
left a comment
There was a problem hiding this comment.
QA Round 2 — PR #54
Verdict: Ready for QA Signoff. Round-1 finding fixed; zero new findings.
Re-verified on HEAD a25d350
- PR body test plan now reads
502 passed✓ (matches.venv/bin/python -m pytest tests/→502 passed in 44.51s) .venv/bin/ruff check src/ tests/— clean- HEAD unchanged from round 1 (doc-only fix in PR body); all of round 1's structural checks (3/3 SHA pins, bot user id, repo secrets, KaC dry-runs on both insertion paths, loop guard, CHANGELOG entry,
python+github-actionslabels, smoke test 19/19) still hold
Releasing QA Active, applying Ready for QA Signoff. QA Approved is for the maintainer.
|
Applying |
Bump github-actions group: actions/checkout 4→6, astral-sh/setup-uv 5→7, codecov/codecov-action 5→6, actions/upload-artifact 4→7, actions/download-artifact 4→8. Validated end-to-end before merge: - PR-side CI green at HEAD `ebffd46` after the auto-CHANGELOG bot commit re-fired the QA-Gate-required checks via App-token push (`test (ubuntu-latest)`, `test (macos-latest)`, `smoke-macos`, `qa-approved` all SUCCESS). Empirically validated `ci.yml` and `sync-labels.yml` paths with the new versions. - TestPyPI workflow_dispatch run `25017398444` exercised the `publish.yml` path that PR-side CI cannot reach: `actions/checkout@v6`, `astral-sh/setup-uv@v7`, `uv build`, `actions/upload-artifact@v7`, `actions/download-artifact@v8`, then `pypa/gh-action-pypi-publish` to TestPyPI. End-to-end success in 28s wall clock; the v4→v7 / v4→v8 cross-major upload/download artifact handoff worked cleanly. `yt-dont-recommend 0.5.0` now present on TestPyPI alongside the prior `0.1.0`, `0.1.1`, `0.1.2` releases. - Per-action breaking-change scan against actual usage: zero hits. We invoke `setup-uv` bare with no inputs (so the v6 removed-input changes — `pyproject-file`, `uv-file`, `server-url`, default `cache-dependency-glob` — are all not-applicable). We download artifacts by name not by ID (so the v5 single-artifact-by-ID path change is not-applicable). We use default zip behavior on upload (so v7 ESM and direct-upload changes are transparent). The `download-artifact@v8` change of "hash mismatch now errors instead of warns" is defense-in-depth tightening, not a regression risk for our usage. This is the first real Dependabot weekly run on `yt-dont-recommend`, opened immediately on Dependabot's initial config-registration scan after PR #54 (Dependabot PR hygiene playbook) merged. Post-merge verification gate from the playbook is now satisfied end-to-end on this repo, lifting the standing "no cascade" rule for the playbook itself on remaining `cmeans/*` repos that need it. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
Cascades the post-
mcp-synology#63Dependabot-PR-hygiene playbook from the validatedcmeans/mcp-clipboard#96rollout. Five files:.github/dependabot.yml(pip + github-actions, weekly Mon 06:00 CT, grouped,choreprefix withinclude: scopeto avoid thechore(deps)(deps):doubled-prefix bug),.github/workflows/dependabot-changelog.yml(pull_request_targetfiltered todependabot[bot], App-token-authed so the bot's commit re-fires QA-Gate-required CI checks, includes the post-#63 Keep-a-Changelog ordering fix in the create-### Changed-from-scratch path),.github/PULL_REQUEST_TEMPLATE.md(humans only — Dependabot bypasses templates),.github/labels.ymladdspython+github-actions, and aCHANGELOG.mdUnreleased / Added entry.Operator prereqs
BOT_APP_ID+BOT_APP_PRIVATE_KEYconfirmed in-place. SHA pins on all three third-party actions verified exact match upstream tags. Bot user id272174644verified viagh api 'users/cmeans-claude-dev[bot]'. Workflow's CHANGELOG insertion logic dry-run on this repo's current[Unreleased](which has### Changedalready) produces correct output.The naive simple
dependabot.ymlalone would break here because of the strict CHANGELOG-per-PR rule + required CI checks + QA-Gate ruleset combination — Dependabot PRs would QA-fail for missing CHANGELOG, andGITHUB_TOKEN-authored auto-fix pushes would not re-fire the required checks. The full playbook handles all three.Test plan
Pre-merge (verifiable now):
.venv/bin/python -m pytest tests/— 502 passed.venv/bin/ruff check src/ tests/— clean.github/dependabot.yml,.github/workflows/dependabot-changelog.yml,.github/labels.ymlast.parse)[Unreleased]produces correct entry under existing### Changedactions/create-github-app-token@v3.1.1=1b10c78c7865c340bc4f6099eb2f838309f1e8c3(gh api repos/actions/create-github-app-token/git/refs/tags/v3.1.1)actions/checkout@v6.0.2=de0fac2e4500dabe0009e67214ff5f5447ce83dddependabot/fetch-metadata@v3.1.0=25dd0e34f4fe68f24cc83900b1fe3fe149efef98272174644resolves tocmeans-claude-dev[bot](type Bot)BOT_APP_ID+BOT_APP_PRIVATE_KEYrepo secrets in-placePost-merge (verification gate per playbook — do NOT cascade or schedule anything until these are observed live):
sync-labels.ymlfires on push to main, createspythonandgithub-actionslabels on the repo@dependabot recheck)cmeans-claude-dev[bot]playwright 1.49.0→1.50.0), not empty→(validatesfetch-metadata@v3.1.0body-metadata path)Awaiting CI→Ready for QAcorrectlyNotes
sync-labels.ymlruns and creates the two new labels before next Monday's Dependabot schedule fires.mcp-synology#63) is fixed in the workflow but won't fire on yt-dont-recommend's current[Unreleased]layout (which already has### Changed). It activates after the next release cuts a fresh empty[Unreleased]and a feature PR adds### Addedbefore any Dependabot bump.dependabot-recreate-no-bot-postsplaybook rule, I will not@dependabot recreateto trigger the live verification — surface that as a maintainer-only action when the time comes.🤖 Generated with Claude Code