From 1476e24af39b2dc3efdb5bce70b9b2ff536c3b7c Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 29 Apr 2026 06:15:01 +0100 Subject: [PATCH] refactor(test): share bundled channel Docker harness helpers --- docs/help/testing.md | 2 +- .../bundled-channel-runtime-deps-docker.sh | 2 + scripts/e2e/lib/bundled-channel/channel.sh | 18 ++--- .../lib/bundled-channel/disabled-config.sh | 18 ++--- .../e2e/lib/bundled-channel/load-failure.sh | 81 +++++++++++-------- scripts/e2e/lib/bundled-channel/root-owned.sh | 17 +--- .../e2e/lib/bundled-channel/setup-entry.sh | 18 ++--- scripts/e2e/lib/bundled-channel/update.sh | 18 ++--- scripts/lib/docker-e2e-logs.sh | 14 ++++ 9 files changed, 87 insertions(+), 101 deletions(-) diff --git a/docs/help/testing.md b/docs/help/testing.md index 150caf95008..ce7d28a64b6 100644 --- a/docs/help/testing.md +++ b/docs/help/testing.md @@ -627,7 +627,7 @@ The live-model Docker runners also bind-mount only the needed CLI auth homes (or Set `OPENCLAW_PLUGINS_E2E_CLAWHUB=0` to skip the ClawHub block, or override the default kitchen-sink package/runtime pair with `OPENCLAW_PLUGINS_E2E_CLAWHUB_SPEC` and `OPENCLAW_PLUGINS_E2E_CLAWHUB_ID`. Without `OPENCLAW_CLAWHUB_URL`/`CLAWHUB_URL`, the test uses a hermetic local ClawHub fixture server. - Plugin update unchanged smoke: `pnpm test:docker:plugin-update` (script: `scripts/e2e/plugin-update-unchanged-docker.sh`) - Config reload metadata smoke: `pnpm test:docker:config-reload` (script: `scripts/e2e/config-reload-source-docker.sh`) -- Bundled plugin runtime deps: `pnpm test:docker:bundled-channel-deps` builds a small Docker runner image by default, builds and packs OpenClaw once on the host, then mounts that tarball into each Linux install scenario. Reuse the image with `OPENCLAW_SKIP_DOCKER_BUILD=1`, skip the host rebuild after a fresh local build with `OPENCLAW_BUNDLED_CHANNEL_HOST_BUILD=0`, or point at an existing tarball with `OPENCLAW_CURRENT_PACKAGE_TGZ=/path/to/openclaw-*.tgz`. The full Docker aggregate and release-path bundled-channel chunks pre-pack this tarball once, then shard bundled channel checks into independent lanes, including separate update lanes for Telegram, Discord, Slack, Feishu, memory-lancedb, and ACPX. Release chunks split channel smokes, update targets, and setup/runtime contracts into `bundled-channels-core`, `bundled-channels-update-a`, `bundled-channels-update-b`, and `bundled-channels-contracts`; the aggregate `bundled-channels` chunk remains available for manual reruns. The release workflow also splits provider installer chunks and bundled plugin install/uninstall chunks; legacy `package-update`, `plugins-runtime`, and `plugins-integrations` chunks remain aggregate aliases for manual reruns. Use `OPENCLAW_BUNDLED_CHANNELS=telegram,slack` to narrow the channel matrix when running the bundled lane directly, or `OPENCLAW_BUNDLED_CHANNEL_UPDATE_TARGETS=telegram,acpx` to narrow the update scenario. The lane also verifies that `channels..enabled=false` and `plugins.entries..enabled=false` suppress doctor/runtime-dependency repair. +- Bundled plugin runtime deps: `pnpm test:docker:bundled-channel-deps` builds a small Docker runner image by default, builds and packs OpenClaw once on the host, then mounts that tarball into each Linux install scenario. Reuse the image with `OPENCLAW_SKIP_DOCKER_BUILD=1`, skip the host rebuild after a fresh local build with `OPENCLAW_BUNDLED_CHANNEL_HOST_BUILD=0`, or point at an existing tarball with `OPENCLAW_CURRENT_PACKAGE_TGZ=/path/to/openclaw-*.tgz`. The full Docker aggregate and release-path bundled-channel chunks pre-pack this tarball once, then shard bundled channel checks into independent lanes, including separate update lanes for Telegram, Discord, Slack, Feishu, memory-lancedb, and ACPX. Release chunks split channel smokes, update targets, and setup/runtime contracts into `bundled-channels-core`, `bundled-channels-update-a`, `bundled-channels-update-b`, and `bundled-channels-contracts`; the aggregate `bundled-channels` chunk remains available for manual reruns. The release workflow also splits provider installer chunks and bundled plugin install/uninstall chunks; legacy `package-update`, `plugins-runtime`, and `plugins-integrations` chunks remain aggregate aliases for manual reruns. Use `OPENCLAW_BUNDLED_CHANNELS=telegram,slack` to narrow the channel matrix when running the bundled lane directly, or `OPENCLAW_BUNDLED_CHANNEL_UPDATE_TARGETS=telegram,acpx` to narrow the update scenario. Per-scenario Docker runs default to `OPENCLAW_BUNDLED_CHANNEL_DOCKER_RUN_TIMEOUT=900s`; the multi-target update scenario defaults to `OPENCLAW_BUNDLED_CHANNEL_UPDATE_DOCKER_RUN_TIMEOUT=2400s`. The lane also verifies that `channels..enabled=false` and `plugins.entries..enabled=false` suppress doctor/runtime-dependency repair. - Narrow bundled plugin runtime deps while iterating by disabling unrelated scenarios, for example: `OPENCLAW_BUNDLED_CHANNEL_SCENARIOS=0 OPENCLAW_BUNDLED_CHANNEL_UPDATE_SCENARIO=0 OPENCLAW_BUNDLED_CHANNEL_ROOT_OWNED_SCENARIO=0 OPENCLAW_BUNDLED_CHANNEL_SETUP_ENTRY_SCENARIO=0 pnpm test:docker:bundled-channel-deps`. diff --git a/scripts/e2e/bundled-channel-runtime-deps-docker.sh b/scripts/e2e/bundled-channel-runtime-deps-docker.sh index fbe269239a6..a78bffac82e 100644 --- a/scripts/e2e/bundled-channel-runtime-deps-docker.sh +++ b/scripts/e2e/bundled-channel-runtime-deps-docker.sh @@ -28,6 +28,7 @@ RUN_LOAD_FAILURE_SCENARIO="${OPENCLAW_BUNDLED_CHANNEL_LOAD_FAILURE_SCENARIO:-1}" RUN_DISABLED_CONFIG_SCENARIO="${OPENCLAW_BUNDLED_CHANNEL_DISABLED_CONFIG_SCENARIO:-1}" CHANNEL_ONLY="${OPENCLAW_BUNDLED_CHANNEL_ONLY:-}" DOCKER_RUN_TIMEOUT="${OPENCLAW_BUNDLED_CHANNEL_DOCKER_RUN_TIMEOUT:-900s}" +DOCKER_UPDATE_RUN_TIMEOUT="${OPENCLAW_BUNDLED_CHANNEL_UPDATE_DOCKER_RUN_TIMEOUT:-${OPENCLAW_BUNDLED_CHANNEL_DOCKER_RUN_TIMEOUT:-2400s}}" docker_e2e_build_or_reuse "$IMAGE_NAME" bundled-channel-deps "$ROOT_DIR/scripts/e2e/Dockerfile" "$ROOT_DIR" "$DOCKER_TARGET" @@ -45,6 +46,7 @@ prepare_package_tgz() { prepare_package_tgz docker_e2e_package_mount_args "$PACKAGE_TGZ" +docker_e2e_harness_mount_args run_bundled_channel_runtime_dep_scenarios diff --git a/scripts/e2e/lib/bundled-channel/channel.sh b/scripts/e2e/lib/bundled-channel/channel.sh index 860473a0183..5b6a92d60fb 100644 --- a/scripts/e2e/lib/bundled-channel/channel.sh +++ b/scripts/e2e/lib/bundled-channel/channel.sh @@ -6,22 +6,22 @@ run_channel_scenario() { local channel="$1" local dep_sentinel="$2" - local run_log local state_script_b64 - run_log="$(docker_e2e_run_log "bundled-channel-deps-$channel")" state_script_b64="$(docker_e2e_test_state_shell_b64 "bundled-channel-deps-$channel" empty)" echo "Running bundled $channel runtime deps Docker E2E..." - if ! timeout "$DOCKER_RUN_TIMEOUT" docker run --rm \ + run_logged_print "bundled-channel-deps-$channel" timeout "$DOCKER_RUN_TIMEOUT" docker run --rm \ -e COREPACK_ENABLE_DOWNLOAD_PROMPT=0 \ -e OPENCLAW_CHANNEL_UNDER_TEST="$channel" \ -e OPENCLAW_DEP_SENTINEL="$dep_sentinel" \ -e "OPENCLAW_TEST_STATE_SCRIPT_B64=$state_script_b64" \ "${DOCKER_E2E_PACKAGE_ARGS[@]}" \ - -i "$IMAGE_NAME" bash -s >"$run_log" 2>&1 <<'EOF' + "${DOCKER_E2E_HARNESS_ARGS[@]}" \ + -i "$IMAGE_NAME" bash -s <<'EOF' set -euo pipefail -eval "$(printf "%s" "${OPENCLAW_TEST_STATE_SCRIPT_B64:?missing OPENCLAW_TEST_STATE_SCRIPT_B64}" | base64 -d)" +source scripts/lib/openclaw-e2e-instance.sh +openclaw_e2e_eval_test_state_from_b64 "${OPENCLAW_TEST_STATE_SCRIPT_B64:?missing OPENCLAW_TEST_STATE_SCRIPT_B64}" export NPM_CONFIG_PREFIX="$HOME/.npm-global" export PATH="$NPM_CONFIG_PREFIX/bin:$PATH" export OPENAI_API_KEY="sk-openclaw-bundled-channel-deps-e2e" @@ -426,12 +426,4 @@ stop_gateway echo "bundled $CHANNEL runtime deps Docker E2E passed" EOF - then - docker_e2e_print_log "$run_log" - rm -f "$run_log" - exit 1 - fi - - docker_e2e_print_log "$run_log" - rm -f "$run_log" } diff --git a/scripts/e2e/lib/bundled-channel/disabled-config.sh b/scripts/e2e/lib/bundled-channel/disabled-config.sh index 853d401bfcf..507813357e5 100644 --- a/scripts/e2e/lib/bundled-channel/disabled-config.sh +++ b/scripts/e2e/lib/bundled-channel/disabled-config.sh @@ -4,20 +4,20 @@ # Sourced by scripts/e2e/bundled-channel-runtime-deps-docker.sh. run_disabled_config_scenario() { - local run_log local state_script_b64 - run_log="$(docker_e2e_run_log bundled-channel-disabled-config)" state_script_b64="$(docker_e2e_test_state_shell_b64 bundled-channel-disabled-config empty)" echo "Running bundled channel disabled-config runtime deps Docker E2E..." - if ! timeout "$DOCKER_RUN_TIMEOUT" docker run --rm \ + run_logged_print bundled-channel-disabled-config timeout "$DOCKER_RUN_TIMEOUT" docker run --rm \ -e COREPACK_ENABLE_DOWNLOAD_PROMPT=0 \ -e "OPENCLAW_TEST_STATE_SCRIPT_B64=$state_script_b64" \ "${DOCKER_E2E_PACKAGE_ARGS[@]}" \ - -i "$IMAGE_NAME" bash -s >"$run_log" 2>&1 <<'EOF' + "${DOCKER_E2E_HARNESS_ARGS[@]}" \ + -i "$IMAGE_NAME" bash -s <<'EOF' set -euo pipefail -eval "$(printf "%s" "${OPENCLAW_TEST_STATE_SCRIPT_B64:?missing OPENCLAW_TEST_STATE_SCRIPT_B64}" | base64 -d)" +source scripts/lib/openclaw-e2e-instance.sh +openclaw_e2e_eval_test_state_from_b64 "${OPENCLAW_TEST_STATE_SCRIPT_B64:?missing OPENCLAW_TEST_STATE_SCRIPT_B64}" export NPM_CONFIG_PREFIX="$HOME/.npm-global" export PATH="$NPM_CONFIG_PREFIX/bin:$PATH" export OPENCLAW_NO_ONBOARD=1 @@ -171,12 +171,4 @@ fi echo "bundled channel disabled-config runtime deps Docker E2E passed" EOF - then - docker_e2e_print_log "$run_log" - rm -f "$run_log" - exit 1 - fi - - docker_e2e_print_log "$run_log" - rm -f "$run_log" } diff --git a/scripts/e2e/lib/bundled-channel/load-failure.sh b/scripts/e2e/lib/bundled-channel/load-failure.sh index 2e8728a8562..16cdf4577cf 100644 --- a/scripts/e2e/lib/bundled-channel/load-failure.sh +++ b/scripts/e2e/lib/bundled-channel/load-failure.sh @@ -4,20 +4,20 @@ # Sourced by scripts/e2e/bundled-channel-runtime-deps-docker.sh. run_load_failure_scenario() { - local run_log local state_script_b64 - run_log="$(docker_e2e_run_log bundled-channel-load-failure)" state_script_b64="$(docker_e2e_test_state_shell_b64 bundled-channel-load-failure empty)" echo "Running bundled channel load-failure isolation Docker E2E..." - if ! timeout "$DOCKER_RUN_TIMEOUT" docker run --rm \ + run_logged_print bundled-channel-load-failure timeout "$DOCKER_RUN_TIMEOUT" docker run --rm \ -e COREPACK_ENABLE_DOWNLOAD_PROMPT=0 \ -e "OPENCLAW_TEST_STATE_SCRIPT_B64=$state_script_b64" \ "${DOCKER_E2E_PACKAGE_ARGS[@]}" \ - -i "$IMAGE_NAME" bash -s >"$run_log" 2>&1 <<'EOF' + "${DOCKER_E2E_HARNESS_ARGS[@]}" \ + -i "$IMAGE_NAME" bash -s <<'EOF' set -euo pipefail -eval "$(printf "%s" "${OPENCLAW_TEST_STATE_SCRIPT_B64:?missing OPENCLAW_TEST_STATE_SCRIPT_B64}" | base64 -d)" +source scripts/lib/openclaw-e2e-instance.sh +openclaw_e2e_eval_test_state_from_b64 "${OPENCLAW_TEST_STATE_SCRIPT_B64:?missing OPENCLAW_TEST_STATE_SCRIPT_B64}" export NPM_CONFIG_PREFIX="$HOME/.npm-global" export PATH="$NPM_CONFIG_PREFIX/bin:$PATH" export OPENCLAW_NO_ONBOARD=1 @@ -106,16 +106,28 @@ if (!bundledPath) { throw new Error("missing packaged bundled channel loader artifact"); } const bundled = await import(pathToFileURL(bundledPath)); -const oneArgExports = Object.entries(bundled).filter( - ([, value]) => typeof value === "function" && value.length === 1, +const loaderNames = [ + "getBundledChannelPlugin", + "getBundledChannelSetupPlugin", + "getBundledChannelSecrets", + "getBundledChannelSetupSecrets", +]; +const exportedLoaders = new Map( + Object.values(bundled) + .filter((value) => typeof value === "function") + .map((fn) => [fn.name, fn]), ); -if (oneArgExports.length === 0) { - throw new Error(`missing one-argument bundled loader exports; exports=${Object.keys(bundled).join(",")}`); -} +const loaders = loaderNames.map((name) => { + const fn = exportedLoaders.get(name); + if (typeof fn !== "function") { + throw new Error(`missing packaged bundled loader export ${name}; exports=${Object.keys(bundled).join(",")}`); + } + return [name, fn]; +}); const id = "load-failure-alpha"; -for (let i = 0; i < 2; i += 1) { - for (const [name, fn] of oneArgExports) { +function exerciseLoaders() { + for (const [name, fn] of loaders) { try { fn(id); } catch (error) { @@ -127,23 +139,30 @@ for (let i = 0; i < 2; i += 1) { } } -const counts = { - plugin: globalThis.__loadFailurePlugin, - setup: globalThis.__loadFailureSetup, - secrets: globalThis.__loadFailureSecrets, - setupSecrets: globalThis.__loadFailureSetupSecrets, -}; -for (const [key, value] of Object.entries({ - plugin: counts.plugin, - setup: counts.setup, - setupSecrets: counts.setupSecrets, -})) { - if (value !== 1) { - throw new Error(`expected ${key} failure to be cached after one load, got ${value}`); +function loadCounts() { + return { + plugin: globalThis.__loadFailurePlugin, + setup: globalThis.__loadFailureSetup, + secrets: globalThis.__loadFailureSecrets, + setupSecrets: globalThis.__loadFailureSetupSecrets, + }; +} + +exerciseLoaders(); +const firstCounts = loadCounts(); +exerciseLoaders(); +const secondCounts = loadCounts(); +for (const key of ["plugin", "setup", "setupSecrets"]) { + const first = firstCounts[key]; + if (!Number.isInteger(first) || first < 1) { + throw new Error(`expected ${key} failure to be exercised at least once, got ${first}`); + } + if (secondCounts[key] !== first) { + throw new Error(`expected ${key} failure to be cached after first pass, got ${first} then ${secondCounts[key]}`); } } -if (counts.secrets !== undefined && counts.secrets !== 1) { - throw new Error(`expected secrets failure to be cached after one load when exercised, got ${counts.secrets}`); +if (firstCounts.secrets !== undefined && secondCounts.secrets !== firstCounts.secrets) { + throw new Error(`expected secrets failure to be cached after first pass, got ${firstCounts.secrets} then ${secondCounts.secrets}`); } console.log("synthetic bundled channel load failures were isolated and cached"); NODE @@ -151,12 +170,4 @@ NODE echo "bundled channel load-failure isolation Docker E2E passed" EOF - then - docker_e2e_print_log "$run_log" - rm -f "$run_log" - exit 1 - fi - - docker_e2e_print_log "$run_log" - rm -f "$run_log" } diff --git a/scripts/e2e/lib/bundled-channel/root-owned.sh b/scripts/e2e/lib/bundled-channel/root-owned.sh index e0600351d67..f0642f78632 100644 --- a/scripts/e2e/lib/bundled-channel/root-owned.sh +++ b/scripts/e2e/lib/bundled-channel/root-owned.sh @@ -4,16 +4,15 @@ # Sourced by scripts/e2e/bundled-channel-runtime-deps-docker.sh. run_root_owned_global_scenario() { - local run_log - run_log="$(docker_e2e_run_log bundled-channel-root-owned)" - echo "Running bundled channel root-owned global install Docker E2E..." - if ! timeout "$DOCKER_RUN_TIMEOUT" docker run --rm --user root \ + run_logged_print bundled-channel-root-owned timeout "$DOCKER_RUN_TIMEOUT" docker run --rm --user root \ -e COREPACK_ENABLE_DOWNLOAD_PROMPT=0 \ "${DOCKER_E2E_PACKAGE_ARGS[@]}" \ - -i "$IMAGE_NAME" bash -s >"$run_log" 2>&1 <<'EOF' + "${DOCKER_E2E_HARNESS_ARGS[@]}" \ + -i "$IMAGE_NAME" bash -s <<'EOF' set -euo pipefail +source scripts/lib/openclaw-e2e-instance.sh export HOME="/root" export OPENAI_API_KEY="sk-openclaw-bundled-channel-root-owned-e2e" export OPENCLAW_NO_ONBOARD=1 @@ -174,12 +173,4 @@ fi echo "root-owned global install Docker E2E passed" EOF - then - docker_e2e_print_log "$run_log" - rm -f "$run_log" - exit 1 - fi - - docker_e2e_print_log "$run_log" - rm -f "$run_log" } diff --git a/scripts/e2e/lib/bundled-channel/setup-entry.sh b/scripts/e2e/lib/bundled-channel/setup-entry.sh index 57756e12b48..648678a2330 100644 --- a/scripts/e2e/lib/bundled-channel/setup-entry.sh +++ b/scripts/e2e/lib/bundled-channel/setup-entry.sh @@ -4,20 +4,20 @@ # Sourced by scripts/e2e/bundled-channel-runtime-deps-docker.sh. run_setup_entry_scenario() { - local run_log local state_script_b64 - run_log="$(docker_e2e_run_log bundled-channel-setup-entry)" state_script_b64="$(docker_e2e_test_state_shell_b64 bundled-channel-setup-entry empty)" echo "Running bundled channel setup-entry runtime deps Docker E2E..." - if ! timeout "$DOCKER_RUN_TIMEOUT" docker run --rm \ + run_logged_print bundled-channel-setup-entry timeout "$DOCKER_RUN_TIMEOUT" docker run --rm \ -e COREPACK_ENABLE_DOWNLOAD_PROMPT=0 \ -e "OPENCLAW_TEST_STATE_SCRIPT_B64=$state_script_b64" \ "${DOCKER_E2E_PACKAGE_ARGS[@]}" \ - -i "$IMAGE_NAME" bash -s >"$run_log" 2>&1 <<'EOF' + "${DOCKER_E2E_HARNESS_ARGS[@]}" \ + -i "$IMAGE_NAME" bash -s <<'EOF' set -euo pipefail -eval "$(printf "%s" "${OPENCLAW_TEST_STATE_SCRIPT_B64:?missing OPENCLAW_TEST_STATE_SCRIPT_B64}" | base64 -d)" +source scripts/lib/openclaw-e2e-instance.sh +openclaw_e2e_eval_test_state_from_b64 "${OPENCLAW_TEST_STATE_SCRIPT_B64:?missing OPENCLAW_TEST_STATE_SCRIPT_B64}" export NPM_CONFIG_PREFIX="$HOME/.npm-global" export PATH="$NPM_CONFIG_PREFIX/bin:$PATH" export OPENCLAW_NO_ONBOARD=1 @@ -256,12 +256,4 @@ done echo "bundled channel setup-entry runtime deps Docker E2E passed" EOF - then - docker_e2e_print_log "$run_log" - rm -f "$run_log" - exit 1 - fi - - docker_e2e_print_log "$run_log" - rm -f "$run_log" } diff --git a/scripts/e2e/lib/bundled-channel/update.sh b/scripts/e2e/lib/bundled-channel/update.sh index 50e66dafd12..4ff7f843333 100644 --- a/scripts/e2e/lib/bundled-channel/update.sh +++ b/scripts/e2e/lib/bundled-channel/update.sh @@ -4,22 +4,22 @@ # Sourced by scripts/e2e/bundled-channel-runtime-deps-docker.sh. run_update_scenario() { - local run_log local state_script_b64 - run_log="$(docker_e2e_run_log bundled-channel-update)" state_script_b64="$(docker_e2e_test_state_shell_b64 bundled-channel-update empty)" echo "Running bundled channel runtime deps Docker update E2E..." - if ! timeout "$DOCKER_RUN_TIMEOUT" docker run --rm \ + run_logged_print bundled-channel-update timeout "$DOCKER_UPDATE_RUN_TIMEOUT" docker run --rm \ -e COREPACK_ENABLE_DOWNLOAD_PROMPT=0 \ -e OPENCLAW_BUNDLED_CHANNEL_UPDATE_BASELINE_VERSION="$UPDATE_BASELINE_VERSION" \ -e "OPENCLAW_BUNDLED_CHANNEL_UPDATE_TARGETS=${OPENCLAW_BUNDLED_CHANNEL_UPDATE_TARGETS:-telegram,discord,slack,feishu,memory-lancedb,acpx}" \ -e "OPENCLAW_TEST_STATE_SCRIPT_B64=$state_script_b64" \ "${DOCKER_E2E_PACKAGE_ARGS[@]}" \ - -i "$IMAGE_NAME" bash -s >"$run_log" 2>&1 <<'EOF' + "${DOCKER_E2E_HARNESS_ARGS[@]}" \ + -i "$IMAGE_NAME" bash -s <<'EOF' set -euo pipefail -eval "$(printf "%s" "${OPENCLAW_TEST_STATE_SCRIPT_B64:?missing OPENCLAW_TEST_STATE_SCRIPT_B64}" | base64 -d)" +source scripts/lib/openclaw-e2e-instance.sh +openclaw_e2e_eval_test_state_from_b64 "${OPENCLAW_TEST_STATE_SCRIPT_B64:?missing OPENCLAW_TEST_STATE_SCRIPT_B64}" export NPM_CONFIG_PREFIX="$HOME/.npm-global" export PATH="$NPM_CONFIG_PREFIX/bin:$PATH" export OPENAI_API_KEY="sk-openclaw-bundled-channel-update-e2e" @@ -430,12 +430,4 @@ fi echo "bundled channel runtime deps Docker update E2E passed" EOF - then - docker_e2e_print_log "$run_log" - rm -f "$run_log" - exit 1 - fi - - docker_e2e_print_log "$run_log" - rm -f "$run_log" } diff --git a/scripts/lib/docker-e2e-logs.sh b/scripts/lib/docker-e2e-logs.sh index de0cb1f2773..24d9cbe008e 100644 --- a/scripts/lib/docker-e2e-logs.sh +++ b/scripts/lib/docker-e2e-logs.sh @@ -17,6 +17,20 @@ run_logged() { rm -f "$log_file" } +run_logged_print() { + local label="$1" + shift + local log_file + log_file="$(docker_e2e_run_log "$label")" + if ! "$@" >"$log_file" 2>&1; then + docker_e2e_print_log "$log_file" + rm -f "$log_file" + return 1 + fi + docker_e2e_print_log "$log_file" + rm -f "$log_file" +} + docker_e2e_run_log() { local label="$1" local tmp_dir="${TMPDIR:-/tmp}"