mirror of
https://github.com/libretro/virtualjaguar-libretro.git
synced 2026-11-07 04:36:00 -10:00
fix(test): make cd_boot_matrix build stamps converge across chunked runs
The matrix stamps every row it writes with scripts/build-id.sh's output and,
on resume, re-runs any row whose stamp differs from the current build. But
the default results file (docs/cd-boot-matrix.md) is tracked, so writing the
first row flipped the tree to "-dirty": the next invocation computed a
different id, judged all the rows it had just written stale, and re-ran them.
A chunked sweep (CD_MATRIX_MAX_RUNS) could therefore never settle, which is
the one thing chunking exists for. Observed as 6 rows stamped 5a83d3d
followed by "pass 1: 0/20 rows stamped 5a83d3d-dirty".
Exclude the results file from the dirty check in build-id.sh, which both
sides of the guard already share: gen-version-h.sh stamps the binary from the
same script, so the binary's embedded id and the harnesses' VJ_EXPECT_BUILD
stay in agreement. A source edit still yields "-dirty" and still invalidates
earlier rows, so the stale-row guard keeps doing its job.
Also warn when CD_MATRIX_OUT points at some other tracked file, which would
hit the same non-convergence without being covered by the ignore list.
Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
1 parent
b8d4c7e90e
commit
d8a7c793ee
2 files changed
+73
-4
No files matched your search
+38
-1
@@ -5,13 +5,50 @@
|
||||
# string reported by a loaded core (VJ_EXPECT_BUILD) so a stale or
|
||||
# wrong-branch binary fails loudly instead of silently testing the
|
||||
# wrong code. POSIX sh compatible -- no bashisms.
|
||||
#
|
||||
# `--ignores` prints the ignore list below, one path per line, so a caller
|
||||
# can check whether the file it is about to write is covered.
|
||||
|
||||
set -e
|
||||
ROOT=$(cd "$(dirname "$0")/.." && pwd)
|
||||
|
||||
# Tracked files that are RESULTS of running the test tools, never inputs to
|
||||
# the build. Changes to these do not make the binary "dirty", because they
|
||||
# cannot change a single byte of it.
|
||||
#
|
||||
# Why this list has to exist: a tool that records its results into a tracked
|
||||
# file AND stamps those results with this build id cannot converge without
|
||||
# it. test/tools/cd_boot_matrix.sh computes the id once per invocation and
|
||||
# writes rows stamped with it into docs/cd-boot-matrix.md; writing the first
|
||||
# row would flip the tree to "-dirty", so the next chunked invocation would
|
||||
# compute a different id, judge every row it had just written to be stale
|
||||
# evidence, and re-run all of them -- forever. Excluding the results file
|
||||
# keeps the stamp meaningful (a real source edit still yields "-dirty")
|
||||
# while letting a chunked sweep settle.
|
||||
#
|
||||
# Keep this minimal and results-only. Anything that feeds a compile, a link
|
||||
# or a code-generation step must NOT be listed here: the whole point of the
|
||||
# stamp is that it changes when the emulator code under test changes.
|
||||
#
|
||||
# Repo-root-relative paths, ONE PER LINE -- the list is fed to `grep -vxF`,
|
||||
# which reads a newline-separated pattern set. Space-separating two entries
|
||||
# makes a single literal pattern that matches no filename at all, silently
|
||||
# restoring the non-convergence this list exists to prevent.
|
||||
BUILD_ID_IGNORE='docs/cd-boot-matrix.md'
|
||||
|
||||
if [ "${1:-}" = "--ignores" ]; then
|
||||
printf '%s\n' "$BUILD_ID_IGNORE"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
REV=$(cd "$ROOT" && git rev-parse --short HEAD 2>/dev/null || echo unknown)
|
||||
if [ "$REV" != "unknown" ]; then
|
||||
if ! (cd "$ROOT" && git diff-index --quiet HEAD -- 2>/dev/null); then
|
||||
# Name filtering rather than an ':(exclude)' pathspec: it needs no
|
||||
# pathspec-magic support, and a malformed entry can only ever fail
|
||||
# towards "-dirty" (the safe direction) instead of silently matching
|
||||
# everything and disabling the guard.
|
||||
if (cd "$ROOT" && git diff-index --name-only HEAD -- 2>/dev/null) \
|
||||
| grep -vxF "$BUILD_ID_IGNORE" | grep -q .; then
|
||||
REV="${REV}-dirty"
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -52,7 +52,11 @@
|
||||
# mktemp -d; NOT committed -- path is printed at the end)
|
||||
# CD_MATRIX_MAX_RUNS max NEW title x mode runs per invocation (default 0 =
|
||||
# unlimited). Combined with the resume guard this lets
|
||||
# a long sweep be chunked across short invocations.
|
||||
# a long sweep be chunked across short invocations:
|
||||
# each chunk skips the rows earlier chunks recorded,
|
||||
# because the build stamp does not move when the only
|
||||
# thing that changed is this script's own output
|
||||
# (scripts/build-id.sh BUILD_ID_IGNORE).
|
||||
set -u
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -68,6 +72,7 @@ FRAMES="${CD_MATRIX_FRAMES:-3000}"
|
||||
TIMEOUT_SECS="${CD_MATRIX_TIMEOUT:-120}"
|
||||
OUT="${CD_MATRIX_OUT:-docs/cd-boot-matrix.md}"
|
||||
LOGDIR="${CD_MATRIX_LOGDIR:-$(mktemp -d "${TMPDIR:-/tmp}/cd_boot_matrix.XXXXXX")}"
|
||||
MAX_RUNS="${CD_MATRIX_MAX_RUNS:-0}" # 0 = unlimited; see the resume guard below
|
||||
|
||||
mkdir -p "$LOGDIR"
|
||||
|
||||
@@ -107,6 +112,25 @@ fi
|
||||
# Build-identity guard: every harness invocation below verifies that the
|
||||
# core's embedded git rev matches the working tree (scripts/build-id.sh),
|
||||
# so matrix rows can never be produced by a stale/wrong-branch binary.
|
||||
#
|
||||
# The id is computed ONCE per invocation and stamped into every row this
|
||||
# invocation writes (see run_title). Resuming across invocations only
|
||||
# works because scripts/build-id.sh excludes the results file from its
|
||||
# dirty check -- otherwise writing the first row would flip the id and the
|
||||
# next invocation would re-run everything it had just recorded. The
|
||||
# default $OUT is on that ignore list; a custom tracked $OUT is not, so
|
||||
# warn rather than let the sweep silently fail to converge. (This applies
|
||||
# to any re-invocation, chunked or not: an interrupted unlimited sweep
|
||||
# resumes through the same guard.)
|
||||
if git ls-files --error-unmatch "$OUT" >/dev/null 2>&1 \
|
||||
&& ! scripts/build-id.sh --ignores 2>/dev/null | grep -qxF "$OUT"; then
|
||||
echo "WARNING: CD_MATRIX_OUT=$OUT is tracked by git but is not in" >&2
|
||||
echo " scripts/build-id.sh's ignore list. Writing rows will flip the build" >&2
|
||||
echo " id to '-dirty', so the next chunked invocation will treat every row" >&2
|
||||
echo " this one records as stale and re-run it. Add the path to" >&2
|
||||
echo " BUILD_ID_IGNORE, or point CD_MATRIX_OUT at an untracked file." >&2
|
||||
fi
|
||||
|
||||
VJ_EXPECT_BUILD=$(scripts/build-id.sh 2>/dev/null || true)
|
||||
export VJ_EXPECT_BUILD
|
||||
if [ -n "$VJ_EXPECT_BUILD" ]; then
|
||||
@@ -352,7 +376,12 @@ echo "=== CD boot matrix: $FRAMES frames/title/mode, ${TIMEOUT_SECS}s wall-clock
|
||||
# every actual harness run of that title passed). Row matching is also
|
||||
# scoped to the primary results table, so rows quoted in prose notes can
|
||||
# never satisfy the resume guard.
|
||||
MAX_RUNS="${CD_MATRIX_MAX_RUNS:-0}" # 0 = unlimited
|
||||
#
|
||||
# The stamp stays stable across the chunks of one sweep because
|
||||
# scripts/build-id.sh does not count writes to this results file as a
|
||||
# source change (its BUILD_ID_IGNORE list); a real edit to emulator code
|
||||
# still flips it to "-dirty" and correctly invalidates earlier rows.
|
||||
# MAX_RUNS is set with the other env knobs at the top of the script.
|
||||
RUNS_DONE=0
|
||||
|
||||
# Write the header only on a fresh file; strip any previous footer so
|
||||
@@ -391,7 +420,10 @@ else
|
||||
printf 'recorded **by the same core build** (each row carries a hidden\n'
|
||||
printf '`<!-- build:<rev> -->` stamp) are skipped, so an interrupted sweep resumes\n'
|
||||
printf 'where it left off; rows recorded by a different build, or unstamped legacy\n'
|
||||
printf 'rows, are re-run and replaced in place rather than silently reused. For\n'
|
||||
printf 'rows, are re-run and replaced in place rather than silently reused.\n'
|
||||
printf 'Recording rows does not itself move the stamp -- `scripts/build-id.sh`\n'
|
||||
printf 'excludes this results file from its dirty check -- so the chunks of one\n'
|
||||
printf 'sweep share a stamp and each chunk resumes where the last stopped. For\n'
|
||||
printf 'long sweeps (or agent sessions with per-command time limits), run chunked:\n\n'
|
||||
printf '```bash\n'
|
||||
printf '# ~3 runs x <=120s wall each per invocation; repeat until every line\n'
|
||||
|
||||
Reference in new issue
Block a user