mirror of
https://github.com/jmcorgan/fips.git
synced 2026-07-30 19:46:15 +00:00
Merge branch 'maint'
Carries today's maint batch: the local CI image-scoping work, which gives each run its own build context and test image tag instead of writing the shared mutable one, and the retirement of the bloom-storm chaos scenario. Both apply unchanged here — the compose files, suite lists and matrix legs they touch are identical on the two lines, so no branch adaptation was needed. Parity stays symmetric across runners at 21 legs a side on this branch and 24 on maint, the gap being the three rekey Docker suites maint keeps by design.
This commit is contained in:
+74
-13
@@ -31,7 +31,6 @@
|
||||
# nat-lan, nostr-publish-consume, stun-faults,
|
||||
# chaos-churn-mixed-10, chaos-ethernet-mesh,
|
||||
# chaos-ethernet-only, chaos-tcp-mesh, chaos-congestion-stress,
|
||||
# chaos-bloom-storm,
|
||||
# sidecar, dns-resolver, deb-install
|
||||
#
|
||||
# Opt-in (require --with-tor; depend on live Tor network):
|
||||
@@ -152,7 +151,6 @@ CHAOS_SUITES=(
|
||||
"ethernet-only ethernet-only"
|
||||
"tcp-mesh tcp-mesh"
|
||||
"congestion-stress congestion-stress"
|
||||
"bloom-storm bloom-storm"
|
||||
)
|
||||
# Scenarios retired 2026-07-23 because their subject was a pure decision the
|
||||
# Docker harness could not test reliably, now covered by sans-IO unit tests:
|
||||
@@ -175,6 +173,24 @@ CHAOS_SUITES=(
|
||||
# plus end-to-end datagram delivery (src/node/tests/forwarding.rs). Real-
|
||||
# UDP convergence smoke still runs via static-mesh and the other chaos
|
||||
# scenarios' baseline assertions, so no Docker coverage is lost.
|
||||
#
|
||||
# Retired 2026-07-26 for a third reason — the guard's power was never
|
||||
# established, and unlike the two blocks above this one DOES lose coverage:
|
||||
# - bloom-storm: guarded the regression in 0caef2a (fixed by 4cdf382), where
|
||||
# a mid-chain tree update changing neither root nor depth leaked downstream
|
||||
# as a sustained bloom announce storm. It was never once run against that
|
||||
# regressed binary; its ceiling was inferred from a separate post-mortem
|
||||
# harness that no longer exists in the tree. On the only regressed
|
||||
# measurement that survives, the tail node's rate scales to ~7 sends per
|
||||
# 30s, well under the scenario's ceiling of 40 — so it is not established
|
||||
# that the assertion could ever have fired on its own bug class. The
|
||||
# ceiling is also uniform per node, calibrated against the flap target
|
||||
# (legitimately ~24) while the storm's actual signature is at the tail,
|
||||
# which sits at 0 on fixed code. COVERAGE GAP: nothing now exercises
|
||||
# downstream containment of a mid-chain ancestor swap. The scenario, its
|
||||
# README, the link_swap sim primitive and the mesh-lab dispatch all stay
|
||||
# on disk and it remains runnable by hand via
|
||||
# testing/chaos/scripts/chaos.sh bloom-storm.
|
||||
GATEWAY_SUITES=(gateway)
|
||||
SIDECAR_SUITES=(sidecar)
|
||||
FIREWALL_SUITES=(firewall)
|
||||
@@ -288,8 +304,9 @@ record() {
|
||||
#
|
||||
# This script may be preempted (a CI worker sends SIGTERM, waits ~30s, then
|
||||
# SIGKILL) so it can restart on a newer tip. To make that safe:
|
||||
# * every docker resource is namespaced to THIS run (compose project prefix
|
||||
# + per-run image tags) so a restart never collides with a dying run;
|
||||
# * every docker resource is namespaced to THIS run (compose project prefix,
|
||||
# per-run image tags, per-run build context) so a restart never collides
|
||||
# with a dying run, and neither does a concurrent one;
|
||||
# * a trap tears down everything this run created on signal/exit, bounded by
|
||||
# `timeout` so a stuck `down` cannot wedge the trap (SIGKILL is the backstop).
|
||||
|
||||
@@ -326,6 +343,14 @@ CI_LABEL_RUN="com.corganlabs.fips-ci.run=${CI_RUN_ID}"
|
||||
export FIPS_CI_RUN_ID="$CI_RUN_ID"
|
||||
export FIPS_TEST_IMAGE="$CI_IMAGE_TEST"
|
||||
export FIPS_TEST_APP_IMAGE="$CI_IMAGE_APP"
|
||||
# The build context is this run's too. testing/docker/ is a single directory in
|
||||
# the working tree, so two runs racing on its CONTENTS produce a per-run-tagged
|
||||
# image built from the other run's binaries — scoping the tag alone does not
|
||||
# close that. Absolute, and it has to be: compose interpolates this into
|
||||
# build.context but resolves a relative result against the compose FILE's
|
||||
# directory, not the working directory.
|
||||
CI_BUILD_CONTEXT="$SCRIPT_DIR/docker-${CI_RUN_ID}"
|
||||
export FIPS_BUILD_CONTEXT="$CI_BUILD_CONTEXT"
|
||||
# Docker container names are GLOBAL — a compose project name does not scope
|
||||
# them — so the suite compose files append this suffix to every explicit
|
||||
# container_name, and the suite scripts append it wherever they address a
|
||||
@@ -413,6 +438,15 @@ ci_teardown() {
|
||||
rm -rf "$SCRIPT_DIR/static/generated-configs${CI_RUN_NAME_SUFFIX}"
|
||||
rm -rf "$SCRIPT_DIR/firewall/generated-configs${CI_RUN_NAME_SUFFIX}"
|
||||
fi
|
||||
|
||||
# 4. This run's build context. Unlike the generated configs it is removed
|
||||
# on a red run too: it holds the binaries and the Dockerfiles, both
|
||||
# reproducible from the commit, so it is never the evidence of a
|
||||
# failure. Guarded on the path having been derived at all, so an early
|
||||
# exit cannot turn this into `rm -rf $SCRIPT_DIR/docker-`.
|
||||
if [[ -n "${CI_BUILD_CONTEXT:-}" && "$CI_BUILD_CONTEXT" != "$SCRIPT_DIR/docker-" ]]; then
|
||||
rm -rf "$CI_BUILD_CONTEXT"
|
||||
fi
|
||||
}
|
||||
|
||||
on_signal() {
|
||||
@@ -786,24 +820,39 @@ run_tor_directory() {
|
||||
run_integration() {
|
||||
stage "Stage 3: Integration Tests"
|
||||
|
||||
# Install binaries to shared docker context
|
||||
# Populate THIS run's build context, then install the binaries into it.
|
||||
# Everything but the binaries is copied from the tracked context directory;
|
||||
# the binaries are installed fresh, and a previous run's are deliberately
|
||||
# not carried over, since inheriting them is the failure this scoping
|
||||
# exists to prevent.
|
||||
info "Preparing build context $CI_BUILD_CONTEXT"
|
||||
rm -rf "$CI_BUILD_CONTEXT"
|
||||
mkdir -p "$CI_BUILD_CONTEXT" || { record "docker-build" 1; return; }
|
||||
local _f
|
||||
for _f in "$SCRIPT_DIR"/docker/*; do
|
||||
case "$(basename "$_f")" in
|
||||
fips|fipsctl|fipstop|fips-gateway) continue ;;
|
||||
esac
|
||||
cp -a "$_f" "$CI_BUILD_CONTEXT/" || { record "docker-build" 1; return; }
|
||||
done
|
||||
|
||||
info "Installing release binaries"
|
||||
install_binaries testing/docker
|
||||
install_binaries "$CI_BUILD_CONTEXT"
|
||||
|
||||
# Build unified test image once (used by all harnesses). Tag per-run
|
||||
# (fips-test:${run}) so a build killed mid-flight never wedges the next
|
||||
# run's rebuild, and concurrent runs never clobber each other's image.
|
||||
# Then retag :latest for the compose files / harness scripts that still
|
||||
# reference fips-test:latest directly; the retag happens only after BOTH
|
||||
# builds succeed, so :latest never points at a half-built image.
|
||||
info "Building $CI_IMAGE_TEST Docker image"
|
||||
docker build -t "$CI_IMAGE_TEST" --label "$CI_LABEL" --label "$CI_LABEL_RUN" testing/docker --quiet \
|
||||
docker build -t "$CI_IMAGE_TEST" --label "$CI_LABEL" --label "$CI_LABEL_RUN" "$CI_BUILD_CONTEXT" --quiet \
|
||||
|| { record "docker-build" 1; return; }
|
||||
docker build -t "$CI_IMAGE_APP" --label "$CI_LABEL" --label "$CI_LABEL_RUN" \
|
||||
-f testing/docker/Dockerfile.app testing/docker --quiet \
|
||||
-f "$CI_BUILD_CONTEXT/Dockerfile.app" "$CI_BUILD_CONTEXT" --quiet \
|
||||
|| { record "docker-build-app" 1; return; }
|
||||
docker tag "$CI_IMAGE_TEST" fips-test:latest
|
||||
docker tag "$CI_IMAGE_APP" fips-test-app:latest
|
||||
# Deliberately NOT retagged to fips-test:latest. Every consumer reads
|
||||
# FIPS_TEST_IMAGE, and a bridge back to the shared mutable name would let a
|
||||
# consumer that does not keep working silently — resolving whichever
|
||||
# concurrent run wrote the tag last, and recording that run's binaries under
|
||||
# this run's commit. Without the bridge a missed consumer fails loudly.
|
||||
|
||||
# Single suite mode
|
||||
if [[ -n "$ONLY_SUITE" ]]; then
|
||||
@@ -1011,6 +1060,17 @@ run_ci_parity() {
|
||||
record "ci-parity" $rc
|
||||
}
|
||||
|
||||
# Nothing may resolve the shared mutable test image. This run does not write
|
||||
# fips-test:latest, so a consumer naming it fails loudly here and now — but only
|
||||
# on a host with no hand-built copy lying around, which is not a property to
|
||||
# rely on. This is the static half of that.
|
||||
run_image_scoping() {
|
||||
local rc=0
|
||||
info "[image-scoping] Checking that nothing names the shared test image"
|
||||
"$SCRIPT_DIR/check-image-scoping.sh" || rc=$?
|
||||
record "image-scoping" $rc
|
||||
}
|
||||
|
||||
# Every daemon log string a test matches on must still be emitted by src/.
|
||||
# A stale one does not fail — it stops observing, and an expect-zero assertion
|
||||
# built on it then passes for the wrong reason.
|
||||
@@ -1064,6 +1124,7 @@ main() {
|
||||
run_ci_parity
|
||||
run_log_strings
|
||||
run_trailing_log
|
||||
run_image_scoping
|
||||
run_wait_converge
|
||||
|
||||
if [[ "$TEST_ONLY" == true ]]; then
|
||||
|
||||
Reference in New Issue
Block a user