diff --git a/scripts/e2e/multi-node-update-docker.sh b/scripts/e2e/multi-node-update-docker.sh index aae06e09f5f8..2ed0134fa722 100755 --- a/scripts/e2e/multi-node-update-docker.sh +++ b/scripts/e2e/multi-node-update-docker.sh @@ -20,7 +20,8 @@ ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" source "$ROOT_DIR/scripts/lib/docker-e2e-image.sh" source "$ROOT_DIR/scripts/lib/docker-e2e-package.sh" -IMAGE_NAME="openclaw-multi-node-update-e2e" +IMAGE_NAME="$(docker_e2e_resolve_image "openclaw-multi-node-update-e2e" OPENCLAW_MULTI_NODE_UPDATE_E2E_IMAGE)" +SKIP_BUILD="${OPENCLAW_MULTI_NODE_UPDATE_E2E_SKIP_BUILD:-0}" DOCKER_RUN_TIMEOUT="${OPENCLAW_MULTI_NODE_DOCKER_TIMEOUT:-300s}" RUN_ID="${OPENCLAW_MULTI_NODE_RUN_ID:-$(date -u +%Y%m%dT%H%M%SZ)-$$}" ARTIFACT_DIR="${OPENCLAW_MULTI_NODE_ARTIFACT_DIR:-$ROOT_DIR/.artifacts/multi-node-update/$RUN_ID}" @@ -33,7 +34,7 @@ cleanup() { trap cleanup EXIT # Build the bare e2e image and prepare the package tarball. -docker_e2e_build_or_reuse "$IMAGE_NAME" multi-node-update "$ROOT_DIR/scripts/e2e/Dockerfile" "$ROOT_DIR" "bare" "${OPENCLAW_SKIP_DOCKER_BUILD:-0}" +docker_e2e_build_or_reuse "$IMAGE_NAME" multi-node-update "$ROOT_DIR/scripts/e2e/Dockerfile" "$ROOT_DIR" "bare" "$SKIP_BUILD" PACKAGE_TGZ="$(docker_e2e_prepare_package_tgz multi-node-update "${OPENCLAW_CURRENT_PACKAGE_TGZ:-}")" docker_e2e_package_mount_args "$PACKAGE_TGZ" diff --git a/test/scripts/docker-build-helper.test.ts b/test/scripts/docker-build-helper.test.ts index 965f9de05534..6fa26eb61ba5 100644 --- a/test/scripts/docker-build-helper.test.ts +++ b/test/scripts/docker-build-helper.test.ts @@ -1826,6 +1826,75 @@ grep -qx -- "OPENCLAW_E2E_COMMAND_TIMEOUT=23s" "$TMPDIR/package-args" ); }); + it("reuses the shared bare image for multi-node update targeted runs", () => { + const workDir = mkdtempSync(join(tmpdir(), "openclaw-multi-node-shared-image-")); + + try { + const rootDir = process.cwd(); + mkdirSync(join(workDir, "bin")); + writeFileSync(join(workDir, "openclaw-current.tgz"), "fake package"); + writeFileSync( + join(workDir, "bin", "docker"), + `#!/usr/bin/env bash +printf "%s\\n" "$*" >>"$TMPDIR/docker-seen" +case "$1 $2" in + "image inspect") + exit 0 + ;; + "run "*) + exit 0 + ;; +esac +exit 9 +`, + ); + writeFileSync( + join(workDir, "bin", "timeout"), + `#!/usr/bin/env bash +case "\${1:-}" in + --kill-after=1s) + exit 0 + ;; + --kill-after=30s) + shift 2 + ;; + *) + shift + ;; +esac +exec "$@" +`, + ); + chmodSync(join(workDir, "bin", "docker"), 0o755); + chmodSync(join(workDir, "bin", "timeout"), 0o755); + + const script = ` +set -euo pipefail +ROOT_DIR=${shellQuote(rootDir)} +TMPDIR=${shellQuote(workDir)} +export ROOT_DIR TMPDIR +export PATH="$TMPDIR/bin:$PATH" +export OPENCLAW_SKIP_DOCKER_BUILD=1 +export OPENCLAW_DOCKER_E2E_IMAGE=shared-bare +export OPENCLAW_CURRENT_PACKAGE_TGZ="$TMPDIR/openclaw-current.tgz" +export OPENCLAW_MULTI_NODE_ARTIFACT_DIR="$TMPDIR/artifacts" + +bash "$ROOT_DIR/scripts/e2e/multi-node-update-docker.sh" + +grep -q '^image inspect shared-bare$' "$TMPDIR/docker-seen" +grep -Fq ' shared-bare ' "$TMPDIR/docker-seen" +if grep -Fq 'openclaw-multi-node-update-e2e' "$TMPDIR/docker-seen"; then + echo "multi-node update lane ignored the shared targeted image" >&2 + exit 1 +fi +`; + + execFileSync("bash", ["-lc", script], { encoding: "utf8" }); + } finally { + rmSync(workDir, { recursive: true, force: true }); + } + }); + it("bounds upgrade survivor foreground OpenClaw CLI calls", () => { const runner = readFileSync(UPGRADE_SURVIVOR_DOCKER_E2E_PATH, "utf8"); const publishedRunner = readFileSync(UPGRADE_SURVIVOR_RUN_SCRIPT, "utf8");