From a7c8b2a46ae56578637f58e8a755065c6d5379aa Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Wed, 3 Jun 2026 11:54:07 +0200 Subject: [PATCH] fix(e2e): bound mock readiness probes --- CHANGELOG.md | 1 + .../lib/openai-web-search-minimal/scenario.sh | 8 +------- scripts/e2e/npm-telegram-rtt-docker.sh | 20 ++++++++++++++++++- test/scripts/docker-build-helper.test.ts | 2 ++ test/scripts/rtt-harness.test.ts | 5 +++++ 5 files changed, 28 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b84f8c9a408..3edaf91a8c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,7 @@ Docs: https://docs.openclaw.ai - Release/CI/E2E: write multi-node update Docker artifacts to unique per-run directories by default so parallel runs cannot overwrite evidence. - Release/CI/E2E: write package Telegram Docker artifacts to unique per-run directories by default so parallel live/RTT runs cannot overwrite evidence. - Release/CI/E2E: keep plugin lifecycle matrix resource artifacts under a unique per-run scratch root so parallel runs cannot overwrite tarballs or inspect output. +- Release/CI/E2E: bound mock OpenAI readiness probes in web-search and Telegram RTT Docker smokes so stalled HTTP accepts cannot hang cleanup or fall through. - Release/CI/E2E: fail secret-provider proof runs when temporary state cleanup still fails after retries instead of hiding the cleanup error. - Release/CI/E2E: fail package-candidate ref proofs when temporary source worktree cleanup fails instead of leaving stale worktrees behind. - Release/CI/E2E: remove package tarball extract directories when tar extraction fails before validation can continue. diff --git a/scripts/e2e/lib/openai-web-search-minimal/scenario.sh b/scripts/e2e/lib/openai-web-search-minimal/scenario.sh index fc27de225f3..9abcebd030d 100644 --- a/scripts/e2e/lib/openai-web-search-minimal/scenario.sh +++ b/scripts/e2e/lib/openai-web-search-minimal/scenario.sh @@ -64,13 +64,7 @@ MOCK_PORT="$MOCK_PORT" \ node scripts/e2e/lib/openai-web-search-minimal/mock-server.mjs >"$MOCK_LOG" 2>&1 & mock_pid="$!" -for _ in $(seq 1 80); do - if node -e "fetch('http://127.0.0.1:${MOCK_PORT}/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))" >/dev/null 2>&1; then - break - fi - sleep 0.1 -done -node -e "fetch('http://127.0.0.1:${MOCK_PORT}/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))" >/dev/null +openclaw_e2e_wait_mock_openai "$MOCK_PORT" gateway_pid="$(openclaw_e2e_start_gateway "$entry" "$PORT" "$GATEWAY_LOG")" openclaw_e2e_wait_gateway_ready "$gateway_pid" "$GATEWAY_LOG" 360 diff --git a/scripts/e2e/npm-telegram-rtt-docker.sh b/scripts/e2e/npm-telegram-rtt-docker.sh index 6ec3ea54860..8ba56bb74ce 100755 --- a/scripts/e2e/npm-telegram-rtt-docker.sh +++ b/scripts/e2e/npm-telegram-rtt-docker.sh @@ -388,12 +388,30 @@ installed_version="$(node -p "require('/npm-global/lib/node_modules/openclaw/pac node /app/scripts/e2e/mock-openai-server.mjs >"$mock_log" 2>&1 & mock_pid="$!" +mock_ready=0 for _ in $(seq 1 60); do - if node -e "fetch('http://127.0.0.1:${mock_port}/health').then((r)=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"; then + if node --input-type=module -e ' + const controller = new AbortController(); + const timer = setTimeout(() => controller.abort(), 1000); + try { + const response = await fetch(process.argv[1], { signal: controller.signal }); + process.exit(response.ok ? 0 : 1); + } catch { + process.exit(1); + } finally { + clearTimeout(timer); + } + ' "http://127.0.0.1:${mock_port}/health"; then + mock_ready=1 break fi sleep 1 done +if [ "$mock_ready" != "1" ]; then + echo "Mock OpenAI server did not become ready" >&2 + cat "$mock_log" >&2 || true + exit 1 +fi mkdir -p "$(dirname "$config_path")" "$HOME/.openclaw/workspace" "$HOME/.openclaw/agents/main/sessions" "$HOME/workspace" diff --git a/test/scripts/docker-build-helper.test.ts b/test/scripts/docker-build-helper.test.ts index 92f3c255be7..3168c43794a 100644 --- a/test/scripts/docker-build-helper.test.ts +++ b/test/scripts/docker-build-helper.test.ts @@ -2153,7 +2153,9 @@ output="$(run_logged_print_heartbeat plugins-run 08 bash -c 'printf "captured co expect(scenario).toContain( 'gateway_pid="$(openclaw_e2e_start_gateway "$entry" "$PORT" "$GATEWAY_LOG")"', ); + expect(scenario).toContain('openclaw_e2e_wait_mock_openai "$MOCK_PORT"'); expect(scenario).toContain('openclaw_e2e_wait_gateway_ready "$gateway_pid" "$GATEWAY_LOG" 360'); + expect(scenario).not.toContain("fetch('http://127.0.0.1:${MOCK_PORT}/health')"); expect(scenario).not.toContain('kill "$gateway_pid"'); expect(scenario).not.toContain('kill "$mock_pid"'); expect(scenario).not.toContain('node "$entry" gateway --port "$PORT"'); diff --git a/test/scripts/rtt-harness.test.ts b/test/scripts/rtt-harness.test.ts index 8c263713e64..0a052a5bf4d 100644 --- a/test/scripts/rtt-harness.test.ts +++ b/test/scripts/rtt-harness.test.ts @@ -207,6 +207,11 @@ describe("RTT harness", () => { expect(script).toContain("start_credential_heartbeat() {\n (\n set +e"); expect(script).toContain("Convex credential heartbeat exited with status"); expect(script).toContain('kill -TERM "$rtt_shell_pid"'); + expect(script).toContain("const controller = new AbortController();"); + expect(script).toContain("const timer = setTimeout(() => controller.abort(), 1000);"); + expect(script).toContain('if [ "$mock_ready" != "1" ]; then'); + expect(script).toContain("Mock OpenAI server did not become ready"); + expect(script).not.toContain("fetch('http://127.0.0.1:${mock_port}/health')"); expect(script).not.toContain('export TELEGRAM_BOT_TOKEN="$OPENCLAW_QA_TELEGRAM_SUT_BOT_TOKEN"'); });