test(push): freeze_source mints its own path so it can never clobber a live mount

The helper took a destination from the caller and rm -rf it. Re-running it into the same path while
a container had that path mounted deleted taint.sc out from under a live scan, and every request
after printed no such cpg query -- the live-mount hazard the helper exists to prevent, in a new
form. It now mints base/frozen-<commit>-<pid>-<n> itself and prints it, so reuse is impossible by
construction and the caller captures the printed path.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01EmM1j46qgKMh3zqD1QMwEo
This commit is contained in:
Marius Ciepluch
2026-09-22 22:22:30 +02:00
co-authored by Claude Opus 4.8
parent 1aa7f175e9
commit 2e96ccb8ea
+20 -9
View File
@@ -1,20 +1,31 @@
#!/usr/bin/env bash
# Export the COMMITTED source for a long measurement run, and prove the export is whole.
# Export the COMMITTED source into a FRESH immutable directory, and prove the export is whole.
#
# Every long run here mounts src into a container. Mounting the working tree is a live mount: edits
# made during a multi-hour run are picked up mid-run, and a measurement whose code changed underneath
# it is not a measurement of anything -- the failure looks exactly like the thing being measured
# failing. A five-hour PHP transfer replay was lost that way on 2026-09-22.
#
# And the export has to be checked. `git archive | tar -x` once produced a tree missing the whole
# ontology (every tracked file after `groovy` alphabetically) and reported success, because tar's
# status in a pipeline was never read. Every scan on that tree died at its first fact load and looked
# like a slow run for fourteen minutes. So: archive to a file, extract, count against git.
# The path is MINTED here, never taken from the caller, so a second freeze can never rm -rf a
# directory a running container is mounting -- which happened once, deleting taint.sc out from under
# a live scan and printing "no such cpg query" for every request after. Reuse is impossible by
# construction: each call gets its own <base>/frozen-<commit>-<pid>-<n>.
#
# Usage: benchmarks/push/freeze_source.sh <dest-dir> -> prints the frozen commit on success
# The export is checked too. `git archive | tar -x` once produced a tree missing the whole ontology
# (every tracked file after `groovy` alphabetically) and reported success, because tar's status in a
# pipeline was never read. So: archive to a file, extract, count against git, require the ontology.
#
# Usage: DEST=$(benchmarks/push/freeze_source.sh <base-dir>) -> prints the minted path on success
set -euo pipefail
dest="${1:?destination directory}"
rm -rf "$dest" && mkdir -p "$dest"
base="${1:?base directory}"
mkdir -p "$base"
commit=$(git rev-parse --short HEAD)
n=0
while :; do
dest="$base/frozen-$commit-$$-$n"
if mkdir "$dest" 2>/dev/null; then break; fi
n=$((n + 1))
done
git archive HEAD src benchmarks > "$dest.tar"
tar -xf "$dest.tar" -C "$dest"
rm -f "$dest.tar"
@@ -25,4 +36,4 @@ if [ "$want" -ne "$have" ]; then
exit 1
fi
test -d "$dest/src/openultrasast/ruleset/semantic" || { echo "export lacks the ontology" >&2; exit 1; }
echo "$(git rev-parse --short HEAD) $have files"
echo "$dest"