From 27310bfa34cee0411eb4370b2e575542eea93f02 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Fri, 19 Jun 2026 00:09:40 +0200 Subject: [PATCH] fix(e2e): validate docker e2e ports --- scripts/e2e/codex-media-path-docker.sh | 2 +- scripts/e2e/mcp-code-mode-gateway-docker.sh | 16 ++------- .../e2e/mcp-code-mode-gateway-live-docker.sh | 13 +------ scripts/e2e/openai-chat-tools-docker.sh | 2 +- scripts/e2e/openwebui-docker.sh | 20 ++--------- scripts/lib/docker-e2e-image.sh | 19 ++++++++++ test/scripts/docker-build-helper.test.ts | 35 ++++++++++--------- 7 files changed, 44 insertions(+), 63 deletions(-) diff --git a/scripts/e2e/codex-media-path-docker.sh b/scripts/e2e/codex-media-path-docker.sh index e9e77f5ab966..6b81a4c23e88 100644 --- a/scripts/e2e/codex-media-path-docker.sh +++ b/scripts/e2e/codex-media-path-docker.sh @@ -5,7 +5,7 @@ ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" source "$ROOT_DIR/scripts/lib/docker-e2e-image.sh" IMAGE_NAME="$(docker_e2e_resolve_image "openclaw-codex-media-path-e2e" OPENCLAW_CODEX_MEDIA_PATH_E2E_IMAGE)" -PORT="${OPENCLAW_CODEX_MEDIA_PATH_PORT:-18790}" +PORT="$(docker_e2e_read_tcp_port_env OPENCLAW_CODEX_MEDIA_PATH_PORT 18790)" TOKEN="codex-media-path-e2e-$$" CODEX_PLUGIN_SPEC="${OPENCLAW_CODEX_MEDIA_PATH_PLUGIN_SPEC:-npm:@openclaw/codex}" diff --git a/scripts/e2e/mcp-code-mode-gateway-docker.sh b/scripts/e2e/mcp-code-mode-gateway-docker.sh index 3002bea0ac4b..ea831214c19c 100755 --- a/scripts/e2e/mcp-code-mode-gateway-docker.sh +++ b/scripts/e2e/mcp-code-mode-gateway-docker.sh @@ -7,23 +7,11 @@ ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" source "$ROOT_DIR/scripts/lib/docker-e2e-image.sh" IMAGE_NAME="$(docker_e2e_resolve_image "openclaw-mcp-code-mode-gateway-e2e" OPENCLAW_IMAGE)" -PORT="${OPENCLAW_MCP_CODE_MODE_GATEWAY_PORT:-18789}" -MOCK_PORT="${OPENCLAW_MCP_CODE_MODE_MOCK_PORT:-44082}" +PORT="$(docker_e2e_read_tcp_port_env OPENCLAW_MCP_CODE_MODE_GATEWAY_PORT 18789)" +MOCK_PORT="$(docker_e2e_read_tcp_port_env OPENCLAW_MCP_CODE_MODE_MOCK_PORT 44082)" TOKEN="mcp-code-mode-e2e-$(date +%s)-$$" CONTAINER_NAME="openclaw-mcp-code-mode-e2e-$$" -validate_tcp_port() { - local label="$1" - local value="$2" - if [[ ! "$value" =~ ^[0-9]+$ ]] || [ "$value" -lt 1 ] || [ "$value" -gt 65535 ]; then - echo "invalid $label: $value" >&2 - exit 2 - fi -} - -validate_tcp_port OPENCLAW_MCP_CODE_MODE_GATEWAY_PORT "$PORT" -validate_tcp_port OPENCLAW_MCP_CODE_MODE_MOCK_PORT "$MOCK_PORT" - CLIENT_LOG="$(mktemp -t openclaw-mcp-code-mode-client-log.XXXXXX)" cleanup() { diff --git a/scripts/e2e/mcp-code-mode-gateway-live-docker.sh b/scripts/e2e/mcp-code-mode-gateway-live-docker.sh index 4f6edb1e8696..7f825dda0724 100755 --- a/scripts/e2e/mcp-code-mode-gateway-live-docker.sh +++ b/scripts/e2e/mcp-code-mode-gateway-live-docker.sh @@ -7,22 +7,11 @@ ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" source "$ROOT_DIR/scripts/lib/docker-e2e-image.sh" IMAGE_NAME="$(docker_e2e_resolve_image "openclaw-mcp-code-mode-gateway-live-e2e" OPENCLAW_IMAGE)" -PORT="${OPENCLAW_MCP_CODE_MODE_LIVE_GATEWAY_PORT:-18789}" +PORT="$(docker_e2e_read_tcp_port_env OPENCLAW_MCP_CODE_MODE_LIVE_GATEWAY_PORT 18789)" TOKEN="mcp-code-mode-live-e2e-$(date +%s)-$$" CONTAINER_NAME="openclaw-mcp-code-mode-live-e2e-$$" PROFILE_FILE="${OPENCLAW_MCP_CODE_MODE_LIVE_PROFILE_FILE:-${OPENCLAW_TESTBOX_PROFILE_FILE:-$HOME/.openclaw-testbox-live.profile}}" -validate_tcp_port() { - local label="$1" - local value="$2" - if [[ ! "$value" =~ ^[0-9]+$ ]] || [ "$value" -lt 1 ] || [ "$value" -gt 65535 ]; then - echo "invalid $label: $value" >&2 - exit 2 - fi -} - -validate_tcp_port OPENCLAW_MCP_CODE_MODE_LIVE_GATEWAY_PORT "$PORT" - CLIENT_LOG="$(mktemp -t openclaw-mcp-code-mode-live-log.XXXXXX)" cleanup() { diff --git a/scripts/e2e/openai-chat-tools-docker.sh b/scripts/e2e/openai-chat-tools-docker.sh index 53b686f859a3..fb2851c6b185 100644 --- a/scripts/e2e/openai-chat-tools-docker.sh +++ b/scripts/e2e/openai-chat-tools-docker.sh @@ -6,7 +6,7 @@ source "$ROOT_DIR/scripts/lib/docker-e2e-image.sh" IMAGE_NAME="$(docker_e2e_resolve_image "openclaw-openai-chat-tools-e2e" OPENCLAW_OPENAI_CHAT_TOOLS_E2E_IMAGE)" SKIP_BUILD="${OPENCLAW_OPENAI_CHAT_TOOLS_E2E_SKIP_BUILD:-0}" -PORT="${OPENCLAW_OPENAI_CHAT_TOOLS_PORT:-18789}" +PORT="$(docker_e2e_read_tcp_port_env OPENCLAW_OPENAI_CHAT_TOOLS_PORT 18789)" TOKEN="openai-chat-tools-e2e-$$" PROFILE_FILE="${OPENCLAW_OPENAI_CHAT_TOOLS_PROFILE_FILE:-${OPENCLAW_TESTBOX_PROFILE_FILE:-$HOME/.openclaw-testbox-live.profile}}" if [ ! -f "$PROFILE_FILE" ] && [ -f "$HOME/.profile" ]; then diff --git a/scripts/e2e/openwebui-docker.sh b/scripts/e2e/openwebui-docker.sh index d4de701cde0a..6c67b5b0393e 100755 --- a/scripts/e2e/openwebui-docker.sh +++ b/scripts/e2e/openwebui-docker.sh @@ -15,8 +15,8 @@ MAX_CPU_PERCENT="$(docker_e2e_read_nonnegative_decimal_env OPENCLAW_OPENWEBUI_MA MODEL="${OPENCLAW_OPENWEBUI_MODEL:-openai/gpt-5.5}" PROMPT_NONCE="OPENWEBUI_DOCKER_E2E_$(date +%s)_$$" PROMPT="${OPENCLAW_OPENWEBUI_PROMPT:-Reply with exactly this token and nothing else: ${PROMPT_NONCE}}" -PORT="${OPENCLAW_OPENWEBUI_GATEWAY_PORT:-18789}" -WEBUI_PORT="${OPENCLAW_OPENWEBUI_PORT:-8080}" +PORT="$(docker_e2e_read_tcp_port_env OPENCLAW_OPENWEBUI_GATEWAY_PORT 18789)" +WEBUI_PORT="$(docker_e2e_read_tcp_port_env OPENCLAW_OPENWEBUI_PORT 8080)" TOKEN="openwebui-e2e-$(date +%s)-$$" ADMIN_EMAIL="${OPENCLAW_OPENWEBUI_ADMIN_EMAIL:-openwebui-e2e@example.com}" ADMIN_PASSWORD="${OPENCLAW_OPENWEBUI_ADMIN_PASSWORD:-OpenWebUI-E2E-Password-$(date +%s)-$$}" @@ -36,22 +36,6 @@ validate_positive_int() { fi } -validate_tcp_port() { - local label="$1" - local value="$2" - if [[ ! "$value" =~ ^[0-9]+$ ]]; then - echo "invalid $label: $value" >&2 - exit 2 - fi - local decimal_value=$((10#$value)) - if [ "$decimal_value" -lt 1 ] || [ "$decimal_value" -gt 65535 ]; then - echo "invalid $label: $value" >&2 - exit 2 - fi -} - -validate_tcp_port OPENCLAW_OPENWEBUI_GATEWAY_PORT "$PORT" -validate_tcp_port OPENCLAW_OPENWEBUI_PORT "$WEBUI_PORT" validate_positive_int OPENCLAW_OPENWEBUI_PROVIDER_TIMEOUT_SECONDS "$PROVIDER_TIMEOUT_SECONDS" PROVIDER_TIMEOUT_SECONDS_DECIMAL=$((10#$PROVIDER_TIMEOUT_SECONDS)) PROBE_FETCH_TIMEOUT_MS="${OPENCLAW_OPENWEBUI_FETCH_TIMEOUT_MS:-$((PROVIDER_TIMEOUT_SECONDS_DECIMAL * 1000 + 60000))}" diff --git a/scripts/lib/docker-e2e-image.sh b/scripts/lib/docker-e2e-image.sh index 2637054166cd..5273f38a7873 100644 --- a/scripts/lib/docker-e2e-image.sh +++ b/scripts/lib/docker-e2e-image.sh @@ -47,6 +47,25 @@ docker_e2e_read_nonnegative_decimal_env() { printf '%s\n' "$value" } +docker_e2e_read_tcp_port_env() { + local name="${1:?missing environment variable name}" + local fallback="${2:?missing fallback value}" + local value="${!name-}" + if [ -z "${!name+x}" ]; then + value="$fallback" + fi + if [[ ! "$value" =~ ^[0-9]+$ ]]; then + echo "invalid $name: $value" >&2 + return 2 + fi + local decimal_value=$((10#$value)) + if [ "$decimal_value" -lt 1 ] || [ "$decimal_value" -gt 65535 ]; then + echo "invalid $name: $value" >&2 + return 2 + fi + printf '%s\n' "$value" +} + docker_e2e_build_or_reuse() { local image_name="$1" local label="$2" diff --git a/test/scripts/docker-build-helper.test.ts b/test/scripts/docker-build-helper.test.ts index f7d0d0b6bfdc..be0e848c84e3 100644 --- a/test/scripts/docker-build-helper.test.ts +++ b/test/scripts/docker-build-helper.test.ts @@ -38,6 +38,8 @@ const CODEX_ON_DEMAND_DOCKER_E2E_PATH = "scripts/e2e/codex-on-demand-docker.sh"; const MCP_CODE_MODE_GATEWAY_DOCKER_E2E_PATH = "scripts/e2e/mcp-code-mode-gateway-docker.sh"; const MCP_CODE_MODE_GATEWAY_LIVE_DOCKER_E2E_PATH = "scripts/e2e/mcp-code-mode-gateway-live-docker.sh"; +const CODEX_MEDIA_PATH_DOCKER_E2E_PATH = "scripts/e2e/codex-media-path-docker.sh"; +const OPENAI_CHAT_TOOLS_DOCKER_E2E_PATH = "scripts/e2e/openai-chat-tools-docker.sh"; const CODEX_MEDIA_PATH_SCENARIO_PATH = "scripts/e2e/lib/codex-media-path/scenario.sh"; const OPENAI_CHAT_TOOLS_SCENARIO_PATH = "scripts/e2e/lib/openai-chat-tools/scenario.sh"; const CODEX_NPM_PLUGIN_LIVE_DOCKER_E2E_PATH = "scripts/e2e/codex-npm-plugin-live-docker.sh"; @@ -2803,8 +2805,8 @@ output="$(cat "$sampler_log")" expect(runner).toContain( 'validate_positive_int OPENCLAW_OPENWEBUI_FETCH_TIMEOUT_MS "$PROBE_FETCH_TIMEOUT_MS"', ); - expect(runner).toContain('validate_tcp_port OPENCLAW_OPENWEBUI_GATEWAY_PORT "$PORT"'); - expect(runner).toContain('validate_tcp_port OPENCLAW_OPENWEBUI_PORT "$WEBUI_PORT"'); + expect(runner).toContain("docker_e2e_read_tcp_port_env OPENCLAW_OPENWEBUI_GATEWAY_PORT 18789"); + expect(runner).toContain("docker_e2e_read_tcp_port_env OPENCLAW_OPENWEBUI_PORT 8080"); expect(runner).toContain("OPENCLAW_OPENWEBUI_MAX_MEMORY_MIB"); expect(runner).toContain("OPENCLAW_OPENWEBUI_MAX_CPU_PERCENT"); expect(runner).toContain('STATS_LOG="$(mktemp'); @@ -2889,22 +2891,21 @@ output="$(cat "$sampler_log")" [MCP_CODE_MODE_GATEWAY_DOCKER_E2E_PATH, "OPENCLAW_MCP_CODE_MODE_GATEWAY_PORT", "1e3"], [MCP_CODE_MODE_GATEWAY_DOCKER_E2E_PATH, "OPENCLAW_MCP_CODE_MODE_MOCK_PORT", "65536"], [MCP_CODE_MODE_GATEWAY_LIVE_DOCKER_E2E_PATH, "OPENCLAW_MCP_CODE_MODE_LIVE_GATEWAY_PORT", "0"], - ])( - "rejects invalid MCP code-mode Docker ports before Docker setup", - (scriptPath, envName, value) => { - const result = spawnSync("bash", [scriptPath], { - encoding: "utf8", - env: { - ...process.env, - [envName]: value, - }, - }); + [CODEX_MEDIA_PATH_DOCKER_E2E_PATH, "OPENCLAW_CODEX_MEDIA_PATH_PORT", "18790tcp"], + [OPENAI_CHAT_TOOLS_DOCKER_E2E_PATH, "OPENCLAW_OPENAI_CHAT_TOOLS_PORT", "0"], + ])("rejects invalid Docker E2E ports before setup", (scriptPath, envName, value) => { + const result = spawnSync("bash", [scriptPath], { + encoding: "utf8", + env: { + ...process.env, + [envName]: value, + }, + }); - expect(result.status).toBe(2); - expect(result.stderr).toContain(`invalid ${envName}: ${value}`); - expect(result.stderr).not.toContain("OPENAI_API_KEY was not available"); - }, - ); + expect(result.status).toBe(2); + expect(result.stderr).toContain(`invalid ${envName}: ${value}`); + expect(result.stderr).not.toContain("OPENAI_API_KEY was not available"); + }); it("forwards every kitchen-sink RPC runtime env knob into Docker", () => { const runner = readFileSync(KITCHEN_SINK_RPC_DOCKER_E2E_PATH, "utf8");