From 3813848b08a166de96aad7b743785e7b2e2d0ca3 Mon Sep 17 00:00:00 2001 From: Noah Gift Date: Mon, 12 Oct 2026 04:53:21 +0200 Subject: [PATCH 1/2] fix(ci): a tag push runs the full workspace and pins its first parent as the base (Fixes #5172) The v0.71.0 tag push (run 38186659898) had two faults. - The tier step reused the merge-queue result on the tagged commit. - The refinement base pin then failed on the push's all-zero `before` sha. So the release tag ran no workspace test and went red. - scripts/ci_test_tier.sh: a push whose GITHUB_REF is refs/tags/* is tier=full. It never reuses a merge-group result and never refines a diff. The refusal is marked # R-TAGREF, and the self-test unsets GITHUB_REF and adds a tag row. - ci/sections.yml: a tag push with a zero `before` pins the tagged commit's first parent as origin/main. The step deepens to it if the tier step did not. A branch push with a zero `before` still fails loudly. - scripts/check_ci_push_reuse.sh: rows T1-T3 cover a tag push, both with and without a queue result (full), and a refs/heads/main push (still reuse). tier() now unsets an inherited GITHUB_REF. Agent: aprender-w71-e3a Co-Authored-By: Claude Opus 5.5 --- ci/sections.yml | 20 ++++++++++++++++++-- scripts/check_ci_push_reuse.sh | 15 +++++++++++++-- scripts/ci_test_tier.sh | 8 ++++++++ 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/ci/sections.yml b/ci/sections.yml index 43ffc4b083..5527b5e029 100644 --- a/ci/sections.yml +++ b/ci/sections.yml @@ -421,7 +421,7 @@ jobs: # workflow_dispatch / merge_group / push shard had no base and the test panicked # "the refinement gate declined". Operator ruling (2026-09-28 09:41): compare HEAD # with the EVENT's base commit -- pull_request.base.sha, merge_group.base_sha, - # push's `before` -- and fall back to the origin/main tip only for + # push's `before` (a tag push: the tagged commit's first parent, #5172) -- and fall back to the origin/main tip only for # workflow_dispatch. That commit is pinned as refs/remotes/origin/main, so at # depth 1 (no merge-base) the gate's tip fallback compares against exactly it. # AFTER the tier step: its pull_request arm fetches main's CURRENT tip into @@ -437,7 +437,23 @@ jobs: case "${GITHUB_EVENT_NAME}" in pull_request) base="${PR_BASE_SHA:-}" ;; merge_group) base="${MG_BASE_SHA:-}" ;; - push) base="${PUSH_BEFORE:-}" ;; + push) + base="${PUSH_BEFORE:-}" + # #5172: a push that CREATES a ref carries before=0000..., and a release tag + # push always does, so v0.71.0's tag run failed here. A tag's base is the + # tagged commit's first parent (the tier step deepened to it, best effort; + # fetched again here). A branch push with a zero `before` still fails. + case "${GITHUB_REF:-}" in + refs/tags/*) + if [ "$base" = 0000000000000000000000000000000000000000 ]; then + git rev-parse -q --verify 'HEAD^1' >/dev/null 2>&1 \ + || bash scripts/ci/fetch_p6.sh --no-tags --depth=2 origin "${GITHUB_SHA}" + base="$(git rev-parse -q --verify 'HEAD^1^{commit}' || true)" + printf 'refinement base: tag push %s has no before; using its first parent %s\n' "${GITHUB_REF#refs/tags/}" "${base:-}" + fi + ;; + esac + ;; workflow_dispatch) bash scripts/ci/fetch_p6.sh --no-tags --depth=1 origin +refs/heads/main:refs/remotes/origin/main printf 'refinement base: origin/main tip %s (workflow_dispatch has no event base)\n' "$(git rev-parse origin/main)" diff --git a/scripts/check_ci_push_reuse.sh b/scripts/check_ci_push_reuse.sh index ead9be4661..11c790a5ca 100755 --- a/scripts/check_ci_push_reuse.sh +++ b/scripts/check_ci_push_reuse.sh @@ -12,6 +12,7 @@ # # L rows the lookup, against a stub `gh` serving canned JSON (no network) # D rows the decision, scripts/ci_test_tier.sh --event push on throwaway repositories +# T rows a tag push (#5172) is full: never reused, never refined # W rows the tier step in ci/sections.yml calls the lookup on push, and survives its failure # A rows the workspace-test aggregator in ci.yml still refuses a split tier # P rows decide-push for x86-main + determinism, on a throwaway repository and canned lists @@ -28,7 +29,7 @@ LOOKUP="${PUSH_REUSE_LOOKUP:-$ROOT/scripts/ci_mg_workspace_result.sh}" TIER="${PUSH_REUSE_TIER:-$ROOT/scripts/ci_test_tier.sh}" MG="${PUSH_REUSE_MG:-$ROOT/scripts/ci_mg_reuse.sh}" -case "${1:-}" in -h|--help) sed -n '2,23p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;; esac +case "${1:-}" in -h|--help) sed -n '2,24p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;; esac if [ "${1:-}" = "--self-test" ]; then # A red table kills every mutant for free: the unmutated table must be green first. @@ -220,7 +221,7 @@ mkrepo() { # mkrepo -> a two-commit repo whose push diff is docs-only (tod git -C "$1" add docs; git -C "$1" -c user.name=t -c user.email=t@t commit -q -m docs } mkrepo "$T/r"; H="$(git -C "$T/r" rev-parse HEAD)" -tier() { (cd "$ROOT" && env -u GITHUB_SHA ${GSHA:+GITHUB_SHA=$GSHA} bash "$TIER" --event push --repo-root "$T/r" "$@" 2>&1); } +tier() { (cd "$ROOT" && env -u GITHUB_SHA -u GITHUB_REF ${GSHA:+GITHUB_SHA=$GSHA} ${GREF:+GITHUB_REF=$GREF} bash "$TIER" --event push --repo-root "$T/r" "$@" 2>&1); } BASE="$(tier)" want "D0 push with no merge_group result -> today's tier (docs-only: none)" "tier=none" "$(grep '^tier=' <<<"$BASE")" hasnt "D0 and no note about a merge_group (no --mg-* given: as before)" "merge_group" "$BASE" @@ -252,6 +253,16 @@ want "D6 a run id that is not a number -> today's tier" "tier=none" "$(grep '^ti OUT="$(tier --mg-sha "$H" --mg-conclusion success)" want "D7 no run id at all -> today's tier" "tier=none" "$(grep '^tier=' <<<"$OUT")" +# #5172: a tag push (the release tag) runs the whole workspace: never reused, never refined. +# The v0.71.0 tag push reused the queue result on its commit and ran no workspace test. +OUT="$(GREF=refs/tags/v9.9.9 GSHA=$H tier --mg-run 7001 --mg-sha "$H" --mg-conclusion success)" +want "T1 a tag push with a merge_group success on its commit -> full, never reuse" "tier=full" "$(grep '^tier=' <<<"$OUT")" +has "T1 the reason names the tag" "push of tag v9.9.9" "$OUT" +OUT="$(GREF=refs/tags/v9.9.9 tier)" +want "T2 a tag push with no merge_group result -> full, never the docs-only diff tier" "tier=full" "$(grep '^tier=' <<<"$OUT")" +OUT="$(GREF=refs/heads/main GSHA=$H tier --mg-run 7001 --mg-sha "$H" --mg-conclusion success)" +want "T3 a branch push (refs/heads/main) still reuses" "tier=reuse" "$(grep '^tier=' <<<"$OUT")" + # a root commit: today's tier is full (no diff can be derived); a refused result keeps it full git init -q -b main "$T/root"; git -C "$T/root" -c user.name=t -c user.email=t@t commit -q --allow-empty -m only OUT="$(cd "$ROOT" && env -u GITHUB_SHA bash "$TIER" --event push --repo-root "$T/root" --mg-run 7001 --mg-sha "$H" --mg-conclusion success 2>&1)" diff --git a/scripts/ci_test_tier.sh b/scripts/ci_test_tier.sh index b630f827ba..8da5c34242 100755 --- a/scripts/ci_test_tier.sh +++ b/scripts/ci_test_tier.sh @@ -294,6 +294,11 @@ decide() { # landing paid an hour for work the PR and the queue had both already # measured. local base how why="" + # #5172: a TAG push (the release tag) runs the whole workspace. The queue result on + # the tagged commit is never cited and no diff is refined: v0.71.0's tag push reused + # it and ran no workspace test at all. + local gref; gref=$(printenv GITHUB_REF || true) + case "$gref" in refs/tags/*) printf 'tier=full\nreason=push of tag %s: a release tag runs the whole workspace -- never a reused merge_group result, never a refined diff (#5172)\n' "${gref#refs/tags/}"; return 0 ;; esac # R-TAGREF if [ "$MG_GIVEN" = 1 ]; then why=$(push_reuse_why) if [ -z "$why" ]; then @@ -393,6 +398,8 @@ self_test() { if [ -n "${CI_TEST_TIER_SELF_TEST_PID:-}" ]; then printf 'ci_test_tier: refusing a nested self-test (outer self-test pid %s)\n' "$CI_TEST_TIER_SELF_TEST_PID" >&2; return 2 fi + # #5172: a tag-push run's own GITHUB_REF would turn every push row below full. + unset GITHUB_REF export CI_TEST_TIER_SELF_TEST_PID=$$ td=$(mktemp -d "${TMPDIR:-/tmp}/ci-tier.XXXXXX"); trap 'rm -rf "${td:?}"' RETURN # One decision, many rows. Each full decision re-runs check_tree_reader_tests.sh @@ -538,6 +545,7 @@ self_test() { row 0 "merge_group on a SQUASH queue ref, roadmap entry only -> none: workspace-test has nothing to measure" '^tier=none$' bash -c "$(replay sq-docs)" row 0 " ...and the reason says docs-only, so the skip is auditable in the log" 'docs-only' bash -c "$(replay sq-docs)" row 0 "push of a SQUASH landing (one parent, no reflog) -> quick over HEAD^1..HEAD, not full" "^crates=.*$leaf" bash "$T" --event push --repo-root "$td/s-leaf" + row 0 "push of a TAG (#5172) -> full over the same squash repo, never the refined diff" '^tier=full' env GITHUB_REF=refs/tags/v9.9.9 bash "$T" --event push --repo-root "$td/s-leaf" # MUTANT: restore the HEAD^2 gate -- the squash rows above must go back to full. sed "s|^\( *\)# IS this PR's diff on the new base. A failed diff still falls closed.|&\n\1if ! git -C \"\$ROOT\" rev-parse -q --verify 'HEAD^2' >/dev/null 2>\&1; then printf 'tier=full\\\\nreason=MUTANT-HEAD2\\\\n'; return 0; fi|" "$T" > "$td/mutant-head2.sh" row 0 "mutant with the HEAD^2 gate restored sends the squash group back to full -- the rows discriminate" 'MUTANT-FULL' bash -c "o=\$(bash '$td/mutant-head2.sh' --event merge_group --repo-root '$td/s-leaf' --pr-head '$(qh "$td/s-leaf")' --pr-head-conclusion success 2>&1); case \"\$o\" in *reason=MUTANT-HEAD2*) echo MUTANT-FULL ;; *) echo MUTANT-NOT-APPLIED ;; esac" From c9f2b14565ce8546c3b7dfd25d36487fe79a6f8d Mon Sep 17 00:00:00 2001 From: Noah Gift Date: Mon, 12 Oct 2026 04:56:30 +0200 Subject: [PATCH 2/2] fix(ci): a tag push always pins its first parent; the self-test tag row counts tier lines (#5172) These changes come from the C314 quorum findings. - ci/sections.yml: a tag push now uses the tagged commit's first parent even when `before` is non-zero. On a moved tag, `before` is the old target, not this commit's base. - scripts/ci_test_tier.sh: the self-test tag row now asserts exactly ONE tier= line and that it is full. A fall-through that also printed a reuse or refined tier would otherwise pass on a grep for ^tier=full alone. Agent: aprender-w71-e3a Co-Authored-By: Claude Opus 5.5 --- ci/sections.yml | 21 +++++++++++---------- scripts/ci_test_tier.sh | 2 +- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/ci/sections.yml b/ci/sections.yml index 5527b5e029..b2efd4a3db 100644 --- a/ci/sections.yml +++ b/ci/sections.yml @@ -421,7 +421,8 @@ jobs: # workflow_dispatch / merge_group / push shard had no base and the test panicked # "the refinement gate declined". Operator ruling (2026-09-28 09:41): compare HEAD # with the EVENT's base commit -- pull_request.base.sha, merge_group.base_sha, - # push's `before` (a tag push: the tagged commit's first parent, #5172) -- and fall back to the origin/main tip only for + # push's `before` (a tag push: the tagged commit's first parent, #5172) -- and + # fall back to the origin/main tip only for # workflow_dispatch. That commit is pinned as refs/remotes/origin/main, so at # depth 1 (no merge-base) the gate's tip fallback compares against exactly it. # AFTER the tier step: its pull_request arm fetches main's CURRENT tip into @@ -440,17 +441,17 @@ jobs: push) base="${PUSH_BEFORE:-}" # #5172: a push that CREATES a ref carries before=0000..., and a release tag - # push always does, so v0.71.0's tag run failed here. A tag's base is the - # tagged commit's first parent (the tier step deepened to it, best effort; - # fetched again here). A branch push with a zero `before` still fails. + # push always does, so v0.71.0's tag run failed here. A tag push's base is + # ALWAYS the tagged commit's first parent, never `before` (on a moved tag that + # is the old target, not this commit's base). The tier step's merge_group|push + # arm deepened to depth 2, best effort; if that missed, fetch it here. A + # branch push with a zero `before` still fails below. case "${GITHUB_REF:-}" in refs/tags/*) - if [ "$base" = 0000000000000000000000000000000000000000 ]; then - git rev-parse -q --verify 'HEAD^1' >/dev/null 2>&1 \ - || bash scripts/ci/fetch_p6.sh --no-tags --depth=2 origin "${GITHUB_SHA}" - base="$(git rev-parse -q --verify 'HEAD^1^{commit}' || true)" - printf 'refinement base: tag push %s has no before; using its first parent %s\n' "${GITHUB_REF#refs/tags/}" "${base:-}" - fi + git rev-parse -q --verify 'HEAD^1' >/dev/null 2>&1 \ + || bash scripts/ci/fetch_p6.sh --no-tags --depth=2 origin "${GITHUB_SHA}" + base="$(git rev-parse -q --verify 'HEAD^1^{commit}' || true)" + printf 'refinement base: tag push %s (before %s); using its first parent %s\n' "${GITHUB_REF#refs/tags/}" "${PUSH_BEFORE:-}" "${base:-}" ;; esac ;; diff --git a/scripts/ci_test_tier.sh b/scripts/ci_test_tier.sh index 8da5c34242..bf41ee72cc 100755 --- a/scripts/ci_test_tier.sh +++ b/scripts/ci_test_tier.sh @@ -545,7 +545,7 @@ self_test() { row 0 "merge_group on a SQUASH queue ref, roadmap entry only -> none: workspace-test has nothing to measure" '^tier=none$' bash -c "$(replay sq-docs)" row 0 " ...and the reason says docs-only, so the skip is auditable in the log" 'docs-only' bash -c "$(replay sq-docs)" row 0 "push of a SQUASH landing (one parent, no reflog) -> quick over HEAD^1..HEAD, not full" "^crates=.*$leaf" bash "$T" --event push --repo-root "$td/s-leaf" - row 0 "push of a TAG (#5172) -> full over the same squash repo, never the refined diff" '^tier=full' env GITHUB_REF=refs/tags/v9.9.9 bash "$T" --event push --repo-root "$td/s-leaf" + row 0 "push of a TAG (#5172) -> ONE tier line, full, over the same squash repo: never the refined diff" '^tier=full 1$' bash -c "o=\$(GITHUB_REF=refs/tags/v9.9.9 bash '$T' --event push --repo-root '$td/s-leaf'); printf '%s %s\\n' \"\$(printf '%s\\n' \"\$o\" | grep '^tier=' | head -n1)\" \"\$(printf '%s\\n' \"\$o\" | grep -c '^tier=')\"" # MUTANT: restore the HEAD^2 gate -- the squash rows above must go back to full. sed "s|^\( *\)# IS this PR's diff on the new base. A failed diff still falls closed.|&\n\1if ! git -C \"\$ROOT\" rev-parse -q --verify 'HEAD^2' >/dev/null 2>\&1; then printf 'tier=full\\\\nreason=MUTANT-HEAD2\\\\n'; return 0; fi|" "$T" > "$td/mutant-head2.sh" row 0 "mutant with the HEAD^2 gate restored sends the squash group back to full -- the rows discriminate" 'MUTANT-FULL' bash -c "o=\$(bash '$td/mutant-head2.sh' --event merge_group --repo-root '$td/s-leaf' --pr-head '$(qh "$td/s-leaf")' --pr-head-conclusion success 2>&1); case \"\$o\" in *reason=MUTANT-HEAD2*) echo MUTANT-FULL ;; *) echo MUTANT-NOT-APPLIED ;; esac"