test(docker): quiet success-path e2e logs

This commit is contained in:
Peter Steinberger
2026-04-09 00:29:24 +01:00
parent ac57c7c309
commit aa79b9fb7d
16 changed files with 103 additions and 33 deletions

View File

@@ -7,7 +7,10 @@ export OPENCLAW_STATE_DIR="/tmp/openclaw-test"
export OPENCLAW_CONFIG_PATH="${OPENCLAW_STATE_DIR}/openclaw.json"
echo "==> Build"
pnpm build
if ! pnpm build >/tmp/openclaw-cleanup-build.log 2>&1; then
cat /tmp/openclaw-cleanup-build.log
exit 1
fi
echo "==> Seed state"
mkdir -p "${OPENCLAW_STATE_DIR}/credentials"
@@ -17,7 +20,10 @@ echo 'creds' >"${OPENCLAW_STATE_DIR}/credentials/marker.txt"
echo 'session' >"${OPENCLAW_STATE_DIR}/agents/main/sessions/sessions.json"
echo "==> Reset (config+creds+sessions)"
pnpm openclaw reset --scope config+creds+sessions --yes --non-interactive
if ! pnpm openclaw reset --scope config+creds+sessions --yes --non-interactive >/tmp/openclaw-cleanup-reset.log 2>&1; then
cat /tmp/openclaw-cleanup-reset.log
exit 1
fi
test ! -f "${OPENCLAW_CONFIG_PATH}"
test ! -d "${OPENCLAW_STATE_DIR}/credentials"
@@ -28,7 +34,10 @@ mkdir -p "${OPENCLAW_STATE_DIR}/credentials"
echo '{}' >"${OPENCLAW_CONFIG_PATH}"
echo "==> Uninstall (state only)"
pnpm openclaw uninstall --state --yes --non-interactive
if ! pnpm openclaw uninstall --state --yes --non-interactive >/tmp/openclaw-cleanup-uninstall.log 2>&1; then
cat /tmp/openclaw-cleanup-uninstall.log
exit 1
fi
test ! -d "${OPENCLAW_STATE_DIR}"

View File

@@ -21,6 +21,9 @@ COPY --chown=appuser:appuser patches ./patches
# Keep the pre-install copy set limited to the manifests needed for root
# workspace resolution so unrelated extension edits do not bust the layer.
RUN --mount=type=cache,id=openclaw-pnpm-store,target=/home/appuser/.local/share/pnpm/store,sharing=locked \
pnpm install --frozen-lockfile --ignore-scripts
if ! pnpm install --frozen-lockfile --ignore-scripts >/tmp/openclaw-qr-pnpm-install.log 2>&1; then \
cat /tmp/openclaw-qr-pnpm-install.log; \
exit 1; \
fi
COPY --chown=appuser:appuser . .

View File

@@ -2,10 +2,11 @@
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
source "$ROOT_DIR/scripts/lib/docker-e2e-logs.sh"
IMAGE_NAME="openclaw-doctor-install-switch-e2e"
echo "Building Docker image..."
docker build -t "$IMAGE_NAME" -f "$ROOT_DIR/scripts/e2e/Dockerfile" "$ROOT_DIR"
run_logged doctor-switch-build docker build -t "$IMAGE_NAME" -f "$ROOT_DIR/scripts/e2e/Dockerfile" "$ROOT_DIR"
echo "Running doctor install switch E2E..."
docker run --rm -e COREPACK_ENABLE_DOWNLOAD_PROMPT=0 "$IMAGE_NAME" bash -lc '

View File

@@ -2,6 +2,7 @@
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
source "$ROOT_DIR/scripts/lib/docker-e2e-logs.sh"
IMAGE_NAME="openclaw-gateway-network-e2e"
PORT="18789"
@@ -16,7 +17,7 @@ cleanup() {
trap cleanup EXIT
echo "Building Docker image..."
docker build -t "$IMAGE_NAME" -f "$ROOT_DIR/scripts/e2e/Dockerfile" "$ROOT_DIR"
run_logged gateway-network-build docker build -t "$IMAGE_NAME" -f "$ROOT_DIR/scripts/e2e/Dockerfile" "$ROOT_DIR"
echo "Creating Docker network..."
docker network create "$NET_NAME" >/dev/null
@@ -31,7 +32,7 @@ docker run -d \
-e "OPENCLAW_SKIP_CRON=1" \
-e "OPENCLAW_SKIP_CANVAS_HOST=1" \
"$IMAGE_NAME" \
bash -lc "set -euo pipefail; entry=dist/index.mjs; [ -f \"\$entry\" ] || entry=dist/index.js; node \"\$entry\" config set gateway.controlUi.enabled false >/dev/null; node \"\$entry\" gateway --port $PORT --bind lan --allow-unconfigured > /tmp/gateway-net-e2e.log 2>&1"
bash -lc "set -euo pipefail; entry=dist/index.mjs; [ -f \"\$entry\" ] || entry=dist/index.js; node \"\$entry\" config set gateway.controlUi.enabled false >/dev/null; node \"\$entry\" gateway --port $PORT --bind lan --allow-unconfigured > /tmp/gateway-net-e2e.log 2>&1" >/dev/null
echo "Waiting for gateway to come up..."
ready=0
@@ -59,7 +60,7 @@ for _ in $(seq 1 40); do
ready=1
break
fi
if docker exec "$GW_NAME" bash -lc "grep -q \"listening on ws://\" /tmp/gateway-net-e2e.log"; then
if docker exec "$GW_NAME" bash -lc "grep -q \"listening on ws://\" /tmp/gateway-net-e2e.log 2>/dev/null"; then
ready=1
break
fi
@@ -76,10 +77,8 @@ if [ "$ready" -ne 1 ]; then
exit 1
fi
docker exec "$GW_NAME" bash -lc "tail -n 50 /tmp/gateway-net-e2e.log"
echo "Running client container (connect + health)..."
docker run --rm \
run_logged gateway-network-client docker run --rm \
--network "$NET_NAME" \
-e "GW_URL=ws://$GW_NAME:$PORT" \
-e "GW_TOKEN=$TOKEN" \

View File

@@ -2,6 +2,7 @@
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
source "$ROOT_DIR/scripts/lib/docker-e2e-logs.sh"
IMAGE_NAME="${OPENCLAW_IMAGE:-openclaw-mcp-channels-e2e}"
PORT="18789"
TOKEN="mcp-e2e-$(date +%s)-$$"
@@ -15,7 +16,7 @@ cleanup() {
trap cleanup EXIT
echo "Building Docker image..."
docker build -t "$IMAGE_NAME" -f "$ROOT_DIR/scripts/e2e/Dockerfile" "$ROOT_DIR"
run_logged mcp-channels-build docker build -t "$IMAGE_NAME" -f "$ROOT_DIR/scripts/e2e/Dockerfile" "$ROOT_DIR"
echo "Running in-container gateway + MCP smoke..."
set +e
@@ -42,7 +43,16 @@ docker run --rm \
kill \"\$gateway_pid\" >/dev/null 2>&1 || true
wait \"\$gateway_pid\" >/dev/null 2>&1 || true
}
dump_gateway_log_on_error() {
status=\$?
if [ \"\$status\" -ne 0 ]; then
tail -n 80 /tmp/mcp-channels-gateway.log 2>/dev/null || true
fi
cleanup_inner
exit \"\$status\"
}
trap cleanup_inner EXIT
trap dump_gateway_log_on_error ERR
for _ in \$(seq 1 80); do
if node --input-type=module -e '
import net from \"node:net\";
@@ -66,13 +76,13 @@ docker run --rm \
sleep 0.25
done
node --import tsx scripts/e2e/mcp-channels-docker-client.ts
tail -n 80 /tmp/mcp-channels-gateway.log
" | tee "$CLIENT_LOG"
" >"$CLIENT_LOG" 2>&1
status=${PIPESTATUS[0]}
set -e
if [ "$status" -ne 0 ]; then
echo "Docker MCP smoke failed"
cat "$CLIENT_LOG"
exit "$status"
fi

View File

@@ -1,4 +1,5 @@
import { randomUUID } from "node:crypto";
import { mkdirSync, writeFileSync } from "node:fs";
import process from "node:process";
import { setTimeout as delay } from "node:timers/promises";
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
@@ -330,6 +331,10 @@ export async function connectMcpClient(params: {
gatewayUrl: string;
gatewayToken: string;
}): Promise<McpClientHandle> {
const tokenDir = "/tmp/openclaw-mcp-client";
const tokenFile = `${tokenDir}/gateway.token`;
mkdirSync(tokenDir, { recursive: true });
writeFileSync(tokenFile, `${params.gatewayToken}\n`, { encoding: "utf8", mode: 0o600 });
const transport = new StdioClientTransport({
command: "node",
args: [
@@ -338,8 +343,8 @@ export async function connectMcpClient(params: {
"serve",
"--url",
params.gatewayUrl,
"--token",
params.gatewayToken,
"--token-file",
tokenFile,
"--claude-channel-mode",
"on",
],

View File

@@ -2,10 +2,11 @@
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
source "$ROOT_DIR/scripts/lib/docker-e2e-logs.sh"
IMAGE_NAME="openclaw-onboard-e2e"
echo "Building Docker image..."
docker build -t "$IMAGE_NAME" -f "$ROOT_DIR/scripts/e2e/Dockerfile" "$ROOT_DIR"
run_logged onboard-build docker build -t "$IMAGE_NAME" -f "$ROOT_DIR/scripts/e2e/Dockerfile" "$ROOT_DIR"
echo "Running onboarding E2E..."
docker run --rm -t "$IMAGE_NAME" bash -lc '
@@ -174,7 +175,7 @@ TRASH
WIZARD_LOG_PATH="$log_path"
export WIZARD_LOG_PATH
# Run under script to keep an interactive TTY for clack prompts.
script -q -f -c "$command" "$log_path" < "$input_fifo" &
script -q -f -c "$command" "$log_path" < "$input_fifo" >/dev/null 2>&1 &
wizard_pid=$!
exec 3> "$input_fifo"
@@ -245,6 +246,16 @@ TRASH
fi
}
run_case_logged() {
local label="$1"
shift
local log_path="/tmp/openclaw-onboard-${label}.log"
if ! "$@" >"$log_path" 2>&1; then
cat "$log_path"
exit 1
fi
}
select_skip_hooks() {
# Hooks multiselect: pick "Skip for now".
wait_for_log "Enable hooks?" 60
@@ -298,7 +309,7 @@ TRASH
local home_dir
home_dir="$(make_home local-basic)"
set_isolated_openclaw_env "$home_dir"
node "$OPENCLAW_ENTRY" onboard \
run_case_logged local-basic node "$OPENCLAW_ENTRY" onboard \
--non-interactive \
--accept-risk \
--flow quickstart \
@@ -374,7 +385,7 @@ NODE
home_dir="$(make_home remote-non-interactive)"
set_isolated_openclaw_env "$home_dir"
# Smoke test non-interactive remote config write.
node "$OPENCLAW_ENTRY" onboard --non-interactive --accept-risk \
run_case_logged remote-non-interactive node "$OPENCLAW_ENTRY" onboard --non-interactive --accept-risk \
--mode remote \
--remote-url ws://gateway.local:18789 \
--remote-token remote-token \
@@ -427,7 +438,7 @@ NODE
}
JSON
node "$OPENCLAW_ENTRY" onboard \
run_case_logged reset-config node "$OPENCLAW_ENTRY" onboard \
--non-interactive \
--accept-risk \
--flow quickstart \

View File

@@ -2,6 +2,7 @@
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
source "$ROOT_DIR/scripts/lib/docker-e2e-logs.sh"
IMAGE_NAME="openclaw-openwebui-e2e"
OPENWEBUI_IMAGE="${OPENWEBUI_IMAGE:-ghcr.io/open-webui/open-webui:v0.8.10}"
@@ -40,7 +41,7 @@ cleanup() {
trap cleanup EXIT
echo "Building Docker image..."
docker build -t "$IMAGE_NAME" -f "$ROOT_DIR/scripts/e2e/Dockerfile" "$ROOT_DIR"
run_logged openwebui-build docker build -t "$IMAGE_NAME" -f "$ROOT_DIR/scripts/e2e/Dockerfile" "$ROOT_DIR"
echo "Pulling Open WebUI image: $OPENWEBUI_IMAGE"
docker pull "$OPENWEBUI_IMAGE" >/dev/null
@@ -90,7 +91,7 @@ NODE
rm -f "$batch_file"
exec node "$entry" gateway --port '"$PORT"' --bind lan --allow-unconfigured > /tmp/openwebui-gateway.log 2>&1
'
' >/dev/null
echo "Waiting for gateway HTTP surface..."
gateway_ready=0
@@ -170,7 +171,8 @@ if ! docker exec \
-e "OPENWEBUI_EXPECTED_NONCE=$PROMPT_NONCE" \
-e "OPENWEBUI_PROMPT=$PROMPT" \
"$GW_NAME" \
node /app/scripts/e2e/openwebui-probe.mjs; then
node /app/scripts/e2e/openwebui-probe.mjs >/tmp/openwebui-probe.log 2>&1; then
cat /tmp/openwebui-probe.log 2>/dev/null || true
echo "Open WebUI probe failed; gateway log tail:"
docker exec "$GW_NAME" bash -lc 'tail -n 200 /tmp/openwebui-gateway.log' || true
echo "Open WebUI container logs:"
@@ -178,7 +180,4 @@ if ! docker exec \
exit 1
fi
echo "Open WebUI container logs:"
docker logs "$OW_NAME" 2>&1 | tail -n 80 || true
echo "OK"

View File

@@ -2,10 +2,11 @@
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
source "$ROOT_DIR/scripts/lib/docker-e2e-logs.sh"
IMAGE_NAME="openclaw-plugins-e2e"
echo "Building Docker image..."
docker build -t "$IMAGE_NAME" -f "$ROOT_DIR/scripts/e2e/Dockerfile" "$ROOT_DIR"
run_logged plugins-build docker build -t "$IMAGE_NAME" -f "$ROOT_DIR/scripts/e2e/Dockerfile" "$ROOT_DIR"
DOCKER_ENV_ARGS=(-e COREPACK_ENABLE_DOWNLOAD_PROMPT=0)
if [[ -n "${OPENAI_API_KEY:-}" && "${OPENAI_API_KEY:-}" != "undefined" && "${OPENAI_API_KEY:-}" != "null" ]]; then
@@ -16,7 +17,8 @@ if [[ -n "${OPENAI_BASE_URL:-}" && "${OPENAI_BASE_URL:-}" != "undefined" && "${O
fi
echo "Running plugins Docker E2E..."
docker run --rm "${DOCKER_ENV_ARGS[@]}" -i "$IMAGE_NAME" bash -s <<'EOF'
RUN_LOG="$(mktemp "${TMPDIR:-/tmp}/openclaw-plugins-run.XXXXXX.log")"
if ! docker run --rm "${DOCKER_ENV_ARGS[@]}" -i "$IMAGE_NAME" bash -s >"$RUN_LOG" 2>&1 <<'EOF'
set -euo pipefail
if [ -f dist/index.mjs ]; then
@@ -981,5 +983,11 @@ NODE
echo "Running bundle MCP CLI-agent e2e..."
pnpm exec vitest run --config vitest.e2e.config.ts src/agents/cli-runner.bundle-mcp.e2e.test.ts
EOF
then
cat "$RUN_LOG"
rm -f "$RUN_LOG"
exit 1
fi
rm -f "$RUN_LOG"
echo "OK"

View File

@@ -2,10 +2,11 @@
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
source "$ROOT_DIR/scripts/lib/docker-e2e-logs.sh"
IMAGE_NAME="${OPENCLAW_QR_SMOKE_IMAGE:-openclaw-qr-smoke}"
echo "Building Docker image..."
docker build -t "$IMAGE_NAME" -f "$ROOT_DIR/scripts/e2e/Dockerfile.qr-import" "$ROOT_DIR"
run_logged qr-import-build docker build -t "$IMAGE_NAME" -f "$ROOT_DIR/scripts/e2e/Dockerfile.qr-import" "$ROOT_DIR"
echo "Running qrcode-terminal import smoke..."
docker run --rm -t "$IMAGE_NAME" node -e "import('qrcode-terminal').then((m)=>m.default.generate('qr-smoke',{small:true}))"
run_logged qr-import-run docker run --rm -t "$IMAGE_NAME" node -e "import('qrcode-terminal').then((m)=>m.default.generate('qr-smoke',{small:true}))"

View File

@@ -0,0 +1,14 @@
#!/usr/bin/env bash
run_logged() {
local label="$1"
shift
local log_file
log_file="$(mktemp "${TMPDIR:-/tmp}/openclaw-${label}.XXXXXX.log")"
if ! "$@" >"$log_file" 2>&1; then
cat "$log_file"
rm -f "$log_file"
return 1
fi
rm -f "$log_file"
}

View File

@@ -14,6 +14,9 @@ openclaw_live_stage_source_tree() {
--exclude=.tmp-precommit-venv \
--exclude=.worktrees \
--exclude=__openclaw_vitest__ \
--exclude=relay.sock \
--exclude='*.sock' \
--exclude='*/*.sock' \
--exclude='apps/*/.build' \
--exclude='apps/*/*.bun-build' \
--exclude='apps/*/.gradle' \
@@ -46,6 +49,9 @@ openclaw_live_stage_state_dir() {
tar -C "$source_dir" \
--exclude=workspace \
--exclude=sandboxes \
--exclude=relay.sock \
--exclude='*.sock' \
--exclude='*/*.sock' \
-cf - . | tar -C "$dest_dir" -xf -
chmod -R u+rwX "$dest_dir" || true
if [ -d "$source_dir/workspace" ] && [ ! -e "$dest_dir/workspace" ]; then

View File

@@ -2,11 +2,12 @@
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
source "$ROOT_DIR/scripts/lib/docker-e2e-logs.sh"
IMAGE_NAME="${OPENCLAW_CLEANUP_SMOKE_IMAGE:-openclaw-cleanup-smoke:local}"
PLATFORM="${OPENCLAW_CLEANUP_SMOKE_PLATFORM:-linux/amd64}"
echo "==> Build image: $IMAGE_NAME"
docker build \
run_logged cleanup-build docker build \
-t "$IMAGE_NAME" \
-f "$ROOT_DIR/scripts/docker/cleanup-smoke/Dockerfile" \
"$ROOT_DIR"

View File

@@ -2,6 +2,7 @@
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
source "$ROOT_DIR/scripts/lib/docker-e2e-logs.sh"
IMAGE_NAME="${OPENCLAW_IMAGE:-openclaw:local}"
LIVE_IMAGE_NAME="${OPENCLAW_LIVE_IMAGE:-${IMAGE_NAME}-live}"
@@ -11,4 +12,4 @@ if [[ "${OPENCLAW_SKIP_DOCKER_BUILD:-}" == "1" ]]; then
fi
echo "==> Build live-test image: $LIVE_IMAGE_NAME (target=build)"
docker build --target build -t "$LIVE_IMAGE_NAME" -f "$ROOT_DIR/Dockerfile" "$ROOT_DIR"
run_logged live-build docker build --target build -t "$LIVE_IMAGE_NAME" -f "$ROOT_DIR/Dockerfile" "$ROOT_DIR"

View File

@@ -122,6 +122,7 @@ docker run --rm -t \
-e HOME=/home/node \
-e NODE_OPTIONS=--disable-warning=ExperimentalWarning \
-e OPENCLAW_SKIP_CHANNELS=1 \
-e OPENCLAW_SUPPRESS_NOTES=1 \
-e OPENCLAW_DOCKER_AUTH_DIRS_RESOLVED="$AUTH_DIRS_CSV" \
-e OPENCLAW_DOCKER_AUTH_FILES_RESOLVED="$AUTH_FILES_CSV" \
-e OPENCLAW_LIVE_TEST=1 \

View File

@@ -132,6 +132,7 @@ docker run --rm -t \
-e HOME=/home/node \
-e NODE_OPTIONS=--disable-warning=ExperimentalWarning \
-e OPENCLAW_SKIP_CHANNELS=1 \
-e OPENCLAW_SUPPRESS_NOTES=1 \
-e OPENCLAW_DOCKER_AUTH_DIRS_RESOLVED="$AUTH_DIRS_CSV" \
-e OPENCLAW_DOCKER_AUTH_FILES_RESOLVED="$AUTH_FILES_CSV" \
-e OPENCLAW_LIVE_TEST=1 \