From b13045918ac4117fda221ff49d189fb0832d315b Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Wed, 23 Sep 2026 11:13:02 -0400 Subject: [PATCH] [CI, scripts, tools] (P7): the pull control strips ctest -V's line prefix, retrace-split pins lavapipe, and the retrace summary reads role logs --- .github/workflows/test.yml | 10 +++++++++- scripts/ci/control_smoke_test.sh | 4 ++++ scripts/ci/retrace_pull_library_control.sh | 5 ++++- scripts/ci/testdata/stub_ctest.sh | 11 +++++++++++ tools/trace_replay/render_retrace_summary.mjs | 8 +++++++- 5 files changed, 35 insertions(+), 3 deletions(-) mode change 100755 => 100644 scripts/ci/testdata/stub_ctest.sh diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f87a6e64..fa4f37e8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -2542,7 +2542,7 @@ jobs: # silently is guarded here. trace_cases.py now also rejects an unknown manifest key, which # was the hole: `"splitt": true` loaded clean and emptied the subset (review N-4). if [ "$(printf '%s' "${SPLIT_MATRIX}" | python3 -c 'import json,sys; print(len(json.load(sys.stdin)["include"]))')" -lt 1 ]; then - echo "::error::the split retrace subset is EMPTY. `split` is an OPT-OUT as of P6 - a CI case is in this subset unless it carries \"split\": false - so an empty subset means either every case opted out or the CI matrix itself is empty. Either way retrace-split would be skipped with no red, and exit gate E2 names OpenRA." + echo "::error::the split retrace subset is EMPTY. 'split' is an OPT-OUT as of P6 - a CI case is in this subset unless it carries \"split\": false - so an empty subset means either every case opted out or the CI matrix itself is empty. Either way retrace-split would be skipped with no red, and exit gate E2 names OpenRA." exit 1 fi echo "split-matrix=${SPLIT_MATRIX}" >> "$GITHUB_OUTPUT" @@ -2979,6 +2979,14 @@ jobs: name: retrace split (${{ matrix.backend }} / ${{ matrix.transport }}, ${{ matrix.case }}) runs-on: ubuntu-latest timeout-minutes: 240 + # THE LAVAPIPE ICD PIN the integration lanes get through -DMOBILEGL_ITEST_VK_ICD. Here it + # can be job-wide: add_trace_replay_test's ENVIRONMENT names no VK_ICD_FILENAMES, so nothing + # overrides it. mesa-vulkan-drivers installs every Mesa ICD, and an unpinned loader probes all + # of them inside the spawned server's lazy Magma bring-up - the MakeCurrent that outlasted the + # client's reply bound in runs 35671704873 / 35706183230. ClientSession's cold-start budget + # is the fix; this pin keeps the bring-up on the one device a runner has. + env: + VK_ICD_FILENAMES: /usr/share/vulkan/icd.d/lvp_icd.json needs: - build-linux-monolith-control - build-linux-split diff --git a/scripts/ci/control_smoke_test.sh b/scripts/ci/control_smoke_test.sh index 520ddbd1..379c615b 100644 --- a/scripts/ci/control_smoke_test.sh +++ b/scripts/ci/control_smoke_test.sh @@ -121,6 +121,10 @@ expect PASSED "run_trace_case.cmake's own sentence, wrapped" -- run_retrace retr # search. The control accepted only the marker sentence until B3's fix round 2, and was red on # every real pull-library run (measured on the B3 package tree). expect PASSED "the no-client-log sentence a pull library gets" -- run_retrace retrace-evidence-nolog +# Both sentences again as `ctest -V` really prints them, with "1: " on every line: folded +# naively that is "never 1: reported resolving it", and the control used to red on it. +expect PASSED "the marker sentence under ctest -V's N: prefix" -- run_retrace retrace-evidence-prefixed +expect PASSED "the no-log sentence under ctest -V's N: prefix" -- run_retrace retrace-evidence-nolog-prefixed # The pull library replaying green is the failure this control exists to catch. expect FAILED "a pull library passed the split retrace" -- run_retrace retrace-green diff --git a/scripts/ci/retrace_pull_library_control.sh b/scripts/ci/retrace_pull_library_control.sh index 2e2d4887..7cecbe78 100644 --- a/scripts/ci/retrace_pull_library_control.sh +++ b/scripts/ci/retrace_pull_library_control.sh @@ -155,7 +155,10 @@ fi # width: "never reported resolving it" arrives split over two lines with a two-space continuation # indent, and a line-oriented grep for the literal finds nothing. That is not hypothetical - it is # the shape the stub reproduces in scripts/ci/testdata/stub_ctest.sh. -if ! tr -s '[:space:]' ' ' < "${out}" | grep -qF "${EVIDENCE}"; then +# `ctest -V` ALSO PREFIXES EVERY OUTPUT LINE WITH ": ", continuation lines included, +# so without stripping it first the folded text reads "never 1: reported resolving it" and the +# control reds on the very sentence it is looking for (the *-prefixed stub modes). +if ! sed -E 's/^[0-9]+: //' "${out}" | tr -s '[:space:]' ' ' | grep -qF "${EVIDENCE}"; then echo "::error::the split retrace went red (ctest exit ${control_rc}) with the pull library in place, but the failure never says the library did not resolve the transport - neither of run_trace_case.cmake's sentences (\"${EVIDENCE//$'\n'/\" / \"}\") is in the output. A loader failure, a missing fixture, a timeout or an SSIM drop all land here, and none of them establishes that the transport-identity assertion is what caught the pull library. Only 'non-zero ctest' used to be checked (ID-46 finding 8b)." exit 1 fi diff --git a/scripts/ci/testdata/stub_ctest.sh b/scripts/ci/testdata/stub_ctest.sh old mode 100755 new mode 100644 index 947a9da9..13cc8514 --- a/scripts/ci/testdata/stub_ctest.sh +++ b/scripts/ci/testdata/stub_ctest.sh @@ -32,6 +32,8 @@ # one match; the run fails one check earlier, with the runner's "wrote no # ... no evidence the transport ever resolved" - the shape a # PULL library produces since P6's per-role log rename +# retrace-evidence-prefixed, retrace-evidence-nolog-prefixed +# the two above with `ctest -V`'s "1: " prefix on every line # retrace-green one match; the run PASSES # # EXIT GATE E2's DRAW-DROP CONTROL (scripts/ci/retrace_drop_draw_control.sh). The library's own @@ -307,6 +309,15 @@ case "${mode}" in echo " counted as a split retrace." exit 8 ;; + retrace-evidence-prefixed|retrace-evidence-nolog-prefixed) + # The two modes above as `ctest -V` really prints them: EVERY line of a test's output carries + # a ": " prefix, continuation lines included, so after whitespace folding the + # wrapped sentence reads "never 1: reported resolving it" / "no evidence the 1: transport ever + # resolved". A short case directory breaks the sentence at exactly those words; CI's long + # paths happened not to (retrace-split, run 35671704873: 5 false reds from this shape). + STUB_MODE="${mode%-prefixed}" bash "$0" "$@" | sed 's/^/1: /' + exit "${PIPESTATUS[0]}" + ;; retrace-green) echo "100% tests passed, 0 tests failed out of 1" exit 0 diff --git a/tools/trace_replay/render_retrace_summary.mjs b/tools/trace_replay/render_retrace_summary.mjs index efe7e9e0..b765cd2a 100644 --- a/tools/trace_replay/render_retrace_summary.mjs +++ b/tools/trace_replay/render_retrace_summary.mjs @@ -144,9 +144,15 @@ function parseGpuLabel(logText) { async function collectGroupLabels(files, defaultGroup) { const labels = new Map(); + // A pull library writes one mobilegl.log. A split library writes one log per ROLE + // (mobilegl.client.log / mobilegl.server.log) and no mobilegl.log, so the Linux split lanes' + // summaries had no GPU label at all; their role logs are read wherever mobilegl.log is absent. + const present = new Set(files.map((file) => normalizeSlashes(file))); const logFiles = files.filter((file) => { const name = path.basename(file).toLowerCase(); - return name === "mobilegl.log" || name === "logcat.txt"; + if (name === "mobilegl.log" || name === "logcat.txt") return true; + if (name !== "mobilegl.client.log" && name !== "mobilegl.server.log") return false; + return !present.has(normalizeSlashes(path.join(path.dirname(file), "mobilegl.log"))); }); for (const logFile of logFiles) { const group = inferGroup(logFile, defaultGroup);