test: share Docker test-state wrapper

This commit is contained in:
Peter Steinberger
2026-04-28 18:47:41 +01:00
parent 4d82dc4fb4
commit 3f780bb27d
9 changed files with 64 additions and 28 deletions

View File

@@ -7,13 +7,7 @@ source "$ROOT_DIR/scripts/lib/docker-e2e-image.sh"
IMAGE_NAME="$(docker_e2e_resolve_image "openclaw-agents-delete-shared-workspace-e2e:local" OPENCLAW_AGENTS_DELETE_SHARED_WORKSPACE_E2E_IMAGE)"
SKIP_BUILD="${OPENCLAW_AGENTS_DELETE_SHARED_WORKSPACE_E2E_SKIP_BUILD:-0}"
DOCKER_COMMAND_TIMEOUT="${OPENCLAW_AGENTS_DELETE_SHARED_WORKSPACE_DOCKER_COMMAND_TIMEOUT:-300s}"
OPENCLAW_TEST_STATE_SCRIPT_B64="$(
node "$ROOT_DIR/scripts/lib/openclaw-test-state.mjs" shell \
--label agents-delete-shared-workspace \
--scenario empty \
| base64 \
| tr -d '\n'
)"
OPENCLAW_TEST_STATE_SCRIPT_B64="$(docker_e2e_test_state_shell_b64 agents-delete-shared-workspace empty)"
docker_cmd() {
if command -v timeout >/dev/null 2>&1; then

View File

@@ -6,8 +6,12 @@ source "$ROOT_DIR/scripts/lib/docker-e2e-image.sh"
IMAGE_NAME="$(docker_e2e_resolve_image "openclaw-bundled-plugin-install-uninstall-e2e" OPENCLAW_BUNDLED_PLUGIN_INSTALL_UNINSTALL_E2E_IMAGE)"
docker_e2e_build_or_reuse "$IMAGE_NAME" bundled-plugin-install-uninstall
OPENCLAW_TEST_STATE_SCRIPT_B64="$(docker_e2e_test_state_shell_b64 bundled-plugin-install-uninstall empty)"
DOCKER_ENV_ARGS=(-e COREPACK_ENABLE_DOWNLOAD_PROMPT=0)
DOCKER_ENV_ARGS=(
-e COREPACK_ENABLE_DOWNLOAD_PROMPT=0
-e "OPENCLAW_TEST_STATE_SCRIPT_B64=$OPENCLAW_TEST_STATE_SCRIPT_B64"
)
for env_name in \
OPENCLAW_BUNDLED_PLUGIN_SWEEP_TOTAL \
OPENCLAW_BUNDLED_PLUGIN_SWEEP_INDEX \
@@ -34,8 +38,7 @@ else
fi
export OPENCLAW_ENTRY
home_dir=$(mktemp -d "/tmp/openclaw-bundled-plugin-sweep.XXXXXX")
export HOME="$home_dir"
eval "$(printf "%s" "${OPENCLAW_TEST_STATE_SCRIPT_B64:?missing OPENCLAW_TEST_STATE_SCRIPT_B64}" | base64 -d)"
node - <<'NODE' > /tmp/bundled-plugin-sweep-ids
const fs = require("node:fs");

View File

@@ -10,16 +10,19 @@ IMAGE_NAME="$(docker_e2e_resolve_image "openclaw-doctor-install-switch-e2e" OPEN
PACKAGE_TGZ="$(docker_e2e_prepare_package_tgz doctor-switch "${OPENCLAW_CURRENT_PACKAGE_TGZ:-}")"
# Bare lanes mount the package artifact instead of baking app sources into the image.
docker_e2e_package_mount_args "$PACKAGE_TGZ"
OPENCLAW_TEST_STATE_FUNCTION_B64="$(docker_e2e_test_state_function_b64)"
docker_e2e_build_or_reuse "$IMAGE_NAME" doctor-switch "$ROOT_DIR/scripts/e2e/Dockerfile" "$ROOT_DIR" "bare"
echo "Running doctor install switch E2E..."
docker run --rm \
-e COREPACK_ENABLE_DOWNLOAD_PROMPT=0 \
-e "OPENCLAW_TEST_STATE_FUNCTION_B64=$OPENCLAW_TEST_STATE_FUNCTION_B64" \
"${DOCKER_E2E_PACKAGE_ARGS[@]}" \
"$IMAGE_NAME" \
bash -lc '
set -euo pipefail
eval "$(printf "%s" "${OPENCLAW_TEST_STATE_FUNCTION_B64:?missing OPENCLAW_TEST_STATE_FUNCTION_B64}" | base64 -d)"
# Keep logs focused; the npm global install step can emit noisy deprecation warnings.
export npm_config_loglevel=error
@@ -215,8 +218,7 @@ NODE
local command_timeout="${OPENCLAW_DOCKER_DOCTOR_SWITCH_COMMAND_TIMEOUT:-300s}"
echo "== Flow: $name =="
home_dir=$(mktemp -d "/tmp/openclaw-switch-${name}.XXXXXX")
export HOME="$home_dir"
openclaw_test_state_create "switch-${name}" empty
export USER="testuser"
if ! timeout "$command_timeout" bash -c "$install_cmd" >"$install_log" 2>&1; then
@@ -262,8 +264,7 @@ NODE
local command_timeout="${OPENCLAW_DOCKER_DOCTOR_SWITCH_COMMAND_TIMEOUT:-300s}"
echo "== Flow: $name =="
home_dir=$(mktemp -d "/tmp/openclaw-switch-${name}.XXXXXX")
export HOME="$home_dir"
openclaw_test_state_create "switch-${name}" empty
export USER="testuser"
unit_path="$HOME/.config/systemd/user/openclaw-gateway.service"
@@ -303,8 +304,7 @@ NODE
local command_timeout="${OPENCLAW_DOCKER_DOCTOR_SWITCH_COMMAND_TIMEOUT:-300s}"
echo "== Flow: $name =="
home_dir=$(mktemp -d "/tmp/openclaw-switch-${name}.XXXXXX")
export HOME="$home_dir"
openclaw_test_state_create "switch-${name}" empty
export USER="testuser"
mkdir -p "$HOME/.local/bin"
local wrapper="$HOME/.local/bin/openclaw-wrapper"

View File

@@ -40,13 +40,7 @@ prepare_package_tgz
docker_e2e_package_mount_args "$PACKAGE_TGZ"
docker_e2e_harness_mount_args
run_log="$(docker_e2e_run_log npm-onboard-channel-agent)"
OPENCLAW_TEST_STATE_SCRIPT_B64="$(
node "$ROOT_DIR/scripts/lib/openclaw-test-state.mjs" shell \
--label npm-onboard-channel-agent \
--scenario empty \
| base64 \
| tr -d '\n'
)"
OPENCLAW_TEST_STATE_SCRIPT_B64="$(docker_e2e_test_state_shell_b64 npm-onboard-channel-agent empty)"
echo "Running npm tarball onboard/channel/agent Docker E2E ($CHANNEL)..."
if ! docker run --rm \

View File

@@ -11,17 +11,18 @@ SKIP_BUILD="${OPENCLAW_OPENAI_IMAGE_AUTH_E2E_SKIP_BUILD:-0}"
docker_e2e_build_or_reuse "$IMAGE_NAME" openai-image-auth "$ROOT_DIR/scripts/e2e/Dockerfile" "$ROOT_DIR" "" "$SKIP_BUILD"
docker_e2e_harness_mount_args
OPENCLAW_TEST_STATE_SCRIPT_B64="$(docker_e2e_test_state_shell_b64 openai-image-auth empty)"
echo "Running OpenAI image auth Docker E2E..."
# Harness files are mounted read-only; the app under test comes from /app/dist.
run_logged openai-image-auth docker run --rm \
-e "OPENAI_API_KEY=sk-openclaw-image-auth-e2e" \
-e "OPENCLAW_QA_ALLOW_LOCAL_IMAGE_PROVIDER=1" \
-e "OPENCLAW_TEST_STATE_SCRIPT_B64=$OPENCLAW_TEST_STATE_SCRIPT_B64" \
"${DOCKER_E2E_HARNESS_ARGS[@]}" \
-i "$IMAGE_NAME" bash -lc '
set -euo pipefail
export HOME="$(mktemp -d "/tmp/openclaw-openai-image-auth.XXXXXX")"
export OPENCLAW_STATE_DIR="$HOME/.openclaw"
eval "$(printf "%s" "${OPENCLAW_TEST_STATE_SCRIPT_B64:?missing OPENCLAW_TEST_STATE_SCRIPT_B64}" | base64 -d)"
export OPENCLAW_SKIP_CHANNELS=1
export OPENCLAW_SKIP_GMAIL_WATCHER=1
export OPENCLAW_SKIP_CRON=1

View File

@@ -81,3 +81,19 @@ docker_e2e_build_or_reuse() {
build_args+=(-t "$image_name" -f "$dockerfile" "$context")
docker_build_run "$label-build" "${build_args[@]}"
}
docker_e2e_test_state_shell_b64() {
local label="${1:?missing test-state label}"
local scenario="${2:-empty}"
node "$ROOT_DIR/scripts/lib/openclaw-test-state.mjs" shell \
--label "$label" \
--scenario "$scenario" \
| base64 \
| tr -d '\n'
}
docker_e2e_test_state_function_b64() {
node "$ROOT_DIR/scripts/lib/openclaw-test-state.mjs" shell-function \
| base64 \
| tr -d '\n'
}

View File

@@ -177,6 +177,7 @@ const bundledPluginInstallUninstallLanes = Array.from(
{
estimateSeconds: 280,
resources: ["npm"],
stateScenario: "empty",
weight: 1,
},
),
@@ -253,6 +254,7 @@ export const mainLanes = [
{ resources: ["npm"], weight: 3 },
),
npmLane("doctor-switch", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:doctor-switch", {
stateScenario: "empty",
weight: 3,
}),
npmLane(
@@ -285,7 +287,9 @@ export const mainLanes = [
npmLane("plugin-update", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:plugin-update"),
serviceLane("config-reload", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:config-reload"),
...bundledScenarioLanes,
lane("openai-image-auth", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:openai-image-auth"),
lane("openai-image-auth", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:openai-image-auth", {
stateScenario: "empty",
}),
lane(
"crestodian-first-run",
"OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:crestodian-first-run",
@@ -484,6 +488,7 @@ const releasePathPackageUpdateCoreLanes = [
{ resources: ["service"], stateScenario: "empty", weight: 3 },
),
npmLane("doctor-switch", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:doctor-switch", {
stateScenario: "empty",
weight: 3,
}),
npmLane(