Repository navigation
Conversation
pull_request_target is disabled by ASF infra policy and GitHub is adding a default policy that blocks it. Add pull_request_signal.yml and trigger labeler.yml and fork_ci_status.yml from its workflow_run. Label merged pull requests from the push to main in release_version_labeler.yaml.
|
Thank you for working on this |
All the credits to Apache Spark community, lets see if it works for us |
|
Nice! Good job :) . World is better with every single |
|
Glad my examples were helpful and useful to replicate :D |
| state: 'open', | ||
| head: `${run.head_repository.owner.login}:${run.head_branch}`, | ||
| }); | ||
| const pr = data.find((pr) => pr.head.sha === run.head_sha); |
There was a problem hiding this comment.
A head branch and SHA do not uniquely identify a PR: the same branch can target main and a release branch. pulls.list defaults to newest first, so find() selects the newer PR for every signal and the older PR never receives labels.
The equivalent lookup in fork_ci_status.yml should filter to main before selecting, otherwise it can select the release PR and skip the main notification.
There was a problem hiding this comment.
Good catch, confirmed. A fork can have open PRs to main and to a release branch from the same branch, and both match head + head_sha. pulls.list returns newest first, so find() always picks the newer PR.
There is one more piece: both PRs share the new concurrency group (head repo + branch) with cancel-in-progress: true, so the two signal runs from one push cancel each other. Fixing find() alone is not enough. The run that survives has to handle every matching PR.
Suggested changes:
labeler.yml: label every matching PR. actions/labeler v7 accepts several numbers in pr-number, one per line:
- const pr = data.find((pr) => pr.head.sha === run.head_sha);
- if (pr) core.setOutput('number', String(pr.number));
- else core.info(`No open pull request for ${run.head_sha}`);
+ const numbers = data
+ .filter((pr) => pr.head.sha === run.head_sha)
+ .map((pr) => String(pr.number));
+ if (numbers.length) core.setOutput('numbers', numbers.join('\n'));
+ else core.info(`No open pull request for ${run.head_sha}`); - name: Assign GitHub labels
- if: steps.pr.outputs.number != ''
+ if: steps.pr.outputs.numbers != ''
uses: actions/labeler@bf12e9b00b37c5c0ca2b87b79b2daf7891dbda13 # v7.0.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- pr-number: ${{ steps.pr.outputs.number }}
+ pr-number: ${{ steps.pr.outputs.numbers }}fork_ci_status.yml: only PRs to main get the mirrored check, so filter on the base in the lookup:
const { data } = await github.rest.pulls.list({
...upstream,
state: 'open',
head: `${run.head_repository.owner.login}:${run.head_branch}`,
+ base: 'main',
});With that, whichever signal run survives the cancellation finds the main PR.
test_fork_ci_status.cjs: add a case with two open PRs from the same head branch, one to main and one to a release branch, where the release PR is newer. The Rust (fork) check should still be created for the main PR.
There was a problem hiding this comment.
Happy to draft PR to your PR if you prefer.
There was a problem hiding this comment.
Thanks, both points confirmed and fixed in the latest commit.
labeler.ymlnow labels every open PR that matches the head commit and passes all numbers topr-number, one per line. I checked that the pinnedactions/labelerdocuments multiple numbers.fork_ci_status.ymllists only PRs withbase: main.test_fork_ci_status.cjshas a case with a newer release-branch PR and an oldermainPR. It fails without thebasefilter.
The shared concurrency group point holds too, so the surviving run now handles every match.
Label every pull request that matches the head commit, and mirror the fork check only for the pull request to main.
Which issue does this PR close?
Rationale for this change
Three workflows use
pull_request_target:labeler.yml,fork_ci_status.ymlandrelease_version_labeler.yaml. ASF infra disables the trigger from November 2026. GitHub also adds a default policy that blocks it on public repositories, enforced from 2026-12-02. Without this change, PRs stop getting labels, theRust (fork)check and the release version label.What changes are included in this PR?
pull_request_signal.yml, an unprivilegedpull_requestworkflow withpermissions: {}and oneechostep.labeler.ymlandfork_ci_status.ymlrun onworkflow_runof that workflow withtypes: [requested]. GitHub runs them from the default branch, so they never run PR code.requestedis sent at once, even for a first-time contributor whose run waits for approval.workflow_run.pull_requestsis empty for fork PRs. Both workflows find the PR fromhead_repository,head_branchandhead_shawithpulls.list, and skip a commit that is no longer the PR head.labeler.ymlpasses the number toactions/labeleraspr-number.workflow_runhead repository and branch, sincegithub.head_refand the PR number are not set.release_version_labeler.yamlruns onpushtomainand labels the merged PR found withlistPullRequestsAssociatedWithCommit.test_fork_ci_status.cjsnow drives the notification with aworkflow_runpayload and covers the stale commit case.What is the testing strategy for this PR?
node --test ci/scripts/test_fork_ci_status.cjspasses (25 tests).actionlintreports nothing on the four workflows.workflow_runflow only takes effect after the merge tomain, because GitHub runs these workflows from the default branch. It is not tested end to end. Things to check after the merge: thatactions/labelerreadslabeler-config.ymlfrom the default branch, that the push-time PR lookup finds merge queue commits without a race onmerged_at, and that a PR from a fork gets labels and theRust (fork)check.Are there any user-facing changes?
No. A PR with merge conflicts does not start
pull_requestworkflows, so it is labeled and gets theRust (fork)check once the conflicts are resolved. Theeditedlabel trigger was dropped, since the old workflow skipped that action already.