Candidate morgana/row24494ab4c2feona36523713, manifest 6e7e3e3c (8 paths). Webby APPROVE r1, rev 3008 (webby-0084, REVIEW-r1.md at webby/reviews ebb3d83bf; request #1757 c30154). Gate on Sage's slot at81e037d20(sage-2147): the five gate-lane files whole 51/0, test-task.sh 91/0, test-release.sh 14/0, mutants M-G, M-L, M-A, M-T and M-F killed.94ab4c2feadds only BUILD.md results. Webby's drift check: a36523713..d37210288 changes none of the 8 paths and no path either suite reads; merge-tree clean. Rulings A and C (sage-1914, sage-2061). The dropped real-model coverage goes to DEFERRED in the follow-up doc commit.
114 lines
5.0 KiB
Bash
Executable File
114 lines
5.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Sandboxed selftests for the release layer.
|
|
#
|
|
# Fast cases (version validation) need no Docker. State-machine cases
|
|
# (status/activate/refusal) run against a sandboxed config and therefore
|
|
# require the Docker daemon; they are skipped when it is unavailable.
|
|
set -uo pipefail
|
|
cd "$(dirname "$0")/.."
|
|
|
|
SANDBOX="$(mktemp -d)"
|
|
RELEASE_BACKUP="$(mktemp)"
|
|
cp RELEASE "$RELEASE_BACKUP"
|
|
# One exit trap: the repo RELEASE is ALWAYS restored from the backup,
|
|
# regardless of how the test run ends.
|
|
trap 'cp "$RELEASE_BACKUP" RELEASE 2>/dev/null; rm -rf "$SANDBOX" "$RELEASE_BACKUP"' EXIT
|
|
# Compose mounts PI_AUTH_FILE. Point it at a fixture so no activation reaches
|
|
# the host's pi credential (row 244). chmod after the write: umask-proof (row 243).
|
|
{ mkdir -p "$SANDBOX/pi" && printf '{}' > "$SANDBOX/pi/auth.json" && chmod 600 "$SANDBOX/pi/auth.json"; } \
|
|
|| { echo "cannot write the pi auth fixture" >&2; exit 1; }
|
|
export PI_AUTH_FILE="$SANDBOX/pi/auth.json"
|
|
|
|
PASS=0
|
|
# Status colors: terminal-only, NO_COLOR-respecting; plain when piped.
|
|
if [ -t 1 ] && [ -z "${NO_COLOR:-}" ]; then
|
|
C_OK=$'\033[0;32m'; C_FAIL=$'\033[0;31m'; C_RESET=$'\033[0m'
|
|
else
|
|
C_OK=""; C_FAIL=""; C_RESET=""
|
|
fi
|
|
FAIL=0
|
|
|
|
expect_exit() {
|
|
local name="$1" expected="$2"
|
|
shift 3
|
|
local rc
|
|
"$@" >/dev/null 2>&1
|
|
rc=$?
|
|
if [ "$rc" -eq "$expected" ]; then
|
|
PASS=$((PASS+1)); echo "${C_OK}OK${C_RESET} $name (exit $rc)"
|
|
else
|
|
FAIL=$((FAIL+1)); echo "${C_FAIL}FAIL${C_RESET} $name (exit $rc, expected $expected)"
|
|
fi
|
|
}
|
|
|
|
check() {
|
|
if [ "$2" = "0" ]; then PASS=$((PASS+1)); echo "${C_OK}OK${C_RESET} $1"; else FAIL=$((FAIL+1)); echo "${C_FAIL}FAIL${C_RESET} $1"; fi
|
|
}
|
|
|
|
# ---------- fast: release identity ----------
|
|
expect_exit "valid RELEASE resolves" 0 -- bash -c 'source scripts/common.sh && load_release'
|
|
|
|
printf 'garbage\n' > RELEASE
|
|
expect_exit "invalid RELEASE exits 1" 1 -- bash -c 'source scripts/common.sh && load_release'
|
|
|
|
mv RELEASE "$SANDBOX/RELEASE.hidden"
|
|
expect_exit "missing RELEASE exits 1" 1 -- bash -c 'source scripts/common.sh && load_release'
|
|
cp "$RELEASE_BACKUP" RELEASE
|
|
|
|
bash -c 'source scripts/common.sh && load_release' >/dev/null 2>&1
|
|
bash -c 'source scripts/common.sh && load_release && case "$MOSAIC_IMAGE_TAG" in mosaic-poc-agent:*-r'"$(cat RELEASE)"') exit 0;; *) exit 1;; esac' >/dev/null 2>&1
|
|
check "valid RELEASE leaves image tag consistent with version" $?
|
|
|
|
# ---------- sandboxed state machine (Docker required) ----------
|
|
if docker info >/dev/null 2>&1; then
|
|
mkdir -p "$SANDBOX/data"
|
|
# The mock adapter: no credential and no provider call in the gate (row 244,
|
|
# ruling A, sage-1914). This suite proves the release state machine, image and
|
|
# Compose path, not that the pi image reaches the provider.
|
|
cat > "$SANDBOX/config.json" <<EOF
|
|
{"configVersion":1,"environment":"development","dataRoot":"$SANDBOX/data","execution":{"backend":"docker","provider":"zai","model":"glm-5.3-flash","adapter":"mock"}}
|
|
EOF
|
|
export MOSAIC_CONFIG="$SANDBOX/config.json"
|
|
|
|
expect_exit "status safe on empty state" 0 -- scripts/release.sh status
|
|
[ ! -e "$SANDBOX/data/state/active.json" ] \
|
|
&& check "status created no pointer" 0 || check "status created no pointer" 1
|
|
|
|
# The mock gives the right marker, so only the fault's wrong expectation refuses.
|
|
expect_exit "fault-injected activation refuses" 1 -- env MOSAIC_MOCK_RESPONSE=MOSAIC_HELLO_OK scripts/release.sh activate --fault-injection
|
|
[ ! -e "$SANDBOX/data/state/active.json" ] \
|
|
&& check "refused activation wrote no pointer" 0 || check "refused activation wrote no pointer" 1
|
|
if [ -f "$SANDBOX/data/state/activation-log.jsonl" ]; then
|
|
node -e '
|
|
const fs = require("fs");
|
|
const lines = fs.readFileSync(process.argv[1], "utf8").split("\n").filter(Boolean);
|
|
if (lines.length !== 1) process.exit(1);
|
|
const e = JSON.parse(lines[0]);
|
|
process.exit(e.event === "refused" && e.release && e.imageTag && e.at ? 0 : 1);
|
|
' "$SANDBOX/data/state/activation-log.jsonl"
|
|
check "refusal logged exactly once with valid fields" $?
|
|
else
|
|
check "refusal logged exactly once with valid fields" 1
|
|
fi
|
|
|
|
expect_exit "healthy activation succeeds" 0 -- env MOSAIC_MOCK_RESPONSE=MOSAIC_HELLO_OK scripts/release.sh activate
|
|
node -e '
|
|
const fs = require("fs");
|
|
const p = JSON.parse(fs.readFileSync(process.argv[1], "utf8"));
|
|
process.exit(p.pointerVersion === 1 && p.release && p.imageTag && p.activatedAt ? 0 : 1);
|
|
' "$SANDBOX/data/state/active.json"
|
|
check "pointer written with valid fields" $?
|
|
|
|
expect_exit "repeat activation succeeds (log grows)" 0 -- env MOSAIC_MOCK_RESPONSE=MOSAIC_HELLO_OK scripts/release.sh activate
|
|
LINES=$(grep -c '' "$SANDBOX/data/state/activation-log.jsonl")
|
|
[ "$LINES" -ge 3 ] && check "log is append-only across activations" 0 || check "log is append-only across activations" 1
|
|
|
|
expect_exit "rollback without previous refuses" 1 -- scripts/release.sh rollback
|
|
else
|
|
echo "skip state-machine cases (docker daemon unavailable)"
|
|
fi
|
|
|
|
echo
|
|
echo "selftest: $PASS passed, $FAIL failed"
|
|
[ "$FAIL" -eq 0 ]
|