Skip to content

Commit 32bd35a

Browse files
committed
actions
1 parent 1a1b63f commit 32bd35a

File tree

3 files changed

+206
-2
lines changed

3 files changed

+206
-2
lines changed

.github/workflows/auto_merge_approved_prs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
- name: Checkout repository
1919
uses: actions/checkout@v4
2020
with:
21-
fetch-depth: 0
21+
fetch-depth: 1 # Only need latest commit for PR operations
2222
token: ${{ secrets.PAT_TOKEN }}
2323

2424
- name: Configure git

.github/workflows/build_master.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
- name: Checkout code
3030
uses: actions/checkout@v4
3131
with:
32-
fetch-depth: 0 #Needed to download everything to be able to access the master & language branches
32+
fetch-depth: 1 # Only fetch the latest commit for faster cloning
3333

3434
# Build the mdBook
3535
- name: Build mdBook
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
name: Cleanup Merged/Closed PR Branches
2+
3+
on:
4+
schedule:
5+
- cron: '0 2 * * 0' # Every Sunday at 2 AM UTC
6+
workflow_dispatch: # Allow manual triggering
7+
inputs:
8+
dry_run:
9+
description: 'Dry run (show what would be deleted without actually deleting)'
10+
required: false
11+
default: 'false'
12+
type: boolean
13+
14+
permissions:
15+
contents: write
16+
pull-requests: read
17+
18+
jobs:
19+
cleanup-branches:
20+
runs-on: ubuntu-latest
21+
22+
steps:
23+
- name: Checkout repository
24+
uses: actions/checkout@v4
25+
with:
26+
fetch-depth: 0 # Need full history to see all branches
27+
token: ${{ secrets.PAT_TOKEN }}
28+
29+
- name: Install GitHub CLI
30+
run: |
31+
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \
32+
&& sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg \
33+
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
34+
&& sudo apt update \
35+
&& sudo apt install gh -y
36+
37+
- name: Configure git
38+
run: |
39+
git config --global user.email "[email protected]"
40+
git config --global user.name "GitHub Action"
41+
42+
- name: Cleanup merged/closed PR branches
43+
env:
44+
GH_TOKEN: ${{ secrets.PAT_TOKEN }}
45+
run: |
46+
echo "Starting branch cleanup process..."
47+
48+
# Check if this is a dry run
49+
DRY_RUN="${{ github.event.inputs.dry_run || 'false' }}"
50+
if [ "$DRY_RUN" = "true" ]; then
51+
echo "🔍 DRY RUN MODE - No branches will actually be deleted"
52+
echo ""
53+
fi
54+
55+
# Define protected branches and patterns
56+
protected_branches=(
57+
"master"
58+
"main"
59+
)
60+
61+
# Translation branch patterns (any 2-letter combination)
62+
translation_pattern="^[a-zA-Z]{2}$"
63+
64+
# Get all remote branches except protected ones
65+
echo "Fetching all remote branches..."
66+
git fetch --all --prune
67+
68+
# Get list of all remote branches (excluding HEAD)
69+
all_branches=$(git branch -r | grep -v 'HEAD' | sed 's/origin\///' | grep -v '^$')
70+
71+
# Get all open PRs to identify branches with open PRs
72+
echo "Getting list of open PRs..."
73+
open_pr_branches=$(gh pr list --state open --json headRefName --jq '.[].headRefName' | sort | uniq)
74+
75+
echo "Open PR branches:"
76+
echo "$open_pr_branches"
77+
echo ""
78+
79+
deleted_count=0
80+
skipped_count=0
81+
82+
for branch in $all_branches; do
83+
branch=$(echo "$branch" | xargs) # Trim whitespace
84+
85+
# Skip if empty
86+
if [ -z "$branch" ]; then
87+
continue
88+
fi
89+
90+
echo "Checking branch: $branch"
91+
92+
# Check if it's a protected branch
93+
is_protected=false
94+
for protected in "${protected_branches[@]}"; do
95+
if [ "$branch" = "$protected" ]; then
96+
echo " ✓ Skipping protected branch: $branch"
97+
is_protected=true
98+
skipped_count=$((skipped_count + 1))
99+
break
100+
fi
101+
done
102+
103+
if [ "$is_protected" = true ]; then
104+
continue
105+
fi
106+
107+
# Check if it's a translation branch (any 2-letter combination)
108+
# Also protect any branch that starts with 2 letters followed by additional content
109+
if echo "$branch" | grep -Eq "$translation_pattern" || echo "$branch" | grep -Eq "^[a-zA-Z]{2}[_-]"; then
110+
echo " ✓ Skipping translation/language branch: $branch"
111+
skipped_count=$((skipped_count + 1))
112+
continue
113+
fi
114+
115+
# Check if branch has an open PR
116+
if echo "$open_pr_branches" | grep -Fxq "$branch"; then
117+
echo " ✓ Skipping branch with open PR: $branch"
118+
skipped_count=$((skipped_count + 1))
119+
continue
120+
fi
121+
122+
# Check if branch had a PR that was merged or closed
123+
echo " → Checking PR history for branch: $branch"
124+
125+
# Look for PRs from this branch (both merged and closed)
126+
pr_info=$(gh pr list --state all --head "$branch" --json number,state,mergedAt --limit 1)
127+
128+
if [ "$pr_info" != "[]" ]; then
129+
pr_state=$(echo "$pr_info" | jq -r '.[0].state')
130+
pr_number=$(echo "$pr_info" | jq -r '.[0].number')
131+
merged_at=$(echo "$pr_info" | jq -r '.[0].mergedAt')
132+
133+
if [ "$pr_state" = "MERGED" ] || [ "$pr_state" = "CLOSED" ]; then
134+
if [ "$DRY_RUN" = "true" ]; then
135+
echo " 🔍 [DRY RUN] Would delete branch: $branch (PR #$pr_number was $pr_state)"
136+
deleted_count=$((deleted_count + 1))
137+
else
138+
echo " ✗ Deleting branch: $branch (PR #$pr_number was $pr_state)"
139+
140+
# Delete the remote branch
141+
if git push origin --delete "$branch" 2>/dev/null; then
142+
echo " Successfully deleted remote branch: $branch"
143+
deleted_count=$((deleted_count + 1))
144+
else
145+
echo " Failed to delete remote branch: $branch"
146+
fi
147+
fi
148+
else
149+
echo " ✓ Skipping branch with open PR: $branch (PR #$pr_number is $pr_state)"
150+
skipped_count=$((skipped_count + 1))
151+
fi
152+
else
153+
# No PR found for this branch - it might be a stale branch
154+
# Check if branch is older than 30 days and has no recent activity
155+
last_commit_date=$(git log -1 --format="%ct" origin/"$branch" 2>/dev/null || echo "0")
156+
157+
if [ "$last_commit_date" != "0" ] && [ -n "$last_commit_date" ]; then
158+
# Calculate 30 days ago in seconds since epoch
159+
thirty_days_ago=$(($(date +%s) - 30 * 24 * 60 * 60))
160+
161+
if [ "$last_commit_date" -lt "$thirty_days_ago" ]; then
162+
if [ "$DRY_RUN" = "true" ]; then
163+
echo " 🔍 [DRY RUN] Would delete stale branch (no PR, >30 days old): $branch"
164+
deleted_count=$((deleted_count + 1))
165+
else
166+
echo " ✗ Deleting stale branch (no PR, >30 days old): $branch"
167+
168+
if git push origin --delete "$branch" 2>/dev/null; then
169+
echo " Successfully deleted stale branch: $branch"
170+
deleted_count=$((deleted_count + 1))
171+
else
172+
echo " Failed to delete stale branch: $branch"
173+
fi
174+
fi
175+
else
176+
echo " ✓ Skipping recent branch (no PR, <30 days old): $branch"
177+
skipped_count=$((skipped_count + 1))
178+
fi
179+
else
180+
echo " ✓ Skipping branch (cannot determine age): $branch"
181+
skipped_count=$((skipped_count + 1))
182+
fi
183+
fi
184+
185+
echo ""
186+
done
187+
188+
echo "=================================="
189+
echo "Branch cleanup completed!"
190+
if [ "$DRY_RUN" = "true" ]; then
191+
echo "Branches that would be deleted: $deleted_count"
192+
else
193+
echo "Branches deleted: $deleted_count"
194+
fi
195+
echo "Branches skipped: $skipped_count"
196+
echo "=================================="
197+
198+
# Clean up local tracking branches (only if not dry run)
199+
if [ "$DRY_RUN" != "true" ]; then
200+
echo "Cleaning up local tracking branches..."
201+
git remote prune origin
202+
fi
203+
204+
echo "Cleanup process finished."

0 commit comments

Comments
 (0)