Re-arm Dependabot PRs that GitHub silently disarmed - #2
Conversation
Auto-merge is armed on PR open, then GitHub disables it when a PR-triggered workflow completes with a skipped job. Nothing re-arms it and every run still reports success, so green PRs accumulate. Measured on appeler/pranaam, where nine had. Adds a scheduled sweep that re-arms or lands stranded PRs and logs a line for each one. Eligibility is still decided once, by fetch-metadata in the pull_request context, and recorded as a label the sweep reads back. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3b390d8fb5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if label not in names: | ||
| verdict, act = "ineligible (no policy label)", "none" |
There was a problem hiding this comment.
Bootstrap labels for already-open eligible PRs
When this workflow is first deployed in a repository with already-open eligible PRs—including the backlog this change is intended to repair—those PRs have never passed through the new labeling step because no new pull_request event is generated. Every scheduled or manual sweep therefore permanently classifies them as ineligible here and never re-arms them; bootstrap the verdict for existing PRs or explicitly migrate their labels.
Useful? React with 👍 / 👎.
| acted=$((acted + 1)) ;; | ||
| merge) | ||
| echo "merging #$n" | ||
| gh pr merge "$n" --squash --delete-branch || echo "::warning::could not merge #$n" |
There was a problem hiding this comment.
Preserve push workflows when landing from the sweep
Whenever the sweep chooses merge, this command authenticates with the repository GITHUB_TOKEN; GitHub suppresses new workflow runs for events generated by that token. Consequently the resulting push to main will not run the push jobs in .github/workflows/ci.yml or .github/workflows/docs.yml, and the latter is the only context where docs are deployed. Re-arm auto-merge or use credentials whose merge event can trigger the required post-merge workflows.
Useful? React with 👍 / 👎.
zizmor's excessive-permissions audit rejects a workflow-level write grant once there is more than one job: it applies to every job whether or not that job needs it. Both jobs here do need both scopes, but they now say so themselves. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Nine green Dependabot PRs had accumulated on
appeler/pranaamwhile every auto-merge run reported success. The cause, from run 30836798988 (PR #29):Auto-merge was armed. GitHub disarmed it once a PR-triggered workflow finished with a skipped job, and
on: pull_requestnever fires again — so nothing re-arms, ever. calibre and the others have not hit this only because they happen to have no skipped job in a PR-triggered workflow. The automation is green throughout.What changed
A
schedule:trigger (every 3h) that re-arms stranded PRs. It converges regardless of why GitHub disarmed, which aworkflow_runtrigger racing the disarm event would not.Eligibility is still decided exactly once, by
dependabot/fetch-metadatain thepull_requestcontext where it is reliable — the verdict is recorded as anautomerge-eligiblelabel and read back by the sweep. Deriving it a second time from a branch name would not recover major-versus-minor, and two copies of the rule would drift.The sweep reads
statusCheckRollup, notmergeStateStatusalone:CLEANis GitHub's opinion about mergeability, and this job needs the stronger fact that every check is terminal and none failed before it merges anything directly.It logs a line per PR — armed / merged / ineligible / checks-failing / already-armed — and warns when an eligible PR it cannot act on has been open past
STALE_AFTER_HOURS. A sweep that quietly does nothing would reproduce the bug it fixes.Verified
Decision logic run against the five real open pranaam PRs and six fixtures:
The five real ones are Python-ecosystem majors and the sweep refuses all of them, which is the negative check.
🤖 Generated with Claude Code