Skip to content

Commit 2675486

Browse files
committed
fixup! tools: prefilter commit queue metadata
1 parent 9972589 commit 2675486

2 files changed

Lines changed: 65 additions & 82 deletions

File tree

‎.github/workflows/commit-queue.yml‎

Lines changed: 32 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@ permissions:
2222
contents: read
2323

2424
jobs:
25-
get_mergeable_prs:
25+
get_candidate_prs:
2626
permissions:
2727
pull-requests: read
2828
if: github.repository == 'nodejs/node'
2929
runs-on: ubuntu-slim
3030
outputs:
31-
numbers: ${{ steps.get_mergeable_prs.outputs.numbers }}
31+
candidates: ${{ steps.get_candidate_prs.outputs.candidates }}
3232
steps:
3333
- name: Get Pull Request Candidates
3434
id: get_candidate_prs
@@ -55,36 +55,48 @@ jobs:
5555
echo "candidates=$candidates" >> "$GITHUB_OUTPUT"
5656
env:
5757
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
58-
58+
commitQueue:
59+
needs: get_candidate_prs
60+
if: needs.get_candidate_prs.outputs.candidates != ''
61+
runs-on: ubuntu-slim
62+
steps:
63+
# Install dependencies
5964
- name: Install Node.js
60-
if: steps.get_candidate_prs.outputs.candidates != ''
6165
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
6266
with:
6367
node-version: ${{ env.NODE_VERSION }}
6468
- name: Install @node-core/utils
65-
if: steps.get_candidate_prs.outputs.candidates != ''
6669
run: npm install -g @node-core/utils
6770

71+
- name: Set variables
72+
run: |
73+
echo "REPOSITORY=$(echo "$GITHUB_REPOSITORY" | cut -d/ -f2)" >> "$GITHUB_ENV"
74+
75+
- name: Configure @node-core/utils
76+
run: |
77+
ncu-config set branch "${GITHUB_REF_NAME}"
78+
ncu-config set upstream origin
79+
ncu-config set username "$USERNAME"
80+
ncu-config set token "$GITHUB_TOKEN"
81+
ncu-config set jenkins_token "$JENKINS_TOKEN"
82+
ncu-config set repo "${REPOSITORY}"
83+
ncu-config set owner "${GITHUB_REPOSITORY_OWNER}"
84+
env:
85+
USERNAME: ${{ secrets.JENKINS_USER }}
86+
GITHUB_TOKEN: ${{ secrets.GH_USER_TOKEN }}
87+
JENKINS_TOKEN: ${{ secrets.JENKINS_TOKEN }}
88+
6889
- name: Filter Pull Requests
69-
if: steps.get_candidate_prs.outputs.candidates != ''
7090
id: get_mergeable_prs
7191
run: |
7292
fail_selector() {
7393
echo "$1"
7494
exit 1
7595
}
7696
77-
repository="${GITHUB_REPOSITORY#*/}"
7897
readme="${RUNNER_TEMP}/README.md"
7998
readme_base64="${RUNNER_TEMP}/README.md.base64"
8099
81-
ncu-config set branch "${GITHUB_REF_NAME}"
82-
ncu-config set username "$USERNAME"
83-
ncu-config set token "$GITHUB_TOKEN"
84-
ncu-config set jenkins_token "$JENKINS_TOKEN"
85-
ncu-config set repo "$repository"
86-
ncu-config set owner "${GITHUB_REPOSITORY_OWNER}"
87-
88100
if ! gh api "repos/${GITHUB_REPOSITORY}/contents/README.md?ref=${GITHUB_REF_NAME}" \
89101
--jq '.content' > "$readme_base64"; then
90102
fail_selector "failed to download README.md"
@@ -101,7 +113,7 @@ jobs:
101113
output="${RUNNER_TEMP}/metadata-${pr}.txt"
102114
if git node metadata "$pr" \
103115
--owner "$GITHUB_REPOSITORY_OWNER" \
104-
--repo "$repository" \
116+
--repo "$REPOSITORY" \
105117
--readme "$readme" \
106118
--json > "$metadata" 2> "$output"; then
107119
metadata_status=0
@@ -148,50 +160,20 @@ jobs:
148160
numbers=$(echo "$numbers" | xargs)
149161
echo "numbers=$numbers" >> "$GITHUB_OUTPUT"
150162
env:
151-
CANDIDATES: ${{ steps.get_candidate_prs.outputs.candidates }}
152-
USERNAME: ${{ secrets.JENKINS_USER }}
163+
CANDIDATES: ${{ needs.get_candidate_prs.outputs.candidates }}
153164
GITHUB_TOKEN: ${{ secrets.GH_USER_TOKEN }}
154-
JENKINS_TOKEN: ${{ secrets.JENKINS_TOKEN }}
155-
commitQueue:
156-
needs: get_mergeable_prs
157-
if: needs.get_mergeable_prs.outputs.numbers != ''
158-
runs-on: ubuntu-slim
159-
steps:
165+
160166
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
167+
if: steps.get_mergeable_prs.outputs.numbers != ''
161168
with:
162169
# A personal token is required because pushing with GITHUB_TOKEN will
163170
# prevent commits from running CI after they land. It needs
164171
# to be set here because `checkout` configures GitHub authentication
165172
# for push as well.
166173
token: ${{ secrets.GH_USER_TOKEN }}
167174

168-
# Install dependencies
169-
- name: Install Node.js
170-
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
171-
with:
172-
node-version: ${{ env.NODE_VERSION }}
173-
- name: Install @node-core/utils
174-
run: npm install -g @node-core/utils
175-
176-
- name: Set variables
177-
run: |
178-
echo "REPOSITORY=$(echo "$GITHUB_REPOSITORY" | cut -d/ -f2)" >> "$GITHUB_ENV"
179-
180-
- name: Configure @node-core/utils
181-
run: |
182-
ncu-config set branch "${GITHUB_REF_NAME}"
183-
ncu-config set upstream origin
184-
ncu-config set username "$USERNAME"
185-
ncu-config set token "$GITHUB_TOKEN"
186-
ncu-config set jenkins_token "$JENKINS_TOKEN"
187-
ncu-config set repo "${REPOSITORY}"
188-
ncu-config set owner "${GITHUB_REPOSITORY_OWNER}"
189-
env:
190-
USERNAME: ${{ secrets.JENKINS_USER }}
191-
GITHUB_TOKEN: ${{ secrets.GH_USER_TOKEN }}
192-
JENKINS_TOKEN: ${{ secrets.JENKINS_TOKEN }}
193-
194175
- name: Start the Commit Queue
195-
run: ./tools/actions/commit-queue.sh "${GITHUB_REPOSITORY_OWNER}" "${REPOSITORY}" ${{ needs.get_mergeable_prs.outputs.numbers }}
176+
if: steps.get_mergeable_prs.outputs.numbers != ''
177+
run: ./tools/actions/commit-queue.sh "${GITHUB_REPOSITORY_OWNER}" "${REPOSITORY}" ${{ steps.get_mergeable_prs.outputs.numbers }}
196178
env:
197179
GITHUB_TOKEN: ${{ secrets.GH_USER_TOKEN }}

‎doc/contributing/commit-queue.md‎

Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ From a high-level, the Commit Queue works as follows:
2727
workflow uses a five-minute cron, but GitHub Actions scheduled workflows are
2828
not guaranteed to run exactly every five minutes. For each candidate, the
2929
queue will:
30-
1. Run a metadata-only readiness check that uses `@node-core/utils` without
31-
checking out the repository
30+
1. In the landing job, install and configure `@node-core/utils`, then run a
31+
metadata-only readiness check without checking out the repository
3232
2. If the metadata check exits with a deferrable readiness code, meaning
3333
the PR is only blocked on wait time, keep the `commit-queue` label and
3434
skip this PR until a later queue run
@@ -93,20 +93,20 @@ reasons:
9393
commit, meaning we wouldn't be able to use it for already opened PRs
9494
without rebasing them first.
9595

96-
`@node-core/utils` is configured with a personal token and a Jenkins token from
97-
[@nodejs-github-bot](https://github.com/nodejs/github-bot). The workflow starts
98-
with a small selector step that uses GitHub CLI to fetch pull requests with the
99-
`commit-queue` label. It first fetches the same age-based and fast-track buckets
100-
the queue used before accepting early queue requests, then fetches the broader
101-
queue and de-duplicates the result. This keeps not-yet-ready PRs from crowding
102-
out PRs that the previous query would have selected if GitHub paginates or caps
103-
a query result.
104-
105-
If there are candidate PRs, the selector installs `@node-core/utils`, downloads
106-
the target branch's README without checking out the repository, and runs
96+
The workflow starts with a small candidate job that uses GitHub CLI to fetch
97+
pull requests with the `commit-queue` label. It first fetches the same
98+
age-based and fast-track buckets the queue used before accepting early queue
99+
requests, then fetches the broader queue and de-duplicates the result. This
100+
keeps not-yet-ready PRs from crowding out PRs that the previous query would
101+
have selected if GitHub paginates or caps a query result.
102+
103+
If there are candidate PRs, the landing job installs and configures
104+
`@node-core/utils` once with a personal token and a Jenkins token from
105+
[@nodejs-github-bot](https://github.com/nodejs/github-bot). It then downloads
106+
the target branch's README without checking out the repository and runs
107107
`git node metadata --readme --json` for each candidate. This uses the same
108108
`@node-core/utils` PR readiness checks as `git node land`, but does not clone,
109-
fetch, or merge the PR. The selector consumes the structured metadata result
109+
fetch, or merge the PR. The filter consumes the structured metadata result
110110
and its exit code instead of matching human-readable output:
111111

112112
* exit code `0`: the PR is ready and is passed to
@@ -119,12 +119,13 @@ and its exit code instead of matching human-readable output:
119119

120120
The `20`-`29` exit code range is reserved by `@node-core/utils` for deferrable
121121
metadata readiness states, and `40`-`49` is reserved for hard metadata failure
122-
states. Unknown selector failures fail the workflow before starting the landing
123-
job and leave PR labels unchanged so the queue can retry on a later scheduled
124-
run. PRs passed through with exit code `40`-`49` continue through
125-
`commit-queue.sh`. The script still applies its existing `request-ci` and
126-
pending-check deferrals before removing the queue label and reporting a hard
127-
failure.
122+
states. Unknown filter failures fail the workflow before starting the landing
123+
script and leave PR labels unchanged so the queue can retry on a later
124+
scheduled run. PRs passed through with exit code `40`-`49` continue through
125+
`commit-queue.sh`. The workflow checks out the repository only when at least
126+
one PR remains after filtering. The script still applies its existing
127+
`request-ci` and pending-check deferrals before removing the queue label and
128+
reporting a hard failure.
128129

129130
> The personal token needs permission for public repositories and to read
130131
> profiles. It is used by `@node-core/utils` and by the landing job for
@@ -146,18 +147,18 @@ done here since `git node land` will fail if the last CI failed.
146147
The script removes the `commit-queue` label, then runs `git node land`,
147148
forwarding stdout and stderr to a file. PRs that are only blocked on wait time
148149
should have already been filtered by the metadata check. If a hard readiness
149-
failure appears between the selector job and `git node land`, the landing job
150-
adds a `commit-queue-failed` label to the PR, leaves a comment with the output
151-
of `git node land`, and then aborts the landing session. If the abort fails,
152-
the queue stops instead of continuing in an unknown state.
153-
154-
Fast-tracked PRs use the metadata check before the landing job. If the
155-
fast-track request has not yet received enough collaborator thumbs-up, the queue
156-
keeps the `commit-queue` label and retries until either the fast-track request
157-
is approved or the PR becomes landable through the regular wait-time rules. The
158-
commit queue does not create the fast-track request comment; that is handled
159-
when the `fast-track` label is added. If that comment is missing, the queue
160-
reports the failure instead of keeping the PR queued.
150+
failure appears between the metadata filter and `git node land`, the landing
151+
job adds a `commit-queue-failed` label to the PR, leaves a comment with the
152+
output of `git node land`, and then aborts the landing session. If the abort
153+
fails, the queue stops instead of continuing in an unknown state.
154+
155+
Fast-tracked PRs use the metadata check before checkout and the landing script.
156+
If the fast-track request has not yet received enough collaborator thumbs-up,
157+
the queue keeps the `commit-queue` label and retries until either the
158+
fast-track request is approved or the PR becomes landable through the regular
159+
wait-time rules. The commit queue does not create the fast-track request
160+
comment; that is handled when the `fast-track` label is added. If that comment
161+
is missing, the queue reports the failure instead of keeping the PR queued.
161162

162163
If no errors happen during `git node land`, the script either pushes the direct
163164
rebase landing to `main` or uses GitHub's squash merge API for single-commit and

0 commit comments

Comments
 (0)