Branch Cleanup #3
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
| name: Branch Cleanup | |
| # Only runs after CI passes on a push to develop or main. | |
| # Deletes the source branch of the merged PR — but ONLY if post-merge CI succeeded. | |
| # If CI fails after merge, the branch stays so you can fix and re-merge. | |
| on: | |
| workflow_run: | |
| workflows: ["CI"] | |
| types: [completed] | |
| branches: [develop, main] | |
| permissions: | |
| contents: write | |
| pull-requests: read | |
| jobs: | |
| cleanup: | |
| name: Delete merged branch | |
| runs-on: ubuntu-latest | |
| if: >- | |
| github.event.workflow_run.conclusion == 'success' && | |
| github.event.workflow_run.event == 'push' | |
| steps: | |
| - name: Find merged PR and delete source branch | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const sha = context.payload.workflow_run.head_sha; | |
| const repo = context.repo; | |
| // Find PRs that were merged with this commit | |
| const { data: prs } = await github.rest.pulls.list({ | |
| ...repo, | |
| state: 'closed', | |
| sort: 'updated', | |
| direction: 'desc', | |
| per_page: 10 | |
| }); | |
| const merged = prs.filter(pr => | |
| pr.merged_at && pr.merge_commit_sha === sha | |
| ); | |
| if (merged.length === 0) { | |
| console.log('No merged PR found for this push — nothing to clean up.'); | |
| return; | |
| } | |
| for (const pr of merged) { | |
| const branch = pr.head.ref; | |
| const base = pr.base.ref; | |
| // Never delete develop or main | |
| if (['develop', 'main', 'master'].includes(branch)) { | |
| console.log(`Skipping protected branch: ${branch}`); | |
| continue; | |
| } | |
| // Only delete if the branch is in this repo (not a fork) | |
| if (pr.head.repo.full_name !== repo.owner + '/' + repo.repo) { | |
| console.log(`Skipping fork branch: ${pr.head.repo.full_name}/${branch}`); | |
| continue; | |
| } | |
| try { | |
| await github.rest.git.deleteRef({ | |
| ...repo, | |
| ref: `heads/${branch}` | |
| }); | |
| console.log(`Deleted branch ${branch} (PR #${pr.number} merged to ${base}, post-merge CI passed)`); | |
| } catch (e) { | |
| if (e.status === 422) { | |
| console.log(`Branch ${branch} already deleted`); | |
| } else { | |
| throw e; | |
| } | |
| } | |
| } | |
| - name: Report if CI failed (branch preserved) | |
| if: github.event.workflow_run.conclusion == 'failure' | |
| run: | | |
| echo "⚠️ Post-merge CI FAILED — source branch NOT deleted." | |
| echo "Fix the issue, then the branch will be cleaned up on the next successful run." |