-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathaction.yml
More file actions
223 lines (187 loc) · 7.76 KB
/
action.yml
File metadata and controls
223 lines (187 loc) · 7.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
name: Trunk Upgrade with Auto-merge
description: Automated Trunk upgrades with status check handling and auto-merge
author: hello@masterpoint.io
inputs:
github-token:
description: GitHub token for creating PRs and performing operations
required: true
app-id:
description: GitHub App ID for bot authentication
app-private-key:
description: GitHub App private key for bot authentication
reviewers:
description: Reviewers to assign to the PR (e.g., '@org/team' or 'user1,user2')
default: ""
prefix:
description: Prefix for commit messages and PR titles
default: "chore: "
merge-method:
description: Method to use for merging (squash, merge, rebase)
default: squash
check-timeout-minutes:
description: Maximum time to wait for status checks (in minutes)
default: "10"
check-interval-seconds:
description: Interval between status check polls (in seconds)
default: "30"
outputs:
pull-request-number:
description: The number of the created pull request
value: ${{ steps.trunk-upgrade.outputs.pull-request-number }}
pull-request-url:
description: The URL of the created pull request
value: ${{ steps.trunk-upgrade.outputs.pull-request-url }}
merged:
description: Whether the PR was successfully merged
value: ${{ steps.auto-merge.outputs.merged }}
runs:
using: composite
steps:
- name: Validate inputs
shell: bash
run: |
if [[ -z "${{ inputs.github-token }}" ]]; then
echo "::error::github-token is required"
exit 1
fi
if [[ "${{ inputs.merge-method }}" != "squash" && "${{ inputs.merge-method }}" != "merge" && "${{ inputs.merge-method }}" != "rebase" ]]; then
echo "::error::merge-method must be one of: squash, merge, rebase"
exit 1
fi
- name: Generate GitHub App Token
if: inputs.app-id != '' && inputs.app-private-key != ''
uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a # v2.1.0
id: generate-token
with:
app_id: ${{ inputs.app-id }}
private_key: ${{ inputs.app-private-key }}
- name: Determine GitHub Token
shell: bash
id: github-token
run: |
if [[ -n "${{ steps.generate-token.outputs.token }}" ]]; then
echo "token=${{ steps.generate-token.outputs.token }}" >> $GITHUB_OUTPUT
else
echo "token=${{ inputs.github-token }}" >> $GITHUB_OUTPUT
fi
- name: Run Trunk Upgrade
id: trunk-upgrade
uses: trunk-io/trunk-action/upgrade@75699af9e26881e564e9d832ef7dc3af25ec031b # v1.2.4
with:
github-token: ${{ steps.github-token.outputs.token }}
reviewers: ${{ inputs.reviewers }}
prefix: ${{ inputs.prefix }}
- name: Auto-merge PR
if: steps.trunk-upgrade.outputs.pull-request-number != ''
id: auto-merge
shell: bash
env:
GH_TOKEN: ${{ inputs.github-token }}
PR_NUMBER: ${{ steps.trunk-upgrade.outputs.pull-request-number }}
REPO_URL: https://github.com/${{ github.repository }}
MERGE_METHOD: ${{ inputs.merge-method }}
TIMEOUT_MINUTES: ${{ inputs.check-timeout-minutes }}
CHECK_INTERVAL: ${{ inputs.check-interval-seconds }}
run: |
set -euo pipefail
# Helper functions
get_checks() {
local check_type="$1"
if [ "$check_type" = "required" ]; then
gh pr checks "$PR_NUMBER" --required --json state,bucket 2>/dev/null || echo "[]"
else
gh pr checks "$PR_NUMBER" --json state,bucket 2>/dev/null || echo "[]"
fi
}
count_checks() {
echo "$1" | jq '. | length'
}
has_failed_checks() {
echo "$1" | jq -e '.[] | select(.bucket=="fail")' >/dev/null 2>&1
}
count_pending_checks() {
echo "$1" | jq '[.[] | select(.state!="SUCCESS" or .bucket!="pass")] | length'
}
approve_and_merge_pr() {
local approval_message="$1"
echo "🤖 Auto-approving and merging PR $REPO_URL/pull/$PR_NUMBER..."
gh pr review "$PR_NUMBER" --approve --body "$approval_message"
# Retry merge up to 3 times to handle base branch updates
local max_retries=3
local retry_count=0
while [ $retry_count -lt $max_retries ]; do
if gh pr merge "$PR_NUMBER" --"$MERGE_METHOD" --delete-branch --admin; then
echo "✅ Successfully merged PR #$PR_NUMBER"
echo "merged=true" >> $GITHUB_OUTPUT
return 0
else
retry_count=$((retry_count + 1))
if [ $retry_count -lt $max_retries ]; then
echo "⚠️ Merge failed (attempt $retry_count/$max_retries). Retrying in 10 seconds..."
echo "This could be due to base branch updates or temporary GitHub issues."
sleep 10
else
echo "❌ Merge failed after $max_retries attempts. Manual intervention may be required."
echo "merged=false" >> $GITHUB_OUTPUT
return 1
fi
fi
done
}
# Main logic
echo "🔍 Checking PR #$PR_NUMBER for required status checks..."
# Allow time for checks to initialize
echo "⏳ Waiting $CHECK_INTERVAL seconds for checks to initialize..."
sleep "$CHECK_INTERVAL"
# Get required checks only (GitHub only requires these for merge)
REQUIRED_CHECKS=$(get_checks "required")
echo "📋 Required checks: $REQUIRED_CHECKS"
REQUIRED_COUNT=$(count_checks "$REQUIRED_CHECKS")
# Handle case with no required checks - can merge immediately
if [ "$REQUIRED_COUNT" -eq 0 ]; then
echo "✅ No required status checks configured. PR is ready to merge."
echo "Proceeding with auto-approval and merge..."
if approve_and_merge_pr "Auto-approved by trunk upgrade action (no required status checks)"; then
exit 0
else
echo "❌ Failed to merge PR. Exiting with error."
exit 1
fi
fi
echo "⏳ Waiting for $REQUIRED_COUNT required status checks to pass..."
# Wait for required checks to complete with timeout
timeout_seconds=$((TIMEOUT_MINUTES * 60))
start_time=$(date +%s)
while true; do
current_time=$(date +%s)
elapsed=$((current_time - start_time))
if [ $elapsed -gt $timeout_seconds ]; then
echo "⏰ Timeout reached after ${TIMEOUT_MINUTES} minutes"
echo "❌ Checks did not complete within the timeout period"
echo "merged=false" >> $GITHUB_OUTPUT
exit 1
fi
CURRENT_CHECKS=$(get_checks "required")
echo "📊 Current checks status: $CURRENT_CHECKS"
# Check for failed checks
if has_failed_checks "$CURRENT_CHECKS"; then
echo "❌ One or more required checks have failed. Exiting..."
echo "merged=false" >> $GITHUB_OUTPUT
exit 1
fi
# Check if all required checks have passed
PENDING_COUNT=$(count_pending_checks "$CURRENT_CHECKS")
if [ "$PENDING_COUNT" -eq 0 ]; then
if approve_and_merge_pr "Auto-approved by trunk upgrade action (all required checks passed)"; then
break
else
echo "❌ Failed to merge PR after all checks passed. Exiting with error."
exit 1
fi
else
remaining=$((timeout_seconds - elapsed))
echo "⏳ Some required checks are still running or pending ($PENDING_COUNT remaining)."
echo "Retrying in ${CHECK_INTERVAL}s (${remaining}s remaining)..."
sleep "$CHECK_INTERVAL"
fi
done