From febbeb6c0129f567091fce89f243327edb35ed52 Mon Sep 17 00:00:00 2001 From: sneak Date: Wed, 14 Oct 2026 07:35:45 +0000 Subject: [PATCH] fix: each browser-suite run builds and removes an image of its own (closes #547) script/test-e2e and script/test-e2e-firefox tagged their image with one fixed name. When two clones ran a suite at once, the second build moved that tag, the image store deleted the first run's now-untagged image, and that suite exited 125 without running a test. Each run now tags its image with the suite's name and twelve random hex digits, runs it by that tag, and removes it in the scripts' existing exit and interrupt cleanup, so no run leaves an image behind. The image-ID file that guarded against a moving tag is no longer needed. README.md's End-to-End Tests section says so. Model: opus-5-5 --- README.md | 6 ++++++ script/test-e2e | 28 +++++++++++++--------------- script/test-e2e-firefox | 23 ++++++++--------------- 3 files changed, 27 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 54a5f07..257dfee 100644 --- a/README.md +++ b/README.md @@ -347,6 +347,12 @@ are outside `make check`. Neither opens the popup from the toolbar button: both load its page in an ordinary tab, so what the toolbar popup itself adds, its size and its closing when it loses focus, is covered by neither. +Each run builds its image under a tag of its own, `autistmask-e2e-chrome:` or +`autistmask-e2e-firefox:` followed by twelve random hex digits, and removes that +image when it exits, an interrupt included. Two clones can therefore run the +same suite at once without one build taking the other's image away, and no run +leaves an image behind. + ### Chrome (`make test-e2e`) `make test-e2e` builds `dist/chrome/` and drives the **real popup in a real diff --git a/script/test-e2e b/script/test-e2e index 2246905..43a3450 100755 --- a/script/test-e2e +++ b/script/test-e2e @@ -22,13 +22,18 @@ set -eu SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)" ROOT="$(cd "$SCRIPT_DIR/.." && pwd -P)" -IMAGE="$("$SCRIPT_DIR/projectname")-e2e-chrome" - -IIDFILE="" +# Each run builds, runs and then removes an image under a tag of its own. +# Under one tag shared by every run, a second clone's build moves the tag +# off this run's image, and the image store can then delete that untagged +# image before or while this run uses it. The tag is random rather than +# $$ because CI jobs share one docker daemon, but each job's container +# numbers its processes from scratch. +IMAGE="$("$SCRIPT_DIR/projectname")-e2e-chrome:$(od -An -N6 -tx1 /dev/urandom | tr -d ' \n')" cleanup() { - if [ -n "$IIDFILE" ]; then - rm -f "$IIDFILE" + # No image to remove when the build failed or was interrupted. + if docker image inspect "$IMAGE" >/dev/null 2>&1; then + docker image rm "$IMAGE" >/dev/null fi } @@ -40,22 +45,15 @@ main() { exit 1 fi - IIDFILE="$(mktemp)" trap cleanup EXIT trap 'cleanup; exit 130' INT TERM echo "Building the Chrome e2e image (extension included)..." # --no-cache: the image build runs make build and its checks, and a # cached layer is a check that did not run. - docker build --no-cache --iidfile "$IIDFILE" -t "$IMAGE" \ - -f tests/e2e/Dockerfile . + docker build --no-cache -t "$IMAGE" -f tests/e2e/Dockerfile . echo "Running e2e suite in the pinned Playwright container..." - # The image is run by ID, not by tag: where two clones of this repo run - # the suite at once, the other build can move the tag between this - # build and this run, and the suite would then silently test the other - # checkout. - # # --ipc=host: Chromium's shared-memory needs more than the default # 64MB /dev/shm or renderers crash. # HOME=/tmp: the image's root home is not a reliable place for the @@ -79,7 +77,7 @@ main() { -e HOME=/tmp \ -e PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 \ -e "E2E_TRACE_NETWORK=${E2E_TRACE_NETWORK:-0}" \ - "$(cat "$IIDFILE")" \ + "$IMAGE" \ node tests/e2e/run.js # Where chrome.storage.local lives, and what moves it: two unpacked loads @@ -95,7 +93,7 @@ main() { docker run --rm \ --ipc=host \ -e HOME=/tmp \ - "$(cat "$IIDFILE")" \ + "$IMAGE" \ node tests/e2e/storagePartition.js } diff --git a/script/test-e2e-firefox b/script/test-e2e-firefox index 892e7e1..6058ba3 100755 --- a/script/test-e2e-firefox +++ b/script/test-e2e-firefox @@ -21,13 +21,13 @@ set -eu SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)" ROOT="$(cd "$SCRIPT_DIR/.." && pwd -P)" -IMAGE="$("$SCRIPT_DIR/projectname")-e2e-firefox" - -IIDFILE="" +# A tag of this run's own, as in script/test-e2e, which says why. +IMAGE="$("$SCRIPT_DIR/projectname")-e2e-firefox:$(od -An -N6 -tx1 /dev/urandom | tr -d ' \n')" cleanup() { - if [ -n "$IIDFILE" ]; then - rm -f "$IIDFILE" + # No image to remove when the build failed or was interrupted. + if docker image inspect "$IMAGE" >/dev/null 2>&1; then + docker image rm "$IMAGE" >/dev/null fi } @@ -39,22 +39,15 @@ main() { exit 1 fi - IIDFILE="$(mktemp)" trap cleanup EXIT trap 'cleanup; exit 130' INT TERM echo "Building the pinned Firefox e2e image (extension included)..." # --no-cache: the image build runs make build and its checks, and a # cached layer is a check that did not run. - docker build --no-cache --iidfile "$IIDFILE" -t "$IMAGE" \ - -f tests/e2e/firefox/Dockerfile . + docker build --no-cache -t "$IMAGE" -f tests/e2e/firefox/Dockerfile . echo "Running the Firefox e2e suite..." - # The image is run by ID, not by tag: where two clones of this repo run - # the suite at once, the other build can move the tag between this - # build and this run, and the suite would then silently test the other - # checkout. - # # --shm-size=1g: Firefox needs more than the default 64MB /dev/shm. # --network none: the suite stubs nothing, so this is what keeps the # run offline and deterministic. The extension swallows its own @@ -72,7 +65,7 @@ main() { --shm-size=1g \ --network none \ -e HOME=/tmp \ - "$(cat "$IIDFILE")" \ + "$IMAGE" \ node tests/e2e/firefox/run.js dist/firefox # The install/uninstall/re-install property, against the packaged XPI @@ -85,7 +78,7 @@ main() { --shm-size=1g \ --network none \ -e HOME=/tmp \ - "$(cat "$IIDFILE")" \ + "$IMAGE" \ node tests/e2e/firefox/reinstall.js }