Branch Cleanup #126
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' | |
| on: | |
| schedule: | |
| - cron: '0 0 * * *' # Daily at midnight UTC | |
| workflow_dispatch: | |
| inputs: | |
| dry_run: | |
| description: 'Dry run (list branches without deleting)' | |
| required: false | |
| default: false | |
| type: boolean | |
| permissions: | |
| contents: write | |
| jobs: | |
| delete-merged-branches: | |
| name: 'Delete Merged Branches' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Delete merged branches | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| DRY_RUN: ${{ github.event.inputs.dry_run || 'false' }} | |
| run: | | |
| echo "## 🧹 Branch Cleanup" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| # Protected branches that should never be deleted | |
| PROTECTED_BRANCHES="main|master|develop|release/.*" | |
| # Get all remote branches | |
| echo "### Scanning branches..." >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| DELETED_COUNT=0 | |
| SKIPPED_COUNT=0 | |
| # List merged branches (excluding HEAD and protected branches) | |
| for branch in $(git branch -r --merged origin/main | grep -v HEAD | grep -v -E "origin/($PROTECTED_BRANCHES)$" | sed 's/origin\///'); do | |
| # Skip if branch name matches protected pattern | |
| if echo "$branch" | grep -qE "^($PROTECTED_BRANCHES)$"; then | |
| echo "⏭️ Skipping protected branch: $branch" >> $GITHUB_STEP_SUMMARY | |
| SKIPPED_COUNT=$((SKIPPED_COUNT + 1)) | |
| continue | |
| fi | |
| if [ "$DRY_RUN" == "true" ]; then | |
| echo "🔍 [DRY RUN] Would delete: $branch" >> $GITHUB_STEP_SUMMARY | |
| DELETED_COUNT=$((DELETED_COUNT + 1)) | |
| else | |
| echo "🗑️ Deleting: $branch" | |
| if gh api --method DELETE "repos/${{ github.repository }}/git/refs/heads/$branch" 2>/dev/null; then | |
| echo "✅ Deleted: $branch" >> $GITHUB_STEP_SUMMARY | |
| DELETED_COUNT=$((DELETED_COUNT + 1)) | |
| else | |
| echo "⚠️ Failed to delete: $branch" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| fi | |
| done | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "### Summary" >> $GITHUB_STEP_SUMMARY | |
| if [ "$DRY_RUN" == "true" ]; then | |
| echo "- **Would delete**: $DELETED_COUNT branches" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "- **Deleted**: $DELETED_COUNT branches" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| echo "- **Skipped (protected)**: $SKIPPED_COUNT branches" >> $GITHUB_STEP_SUMMARY |