Stop local CI writing the shared mutable test image tag

The run built per-run images and then retagged them to fips-test:latest as
a compatibility bridge for the consumers that had never been migrated. The
bridge was the defect: while it existed, two concurrent runs shared one
binding, so a suite could start containers from the other run's binaries
and the verdict was recorded against a commit whose code never ran. It
fails silently by construction — the run is green either way, and nothing
compares a running container's binary against the commit under test.

Every consumer now reads the run's image, so the retag is deleted rather
than kept. That is the point of deleting it: a consumer that was missed
fails loudly instead of quietly resolving whichever run wrote the tag last.

Two consequences handled here. The cleanup script ran ip(8) inside
fips-test:latest to reap simulation interfaces, and nothing writes that tag
any more, so it now takes the caller's image, then the run's, then any
surviving test image — the last of which is what keeps an unscoped --reap
working, since that path execs before the run identity is exported. And a
guard checks statically that nothing names the shared tag, because on a
host with a hand-built copy lying around a reintroduction would run green;
it is break-checked against a reintroduced compose consumer and a
reintroduced default. Both runners gate on it, as they do the other guards.
This commit is contained in:
Johnathan Corgan
2026-07-26 15:47:22 +00:00
parent 49163befd5
commit cdda660f10
5 changed files with 165 additions and 16 deletions
+26 -5
View File
@@ -66,9 +66,15 @@ RUN_ID="" # broad default: every CI run
IMAGES=""
VETH_SUFFIXES="" # empty AND no --run-id: every simulation veth name
# ip(8) runs inside this image, the same way the simulation creates the
# interfaces, so the reap works wherever the simulation does. The chaos
# simulation builds it, and it carries iproute2.
VETH_IMAGE="fips-test:latest"
# interfaces, so the reap works wherever the simulation does. Any fips test
# image will do; it is wanted only for its iproute2.
#
# Empty here and resolved after the argument loop, because the resolution has
# to consider --veth-image. The old default of fips-test:latest is no longer
# safe on its own: ci-local.sh does not write that tag, so on a host that has
# only ever run the harness it need not exist at all, and the reap this script
# advertises as the remedy for orphaned interfaces would be a permanent no-op.
VETH_IMAGE=""
while [[ $# -gt 0 ]]; do
case "$1" in
@@ -77,11 +83,26 @@ while [[ $# -gt 0 ]]; do
--run-id) RUN_ID="$2"; shift 2 ;;
--images) IMAGES="$2"; shift 2 ;;
--veth-suffixes) VETH_SUFFIXES="$2"; shift 2 ;;
--veth-image) VETH_IMAGE="$2"; shift 2 ;;
-h|--help) sed -n '2,/^set /{ /^set /d; s/^# \?//; p }' "$0"; exit 0 ;;
*) echo "Unknown option: $1" >&2; exit 2 ;;
esac
done
# Resolve the image to run ip(8) in: the caller's choice, then the run's own
# image, then any surviving fips test image. That last fallback is what keeps
# an unscoped `ci-local.sh --reap` working — it execs this script from inside
# its own argument loop, before the run identity is exported, so it can pass
# neither. The empty case is handled at the point of use, which already warns
# and skips rather than failing the sweep.
if [[ -z "$VETH_IMAGE" ]]; then
VETH_IMAGE="${FIPS_TEST_IMAGE:-}"
fi
if [[ -z "$VETH_IMAGE" ]] && command -v docker >/dev/null 2>&1; then
VETH_IMAGE="$(timeout 10 docker image ls --format '{{.Repository}}:{{.Tag}}' fips-test 2>/dev/null | head -n1)"
fi
[[ -z "$VETH_IMAGE" ]] && VETH_IMAGE="fips-test:latest"
if ! command -v docker >/dev/null 2>&1; then
# No docker, nothing to reap.
exit 0
@@ -217,8 +238,8 @@ reap_veths() {
[[ -z "$pattern" ]] && return 0
# Without the image there is no way to run ip(8). Orphans can outlive it —
# `docker image prune -a`, a build host that prunes between runs, or a run
# aborted before ci-local.sh retags :latest all remove it while interfaces
# are still up — so this is a real skip, not "nothing was ever run here".
# whose per-run image was already reaped all remove it while interfaces are
# still up — so this is a real skip, not "nothing was ever run here".
if ! docker image inspect "$VETH_IMAGE" >/dev/null 2>&1; then
veth_warn "image $VETH_IMAGE not present, cannot run ip(8)"
return 0