fix(e2e): validate docker resource limits

This commit is contained in:
Vincent Koc 2026-06-19 00:00:37 +02:00
parent 9928516a78
commit 0df60ad306
No known key found for this signature in database
6 changed files with 70 additions and 12 deletions

View file

@ -5,7 +5,6 @@ ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
source "$ROOT_DIR/scripts/lib/docker-e2e-image.sh"
IMAGE_NAME="$(docker_e2e_resolve_image "openclaw-kitchen-sink-plugin-e2e" OPENCLAW_KITCHEN_SINK_PLUGIN_E2E_IMAGE)"
docker_e2e_build_or_reuse "$IMAGE_NAME" kitchen-sink-plugin
OPENCLAW_TEST_STATE_SCRIPT_B64="$(docker_e2e_test_state_shell_b64 kitchen-sink-plugin empty)"
KITCHEN_SINK_NPM_SPEC="${OPENCLAW_KITCHEN_SINK_NPM_SPEC:-npm:@openclaw/kitchen-sink@latest}"
KITCHEN_SINK_NPM_MISSING_SPEC="${OPENCLAW_KITCHEN_SINK_NPM_MISSING_SPEC:-npm:@openclaw/kitchen-sink@beta}"
@ -22,8 +21,14 @@ npm-to-clawhub|clawhub:@openclaw/kitchen-sink@latest|openclaw-kitchen-sink-fixtu
SCENARIOS
)"
KITCHEN_SINK_SCENARIOS="${OPENCLAW_KITCHEN_SINK_PLUGIN_SCENARIOS:-$DEFAULT_KITCHEN_SINK_SCENARIOS}"
MAX_MEMORY_MIB="${OPENCLAW_KITCHEN_SINK_PLUGIN_MAX_MEMORY_MIB:-${OPENCLAW_KITCHEN_SINK_MAX_MEMORY_MIB:-2304}}"
MAX_CPU_PERCENT="${OPENCLAW_KITCHEN_SINK_MAX_CPU_PERCENT:-1200}"
MAX_MEMORY_MIB="$(
if [[ -n "${OPENCLAW_KITCHEN_SINK_PLUGIN_MAX_MEMORY_MIB:-}" ]]; then
docker_e2e_read_nonnegative_decimal_env OPENCLAW_KITCHEN_SINK_PLUGIN_MAX_MEMORY_MIB 2304
else
docker_e2e_read_nonnegative_decimal_env OPENCLAW_KITCHEN_SINK_MAX_MEMORY_MIB 2304
fi
)"
MAX_CPU_PERCENT="$(docker_e2e_read_nonnegative_decimal_env OPENCLAW_KITCHEN_SINK_MAX_CPU_PERCENT 1200)"
DOCKER_RUN_TIMEOUT="${OPENCLAW_KITCHEN_SINK_PLUGIN_DOCKER_RUN_TIMEOUT:-1200s}"
KITCHEN_SINK_CLI_TIMEOUT="${OPENCLAW_KITCHEN_SINK_PLUGIN_CLI_TIMEOUT:-${KITCHEN_SINK_CLI_TIMEOUT:-180s}}"
CONTAINER_NAME="openclaw-kitchen-sink-plugin-e2e-$$"
@ -36,6 +41,8 @@ cleanup() {
}
trap cleanup EXIT
docker_e2e_build_or_reuse "$IMAGE_NAME" kitchen-sink-plugin
DOCKER_ENV_ARGS=(
-e COREPACK_ENABLE_DOWNLOAD_PROMPT=0
-e "OPENCLAW_TEST_STATE_SCRIPT_B64=$OPENCLAW_TEST_STATE_SCRIPT_B64"

View file

@ -5,8 +5,8 @@ ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
source "$ROOT_DIR/scripts/lib/docker-e2e-image.sh"
IMAGE_NAME="$(docker_e2e_resolve_image "openclaw-kitchen-sink-rpc-e2e" OPENCLAW_KITCHEN_SINK_RPC_E2E_IMAGE)"
MAX_MEMORY_MIB="${OPENCLAW_KITCHEN_SINK_MAX_MEMORY_MIB:-2048}"
MAX_CPU_PERCENT="${OPENCLAW_KITCHEN_SINK_MAX_CPU_PERCENT:-1200}"
MAX_MEMORY_MIB="$(docker_e2e_read_nonnegative_decimal_env OPENCLAW_KITCHEN_SINK_MAX_MEMORY_MIB 2048)"
MAX_CPU_PERCENT="$(docker_e2e_read_nonnegative_decimal_env OPENCLAW_KITCHEN_SINK_MAX_CPU_PERCENT 1200)"
DOCKER_RUN_TIMEOUT="${OPENCLAW_KITCHEN_SINK_RPC_DOCKER_RUN_TIMEOUT:-900s}"
CONTAINER_NAME="openclaw-kitchen-sink-rpc-e2e-$$"
RUN_LOG="$(mktemp "${TMPDIR:-/tmp}/openclaw-kitchen-sink-rpc.XXXXXX")"

View file

@ -5,8 +5,8 @@ ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
source "$ROOT_DIR/scripts/lib/docker-e2e-image.sh"
IMAGE_NAME="$(docker_e2e_resolve_image "openclaw-onboard-e2e" OPENCLAW_ONBOARD_E2E_IMAGE)"
OPENCLAW_TEST_STATE_FUNCTION_B64="$(docker_e2e_test_state_function_b64)"
MAX_MEMORY_MIB="${OPENCLAW_ONBOARD_MAX_MEMORY_MIB:-2048}"
MAX_CPU_PERCENT="${OPENCLAW_ONBOARD_MAX_CPU_PERCENT:-1200}"
MAX_MEMORY_MIB="$(docker_e2e_read_nonnegative_decimal_env OPENCLAW_ONBOARD_MAX_MEMORY_MIB 2048)"
MAX_CPU_PERCENT="$(docker_e2e_read_nonnegative_decimal_env OPENCLAW_ONBOARD_MAX_CPU_PERCENT 1200)"
DOCKER_RUN_TIMEOUT="${OPENCLAW_ONBOARD_DOCKER_RUN_TIMEOUT:-1200s}"
COMMAND_TIMEOUT="${OPENCLAW_ONBOARD_COMMAND_TIMEOUT:-${OPENCLAW_E2E_COMMAND_TIMEOUT:-300s}}"
CONTAINER_NAME="openclaw-onboard-e2e-$$"

View file

@ -8,8 +8,8 @@ source "$ROOT_DIR/scripts/lib/docker-e2e-image.sh"
IMAGE_NAME="$(docker_e2e_resolve_image "openclaw-openwebui-e2e" OPENCLAW_OPENWEBUI_E2E_IMAGE)"
OPENWEBUI_IMAGE="${OPENWEBUI_IMAGE:-ghcr.io/open-webui/open-webui:v0.8.10}"
MAX_MEMORY_MIB="${OPENCLAW_OPENWEBUI_MAX_MEMORY_MIB:-8192}"
MAX_CPU_PERCENT="${OPENCLAW_OPENWEBUI_MAX_CPU_PERCENT:-1600}"
MAX_MEMORY_MIB="$(docker_e2e_read_nonnegative_decimal_env OPENCLAW_OPENWEBUI_MAX_MEMORY_MIB 8192)"
MAX_CPU_PERCENT="$(docker_e2e_read_nonnegative_decimal_env OPENCLAW_OPENWEBUI_MAX_CPU_PERCENT 1600)"
# Keep the default on the preferred GPT-5 OpenAI model for Open WebUI
# compatibility smoke. Callers can still override this explicitly.
MODEL="${OPENCLAW_OPENWEBUI_MODEL:-openai/gpt-5.5}"

View file

@ -33,6 +33,20 @@ docker_e2e_resolve_image() {
printf '%s\n' "$default_image"
}
docker_e2e_read_nonnegative_decimal_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|[1-9][0-9]*)(\.[0-9]+)?$ ]]; 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"

View file

@ -300,6 +300,43 @@ docker_build_transient_failure "$LOG_PATH"
);
});
it("rejects malformed Docker E2E resource limits before a suite starts", () => {
const helper = readFileSync(DOCKER_E2E_IMAGE_HELPER_PATH, "utf8");
const scripts = [
readFileSync(ONBOARD_DOCKER_E2E_PATH, "utf8"),
readFileSync(KITCHEN_SINK_PLUGIN_DOCKER_E2E_PATH, "utf8"),
readFileSync(KITCHEN_SINK_RPC_DOCKER_E2E_PATH, "utf8"),
readFileSync(OPENWEBUI_DOCKER_E2E_PATH, "utf8"),
];
expect(helper).toContain("docker_e2e_read_nonnegative_decimal_env()");
for (const script of scripts) {
expect(script).toContain("docker_e2e_read_nonnegative_decimal_env");
}
const runProbe = (value: string) => {
const script = [
"source scripts/lib/docker-e2e-image.sh",
"docker_e2e_read_nonnegative_decimal_env OPENCLAW_SAMPLE_RESOURCE_LIMIT 2048",
].join("\n");
return spawnSync("bash", ["-c", script], {
cwd: process.cwd(),
encoding: "utf8",
env: {
...process.env,
OPENCLAW_SAMPLE_RESOURCE_LIMIT: value,
},
});
};
const invalid = runProbe("12mb");
const decimal = runProbe("12.5");
expect(invalid.status).toBe(2);
expect(invalid.stderr).toContain("invalid OPENCLAW_SAMPLE_RESOURCE_LIMIT: 12mb");
expect(decimal.status).toBe(0);
expect(decimal.stdout.trimEnd()).toBe("12.5");
});
it("keeps Testbox image-build fallback before isolating live MCP code-mode runtime flags", () => {
const script = readFileSync(MCP_CODE_MODE_GATEWAY_LIVE_DOCKER_E2E_PATH, "utf8");
const buildIndex = script.indexOf('docker_e2e_build_or_reuse "$IMAGE_NAME"');
@ -3003,10 +3040,10 @@ output="$(cat "$sampler_log")"
const wrapper = readFileSync("scripts/test-install-sh-e2e-docker.sh", "utf8");
expect(runner).toContain(
"AGENT_TURNS_PARALLEL=\"$(read_boolean_env OPENCLAW_INSTALL_E2E_AGENT_TURNS_PARALLEL 1)\"",
'AGENT_TURNS_PARALLEL="$(read_boolean_env OPENCLAW_INSTALL_E2E_AGENT_TURNS_PARALLEL 1)"',
);
expect(runner).toContain(
"AGENT_TOOL_SMOKE=\"$(read_boolean_env OPENCLAW_INSTALL_E2E_AGENT_TOOL_SMOKE 1)\"",
'AGENT_TOOL_SMOKE="$(read_boolean_env OPENCLAW_INSTALL_E2E_AGENT_TOOL_SMOKE 1)"',
);
expect(runner).toContain("time_phase");
expect(runner).toContain("phase_mark_start");
@ -3033,7 +3070,7 @@ output="$(cat "$sampler_log")"
expect(runner).toContain("OPENCLAW_INSTALL_E2E_OPENAI_MODEL");
expect(runner).toContain("OPENCLAW_INSTALL_E2E_OPENAI_PROVIDER_TIMEOUT_SECONDS");
expect(runner).toContain(
"AGENT_TURN_TIMEOUT_SECONDS=\"$(read_positive_int_env OPENCLAW_INSTALL_E2E_AGENT_TURN_TIMEOUT_SECONDS 300)\"",
'AGENT_TURN_TIMEOUT_SECONDS="$(read_positive_int_env OPENCLAW_INSTALL_E2E_AGENT_TURN_TIMEOUT_SECONDS 300)"',
);
});