Derive PR number from the triggering run in the size labeler - #6259
Merged
Conversation
10 tasks
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #6259 +/- ##
==========================================
- Coverage 72.72% 72.71% -0.02%
==========================================
Files 742 742
Lines 77299 77299
==========================================
- Hits 56216 56208 -8
- Misses 17122 17128 +6
- Partials 3961 3963 +2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
rdimitrov
previously approved these changes
Aug 10, 2026
pr-size-labeler.yml runs on pull_request, so a pull request supplies the workflow definition that writes the artifact — including one from a fork. pr-size-label-apply.yml then consumed that artifact in the base repository, with pull-requests: write, taking both the target pull request number and the label name from it verbatim. The number is now derived from this job's own workflow_run event and the label is checked against the five known size labels. The artifact no longer carries a pull request number at all, so there is nothing left to trust in it beyond a value that must match a fixed list. workflow_run.pull_requests cannot be used on its own: it is empty for every fork pull request and for most same-repository ones, so it is a fast path with a head-commit lookup behind it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ChrisJBurns
force-pushed
the
harden-pr-size-labeling
branch
from
August 10, 2026 17:27
4709a5b to
90a87d3
Compare
`workflow_run` consumers always execute the copy of the workflow on the default branch, so a pull request can change the producer but not the consumer reading its output. Dropping pr-number.txt here failed the apply job on every open pull request, because the consumer still on main reads that file. The value is written again, bound through env: so it is not interpolated into the shell. The new consumer ignores it; removing the write is a follow-up once this has merged. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
rdimitrov
approved these changes
Aug 10, 2026
10 tasks
This was referenced Aug 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
pr-size-labeler.ymlruns onpull_request, which means the pull request supplies the workflow definition that produces the artifact.pr-size-label-apply.ymlthen consumed it onworkflow_run— in the base repository, withpull-requests: write— and took both the pull request number and the label name from it verbatim, with no validation.size/*values. The artifact still carries a pull request number, but nothing reads it — see the rollout note below.This is the standard
workflow_runartifact-trust pattern: the producing workflow is attacker-influenced, the consuming workflow is privileged, and anything crossing between them is untrusted input.Why
workflow_run.pull_requestsisn't enough on its ownThe obvious fix is
github.event.workflow_run.pull_requests[0].number. That field is empty for pull requests from forks — which is the case that matters — so a naive swap would silently stop labelling exactly those pull requests.Measured over the last 30 runs of this workflow:
pull_requestspopulatedstacklok/toolhiveSo it's unreliable in general, not just for forks. It's kept as a fast path with a
listPullRequestsAssociatedWithCommitlookup onhead_shabehind it, and the job fails rather than guessing if that doesn't resolve to exactly one open pull request.Why the artifact still carries a PR number
workflow_runconsumers always execute the copy of the workflow on the default branch, never the version in the pull request. So a pull request can change the producer — which does run from the pull request head — but cannot change the consumer reading its output until it merges.Removing
pr-number.txthere in the same change therefore broke the apply job for every open pull request: the producer stopped writing the file while the consumer still onmainwas reading it. This is a two-phase rollout instead:pr-number.txt, bound throughenv:so it is not interpolated into the shell, and the new consumer ignores it.main, drop the write.Behaviour
No change for a normal pull request, fork or not — the same label lands on the same pull request. The differences are that an unrecognised label now fails the job instead of being applied, and the target is no longer something the artifact can influence.
Part of #6253
Type of change
Test plan
Unit tests (
task test)E2E tests (
task test-e2e)Linting (
task lint-fix)Manual testing (describe below)
Queried the last 30 runs of
pr-size-labeler.ymlthrough the API to confirm thepull_requestsbehaviour above, rather than relying on the documented behaviour.Checked all three embedded
github-scriptbodies withnode --check.Both workflows parse as YAML;
actionlintreports 12 findings before and after, all pre-existing.zizmortemplate-injectiononpr-size-labeler.ymlgoes 1 → 0, as a side effect of no longer interpolating the label into the shell.This pull request exercises both workflows directly. The first push dropped
pr-number.txtand the apply job failed for exactly the reason above; the current revision keeps it and the job passes.Does this introduce a user-facing change?
No.
Special notes for reviewers
listPullRequestsAssociatedWithCommitresolves fork pull requests because the head commit is reachable in the base repository viarefs/pull/N/head. If it ever returns more or fewer than one open pull request the job fails loudly rather than labelling something arbitrary.size/*allow-list is duplicated between the resolve step and the existing "Remove old size labels" step. Left as-is to keep the diff focused; worth hoisting if this file grows.Generated with Claude Code