|
1 | | -name: 'Stale Bot' |
| 1 | +name: "Manage Stale Issues, PRs & Unmerged Branches" |
| 2 | + |
2 | 3 | on: |
3 | 4 | schedule: |
4 | | - - cron: '30 1 * * *' |
| 5 | + - cron: '30 1 * * *' # Runs daily at 1:30 AM UTC |
| 6 | + workflow_dispatch: # Allows manual triggering |
5 | 7 |
|
6 | 8 | permissions: |
7 | 9 | contents: write |
|
12 | 14 | stale: |
13 | 15 | runs-on: ubuntu-latest |
14 | 16 | steps: |
15 | | - - uses: actions/stale@v9 |
| 17 | + - name: Mark Stale Issues and PRs |
| 18 | + uses: actions/stale@v9 |
16 | 19 | with: |
17 | | - stale-issue-message: 'This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 30 days.' |
| 20 | + stale-issue-message: "This issue is stale because it has been open 180 days with no activity. Remove stale label or comment, or it will be closed in 30 days." |
| 21 | + stale-pr-message: "This PR is stale because it has been open 180 days with no activity. Please update or it will be closed in 30 days." |
18 | 22 | days-before-stale: 180 |
19 | 23 | days-before-close: 30 |
| 24 | + exempt-issue-labels: "keep" |
| 25 | + exempt-pr-labels: "keep" |
| 26 | + |
| 27 | + cleanup-branches: |
| 28 | + runs-on: ubuntu-latest |
| 29 | + steps: |
| 30 | + - name: Checkout Repository |
| 31 | + uses: actions/checkout@v4 |
| 32 | + with: |
| 33 | + fetch-depth: 0 # Fetch full history for accurate branch checks |
| 34 | + |
| 35 | + - name: Fetch All Branches |
| 36 | + run: git fetch --all --prune |
| 37 | + |
| 38 | + - name: Create CSV File |
| 39 | + run: echo "Branch,Last Commit Date,Merged Into,Status" > stale-branches-report.csv |
| 40 | + |
| 41 | + - name: Identify & List Stale Merged Branches with No Activity in Last 3 Months |
| 42 | + run: | |
| 43 | + echo "Checking merged branches with no activity in the last 3 months..." |
| 44 | + for branch_info in $(git for-each-ref --format '%(refname:short) %(committerdate:unix)' refs/remotes/origin | awk -v date=$(date -d '3 months ago' +%s) '$2 < date {print $1","$2}'); do |
| 45 | + branch=$(echo $branch_info | cut -d',' -f1) |
| 46 | + last_commit_date=$(git log -1 --format=%ci origin/$branch || echo "Unknown") |
| 47 | + merged_into=$(git branch -r --contains $branch | grep -E 'origin/main|origin/dev' | awk -F'/' '{print $2}' | tr '\n' ',' | sed 's/,$//') |
| 48 | + merged_into=${merged_into:-"Unknown"} |
| 49 | +
|
| 50 | + echo "$branch,$last_commit_date,$merged_into,Marked for Deletion" >> stale-branches-report.csv |
| 51 | + |
| 52 | + done |
| 53 | +
|
| 54 | + - name: Identify & List PR Approved & Merged Branches (Older Than 30 Days) |
| 55 | + run: | |
| 56 | + echo "Checking PR branches that were approved and merged more than 30 days ago..." |
| 57 | + for branch_info in $(gh api repos/${{ github.repository }}/pulls --jq '.[] | select(.merged_at != null and (.base.ref == "main" or .base.ref == "dev")) | select(.merged_at | fromdateiso8601 < (now - 2592000)) | [.head.ref, .merged_at, .base.ref] | @csv'); do |
| 58 | + branch=$(echo $branch_info | awk -F, '{print $1}' | tr -d '"') |
| 59 | + last_commit_date=$(git log -1 --format=%ci origin/$branch || echo "Unknown") |
| 60 | + merged_into=$(echo $branch_info | awk -F, '{print $3}' | tr -d '"') |
| 61 | +
|
| 62 | + echo "$branch,$last_commit_date,$merged_into,Marked for Deletion" >> stale-branches-report.csv |
| 63 | + |
| 64 | + done |
| 65 | + env: |
| 66 | + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
| 67 | + |
| 68 | + - name: Upload Stale Branch Report |
| 69 | + uses: actions/upload-artifact@v4 |
| 70 | + with: |
| 71 | + name: stale-branches-report |
| 72 | + path: stale-branches-report.csv |
| 73 | + retention-days: 30 |
0 commit comments