1+ name : Scheduled Dependabot PRs Auto-Merge
2+
3+ on :
4+ schedule :
5+ - cron : ' 0 0 * * *' # Runs once a day at midnight UTC
6+ workflow_dispatch :
7+
8+ permissions :
9+ contents : write
10+ pull-requests : write
11+
12+ jobs :
13+ merge-dependabot :
14+ runs-on : ubuntu-latest
15+ steps :
16+ - name : Checkout repository
17+ uses : actions/checkout@v4
18+
19+ - name : Install GitHub CLI
20+ run : |
21+ sudo apt update
22+ sudo apt install -y gh
23+
24+ - name : Fetch & Filter Dependabot PRs
25+ env :
26+ GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
27+ run : |
28+ echo "🔍 Fetching all Dependabot PRs targeting 'dependabotchanges'..."
29+ > matched_prs.txt
30+ pr_batch=$(gh pr list --state open --json number,title,author,baseRefName,url \
31+ --jq '.[] | "\(.number)|\(.title)|\(.author.login)|\(.baseRefName)|\(.url)"')
32+ while IFS='|' read -r number title author base url; do
33+ author=$(echo "$author" | xargs)
34+ base=$(echo "$base" | xargs)
35+ if [[ "$author" == "app/dependabot" && "$base" == "dependabotchanges" ]]; then
36+ echo "$url" >> matched_prs.txt
37+ echo "✅ Matched PR #$number - $title"
38+ else
39+ echo "❌ Skipped PR #$number - $title (Author: $author, Base: $base)"
40+ fi
41+ done <<< "$pr_batch"
42+ echo "👉 Matched PRs:"
43+ cat matched_prs.txt || echo "None"
44+
45+ - name : Rebase PR if Conflicts Exist
46+ if : success()
47+ env :
48+ GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
49+ run : |
50+ if [[ ! -s matched_prs.txt ]]; then
51+ echo "⚠️ No matching PRs to process."
52+ exit 0
53+ fi
54+ while IFS= read -r pr_url; do
55+ pr_number=$(basename "$pr_url")
56+ echo "🔁 Rebasing PR #$pr_number if conflicts exist"
57+ mergeable=$(gh pr view "$pr_number" --json mergeable --jq '.mergeable')
58+ if [[ "$mergeable" == "CONFLICTING" ]]; then
59+ echo "❌ Merge conflicts detected. Rebasing PR #$pr_number"
60+ gh pr update-branch "$pr_url" || echo "❗ Rebase (update-branch) failed."
61+ fi
62+ done < matched_prs.txt
63+
64+ - name : Auto-Merge if Mergeable
65+ if : success()
66+ env :
67+ GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
68+ run : |
69+ if [[ ! -s matched_prs.txt ]]; then
70+ echo "⚠️ No matching PRs to process."
71+ exit 0
72+ fi
73+ while IFS= read -r pr_url; do
74+ echo "🔍 Checking mergeability for $pr_url"
75+ pr_number=$(basename "$pr_url")
76+ attempt=0
77+ max_attempts=8
78+ mergeable=""
79+ sleep 5 # Initial delay to allow GitHub to compute mergeability
80+ while [[ $attempt -lt $max_attempts ]]; do
81+ mergeable=$(gh pr view "$pr_number" --json mergeable --jq '.mergeable' 2>/dev/null || echo "UNKNOWN")
82+ echo "🔁 Attempt $((attempt+1))/$max_attempts: mergeable=$mergeable"
83+ if [[ "$mergeable" == "MERGEABLE" ]]; then
84+ echo "🚀 Enabling auto-merge..."
85+ set -x
86+ merge_output=$(gh pr merge --auto --merge "$pr_url" 2>&1)
87+ merge_status=$?
88+ set +x
89+ echo "$merge_output"
90+ if [[ $merge_status -ne 0 ]]; then
91+ echo "❗ Auto-merge failed. Output: $merge_output"
92+ else
93+ echo "✅ Auto-merge succeeded!"
94+ fi
95+ break
96+ elif [[ "$mergeable" == "CONFLICTING" ]]; then
97+ echo "❌ Cannot merge due to conflicts. Skipping."
98+ break
99+ else
100+ echo "🕒 Waiting for GitHub to determine mergeable status..."
101+ sleep 15
102+ fi
103+ ((attempt++))
104+ done
105+ if [[ "$mergeable" != "MERGEABLE" && "$mergeable" != "CONFLICTING" ]]; then
106+ echo "❌ Mergeability undetermined after $max_attempts attempts. Skipping PR #$pr_number"
107+ fi
108+ done < matched_prs.txt || echo "⚠️ Completed loop with some errors, but continuing gracefully."
0 commit comments