Skip to content

Commit cd0e485

Browse files
authored
Add auto-merge queue workflow for PRs
This workflow automates the merging of pull requests based on CI success and the presence of an 'auto-merge' label. It handles various events and conditions to manage the merge queue effectively.
1 parent 39b6044 commit cd0e485

File tree

1 file changed

+248
-0
lines changed

1 file changed

+248
-0
lines changed
Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
name: Auto Merge Queue on CI Success
2+
on:
3+
check_suite:
4+
types: [completed]
5+
pull_request:
6+
types: [labeled]
7+
branches: [master-gmq]
8+
workflow_dispatch:
9+
inputs:
10+
pr_number:
11+
description: 'PR number to test workflow'
12+
required: true
13+
type: string
14+
15+
jobs:
16+
auto_enqueue:
17+
runs-on: ubuntu-latest
18+
steps:
19+
- name: Debug Event Information
20+
run: |
21+
echo "Event name: ${{ github.event_name }}"
22+
echo "Event action: ${{ github.event.action || 'N/A' }}"
23+
24+
if [[ "${{ github.event_name }}" == "check_suite" ]]; then
25+
echo "Check suite conclusion: ${{ github.event.check_suite.conclusion }}"
26+
echo "Check suite status: ${{ github.event.check_suite.status }}"
27+
echo "Check suite head branch: ${{ github.event.check_suite.head_branch }}"
28+
echo "Pull requests count: ${{ github.event.check_suite.pull_requests[0] && '1+' || '0' }}"
29+
elif [[ "${{ github.event_name }}" == "pull_request" ]]; then
30+
echo "PR number: ${{ github.event.pull_request.number }}"
31+
echo "PR base ref: ${{ github.event.pull_request.base.ref }}"
32+
echo "PR state: ${{ github.event.pull_request.state }}"
33+
elif [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
34+
echo "Manual trigger for PR: ${{ github.event.inputs.pr_number }}"
35+
fi
36+
37+
- name: Determine PR Number and Validate
38+
id: get_pr
39+
run: |
40+
if [[ "${{ github.event_name }}" == "check_suite" ]]; then
41+
# For check_suite events
42+
if [[ "${{ github.event.check_suite.conclusion }}" != "success" ]]; then
43+
echo "Skip: Check suite conclusion is not success"
44+
echo "should_run=false" >> $GITHUB_OUTPUT
45+
exit 0
46+
fi
47+
48+
if [[ -z "${{ github.event.check_suite.pull_requests[0].number }}" ]]; then
49+
echo "Skip: No pull requests in check suite"
50+
echo "should_run=false" >> $GITHUB_OUTPUT
51+
exit 0
52+
fi
53+
54+
PR_NUMBER="${{ github.event.check_suite.pull_requests[0].number }}"
55+
BASE_REF="${{ github.event.check_suite.pull_requests[0].base.ref }}"
56+
57+
elif [[ "${{ github.event_name }}" == "pull_request" ]]; then
58+
# For pull_request events
59+
PR_NUMBER="${{ github.event.pull_request.number }}"
60+
BASE_REF="${{ github.event.pull_request.base.ref }}"
61+
62+
# Only process if auto-merge label was added
63+
if [[ "${{ github.event.action }}" == "labeled" && "${{ github.event.label.name }}" != "auto-merge" ]]; then
64+
echo "Skip: Label '${{ github.event.label.name }}' is not 'auto-merge'"
65+
echo "should_run=false" >> $GITHUB_OUTPUT
66+
exit 0
67+
fi
68+
69+
elif [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
70+
# For manual dispatch
71+
PR_NUMBER="${{ github.event.inputs.pr_number }}"
72+
# Get base ref from API
73+
BASE_REF=$(gh api repos/${{ github.repository }}/pulls/$PR_NUMBER --jq '.base.ref')
74+
75+
else
76+
echo "Skip: Unsupported event type"
77+
echo "should_run=false" >> $GITHUB_OUTPUT
78+
exit 0
79+
fi
80+
81+
# Validate base branch is master-gmq
82+
if [[ "$BASE_REF" != "master-gmq" ]]; then
83+
echo "Skip: PR base branch '$BASE_REF' is not 'master-gmq'"
84+
echo "should_run=false" >> $GITHUB_OUTPUT
85+
exit 0
86+
fi
87+
88+
echo "PR Number: $PR_NUMBER"
89+
echo "Base Ref: $BASE_REF"
90+
echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT
91+
echo "should_run=true" >> $GITHUB_OUTPUT
92+
env:
93+
GITHUB_TOKEN: ${{ secrets.MERGE_QUEUE_PAT }}
94+
95+
- name: Check if PR has auto-merge label
96+
id: check_label
97+
if: steps.get_pr.outputs.should_run == 'true'
98+
run: |
99+
PR_NUMBER="${{ steps.get_pr.outputs.pr_number }}"
100+
echo "Checking auto-merge label for PR #$PR_NUMBER"
101+
102+
HAS_LABEL=$(gh api repos/${{ github.repository }}/pulls/$PR_NUMBER --jq '.labels[] | select(.name == "auto-merge") | .name')
103+
echo "Label result: '$HAS_LABEL'"
104+
105+
if [[ -n "$HAS_LABEL" ]]; then
106+
echo "✅ PR has auto-merge label"
107+
echo "has_auto_merge_label=true" >> $GITHUB_OUTPUT
108+
else
109+
echo "❌ PR does not have auto-merge label"
110+
echo "has_auto_merge_label=false" >> $GITHUB_OUTPUT
111+
fi
112+
env:
113+
GITHUB_TOKEN: ${{ secrets.MERGE_QUEUE_PAT }}
114+
115+
- name: Verify All Required Checks Passed
116+
id: check_status
117+
if: steps.check_label.outputs.has_auto_merge_label == 'true'
118+
run: |
119+
PR_NUMBER="${{ steps.get_pr.outputs.pr_number }}"
120+
echo "Checking CI status for PR #$PR_NUMBER"
121+
122+
# Get PR details and check status
123+
CHECKS_STATUS=$(gh api graphql \
124+
-f owner="${{ github.repository_owner }}" \
125+
-f repo="${{ github.event.repository.name }}" \
126+
-F number="$PR_NUMBER" \
127+
-f query='
128+
query($owner: String!, $repo: String!, $number: Int!) {
129+
repository(owner: $owner, name: $repo) {
130+
pullRequest(number: $number) {
131+
commits(last: 1) {
132+
nodes {
133+
commit {
134+
statusCheckRollup {
135+
state
136+
}
137+
}
138+
}
139+
}
140+
}
141+
}
142+
}' --jq '.data.repository.pullRequest.commits.nodes[0].commit.statusCheckRollup.state')
143+
144+
echo "CI Status: $CHECKS_STATUS"
145+
echo "checks_status=$CHECKS_STATUS" >> $GITHUB_OUTPUT
146+
147+
if [[ "$CHECKS_STATUS" == "SUCCESS" ]]; then
148+
echo "✅ All CI checks passed"
149+
else
150+
echo "❌ CI checks not successful (status: $CHECKS_STATUS)"
151+
fi
152+
env:
153+
GITHUB_TOKEN: ${{ secrets.MERGE_QUEUE_PAT }}
154+
155+
- name: Add to Merge Queue
156+
if: |
157+
steps.check_label.outputs.has_auto_merge_label == 'true' &&
158+
steps.check_status.outputs.checks_status == 'SUCCESS'
159+
run: |
160+
PR_NUMBER="${{ steps.get_pr.outputs.pr_number }}"
161+
162+
echo "🚀 Adding PR #$PR_NUMBER to merge queue with PAT..."
163+
164+
# Get PR ID using GraphQL
165+
PR_ID=$(gh api graphql \
166+
-f owner="${{ github.repository_owner }}" \
167+
-f repo="${{ github.event.repository.name }}" \
168+
-F number="$PR_NUMBER" \
169+
-f query='
170+
query($owner: String!, $repo: String!, $number: Int!) {
171+
repository(owner: $owner, name: $repo) {
172+
pullRequest(number: $number) {
173+
id
174+
title
175+
baseRefName
176+
}
177+
}
178+
}' --jq '.data.repository.pullRequest.id')
179+
180+
echo "📋 PR ID: $PR_ID"
181+
182+
# Enqueue PR using GraphQL mutation
183+
RESULT=$(gh api graphql \
184+
-f pr_id="$PR_ID" \
185+
-f query='
186+
mutation($pr_id: ID!) {
187+
enqueuePullRequest(input: {
188+
pullRequestId: $pr_id
189+
}) {
190+
clientMutationId
191+
mergeQueueEntry {
192+
id
193+
position
194+
}
195+
}
196+
}')
197+
198+
echo "GraphQL Result: $RESULT"
199+
200+
QUEUE_POSITION=$(echo "$RESULT" | jq -r '.data.enqueuePullRequest.mergeQueueEntry.position // "unknown"')
201+
echo "✅ Successfully added to merge queue at position: $QUEUE_POSITION"
202+
203+
# Comment on PR with success
204+
gh api repos/${{ github.repository }}/issues/$PR_NUMBER/comments \
205+
-f body="🤖 Automatically added to merge queue at position **$QUEUE_POSITION** after CI success ✅
206+
207+
Event: ${{ github.event_name }}
208+
Trigger: Auto-merge label detected with successful CI"
209+
210+
env:
211+
GITHUB_TOKEN: ${{ secrets.MERGE_QUEUE_PAT }}
212+
213+
- name: Handle Conditions Not Met
214+
if: |
215+
steps.get_pr.outputs.should_run == 'true' &&
216+
(steps.check_label.outputs.has_auto_merge_label != 'true' ||
217+
steps.check_status.outputs.checks_status != 'SUCCESS')
218+
run: |
219+
PR_NUMBER="${{ steps.get_pr.outputs.pr_number }}"
220+
HAS_LABEL="${{ steps.check_label.outputs.has_auto_merge_label }}"
221+
CHECKS_STATUS="${{ steps.check_status.outputs.checks_status }}"
222+
223+
echo "❌ Conditions not met for PR #$PR_NUMBER:"
224+
echo " - Has auto-merge label: $HAS_LABEL"
225+
echo " - CI status: $CHECKS_STATUS"
226+
227+
if [[ "$HAS_LABEL" == "true" && "$CHECKS_STATUS" != "SUCCESS" ]]; then
228+
gh api repos/${{ github.repository }}/issues/$PR_NUMBER/comments \
229+
-f body="⏳ PR has auto-merge label but CI checks are not successful yet (status: $CHECKS_STATUS). Will auto-queue when CI passes."
230+
fi
231+
env:
232+
GITHUB_TOKEN: ${{ secrets.MERGE_QUEUE_PAT }}
233+
234+
- name: Handle Enqueue Failure
235+
if: failure()
236+
run: |
237+
if [[ "${{ steps.get_pr.outputs.should_run }}" == "true" ]]; then
238+
PR_NUMBER="${{ steps.get_pr.outputs.pr_number }}"
239+
echo "❌ Failed to add PR #$PR_NUMBER to merge queue"
240+
241+
# Comment on PR with failure
242+
gh api repos/${{ github.repository }}/issues/$PR_NUMBER/comments \
243+
-f body="❌ Failed to add PR to merge queue automatically. Please check the [action logs](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) or add manually using GraphQL.
244+
245+
Error occurred during: ${{ github.event_name }} event"
246+
fi
247+
env:
248+
GITHUB_TOKEN: ${{ secrets.MERGE_QUEUE_PAT }}

0 commit comments

Comments
 (0)