Repository navigation
feat(pr-pipeline): delete finished branches daily, keeping each while its issue is open - #8976
Conversation
…rule Owner decision W-7: no non-default branch lives forever. A daily maintenance-delete-stale-branches.yml sorts every branch: closed or merged PR and closed linked issue at least min-age-days (14) ago deletes, at most max-deletes-per-run (25) a run; an open issue, an open PR, a protected or ruleset branch, and a stopped lane run's branch are never deleted; anything unreadable or without a PR is listed for a person. Each delete re-reads the tip and open PRs and writes a ledger line first. Manual runs default to dry-run, which refuses every non-GET request. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…p suite Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Owner decision on #8958: no dates. A branch lives as long as its issue is open and is deleted once the issue closes. Remove the min-age-days key and every age check, and the stopped-run keep: a lane branch whose issue closed and that has no open pull request is deletable whatever stop or resume marker the lanes App left. The cap now takes branches in listing order. Everything else holds: open issue or open pull request keeps, merged-with-commits-ahead and never-had-a-PR branches go to a person, exclusions, cap, kill switch, dry-run and ledger. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Evaluation spent the shared 600-call budget, so with about 300 deletable branches every planned delete failed its re-read and nothing was ever deleted (Codex review on #8959). cleanup.mjs now reserves 4 calls per planned delete from the client's budget, evaluates with the rest, and stops evaluating once it has found max-deletes-per-run candidates or spent its share; the remaining branches wait for the next run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
claude-security-review reviewed Security review (incremental, 9c20bb6 → 6c1af60): no security issues found. Files read:
|
|
claude-review reviewed Code review (incremental, 9c20bb6 → 6c1af60)No findings. Reviewed Change reviewed: the run now starts at Checked by reading the code (
Not verified: I could not run Minor, not blocking: the README line 1603 still says the job deletes "in listing order", though the order now starts at a rotated point. The same paragraph explains the rotation, so it is not misleading. claude-lane: claude-review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9c20bb61f3
ℹ️ 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".
Evaluation always started at the head of the branch listing, so kept or reported branches early in it spent the evaluation share every run and the later branches were never read. Each run now starts at GITHUB_RUN_NUMBER times a quarter of the evaluation share, modulo the listing length, wrapping around, so successive runs cover the whole listing. The summary says the next run starts elsewhere instead of claiming it continues. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs: #8958
Summary
This is the single W-7 branch-cleanup PR and supersedes #8959. A daily job,
maintenance-delete-stale-branches.yml, deletes the branches whose work is finished. Owner decision (2026-10-22, #8958): no dates. A branch lives as long as its issue is open and is deleted once that issue closes.Fix
.github/workflows/maintenance-delete-stale-branches.yml, with its rules and tests in.github/scripts/branch-cleanup/. It is REST only, runs no model, and checks out no branch code. Its token can write contents and read issues and pull requests. The lanes kill switch stops it. The schedule deletes; a manual run is a dry-run unless set otherwise, and in dry-run the client refuses every request butGET.release/*,dependabot/*andgh-readonly-queue/*.min-age-dayskey.max-deletes-per-run(default 25), in listing order. Before each delete the job re-reads the branch tip and the open pull requests from and into the branch. Every delete appends{repo, branch, sha, rule, issue, pr, deletedAt}to the step summary and to the ledger artifact.max-deletes-per-runcandidates or spent that share; the branches after that wait for the next run. Before this fix, about 300 deletable branches used up the whole budget during evaluation, so every planned delete failed its re-read and nothing was deleted.branch-cleanupleaf (max-deletes-per-run) is inpr-pipeline.yamland its schema.branchCleanupFromBaseis in resolve-config. The README has a "Branch cleanup" section. There is a changelog fragment under.changes/pr-pipeline/.Still open from #8958: item 1 (atomic compare-and-delete) and item 2 (split plan from delete). That is why this PR uses
Refs:.Verification
node --testin.github/scripts/branch-cleanup/: 20 pass, 0 fail. The new budget test uses the realclient()over a stubbedfetch. It covers 300 deletable branches under a 600-call budget, and the run deletes 25. Before the fix it failed: 0 deleted. The tests for issue lifetime failed on the pre-change rules: a stopped run's branch is kept while its issue is open and deleted once it closes, and a closed PR branch with no linked issue is deleted.node --testin.github/actions/resolve-config/: 551 pass, 0 fail.scripts/check-affected.sh: 9 passed, 4 skipped, 0 failed.Live dry run: not run by the implementer. The owner should run this and paste the summary here:
Related
🤖 Generated with Claude Code