fix(e2e): bound package cli scenarios

This commit is contained in:
Vincent Koc 2026-05-27 03:49:26 +02:00
parent 716d719d4c
commit d0cb7ba55b
No known key found for this signature in database
13 changed files with 185 additions and 6 deletions

View file

@ -197,6 +197,7 @@ chmod 700 "$XDG_CACHE_HOME" "$NPM_CONFIG_CACHE" || true
openclaw_e2e_install_package /tmp/openclaw-install.log
command -v openclaw >/dev/null
openclaw_e2e_enable_openclaw_cli_timeout
echo "Installing Codex plugin: $CODEX_PLUGIN_SPEC"
openclaw plugins install "$CODEX_PLUGIN_SPEC" "${PLUGIN_INSTALL_FLAGS[@]}" >/tmp/openclaw-codex-plugin-install.log 2>&1

View file

@ -77,6 +77,7 @@ chmod 700 "$XDG_CACHE_HOME" "$NPM_CONFIG_CACHE" || true
openclaw_e2e_install_package /tmp/openclaw-install.log
command -v openclaw >/dev/null
openclaw_e2e_enable_openclaw_cli_timeout
openclaw_e2e_assert_dep_absent "@openclaw/codex" "$HOME/.openclaw" "$NPM_CONFIG_PREFIX"
openclaw_e2e_assert_dep_absent "@openai/codex" "$HOME/.openclaw" "$NPM_CONFIG_PREFIX"

View file

@ -83,6 +83,7 @@ entry="$(openclaw_e2e_package_entrypoint "$package_root")"
printf 'OPENCLAW_STATE_DIR=%s\n' "$OPENCLAW_STATE_DIR"
printf 'OPENCLAW_CONFIG_PATH=%s\n' "$OPENCLAW_CONFIG_PATH"
} >/tmp/openclaw-release-media-memory-env.log
openclaw_e2e_enable_openclaw_cli_timeout
(
cd "$package_root/dist/extensions/memory-core"
find . -type f | sed 's#^\./##' | sort

View file

@ -35,6 +35,7 @@ trap 'status=$?; dump_debug_logs "$status"; exit "$status"' ERR
openclaw_e2e_install_package /tmp/openclaw-release-plugin-marketplace-install.log
command -v openclaw >/dev/null
openclaw_e2e_enable_openclaw_cli_timeout
openclaw onboard \
--non-interactive \

View file

@ -83,6 +83,7 @@ openclaw_e2e_install_package /tmp/openclaw-release-typed-onboarding-install.log
command -v openclaw >/dev/null
package_root="$(openclaw_e2e_package_root)"
entry="$(openclaw_e2e_package_entrypoint "$package_root")"
openclaw_e2e_enable_openclaw_cli_timeout
mock_pid="$(openclaw_e2e_start_mock_openai "$MOCK_PORT" /tmp/openclaw-release-typed-onboarding-openai.log)"
openclaw_e2e_wait_mock_openai "$MOCK_PORT"

View file

@ -76,6 +76,7 @@ fi
command -v openclaw >/dev/null
baseline_root="$(openclaw_e2e_package_root)"
baseline_entry="$(openclaw_e2e_package_entrypoint "$baseline_root")"
openclaw_e2e_enable_openclaw_cli_timeout
mock_pid="$(openclaw_e2e_start_mock_openai "$MOCK_PORT" /tmp/openclaw-release-upgrade-openai.log)"
openclaw_e2e_wait_mock_openai "$MOCK_PORT"
@ -93,7 +94,7 @@ for _ in $(seq 1 100); do
done
openclaw_e2e_probe_http_status "http://127.0.0.1:$CLICKCLACK_PORT/health" 200
node "$baseline_entry" onboard \
openclaw_e2e_run_command node "$baseline_entry" onboard \
--non-interactive \
--accept-risk \
--flow quickstart \
@ -125,6 +126,7 @@ node scripts/e2e/lib/release-user-journey/assertions.mjs configure-clickclack "h
openclaw_e2e_install_package /tmp/openclaw-release-upgrade-candidate-install.log "candidate OpenClaw package"
package_root="$(openclaw_e2e_package_root)"
entry="$(openclaw_e2e_package_entrypoint "$package_root")"
openclaw_e2e_enable_openclaw_cli_timeout
node scripts/e2e/lib/release-scenarios/assertions.mjs assert-package-version "$package_root" "$candidate_version" candidate
openclaw agent --local \

View file

@ -116,6 +116,7 @@ openclaw_e2e_install_package /tmp/openclaw-release-user-journey-install.log
command -v openclaw >/dev/null
package_root="$(openclaw_e2e_package_root)"
entry="$(openclaw_e2e_package_entrypoint "$package_root")"
openclaw_e2e_enable_openclaw_cli_timeout
mock_pid="$(openclaw_e2e_start_mock_openai "$MOCK_PORT" /tmp/openclaw-release-user-journey-openai.log)"
openclaw_e2e_wait_mock_openai "$MOCK_PORT"

View file

@ -129,6 +129,7 @@ chmod 700 "$XDG_CACHE_HOME" "$NPM_CONFIG_CACHE" || true
openclaw_e2e_install_package /tmp/openclaw-install.log
command -v openclaw >/dev/null
openclaw_e2e_enable_openclaw_cli_timeout
fixture_dir="$(mktemp -d /tmp/openclaw-live-plugin-tool.XXXXXX)"
plugin_dir="$fixture_dir/package"

View file

@ -130,6 +130,7 @@ trap 'status=$?; dump_debug_logs "$status"; exit "$status"' ERR
openclaw_e2e_install_package /tmp/openclaw-install.log
command -v openclaw >/dev/null
openclaw_e2e_enable_openclaw_cli_timeout
package_root="$(openclaw_e2e_package_root)"
if [ -d "$package_root/dist/extensions/$CHANNEL" ]; then
CHANNEL_PACKAGE_MODE="bundled"

View file

@ -100,6 +100,9 @@ docker_e2e_package_mount_args() {
if [ -n "${OPENCLAW_E2E_NPM_INSTALL_TIMEOUT:-}" ]; then
DOCKER_E2E_PACKAGE_ARGS+=(-e "OPENCLAW_E2E_NPM_INSTALL_TIMEOUT=$OPENCLAW_E2E_NPM_INSTALL_TIMEOUT")
fi
if [ -n "${OPENCLAW_E2E_COMMAND_TIMEOUT:-}" ]; then
DOCKER_E2E_PACKAGE_ARGS+=(-e "OPENCLAW_E2E_COMMAND_TIMEOUT=$OPENCLAW_E2E_COMMAND_TIMEOUT")
fi
}
docker_e2e_cleanup_package_tgz() {

View file

@ -236,12 +236,13 @@ TRASH
openclaw_e2e_run_script_with_pty() {
local command="$1"
local log_path="$2"
local timeout_value="${OPENCLAW_E2E_COMMAND_TIMEOUT:-300s}"
if script --version >/dev/null 2>&1; then
script -q -f -c "$command" "$log_path"
openclaw_e2e_maybe_timeout "$timeout_value" script -q -f -c "$command" "$log_path"
elif node -e 'import("@lydell/node-pty")' >/dev/null 2>&1; then
node scripts/e2e/lib/run-with-pty.mjs "$log_path" /bin/bash -lc "$command"
openclaw_e2e_maybe_timeout "$timeout_value" node scripts/e2e/lib/run-with-pty.mjs "$log_path" /bin/bash -lc "$command"
else
script -q -F "$log_path" /bin/bash -lc "$command"
openclaw_e2e_maybe_timeout "$timeout_value" script -q -F "$log_path" /bin/bash -lc "$command"
fi
}
openclaw_e2e_stop_process() {
@ -332,8 +333,22 @@ openclaw_e2e_assert_log_not_contains() {
openclaw_e2e_run_logged() {
local label="$1" log_path="/tmp/openclaw-onboard-${1}.log"
shift
openclaw_e2e_run_command "$@" >"$log_path" 2>&1 || { cat "$log_path"; exit 1; }
}
openclaw_e2e_run_command() {
local timeout_value="${OPENCLAW_E2E_COMMAND_TIMEOUT:-300s}"
openclaw_e2e_maybe_timeout "$timeout_value" "$@" >"$log_path" 2>&1 || { cat "$log_path"; exit 1; }
openclaw_e2e_maybe_timeout "$timeout_value" "$@"
}
openclaw_e2e_enable_openclaw_cli_timeout() {
OPENCLAW_E2E_CLI_BIN="$(type -P openclaw)"
if [ -z "$OPENCLAW_E2E_CLI_BIN" ]; then
echo "OpenClaw CLI binary not found on PATH" >&2
return 1
fi
export OPENCLAW_E2E_CLI_BIN
openclaw() {
openclaw_e2e_run_command "$OPENCLAW_E2E_CLI_BIN" "$@"
}
}
openclaw_e2e_dump_logs() {
local path

View file

@ -921,7 +921,7 @@ test -f "$external_dir/openclaw-current.tgz"
}
});
it("propagates the shared E2E npm install timeout into package-backed containers", () => {
it("propagates shared E2E command timeouts into package-backed containers", () => {
const workDir = mkdtempSync(join(tmpdir(), "openclaw-docker-package-timeout-env-"));
try {
@ -936,12 +936,14 @@ source "$ROOT_DIR/scripts/lib/docker-e2e-package.sh"
package="$TMPDIR/openclaw-current.tgz"
printf fixture >"$package"
export OPENCLAW_E2E_NPM_INSTALL_TIMEOUT=42s
export OPENCLAW_E2E_COMMAND_TIMEOUT=23s
docker_e2e_package_mount_args "$package"
printf "%s\\n" "\${DOCKER_E2E_PACKAGE_ARGS[@]}" >"$TMPDIR/package-args"
grep -qx -- "-e" "$TMPDIR/package-args"
grep -qx -- "OPENCLAW_CURRENT_PACKAGE_TGZ=/tmp/openclaw-current.tgz" "$TMPDIR/package-args"
grep -qx -- "OPENCLAW_E2E_NPM_INSTALL_TIMEOUT=42s" "$TMPDIR/package-args"
grep -qx -- "OPENCLAW_E2E_COMMAND_TIMEOUT=23s" "$TMPDIR/package-args"
`;
execFileSync("bash", ["-lc", script], { encoding: "utf8" });
@ -994,6 +996,29 @@ grep -qx -- "OPENCLAW_E2E_NPM_INSTALL_TIMEOUT=42s" "$TMPDIR/package-args"
}
});
it("wraps package-backed scenario OpenClaw CLI calls with the shared timeout helper", () => {
const paths = [
CODEX_ON_DEMAND_DOCKER_E2E_PATH,
CODEX_NPM_PLUGIN_LIVE_DOCKER_E2E_PATH,
LIVE_PLUGIN_TOOL_DOCKER_E2E_PATH,
NPM_ONBOARD_CHANNEL_AGENT_DOCKER_E2E_PATH,
RELEASE_UPGRADE_USER_JOURNEY_SCENARIO_PATH,
"scripts/e2e/lib/release-media-memory/scenario.sh",
"scripts/e2e/lib/release-plugin-marketplace/scenario.sh",
"scripts/e2e/lib/release-typed-onboarding/scenario.sh",
"scripts/e2e/lib/release-user-journey/scenario.sh",
];
for (const path of paths) {
const script = readFileSync(path, "utf8");
expect(script, path).toContain("openclaw_e2e_enable_openclaw_cli_timeout");
}
expect(readFileSync(RELEASE_UPGRADE_USER_JOURNEY_SCENARIO_PATH, "utf8")).toContain(
'openclaw_e2e_run_command node "$baseline_entry" onboard',
);
});
it("kills timed Docker scenario runners after the grace period", () => {
const multiNode = readFileSync(MULTI_NODE_UPDATE_DOCKER_E2E_PATH, "utf8");
const upgradeSurvivor = readFileSync(UPGRADE_SURVIVOR_DOCKER_E2E_PATH, "utf8");

View file

@ -386,4 +386,130 @@ describe("scripts/lib/openclaw-e2e-instance.sh", () => {
fs.rmSync(logPath, { force: true });
}
});
it("wraps package-installed OpenClaw CLI calls with the configured timeout", () => {
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-e2e-instance-openclaw-cli-"));
try {
const timeoutArgsPath = path.join(tempDir, "timeout-args.txt");
const commandArgsPath = path.join(tempDir, "openclaw-args.txt");
fs.writeFileSync(
path.join(tempDir, "timeout"),
[
"#!/usr/bin/env bash",
"set -euo pipefail",
'printf "%s\\n" "$*" >"$OPENCLAW_TEST_TIMEOUT_ARGS"',
`while [ "$#" -gt 0 ] && [ "$1" != ${shellQuote(path.join(tempDir, "openclaw"))} ]; do shift; done`,
'exec "$@"',
"",
].join("\n"),
);
fs.writeFileSync(
path.join(tempDir, "openclaw"),
[
"#!/usr/bin/env bash",
"set -euo pipefail",
'printf "%s\\n" "$*" >"$OPENCLAW_TEST_COMMAND_ARGS"',
"",
].join("\n"),
);
fs.chmodSync(path.join(tempDir, "timeout"), 0o755);
fs.chmodSync(path.join(tempDir, "openclaw"), 0o755);
const result = spawnSync(
"/bin/bash",
[
"-c",
[
"set -euo pipefail",
`source ${shellQuote(helperPath)}`,
"openclaw_e2e_enable_openclaw_cli_timeout",
"openclaw_e2e_enable_openclaw_cli_timeout",
"openclaw plugins list --json",
].join("; "),
],
{
encoding: "utf8",
env: {
...process.env,
PATH: `${tempDir}:${process.env.PATH ?? ""}`,
OPENCLAW_E2E_COMMAND_TIMEOUT: "23s",
OPENCLAW_TEST_TIMEOUT_ARGS: timeoutArgsPath,
OPENCLAW_TEST_COMMAND_ARGS: commandArgsPath,
},
},
);
expect(result.status).toBe(0);
expect(fs.readFileSync(timeoutArgsPath, "utf8").trim()).toBe(
`--kill-after=30s 23s ${path.join(tempDir, "openclaw")} plugins list --json`,
);
expect(fs.readFileSync(commandArgsPath, "utf8").trim()).toBe("plugins list --json");
} finally {
fs.rmSync(tempDir, { force: true, recursive: true });
}
});
it("wraps interactive PTY scripts with the configured timeout", () => {
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-e2e-instance-pty-timeout-"));
try {
const timeoutArgsPath = path.join(tempDir, "timeout-args.txt");
const scriptArgsPath = path.join(tempDir, "script-args.txt");
const logPath = path.join(tempDir, "pty.log");
fs.writeFileSync(
path.join(tempDir, "timeout"),
[
"#!/usr/bin/env bash",
"set -euo pipefail",
'printf "%s\\n" "$*" >"$OPENCLAW_TEST_TIMEOUT_ARGS"',
'while [ "$#" -gt 0 ] && [ "$1" != "script" ]; do shift; done',
'exec "$@"',
"",
].join("\n"),
);
fs.writeFileSync(
path.join(tempDir, "script"),
[
"#!/usr/bin/env bash",
"set -euo pipefail",
'if [ "${1:-}" = "--version" ]; then exit 0; fi',
'printf "%s\\n" "$*" >"$OPENCLAW_TEST_SCRIPT_ARGS"',
"",
].join("\n"),
);
fs.chmodSync(path.join(tempDir, "timeout"), 0o755);
fs.chmodSync(path.join(tempDir, "script"), 0o755);
const result = spawnSync(
"/bin/bash",
[
"-c",
[
"set -euo pipefail",
`source ${shellQuote(helperPath)}`,
`openclaw_e2e_run_script_with_pty ${shellQuote("node /tmp/entry onboard")} ${shellQuote(logPath)}`,
].join("; "),
],
{
encoding: "utf8",
env: {
...process.env,
PATH: `${tempDir}:${process.env.PATH ?? ""}`,
OPENCLAW_E2E_COMMAND_TIMEOUT: "31s",
OPENCLAW_TEST_TIMEOUT_ARGS: timeoutArgsPath,
OPENCLAW_TEST_SCRIPT_ARGS: scriptArgsPath,
},
},
);
expect(result.status).toBe(0);
expect(fs.readFileSync(timeoutArgsPath, "utf8").trim()).toBe(
`--kill-after=30s 31s script -q -f -c node /tmp/entry onboard ${logPath}`,
);
expect(fs.readFileSync(scriptArgsPath, "utf8").trim()).toBe(
`-q -f -c node /tmp/entry onboard ${logPath}`,
);
} finally {
fs.rmSync(tempDir, { force: true, recursive: true });
}
});
});