Skip to content

Commit 4616964

Browse files
authored
ci: Skip merge queue if pull request is up-to-date (#7514)
## Explanation This adds a new action which determines whether a pull request in the merge queue is up-to-date, meaning: - The pull request is based on the latest commit on `main`. - The pull request is the first in the merge queue. In this case, all status checks have already passed on the branch, and running in the merge queue would be redundant, meaning we can skip the merge queue checks. To accomplish this, I've added an output to the action (`up-to-date`) which we can use in all steps in the main workflow to determine if they should run. If `up-to-date` is `true`, all jobs except `all-jobs-pass` will be skipped, and the pull request will be merged much quicker. ## References <!-- Are there any issues that this pull request is tied to? Are there other links that reviewers should consult to understand these changes better? Are there client or consumer pull requests to adopt any breaking changes? For example: * Fixes #12345 * Related to #67890 --> WPC-184 ## Checklist - [ ] I've updated the test suite for new or updated code as appropriate - [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate - [ ] I've communicated my changes to consumers by [updating changelogs for packages I've changed](https://github.com/MetaMask/core/tree/main/docs/contributing.md#updating-changelogs) - [ ] I've introduced [breaking changes](https://github.com/MetaMask/core/tree/main/docs/breaking-changes.md) in this PR and have prepared draft pull requests for clients and consumer packages to resolve them <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Adds a composite action to detect up-to-date PRs in the merge queue and gates workflow jobs to skip queue checks when eligible. > > - **CI**: > - **New composite action** `/.github/actions/check-merge-queue`: > - Extracts PR number from `head-ref`, queries GraphQL for `headRefName` and `mergeQueueEntry.position`, and outputs `up-to-date` when branch is based on latest `base-ref` and queue position is `1`. > - **Workflow updates** `/.github/workflows/main.yml`: > - Adds `check-skip-merge-queue` job (merge_group only) exposing `skip-merge-queue`. > - Gates `check-workflows` with conditional `needs`/`if` to skip when `skip-merge-queue` is `true`. > - Updates `all-jobs-pass` to depend on `check-skip-merge-queue` and succeed if either all jobs passed or skipping is allowed via `PASSED` env. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit ceccfa8. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent 9700a18 commit 4616964

File tree

2 files changed

+118
-3
lines changed

2 files changed

+118
-3
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
name: Check 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+
inputs:
6+
head-ref:
7+
description: The name of the head ref (the pull request branch).
8+
required: true
9+
default: ${{ github.event.merge_group.head_ref }}
10+
11+
base-ref:
12+
description: The name of the base ref (e.g., main, master).
13+
required: true
14+
default: main
15+
16+
github-token:
17+
description: The GitHub token to use for authentication.
18+
required: true
19+
default: ${{ github.token }}
20+
21+
outputs:
22+
up-to-date:
23+
value: ${{ steps.up-to-date.outputs.up-to-date }}
24+
description: Whether the pull request is up-to-date with the base branch
25+
and is first in the merge queue, allowing it to skip the merge queue.
26+
27+
runs:
28+
using: composite
29+
steps:
30+
- name: Checkout repository
31+
uses: actions/checkout@v6
32+
with:
33+
fetch-depth: 0
34+
35+
- name: Get pull request details
36+
id: pr-details
37+
uses: actions/github-script@v8
38+
env:
39+
HEAD_REF: ${{ inputs.head-ref }}
40+
with:
41+
github-token: ${{ inputs.github-token }}
42+
script: |
43+
const { HEAD_REF } = process.env;
44+
const match = HEAD_REF.match(/\/pr-([0-9]+)-/u);
45+
if (!match) {
46+
return core.setFailed(`Could not extract pull request number from head ref: "${HEAD_REF}".`);
47+
}
48+
49+
const number = parseInt(match[1], 10);
50+
const result = await github.graphql(`
51+
query($owner: String!, $name: String!, $number: Int!) {
52+
repository(owner: $owner, name: $name) {
53+
pullRequest(number: $number) {
54+
headRefName
55+
mergeQueueEntry { position }
56+
}
57+
}
58+
}
59+
`, {
60+
owner: context.repo.owner,
61+
name: context.repo.repo,
62+
number,
63+
});
64+
65+
if (!result.repository.pullRequest) {
66+
return core.setFailed(`Pull request #${number} not found in repository "${context.repo.owner}/${context.repo.repo}".`);
67+
}
68+
69+
const position = result.repository.pullRequest.mergeQueueEntry?.position;
70+
if (!position) {
71+
return core.setFailed(`Pull request #${number} is not in the merge queue.`);
72+
}
73+
74+
core.setOutput('pr-number', number);
75+
core.setOutput('pr-branch', result.repository.pullRequest.headRefName);
76+
core.setOutput('merge-queue-position', position);
77+
78+
- name: Check if pull request is up-to-date with base branch
79+
id: up-to-date
80+
shell: bash
81+
env:
82+
BASE_REF: ${{ inputs.base-ref }}
83+
PR_BRANCH: ${{ steps.pr-details.outputs.pr-branch }}
84+
MERGE_QUEUE_POSITION: ${{ steps.pr-details.outputs.merge-queue-position }}
85+
run: |
86+
set -euo pipefail
87+
if git merge-base --is-ancestor "origin/${BASE_REF}" "origin/${PR_BRANCH}" && [ "${MERGE_QUEUE_POSITION}" -eq 1 ]; then
88+
echo "up-to-date=true" >> "$GITHUB_OUTPUT"
89+
else
90+
echo "up-to-date=false" >> "$GITHUB_OUTPUT"
91+
fi

.github/workflows/main.yml

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,29 @@ concurrency:
1111
cancel-in-progress: ${{ !contains(github.ref, 'refs/heads/main') }}
1212

1313
jobs:
14+
check-skip-merge-queue:
15+
name: Check if pull request can skip merge queue
16+
runs-on: ubuntu-latest
17+
outputs:
18+
skip-merge-queue: ${{ steps.check-skip-merge-queue.outputs.up-to-date }}
19+
steps:
20+
- name: Checkout repository
21+
uses: actions/checkout@v6
22+
if: github.event_name == 'merge_group'
23+
- name: Check pull request merge queue status
24+
id: check-skip-merge-queue
25+
if: github.event_name == 'merge_group'
26+
uses: ./.github/actions/check-merge-queue
27+
with:
28+
head-ref: ${{ github.event.merge_group.head_ref }}
29+
base-ref: main
30+
github-token: ${{ secrets.GITHUB_TOKEN }}
31+
1432
check-workflows:
1533
name: Check workflows
34+
needs:
35+
- check-skip-merge-queue
36+
if: github.event_name != 'merge_group' || needs.check-skip-merge-queue.outputs.skip-merge-queue != 'true'
1637
runs-on: ubuntu-latest
1738
steps:
1839
- uses: actions/checkout@v5
@@ -127,11 +148,14 @@ jobs:
127148
name: All jobs pass
128149
if: ${{ always() }}
129150
runs-on: ubuntu-latest
130-
needs: all-jobs-complete
151+
needs:
152+
- all-jobs-complete
153+
- check-skip-merge-queue
154+
env:
155+
PASSED: ${{ needs.all-jobs-complete.outputs.passed == 'true' || needs.check-skip-merge-queue.outputs.skip-merge-queue == 'true' }}
131156
steps:
132157
- name: Check that all jobs have passed
133158
run: |
134-
passed="${{ needs.all-jobs-complete.outputs.passed }}"
135-
if [[ $passed != "true" ]]; then
159+
if [[ "$PASSED" != "true" ]]; then
136160
exit 1
137161
fi

0 commit comments

Comments
 (0)