Files
ci/bin/imgplat_test.sh
zeekayandHanzo Dev efb58d8b87
Hanzo CI/CD / test (linux-amd64) (push) Successful in 9m18s
Hanzo CI/CD / test (linux-arm64) (push) Successful in 9m14s
Hanzo CI/CD / cicd (push) Failing after 5m39s
CI/CD / gate (push) Failing after 19m36s
Hand grep its input instead of piping into grep -q
Under pipefail, a pipe into `grep -q` reports the writer's status too, and
grep quits at its first match, so the answer depends on whether the writer
finished before the pipe closed. The imgtags suite failed that way on an amd64
runner and passed on the arm64 one at the same commit. A here-string has no
second process to lose.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-23 01:57:09 -07:00

84 lines
4.1 KiB
Bash
Executable File

#!/usr/bin/env bash
# Tests for bin/imgplat, and for the property the script exists to hold: BOTH
# build lanes read back what they published. Runs offline — a stub `crane` on
# PATH answers with manifests taken from real registry replies, so what is tested
# is the parse and the refusal, not the network.
# Run: bash bin/imgplat_test.sh
set -uo pipefail
cd "$(dirname "$0")/.."
IMGPLAT="$PWD/bin/imgplat"
WF=".github/workflows/build.yml"
fail=0
STUB=$(mktemp -d); trap 'rm -rf "$STUB"' EXIT
# A stub crane: the manifest is whatever MANIFEST names, the config whatever
# CONFIG names. docker must be invisible so the crane branch is the one taken.
cat > "$STUB/crane" <<'EOF'
#!/usr/bin/env bash
case "$1" in
manifest) cat "$MANIFEST" ;;
config) cat "$CONFIG" ;;
esac
EOF
chmod +x "$STUB/crane"
PATH="$STUB:$PATH"
m() { printf '%s' "$1" > "$STUB/m.json"; export MANIFEST="$STUB/m.json"; }
c() { printf '%s' "$1" > "$STUB/c.json"; export CONFIG="$STUB/c.json"; }
t() { # t <name> <want> <args...>
local name="$1" want="$2"; shift 2
got=$(bash "$IMGPLAT" "$@" 2>/dev/null | tr '\n' ' ' | sed 's/ $//')
[ -z "$got" ] && got="ERROR"
if [ "$got" = "$want" ]; then printf 'ok %-56s -> %s\n' "$name" "$got"
else printf 'FAIL %-56s -> %s (want %s)\n' "$name" "$got" "$want"; fail=1; fi
}
r() { # r <name> <expect-exit> <args...>
local name="$1" want="$2"; shift 2
bash "$IMGPLAT" "$@" >/dev/null 2>&1; local got=$?
if [ "$got" = "$want" ]; then printf 'ok %-56s -> exit %s\n' "$name" "$got"
else printf 'FAIL %-56s -> exit %s (want %s)\n' "$name" "$got" "$want"; fail=1; fi
}
IDX2='{"manifests":[{"platform":{"os":"linux","architecture":"amd64"}},{"platform":{"os":"linux","architecture":"arm64"}}]}'
IDX1='{"manifests":[{"platform":{"os":"linux","architecture":"amd64"}}]}'
ATT='{"manifests":[{"platform":{"os":"linux","architecture":"amd64"}},{"platform":{"os":"unknown","architecture":"unknown"}}]}'
BARE='{"config":{"digest":"sha256:x"}}'
# --- what an image serves ----------------------------------------------------
m "$IDX2"; t "an index with two manifests serves two" "linux/amd64 linux/arm64" x:1
m "$IDX1"; t "an index with one manifest serves one" "linux/amd64" x:1
m "$ATT"; t "an attestation is not an architecture" "linux/amd64" x:1
m "$BARE"; c '{"os":"linux","architecture":"arm64"}'
t "a bare manifest answers from its config" "linux/arm64" x:1
# --- the refusal -------------------------------------------------------------
m "$IDX2"; r "both declared, both served" 0 x:1 linux/amd64,linux/arm64
m "$IDX2"; r "order is not part of the comparison" 0 x:1 linux/arm64,linux/amd64
m "$IDX1"; r "an arch-neutral tag over one platform" 1 x:1 linux/amd64,linux/arm64
m "$IDX2"; r "a second platform nobody declared" 1 x:1 linux/amd64
V8='{"manifests":[{"platform":{"os":"linux","architecture":"amd64"}},{"platform":{"os":"linux","architecture":"arm64","variant":"v8"}}]}'
V7='{"manifests":[{"platform":{"os":"linux","architecture":"arm","variant":"v7"}}]}'
m "$V8"; r "arm64/v8 is arm64" 0 x:1 linux/amd64,linux/arm64
m "$V7"; r "arm/v7 is not arm/v6" 1 x:1 linux/arm/v6
m "$V7"; r "arm/v7 is arm/v7" 0 x:1 linux/arm/v7
m "$IDX1"; r "no expectation asserts nothing" 0 x:1
# --- one rule, both lanes ----------------------------------------------------
# The whole point of the script is that neither lane can publish an image it did
# not prove. A lane that stops calling it publishes the same silence that made
# cloud:sha-ac39bda an arch-neutral tag over a single amd64 manifest.
for lane in "Build & push images (per hanzo.yml)" "Delegate build to the runner (mode=delegate)"; do
s=$(awk -v n=" - name: $lane" 'index($0,n)==1{f=1;next} f&&/^ - name: /{exit} f' "$WF")
if grep -q 'bin/imgplat' <<<"$s"; then
printf 'ok %-56s -> proves what it published\n' "${lane%% (*}"
else
printf 'FAIL %-56s -> publishes without reading the manifest back\n' "${lane%% (*}"; fail=1
fi
done
echo
[ $fail -eq 0 ] && echo "imgplat: all cases pass" || echo "imgplat: FAILURES"
exit $fail