Skip to content

Commit b272ab2

Browse files
committed
feat: add auto-merge workflow for Dependabot updates
1 parent bb6d1f7 commit b272ab2

File tree

1 file changed

+171
-0
lines changed

1 file changed

+171
-0
lines changed
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
name: auto-merge dependabot updates
2+
3+
on:
4+
pull_request_target:
5+
branches: [ main ]
6+
types:
7+
- opened
8+
- synchronize
9+
- reopened
10+
- ready_for_review
11+
12+
permissions:
13+
pull-requests: write
14+
contents: write
15+
16+
jobs:
17+
dependabot-merge:
18+
runs-on: ubuntu-latest
19+
if: ${{ github.actor == 'dependabot[bot]' }}
20+
21+
steps:
22+
- name: Dependabot metadata
23+
id: metadata
24+
uses: dependabot/[email protected]
25+
with:
26+
github-token: "${{ secrets.DEPENDABOT_PAT }}" # Using PAT for enhanced features, alert-lookup, and compat-lookup
27+
alert-lookup: true # Enable security alert information
28+
compat-lookup: true # Enable compatibility score checking
29+
30+
- name: Check security and compatibility
31+
id: security_check
32+
run: |
33+
DEPS_JSON='${{ steps.metadata.outputs.updated-dependencies-json }}'
34+
35+
# Perform checks
36+
if [ "${{ steps.metadata.outputs.alert-state }}" = "OPEN" ]; then
37+
echo "⚠️ Security alert detected (GHSA: ${{ steps.metadata.outputs.ghsa-id }})"
38+
echo "CVSS Score: ${{ steps.metadata.outputs.cvss }}"
39+
echo "is_security_update=true" >> $GITHUB_OUTPUT
40+
else
41+
echo "is_security_update=false" >> $GITHUB_OUTPUT
42+
fi
43+
44+
if [ "${{ steps.metadata.outputs.compatibility-score }}" -lt 75 ]; then
45+
echo "⚠️ Low compatibility score: ${{ steps.metadata.outputs.compatibility-score }}"
46+
echo "is_compatible=false" >> $GITHUB_OUTPUT
47+
else
48+
echo "is_compatible=true" >> $GITHUB_OUTPUT
49+
fi
50+
51+
if [ "${{ steps.metadata.outputs.maintainer-changes }}" = "true" ]; then
52+
echo "⚠️ Maintainer changes detected"
53+
echo "has_maintainer_changes=true" >> $GITHUB_OUTPUT
54+
else
55+
echo "has_maintainer_changes=false" >> $GITHUB_OUTPUT
56+
fi
57+
58+
- name: Checkout repository
59+
uses: actions/checkout@v4
60+
if: ${{ steps.metadata.outputs.package-ecosystem == 'gomod' }}
61+
62+
- name: Setup Go
63+
uses: actions/setup-go@v5
64+
if: ${{ steps.metadata.outputs.package-ecosystem == 'gomod' }}
65+
with:
66+
go-version: 'stable'
67+
68+
- name: Process Go dependencies
69+
if: ${{ steps.metadata.outputs.package-ecosystem == 'gomod' }}
70+
run: |
71+
log_update_details() {
72+
local pr_number=$1
73+
echo "::group::Dependency Update Details for PR #$pr_number"
74+
echo "🔄 Dependencies: ${{ steps.metadata.outputs.dependency-names }}"
75+
echo "📦 Type: ${{ steps.metadata.outputs.dependency-type }}"
76+
echo "📈 Version: ${{ steps.metadata.outputs.previous-version }} → ${{ steps.metadata.outputs.new-version }}"
77+
echo "📂 Directory: ${{ steps.metadata.outputs.directory }}"
78+
[ "${{ steps.security_check.outputs.is_security_update }}" = "true" ] && \
79+
echo "🚨 Security update (CVSS: ${{ steps.metadata.outputs.cvss }})"
80+
echo "::endgroup::"
81+
}
82+
83+
echo "🔍 Fetching all Go-related Dependabot PRs..."
84+
GO_PRS=$(gh pr list \
85+
--author "dependabot[bot]" \
86+
--json number,title,createdAt,headRefName \
87+
--state open \
88+
--jq 'sort_by(.createdAt) | .[] | select(.title | contains("go.mod"))')
89+
90+
CURRENT_PR_PROCESSED=false
91+
92+
echo "$GO_PRS" | while read -r pr; do
93+
PR_NUMBER=$(echo "$pr" | jq -r .number)
94+
HEAD_BRANCH=$(echo "$pr" | jq -r .headRefName)
95+
96+
log_update_details $PR_NUMBER
97+
98+
# Skip indirect dependencies unless they're security updates
99+
if [ "${{ steps.metadata.outputs.dependency-type }}" = "indirect" ] && \
100+
[ "${{ steps.security_check.outputs.is_security_update }}" != "true" ]; then
101+
echo "⏭️ Skipping indirect dependency update"
102+
continue
103+
fi
104+
105+
# Special handling for security updates
106+
if [ "${{ steps.security_check.outputs.is_security_update }}" = "true" ]; then
107+
echo "🚨 Processing security update with priority"
108+
PRIORITY_MERGE=true
109+
fi
110+
111+
git fetch origin $HEAD_BRANCH
112+
git checkout $HEAD_BRANCH
113+
git pull origin $HEAD_BRANCH
114+
115+
echo "🛠️ Running go mod tidy for PR #$PR_NUMBER"
116+
go mod tidy
117+
118+
if git diff --quiet; then
119+
echo "✨ No changes required for PR #$PR_NUMBER"
120+
else
121+
echo "💾 Committing changes for PR #$PR_NUMBER"
122+
git config --global user.name "GitHub Actions"
123+
git config --global user.email "[email protected]"
124+
git commit -am "chore: go mod tidy for PR #$PR_NUMBER"
125+
git push origin $HEAD_BRANCH
126+
fi
127+
128+
# Auto-merge decision logic
129+
if [ "$PR_NUMBER" = "$CURRENT_PR_NUMBER" ]; then
130+
CURRENT_PR_PROCESSED=true
131+
if { [ "$UPDATE_TYPE" != "version-update:semver-major" ] || \
132+
[ "${{ steps.security_check.outputs.is_security_update }}" = "true" ]; } && \
133+
[ "${{ steps.security_check.outputs.is_compatible }}" = "true" ] && \
134+
[ "${{ steps.security_check.outputs.has_maintainer_changes }}" = "false" ]; then
135+
echo "🤖 Enabling auto-merge for current PR #$PR_NUMBER"
136+
gh pr merge --auto --merge "$PR_URL"
137+
fi
138+
elif [ "$CURRENT_PR_PROCESSED" = false ]; then
139+
echo "🔄 Processing older PR #$PR_NUMBER first"
140+
gh pr merge --auto --merge "$PR_NUMBER"
141+
fi
142+
done
143+
env:
144+
GITHUB_TOKEN: ${{ secrets.DEPENDABOT_PAT }}
145+
PR_URL: ${{ github.event.pull_request.html_url }}
146+
CURRENT_PR_NUMBER: ${{ github.event.pull_request.number }}
147+
UPDATE_TYPE: ${{ steps.metadata.outputs.update-type }}
148+
149+
# Handle other dependencies with security awareness
150+
- name: Enable auto-merge for pipeline dependencies
151+
if: |
152+
steps.security_check.outputs.is_compatible == 'true' &&
153+
steps.security_check.outputs.has_maintainer_changes == 'false' &&
154+
(steps.metadata.outputs.update-type != 'version-update:semver-major' || steps.security_check.outputs.is_security_update == 'true') &&
155+
contains(steps.metadata.outputs.directory, '.github/workflows')
156+
run: gh pr merge --auto --merge "$PR_URL"
157+
env:
158+
PR_URL: ${{github.event.pull_request.html_url}}
159+
GITHUB_TOKEN: ${{secrets.DEPENDABOT_PAT}}
160+
161+
- name: Enable auto-merge for other dependencies
162+
if: |
163+
steps.security_check.outputs.is_compatible == 'true' &&
164+
steps.security_check.outputs.has_maintainer_changes == 'false' &&
165+
(steps.metadata.outputs.update-type != 'version-update:semver-major' || steps.security_check.outputs.is_security_update == 'true') &&
166+
steps.metadata.outputs.package-ecosystem != 'gomod' &&
167+
!contains(steps.metadata.outputs.directory, '.github/workflows')
168+
run: gh pr merge --auto --merge "$PR_URL"
169+
env:
170+
PR_URL: ${{github.event.pull_request.html_url}}
171+
GITHUB_TOKEN: ${{secrets.DEPENDABOT_PAT}}

0 commit comments

Comments
 (0)