Repository navigation
ci: delete a PR's head branch after it merges, with an allowlist - #1
Conversation
GitHub has no account-wide setting for this, the per-repo toggle deletes every merged head branch, and Free-plan private repos cannot protect long-lived branches such as develop. This self-contained workflow runs on merged same-repo PRs and deletes the head branch unless it is the default branch, one of main/master/develop/staging/test/gh-pages/ deploy-*/release/*, or the base of another open PR. A branch that is already gone counts as success. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012rYJxu978iUSGFZ1UuqTsi
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 52 minutes. View limit detailsLimit details: You’ve used the included review currently available. Review configuration: ⚙️ Run configuration
📒 Files selected for processing (1)
📝 SummarySummary by CodeRabbit
WalkthroughAdds a GitHub Actions workflow that runs when a pull request closes. For merged pull requests from the same repository, it preserves specified branches and branches used as the base of open pull requests. It deletes other branch refs and handles missing refs separately from other API errors. ChangesBranch cleanup workflow
Priority: ⬇️ Low Estimated code review effort: 2 (Simple) | ~10 minutes Change: Feature Merge Risk: ⚪ Minimal · up to The branch-cleanup workflow is mergeable after normal checks; no concrete merge-blocking defect remains established. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Apprentice, the closed branch meets its test, Comment |
There was a problem hiding this comment.
🔇 Additional comments (2)
.github/workflows/branch-cleanup.yml-29-31 (1)
29-31: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
⚠️ Unverified finding
Verification ran but could not confirm this finding. It is shown for review, not as a verified issue.Apprentice, document your permissions. Zizmor reports them as undocumented.
Add short comments that explain why each permission is needed.
contents: writeis needed to delete the ref.pull-requests: readis needed forgh pr list. This shows the power of the Dark Side.Proposed change
permissions: - contents: write - pull-requests: read + contents: write # Delete the merged head branch ref. + pull-requests: read # List open PRs that use the branch as their base.Source: Linters/SAST tools
.github/workflows/branch-cleanup.yml-26-26 (1)
26-26: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
⚠️ Unverified finding
Verification ran but could not confirm this finding. It is shown for review, not as a verified issue.Apprentice, the rebel scum hides in a race: a failed lookup of open PRs is not the only risk, the
mergedgate is also too loose.The
ifcondition passes for every merged PR from the same repository. The workflow deletes the head branch of any merged PR that is not on the allowlist. Allowlist patterns do not cover long-lived branches such asnext,dev,productionorhotfix/*. Merging one of these branches as a PR head deletes it. Extend the allowlist to match your real long-lived branches.The
gh pr list --repo "$REPO" --base "$HEAD_REF" --state opencheck has one more gap. It returns a count only. It does not distinguish PRs with a base in the same repository from those in other contexts. This is acceptable, but document the assumption.
ℹ️ Review info
⚙️ Run configuration
- Configuration used: Organization UI
- Review profile: ASSERTIVE
- Plan: Advanced
- Run ID:
64793a01-e836-46e8-93c5-f0886f1cc7b4
📒 Files selected for processing (1)
.github/workflows/branch-cleanup.yml
Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.
📜 Review details
🧰 Additional context used
🪛 zizmor (1.30.1)
.github/workflows/branch-cleanup.yml
[warning] 30-30: permissions without explanatory comments (undocumented-permissions): needs an explanatory comment
(undocumented-permissions)
[info] 25-25: workflow or action definition without a name (anonymous-definition): this job
(anonymous-definition)
[warning] 18-20: insufficient job-level concurrency limits (concurrency-limits): workflow is missing concurrency setting
(concurrency-limits)
… PRs From CodeRabbit review: keep the branch when another open PR uses it as its head; read the branch's current SHA first and keep it if it moved past the merged PR head (REST has no conditional delete, so only the instant between read and DELETE is unguarded); comment each permission. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012rYJxu978iUSGFZ1UuqTsi
rishitank
left a comment
There was a problem hiding this comment.
Self-review by Claude of the final file (blob acc371c), which is byte-identical to the version proven live on rishitank/test#16. Checked:
- no
${{ }}inrun:; - workflow permissions
{}, and the job gets onlycontents: writeandpull-requests: read, each commented; - merged same-repo PRs only, plus the allowlist;
- keeps branches that are the base or head of open PRs;
- deletes only if the ref still equals
pull_request.head.sha; - 422/404 count as success, and other errors fail red.
actionlint and shellcheck are clean. CodeRabbit's review-body suggestions are handled as follows. The permission comments were added. The allowlist stays as specified (main, master, develop, staging, test, gh-pages, deploy-, release/); next, dev, production and hotfix/* aren't used in this estate. Nothing else to fix.
Why
Merged PR branches pile up. GitHub has no account-wide setting to delete them: "Automatically delete head branches" is a per-repository toggle, and it deletes every merged head branch with no exceptions. Private repositories on the Free plan can't protect branches, so that toggle could delete a long-lived branch such as
developthe first time it is merged as a PR head.This workflow does the cleanup with an explicit allowlist instead.
What changed
.github/workflows/branch-cleanup.yml. Self-contained, no reusable workflow (rishitank/.githubmain is ruleset-blocked, so a shared copy can't land yet).pull_requestclosed. The one job runs only when the PR was merged and its head is in this repository (never a fork's branch).::notice::, when it is the default branch, or one ofmain,master,develop,staging,test,gh-pages,deploy-*,release/*, or when any open PR still uses it as its base.gh api -X DELETE repos/$REPO/git/refs/heads/<ref>, the ref URL-encoded withjq @uri. "Reference does not exist" (422) or a 404 counts as success, since the branch is already gone.{}; the job getscontents: write(delete the ref) andpull-requests: read(the open-PR check).timeout-minutes: 2.${{ }}inrun:. Every event value reaches the shell throughenv:and is quoted.ghfor the default branch, each allowlisted name, a branch with open child PRs, a ref containing/, a space and#, an already-deleted ref (422 and 404), and a 403, which fails the job.🤖 Generated with Claude Code
https://claude.ai/code/session_012rYJxu978iUSGFZ1UuqTsi