From e19efddd5d5bd3394f98104e530057ada2a11c2f Mon Sep 17 00:00:00 2001 From: Niels Mokkenstorm Date: Tue, 11 Aug 2026 09:50:32 +0200 Subject: [PATCH] fix: make the devnet image-lock override guard test the shipped invocation --- Makefile | 10 +++++----- e2e/devnet/compose.sh | 10 ++++++++++ e2e/devnet/verify-image-lock-overrides.sh | 5 +++-- e2e/devnet/verify-images.sh | 13 +++++-------- 4 files changed, 23 insertions(+), 15 deletions(-) create mode 100755 e2e/devnet/compose.sh diff --git a/Makefile b/Makefile index d24faba..556fcbd 100644 --- a/Makefile +++ b/Makefile @@ -112,8 +112,8 @@ e2e-images-override-check: ## regression-check that local image overrides cannot cd e2e/devnet && ./verify-image-lock-overrides.sh e2e-up: e2e-images-verify ## fresh devnet from locked images: wipe state, boot, wait, seed accounts - cd e2e/devnet && env -u JETSTREAM_IMAGE -u CONSTELLATION_IMAGE -u SLINGSHOT_IMAGE docker compose --env-file .env --env-file images.env down -v - cd e2e/devnet && env -u JETSTREAM_IMAGE -u CONSTELLATION_IMAGE -u SLINGSHOT_IMAGE docker compose --env-file .env --env-file images.env up -d + cd e2e/devnet && ./compose.sh --env-file .env --env-file images.env down -v + cd e2e/devnet && ./compose.sh --env-file .env --env-file images.env up -d @echo "waiting for the devnet PDS to become healthy..." @for i in $$(seq 1 60); do \ st=$$(docker inspect -f '{{.State.Health.Status}}' crate-devnet-pds-1 2>/dev/null); \ @@ -124,8 +124,8 @@ e2e-up: e2e-images-verify ## fresh devnet from locked images: wipe state, boot, e2e-up-local: ## fresh devnet rebuilt locally from the pinned external source revisions cd e2e/devnet && ./setup.sh - cd e2e/devnet && env -u JETSTREAM_IMAGE -u CONSTELLATION_IMAGE -u SLINGSHOT_IMAGE docker compose --env-file .env --env-file images.env -f docker-compose.yml -f docker-compose.local-build.yml down -v - cd e2e/devnet && env -u JETSTREAM_IMAGE -u CONSTELLATION_IMAGE -u SLINGSHOT_IMAGE docker compose --env-file .env --env-file images.env -f docker-compose.yml -f docker-compose.local-build.yml up -d --build + cd e2e/devnet && ./compose.sh --env-file .env --env-file images.env -f docker-compose.yml -f docker-compose.local-build.yml down -v + cd e2e/devnet && ./compose.sh --env-file .env --env-file images.env -f docker-compose.yml -f docker-compose.local-build.yml up -d --build @echo "waiting for the devnet PDS to become healthy..." @for i in $$(seq 1 60); do \ st=$$(docker inspect -f '{{.State.Health.Status}}' crate-devnet-pds-1 2>/dev/null); \ @@ -135,7 +135,7 @@ e2e-up-local: ## fresh devnet rebuilt locally from the pinned external source re cd e2e/devnet && ./create-test-accounts.sh e2e-down: ## tear down the devnet and wipe its state - cd e2e/devnet && env -u JETSTREAM_IMAGE -u CONSTELLATION_IMAGE -u SLINGSHOT_IMAGE docker compose --env-file .env --env-file images.env down -v + cd e2e/devnet && ./compose.sh --env-file .env --env-file images.env down -v e2e: e2e-up ## full cycle: fresh devnet + run the e2e suite against it (crate's own dev server must already be running — see e2e/README.md) cd e2e && npm test diff --git a/e2e/devnet/compose.sh b/e2e/devnet/compose.sh new file mode 100755 index 0000000..04f769f --- /dev/null +++ b/e2e/devnet/compose.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +# Single source of truth for the shell-override guard: every devnet Compose +# invocation goes through here so JETSTREAM_IMAGE, CONSTELLATION_IMAGE, and +# SLINGSHOT_IMAGE can only come from images.env, never from an ambient shell +# or secrets export. Update this list in one place, not per caller. +set -euo pipefail +cd "$(dirname "${BASH_SOURCE[0]}")" + +exec env -u JETSTREAM_IMAGE -u CONSTELLATION_IMAGE -u SLINGSHOT_IMAGE \ + docker compose "$@" diff --git a/e2e/devnet/verify-image-lock-overrides.sh b/e2e/devnet/verify-image-lock-overrides.sh index 3c672be..9d6f3ae 100755 --- a/e2e/devnet/verify-image-lock-overrides.sh +++ b/e2e/devnet/verify-image-lock-overrides.sh @@ -25,12 +25,13 @@ printf '%s\n' \ 'SLINGSHOT_IMAGE=ghcr.io/riotbyte/crate-devnet-slingshot:mutable' \ >"$temp_env" +# Goes through compose.sh, the same wrapper e2e-up uses, so this exercises +# the guard as shipped rather than a private copy of it. resolved="$(env \ JETSTREAM_IMAGE=ghcr.io/riotbyte/crate-devnet-jetstream:mutable \ CONSTELLATION_IMAGE=ghcr.io/riotbyte/crate-devnet-constellation:mutable \ SLINGSHOT_IMAGE=ghcr.io/riotbyte/crate-devnet-slingshot:mutable \ - env -u JETSTREAM_IMAGE -u CONSTELLATION_IMAGE -u SLINGSHOT_IMAGE \ - docker compose --env-file "$temp_env" --env-file images.env config --format json)" + ./compose.sh --env-file "$temp_env" --env-file images.env config --format json)" printf '%s' "$resolved" | jq -e \ --arg jetstream "$JETSTREAM_IMAGE" \ diff --git a/e2e/devnet/verify-images.sh b/e2e/devnet/verify-images.sh index 12c4643..b027305 100755 --- a/e2e/devnet/verify-images.sh +++ b/e2e/devnet/verify-images.sh @@ -32,14 +32,11 @@ if [[ ! -f .env ]]; then exit 1 fi -# Compose gives shell variables precedence over --env-file values. Clear the -# three image variables and put the committed lock after local secrets so no -# ambient shell or .env value can replace a digest. -resolved="$(env \ - -u JETSTREAM_IMAGE \ - -u CONSTELLATION_IMAGE \ - -u SLINGSHOT_IMAGE \ - docker compose --env-file .env --env-file images.env config --format json)" +# Compose gives shell variables precedence over --env-file values. compose.sh +# clears the three image variables so no ambient shell or .env value can +# replace a digest; the committed lock is the last --env-file, after local +# secrets. +resolved="$(./compose.sh --env-file .env --env-file images.env config --format json)" printf '%s' "$resolved" | jq -e \ --arg jetstream "$JETSTREAM_IMAGE" \ -- 2.51.2