Skip to content

Commit 0943541

Browse files
authored
feat: Add action which determines if the merge queue can be safely skipped (#191)
* Add action which determines if the merge queue can be safely skipped * Add error handling and continue on error
1 parent e312838 commit 0943541

File tree

1 file changed

+111
-0
lines changed

1 file changed

+111
-0
lines changed
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
name: Check skip merge queue
2+
description: Check whether a pull request can skip the merge queue when it's
3+
up-to-date with the base branch.
4+
5+
This action determines if the pull request is the first in the merge queue
6+
and whether it is up-to-date with the base branch. If both conditions are
7+
met, the action outputs that the pull request can skip the merge queue.
8+
Actual skipping of the merge queue must be handled separately, since GitHub
9+
Actions cannot modify the merge queue behaviour directly.
10+
11+
This action should be used in workflows triggered by `merge_group` events.
12+
13+
inputs:
14+
head-ref:
15+
description: The name of the head ref (the pull request branch). Defaults
16+
to the head ref of the merge group event.
17+
required: true
18+
default: ${{ github.event.merge_group.head_ref }}
19+
20+
base-ref:
21+
description: The name of the base ref (e.g., main, master). Defaults to
22+
main.
23+
required: true
24+
default: main
25+
26+
github-token:
27+
description: The GitHub token to use for authentication. Defaults to the
28+
standard GITHUB_TOKEN.
29+
required: true
30+
default: ${{ github.token }}
31+
32+
outputs:
33+
up-to-date:
34+
value: ${{ steps.up-to-date.outputs.up-to-date }}
35+
description: Whether the pull request is up-to-date with the base branch
36+
and is first in the merge queue, allowing it to skip the merge queue.
37+
38+
runs:
39+
using: composite
40+
steps:
41+
- name: Checkout repository
42+
uses: actions/checkout@v6
43+
with:
44+
fetch-depth: 0
45+
46+
- name: Get pull request details
47+
continue-on-error: true
48+
id: pr-details
49+
uses: actions/github-script@v8
50+
env:
51+
HEAD_REF: ${{ inputs.head-ref }}
52+
with:
53+
github-token: ${{ inputs.github-token }}
54+
script: |
55+
const { HEAD_REF } = process.env;
56+
const match = HEAD_REF.match(/\/pr-([0-9]+)-/u);
57+
if (!match) {
58+
return core.setFailed(`Could not extract pull request number from head ref: "${HEAD_REF}".`);
59+
}
60+
61+
const number = parseInt(match[1], 10);
62+
const result = await github.graphql(`
63+
query($owner: String!, $name: String!, $number: Int!) {
64+
repository(owner: $owner, name: $name) {
65+
pullRequest(number: $number) {
66+
headRefName
67+
mergeQueueEntry { position }
68+
}
69+
}
70+
}
71+
`, {
72+
owner: context.repo.owner,
73+
name: context.repo.repo,
74+
number,
75+
});
76+
77+
if (!result.repository.pullRequest) {
78+
return core.setFailed(`Pull request #${number} not found in repository "${context.repo.owner}/${context.repo.repo}".`);
79+
}
80+
81+
const position = result.repository.pullRequest.mergeQueueEntry?.position;
82+
if (!position) {
83+
return core.setFailed(`Pull request #${number} is not in the merge queue.`);
84+
}
85+
86+
core.setOutput('pr-number', number);
87+
core.setOutput('pr-branch', result.repository.pullRequest.headRefName);
88+
core.setOutput('merge-queue-position', position);
89+
90+
- name: Check if pull request is up-to-date with base branch
91+
continue-on-error: true
92+
id: up-to-date
93+
shell: bash
94+
env:
95+
BASE_REF: ${{ inputs.base-ref }}
96+
PR_BRANCH: ${{ steps.pr-details.outputs.pr-branch }}
97+
MERGE_QUEUE_POSITION: ${{ steps.pr-details.outputs.merge-queue-position }}
98+
run: |
99+
set -euo pipefail
100+
if git merge-base --is-ancestor "origin/${BASE_REF}" "origin/${PR_BRANCH}" && [ "${MERGE_QUEUE_POSITION}" -eq 1 ]; then
101+
echo "up-to-date=true" >> "$GITHUB_OUTPUT"
102+
else
103+
echo "up-to-date=false" >> "$GITHUB_OUTPUT"
104+
fi
105+
106+
- name: Output `false` on failure
107+
if: steps.pr-details.outcome == 'failure' || steps.up-to-date.outcome == 'failure'
108+
shell: bash
109+
# If any previous step failed for any reason, instead of failing the
110+
# entire action, we catch the failure here and set the output to false.
111+
run: echo "up-to-date=false" >> "$GITHUB_OUTPUT"

0 commit comments

Comments
 (0)