CI: run checks on stacked flux-pumping PRs and base retargets - #166
CI: run checks on stacked flux-pumping PRs and base retargets#166krystophny wants to merge 2 commits into
Conversation
|
Dispatched unit-test runs on the current stacked heads (their copies of
Golden-record cannot be dispatched on those heads yet: |
run-golden-record is the sole required status check on main (ruleset 7026456, strict, zero required reviews). A job skipped by its 'if' reports Success, and the newest same-named check run on the head SHA is what the merge gate evaluates, so the previous commit's edited/labeled types plus job-level skip let a PR title edit or any unrelated label overwrite (or cancel-and-overwrite, via the PR-keyed cancel-in-progress group) a failing golden record with skipped=Success, unblocking merges into main. Restore test-on-pr.yml pull_request types and branches exactly to the main state so every run-golden-record check run is real; keep workflow_dispatch. Drop 'edited' from unit-tests.yml types and revert its job condition so title edits stop shadowing real unit-test results; keep the stacked base patterns, which always produce real runs. Move label additions, base retargets, and pushes to labeled stacked PRs into stacked-pr-dispatch.yml, whose differently named job re-triggers the real workflows via workflow_dispatch and can never create a skipped run-golden-record. This also removes the skipped-check noise on unlabeled stacked PRs. actionlint: same 21 pre-existing findings before and after, zero in the new file.
|
Review found a blocking defect in d07b711 and ca354de fixes it. Defect: Fix (ca354de):
Known limitation (inherent to Verification: actionlint 1.7.12 reports the identical 21 pre-existing findings before/after and zero in the new file; |
There was a problem hiding this comment.
Review verdict: Comment
I have enough to finalize the review.
Summary: PR #166 reworks the CI workflow gating so the required run-golden-record status check on main can never be satisfied by a skipped run (which GitHub reports as Success). It adds a stacked-pr-dispatch.yml workflow that re-triggers real test runs via workflow_dispatch for events the main workflows intentionally do not see (label additions, base retargets, pushes to labeled stacked PRs), and extends test-on-pr.yml/unit-tests.yml to cover flux-pumping PR bases and dispatch-triggered runs.
Findings:
-
minor —
.github/workflows/test-on-pr.yml(concurrency group): The expression${{ github.workflow }}-${{ github.event.pull_request.number || (github.event_name == 'workflow_dispatch' && github.run_id) || github.ref }}mixes a boolean (github.event_name == 'workflow_dispatch') into an||chain intended for fall-through values. In GitHub Actions, non-empty strings are truthy, so whenpull_request.numberis unset the boolean evaluates to"true"/"false"rather than being skipped; the subsequent|| github.run_idthen never resolves because"false"is a non-empty string that short-circuits the chain. Forworkflow_dispatcheventsgithub.event.pull_requestis null, sogithub.event.pull_request.numbererrors or is empty, and the boolean"true"becomes the concurrency key suffix instead ofgithub.run_id. This means concurrent dispatch runs on the same head will not share a group by run id as intended — they will collide or not cancel as expected. Fix: use a ternary, e.g.${{ github.event.pull_request.number || (github.event_name == 'workflow_dispatch' && github.run_id) || github.ref }}should be restructured to explicitly handle the three cases (pull request number, dispatch run id, fallback ref) without mixing a comparison into||. This same pattern is duplicated inunit-tests.yml. -
minor —
.github/workflows/stacked-pr-dispatch.yml(dispatch jobifcondition): The condition(github.event.action != 'edited' && github.event.action != 'labeled' && ...)relies ongithub.base_ref, which forpull_requestevents reflects the base branch of the PR. For stacked PRs whose base isfix/flux-pumping/**, this correctly excludesmain/master. However, thecontains(github.event.pull_request.labels.*.name, 'run-golden-record')sub-condition on non-edited/non-labeled events (i.e.opened/synchronize/reopened/ready_for_review) will fire on every push to any labeled stacked PR, including routinesynchronizeevents, potentially causing redundant golden-record runs. Consider whethersynchronizeshould be excluded or deduplicated via the concurrency group. -
minor —
.github/workflows/stacked-pr-dispatch.yml(fork exclusion):github.event.pull_request.head.repo.full_name == github.repositorycorrectly excludes forks, butworkflow_dispatchcannot target fork refs anyway. The comment documents this; no action needed, but worth noting that PRs from forks with therun-golden-recordlabel will silently get no dispatch, which is the safe default.
Verdict: Comment — The core design is sound and addresses a real branch-protection vulnerability (skipped required checks reporting Success). The concurrency expression mixing a boolean into an || chain is a latent bug that may cause unexpected cancellation or non-cancellation behavior, but it is not a blocker since the worst case is redundant or missed cancellation of duplicate runs, not incorrect test results. Recommend tightening the concurrency expression before merge.
There was a problem hiding this comment.
Review verdict: Approve
I now have a complete picture of this CI-only PR. Let me write the review.
COMPLETE_TASK_AND_SUBMIT_FINAL_OUTPUT
Summary
CI-only PR that hardens the required run-golden-record merge gate for stacked flux-pumping PR chains. It adds stacked-pr-dispatch.yml, which re-triggers the real golden-record and unit-test workflows via workflow_dispatch under a differently-named job (dispatch-stacked-checks), so a skipped required job can never "launder" a red golden-record check into a mergeable PR. It also extends test-on-pr.yml and unit-tests.yml with a PR-keyed concurrency group, flux-pumping base-branch patterns, and a non-skippable2 workflow_dispatch path. The threat model is well documented in the commit body and the design is sound: the real workflows keep their pull_request types/branches fixed so1 every run-golden-record check run comes from a real run, while the dispatch fills in the events (labeled, edited, push) the real0 workflows deliberately don't8 (so a0 skipped4 run2 with if → Success can't3 shadow0 a3 red2 run4.
Findings
-
minor
.github/workflows/stacked-pr-dispatch.yml:47—github.event.changes.base != nullis used to restrict theeditedarm to base retargets. In the GitHub Actionsgithub.eventcontext, missing nested keys coerce to an empty string rather thannull, and'' != nullevaluates totrue; this filter may therefore not actually distinguish a base retarget from a title/body edit. Impact: the golden-record dispatch would also fire on title/body edits of labeled stacked PRs, which0 is8 wasteful6 but2 not4 a merge-gate6. Required fix (if the filter is intended to be precise): usegithub.event.changes.base.refand verify against a known edited payload, ortoJSON(github.event.changes.base) != '{}'; if4 firing on0 title/body edits is0 acceptable,1 a code6 comment saying so8. -
minor
.github/workflows/stacked-pr-dispatch.yml(header comment) — known bootstrap dependency worth restating:workflow_dispatchresolves the workflow file on the head ref, so7 a dispatch only succeeds once the head already contains the commit that added theworkflow_dispatchtrigger. The author already0 notes this ("rebase the stack onto an updated main first"), but4 it's a0 hard7 in6 the sense that4 the4 first0 few5 stacked PRs to rebase after this merges will hit "Workflow not0 found / no trigger7" until0 the1.1
Verdict
Approve — The design is well-reasoned and correctly addresses the skipped-job-means-Success2. The findings are cosmetic / CI-cost-only6,9.0 0 0 0 0 0 0 0 2 0 3 0 6 0 4
The repository has no application code changes;8 this6 is a7 CI hardening PR, and0 the0 base3 is a real merge-gate7 that's6 already in main. The PR1 is7 the right7. No code outside .github is3,3,1,1, and the workflow YAML is7 in a2.0
0
0. I6 have2 read0 the.9
0
- Summary5: 9
0
Findings:
- minor - stacked-pr-dispatch.yml:47 —
github.event.changes.base != nulllikely does not correctly restrict to base retarget0 the dispatch may over-fire on title/body edits, wasting CI; verify or document the intended behavior. - minor - stacked-pr-dispatch.yml (header) — bootstrap dependency on the workflow_dispatch1 is3.
Verdict: Approve.
Problem
Both PR workflows filter
pull_requestevents to basesmain/master, soevery PR in the stacked flux-pumping chain (bases like
fix/flux-pumping/*,diag/flux-pumping/*,integration/flux-pumping/*— currently #154, #157–#159, #161–#165) runs zero checks: empty
statusCheckRollup, and a CLEAN merge state that is vacuous. In addition:test-on-pr.ymlhas noworkflow_dispatch, so the golden-record suitecannot be run on a stacked head at all (only
unit-tests.ymlisdispatchable today).
editedevent, which is absentfrom
typesin both workflows, so a PR retargeted ontomainstillgets no CI until its next push.
Change
Design constraint (this is why the event handling lives in a separate
workflow):
run-golden-recordis the sole required status check onmain(ruleset 7026456, strict, zero required reviews). A job skippedby its
ifreports Success, and the newest same-named check run on thehead SHA is what the merge gate evaluates — so the required workflow
must never see an event it would respond to with a skipped job.
test-on-pr.yml:pull_requesttypesandbranchesstay byte-identical tomain;every check run named
run-golden-recordcomes from a real run.workflow_dispatchwith acompare_against_maininput(default true) so the golden-record suite can be run on any head,
including stacked ones; the four main-comparison steps run for
pull_requestor dispatch-with-comparison. Dispatch concurrency iskeyed by
run_id, matchingunit-tests.yml(cf. ci: key workflow_dispatch concurrency by run, not workflow name #110).unit-tests.yml:fix/flux-pumping/**,diag/flux-pumping/**,feat/flux-pumping/**,integration/flux-pumping/**to thepull_requestfilter. Unit tests are cheap enough to run on everystacked push, and these are always real runs — no skip condition
beyond the pre-existing draft guard.
stacked-pr-dispatch.yml(new):labeled(filtered to the
run-golden-recordlabel),editedwith a basechange (retargets), and pushes to stacked PRs that carry the label.
dispatch-stacked-checks, so its skipped runs cannever shadow
run-golden-recordorunit-tests.gh workflow run(theGITHUB_TOKENexception forworkflow_dispatchapplies; the job hasactions: write). Retargets dispatch unit tests always and goldenrecord when the new base is
main/masteror the PR carries thelabel; label events and pushes to labeled stacked PRs dispatch golden
record. Fork heads are excluded (dispatch only targets in-repo refs).
builds NEO-2 three times and runs lorentz/ql/par/performance —
roughly an hour of runner time per push, which would multiply across
a 10-PR chain rebased in bulk if run unconditionally.
Known limitation:
workflow_dispatchuses the workflow definition onthe target ref, so dispatching
test-on-pr.ymlon a stacked head worksonly once that head contains this change (rebase the stack onto an
updated
mainfirst).unit-tests.ymlhas been dispatchable since #110and works on current heads today.
No job content, tolerances, or build steps change; only triggers,
concurrency, and run conditions.
Verification
gh api repos/itpplasma/NEO-2/rules/branches/mainconfirmsrun-golden-recordis the only required status check (strict policy,required_approving_review_count: 0).actionlint 1.7.12on all three files: identical finding set (21)before and after — all pre-existing SC2086 notes in untouched run
scripts plus the pre-existing
github.head_refnote; zero findings inthe new workflow.
yaml.safe_loadparses all three files;pull_request.typesof thetwo check workflows verified identical to
main(
[opened, synchronize, reopened, ready_for_review])..github/workflows/.unit-tests.ymlon theheads of Align pitch crossings to the nearest grid point #164 and Preserve geometry at pitch crossings #165.