Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion .github/workflows/auto-merge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@
# auto-merge waits for. enforce-repo-settings.yml flips allow_auto_merge
# automatically across the fleet.
#
# delete-merged-branch: repo-level delete_branch_on_merge reliably fires for
# user-initiated merges but not for merges landed by the github-actions app
# via native auto-merge (observed fleet-wide, e.g. qyl #452–#456, #477–#479
# survived; user-merged #476 was deleted). This job closes that gap for the
# automation prefixes. HEAD_REF is passed via env, never interpolated into
# the script, so a crafted branch name cannot inject into the shell under
# pull_request_target's write token.
#
# Branch-prefix policy:
# - claude/ — Claude Code agents
# - copilot/ — GitHub Copilot agents when enabled
Expand All @@ -21,7 +29,7 @@ name: Auto-merge

on:
pull_request_target:
types: [opened, synchronize, reopened, ready_for_review]
types: [opened, synchronize, reopened, ready_for_review, closed]

permissions:
contents: write
Expand All @@ -31,6 +39,7 @@ jobs:
enable-auto-merge:
runs-on: ubuntu-latest
if: |
github.event.action != 'closed' &&
github.event.pull_request.draft == false && (
startsWith(github.event.pull_request.head.ref, 'claude/') ||
startsWith(github.event.pull_request.head.ref, 'copilot/')
Expand All @@ -40,3 +49,21 @@ jobs:
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh pr merge ${{ github.event.pull_request.number }} --auto --squash --repo ${{ github.repository }}

delete-merged-branch:
runs-on: ubuntu-latest
if: |
github.event.action == 'closed' &&
github.event.pull_request.merged == true &&
github.event.pull_request.head.repo.full_name == github.repository && (
startsWith(github.event.pull_request.head.ref, 'claude/') ||
startsWith(github.event.pull_request.head.ref, 'copilot/')
)
steps:
- name: Delete merged head branch
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
HEAD_REF: ${{ github.event.pull_request.head.ref }}
run: |
gh api -X DELETE "repos/${{ github.repository }}/git/refs/heads/$HEAD_REF" \
|| echo "head branch already deleted"
Comment on lines +67 to +69
29 changes: 28 additions & 1 deletion templates/auto-merge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@
# auto-merge waits for. enforce-repo-settings.yml flips allow_auto_merge
# automatically across the fleet.
#
# delete-merged-branch: repo-level delete_branch_on_merge reliably fires for
# user-initiated merges but not for merges landed by the github-actions app
# via native auto-merge (observed fleet-wide, e.g. qyl #452–#456, #477–#479
# survived; user-merged #476 was deleted). This job closes that gap for the
# automation prefixes. HEAD_REF is passed via env, never interpolated into
# the script, so a crafted branch name cannot inject into the shell under
# pull_request_target's write token.
#
# Branch-prefix policy:
# - claude/ — Claude Code agents
# - copilot/ — GitHub Copilot agents when enabled
Expand All @@ -21,7 +29,7 @@ name: Auto-merge

on:
pull_request_target:
types: [opened, synchronize, reopened, ready_for_review]
types: [opened, synchronize, reopened, ready_for_review, closed]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Don’t rely on closed events from GITHUB_TOKEN auto-merges

For the app-merged PRs this is meant to clean up, the merge is caused by this workflow’s secrets.GITHUB_TOKEN auto-merge call, and GitHub documents that GITHUB_TOKEN-triggered events do not create workflow runs except workflow_dispatch, repository_dispatch, and pull_request opened/synchronize/reopened; closed is explicitly excluded (docs). Adding closed here therefore will not start the new deletion job for the github-actions native auto-merges whose branches are surviving, so the fleet cleanup remains ineffective unless the merge/delete path uses a PAT/App token or another dispatch/wait mechanism.

Useful? React with 👍 / 👎.


permissions:
contents: write
Expand All @@ -31,6 +39,7 @@ jobs:
enable-auto-merge:
runs-on: ubuntu-latest
if: |
github.event.action != 'closed' &&
github.event.pull_request.draft == false && (
startsWith(github.event.pull_request.head.ref, 'claude/') ||
startsWith(github.event.pull_request.head.ref, 'copilot/')
Expand All @@ -40,3 +49,21 @@ jobs:
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh pr merge ${{ github.event.pull_request.number }} --auto --squash --repo ${{ github.repository }}

delete-merged-branch:
runs-on: ubuntu-latest
if: |
github.event.action == 'closed' &&
github.event.pull_request.merged == true &&
github.event.pull_request.head.repo.full_name == github.repository && (
startsWith(github.event.pull_request.head.ref, 'claude/') ||
startsWith(github.event.pull_request.head.ref, 'copilot/')
)
steps:
- name: Delete merged head branch
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
HEAD_REF: ${{ github.event.pull_request.head.ref }}
run: |
gh api -X DELETE "repos/${{ github.repository }}/git/refs/heads/$HEAD_REF" \
|| echo "head branch already deleted"
Comment on lines +67 to +69

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Fail on branch deletion errors other than 404

When this job does run, this catch-all makes the workflow succeed for every gh api failure, not only the already-deleted branch case; GitHub CLI documents that failed commands return a nonzero exit code (docs), and the delete-ref API has distinct failure statuses such as 409/422 (docs). If a token permission, ruleset, API validation, or transient service failure prevents deletion, the step still ends green after printing “head branch already deleted,” so branch cleanup can silently do nothing.

Useful? React with 👍 / 👎.