Skip to content

Commit bb44c53

Browse files
committed
fix(e2e): validate docker log limits
1 parent 4764258 commit bb44c53

3 files changed

Lines changed: 115 additions & 23 deletions

File tree

scripts/lib/docker-e2e-logs.sh

Lines changed: 51 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,39 @@
44
# They centralize temporary log naming and the small success/failure print
55
# pattern used by Docker scenario scripts.
66

7+
docker_e2e_normalize_positive_int_value() {
8+
local label="${1:?missing value label}"
9+
local value="${2-}"
10+
if [[ ! "$value" =~ ^[0-9]+$ ]] || (( 10#$value < 1 )); then
11+
echo "invalid $label: $value" >&2
12+
return 2
13+
fi
14+
printf '%s\n' "$((10#$value))"
15+
}
16+
17+
docker_e2e_read_positive_int_env() {
18+
local name="${1:?missing environment variable name}"
19+
local fallback="${2:?missing fallback value}"
20+
local value="${!name-}"
21+
if [ -z "${!name+x}" ]; then
22+
value="$fallback"
23+
fi
24+
docker_e2e_normalize_positive_int_value "$name" "$value"
25+
}
26+
727
run_logged() {
828
local label="$1"
929
shift
30+
docker_e2e_read_positive_int_env OPENCLAW_DOCKER_E2E_LOG_PRINT_BYTES 65536 >/dev/null || return $?
1031
local log_file
1132
log_file="$(docker_e2e_run_log "$label")"
1233
if ! "$@" >"$log_file" 2>&1; then
13-
docker_e2e_print_log "$log_file"
34+
local print_status=0
35+
docker_e2e_print_log "$log_file" || print_status="$?"
1436
rm -f "$log_file"
37+
if [ "$print_status" -ne 0 ]; then
38+
return "$print_status"
39+
fi
1540
return 1
1641
fi
1742
rm -f "$log_file"
@@ -20,26 +45,36 @@ run_logged() {
2045
run_logged_print() {
2146
local label="$1"
2247
shift
48+
docker_e2e_read_positive_int_env OPENCLAW_DOCKER_E2E_LOG_PRINT_BYTES 65536 >/dev/null || return $?
2349
local log_file
2450
log_file="$(docker_e2e_run_log "$label")"
2551
if ! "$@" >"$log_file" 2>&1; then
26-
docker_e2e_print_log "$log_file"
52+
local print_status=0
53+
docker_e2e_print_log "$log_file" || print_status="$?"
2754
rm -f "$log_file"
55+
if [ "$print_status" -ne 0 ]; then
56+
return "$print_status"
57+
fi
2858
return 1
2959
fi
30-
docker_e2e_print_log "$log_file"
60+
docker_e2e_print_log "$log_file" || {
61+
local print_status="$?"
62+
rm -f "$log_file"
63+
return "$print_status"
64+
}
3165
rm -f "$log_file"
3266
}
3367

3468
run_logged_print_heartbeat() {
3569
local label="$1"
3670
local interval_seconds="$2"
3771
shift 2
38-
if ! [[ "$interval_seconds" =~ ^[0-9]+$ ]] || [ "$interval_seconds" -lt 1 ]; then
39-
interval_seconds="30"
40-
else
41-
interval_seconds="$((10#$interval_seconds))"
42-
fi
72+
docker_e2e_read_positive_int_env OPENCLAW_DOCKER_E2E_LOG_PRINT_BYTES 65536 >/dev/null || return $?
73+
interval_seconds="$(docker_e2e_normalize_positive_int_value "Docker E2E log heartbeat interval" "$interval_seconds")" || return $?
74+
local heartbeat_term_grace_seconds
75+
heartbeat_term_grace_seconds="$(
76+
docker_e2e_read_positive_int_env OPENCLAW_DOCKER_E2E_HEARTBEAT_TERM_GRACE_SECONDS 30
77+
)" || return $?
4378
local log_file
4479
log_file="$(docker_e2e_run_log "$label")"
4580
local command_pid=""
@@ -55,14 +90,8 @@ run_logged_print_heartbeat() {
5590
return 0
5691
fi
5792
kill -TERM "$command_pid" 2>/dev/null || true
58-
local grace_seconds="${OPENCLAW_DOCKER_E2E_HEARTBEAT_TERM_GRACE_SECONDS:-30}"
59-
if ! [[ "$grace_seconds" =~ ^[0-9]+$ ]] || [ "$grace_seconds" -lt 1 ]; then
60-
grace_seconds="30"
61-
else
62-
grace_seconds="$((10#$grace_seconds))"
63-
fi
6493
local wait_attempt
65-
for wait_attempt in $(seq 1 "$((grace_seconds * 10))"); do
94+
for wait_attempt in $(seq 1 "$((heartbeat_term_grace_seconds * 10))"); do
6695
if ! kill -0 "$command_pid" 2>/dev/null; then
6796
return 0
6897
fi
@@ -130,7 +159,11 @@ run_logged_print_heartbeat() {
130159
wait "$command_pid"
131160
status=$?
132161
set -e
133-
docker_e2e_print_log "$log_file"
162+
docker_e2e_print_log "$log_file" || {
163+
local print_status="$?"
164+
cleanup_heartbeat_command 0
165+
return "$print_status"
166+
}
134167
cleanup_heartbeat_command 0
135168
return "$status"
136169
}
@@ -144,12 +177,8 @@ docker_e2e_run_log() {
144177

145178
docker_e2e_print_log() {
146179
local log_file="$1"
147-
local max_bytes="${OPENCLAW_DOCKER_E2E_LOG_PRINT_BYTES:-65536}"
148-
if ! [[ "$max_bytes" =~ ^[0-9]+$ ]] || [ "$max_bytes" -lt 1 ]; then
149-
max_bytes="65536"
150-
else
151-
max_bytes="$((10#$max_bytes))"
152-
fi
180+
local max_bytes
181+
max_bytes="$(docker_e2e_read_positive_int_env OPENCLAW_DOCKER_E2E_LOG_PRINT_BYTES 65536)" || return $?
153182
if [ ! -f "$log_file" ]; then
154183
return 0
155184
fi

scripts/lib/docker-e2e-package.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,9 +409,11 @@ docker_e2e_run_logged_with_harness() {
409409
docker_e2e_run_logged_print_with_harness() {
410410
local label="$1"
411411
shift
412+
local heartbeat_seconds
413+
heartbeat_seconds="$(docker_e2e_read_positive_int_env OPENCLAW_DOCKER_E2E_LOG_HEARTBEAT_SECONDS 30)" || return $?
412414
run_logged_print_heartbeat \
413415
"$label" \
414-
"${OPENCLAW_DOCKER_E2E_LOG_HEARTBEAT_SECONDS:-30}" \
416+
"$heartbeat_seconds" \
415417
docker_e2e_run_with_harness \
416418
"$@"
417419
}

test/scripts/docker-build-helper.test.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2625,6 +2625,67 @@ output="$(run_logged_print_heartbeat plugins-run 30 bash -c 'printf "DO_NOT_PRIN
26252625
}
26262626
});
26272627

2628+
it.each([
2629+
["printed log bytes", "OPENCLAW_DOCKER_E2E_LOG_PRINT_BYTES", "64kb"],
2630+
["heartbeat termination grace", "OPENCLAW_DOCKER_E2E_HEARTBEAT_TERM_GRACE_SECONDS", "soon"],
2631+
])("rejects invalid Docker E2E %s before setup", (_label, envName, value) => {
2632+
const workDir = mkdtempSync(join(tmpdir(), "openclaw-docker-e2e-log-invalid-"));
2633+
2634+
try {
2635+
const rootDir = process.cwd();
2636+
const script = `
2637+
set -euo pipefail
2638+
ROOT_DIR=${shellQuote(rootDir)}
2639+
TMPDIR=${shellQuote(workDir)}
2640+
export ROOT_DIR TMPDIR
2641+
export ${envName}=${shellQuote(value)}
2642+
2643+
source "$ROOT_DIR/scripts/lib/docker-e2e-logs.sh"
2644+
2645+
run_logged_print_heartbeat plugins-run 30 bash -c 'printf "should not print\\\\n"'
2646+
`;
2647+
2648+
const result = spawnSync("bash", ["-lc", script], { encoding: "utf8" });
2649+
2650+
expect(result.status).toBe(2);
2651+
expect(result.stderr).toContain(`invalid ${envName}: ${value}`);
2652+
expect(result.stdout).toBe("");
2653+
} finally {
2654+
rmSync(workDir, { recursive: true, force: true });
2655+
}
2656+
});
2657+
2658+
it("rejects invalid Docker E2E log heartbeat env before harness setup", () => {
2659+
const workDir = mkdtempSync(join(tmpdir(), "openclaw-docker-e2e-log-heartbeat-invalid-"));
2660+
2661+
try {
2662+
const rootDir = process.cwd();
2663+
const script = `
2664+
set -euo pipefail
2665+
ROOT_DIR=${shellQuote(rootDir)}
2666+
TMPDIR=${shellQuote(workDir)}
2667+
export ROOT_DIR TMPDIR
2668+
export OPENCLAW_DOCKER_E2E_LOG_HEARTBEAT_SECONDS=1e3
2669+
2670+
source "$ROOT_DIR/scripts/lib/docker-e2e-package.sh"
2671+
2672+
docker_e2e_run_with_harness() {
2673+
echo "should not run"
2674+
}
2675+
2676+
docker_e2e_run_logged_print_with_harness plugins-run image-name
2677+
`;
2678+
2679+
const result = spawnSync("bash", ["-lc", script], { encoding: "utf8" });
2680+
2681+
expect(result.status).toBe(2);
2682+
expect(result.stderr).toContain("invalid OPENCLAW_DOCKER_E2E_LOG_HEARTBEAT_SECONDS: 1e3");
2683+
expect(result.stdout).toBe("");
2684+
} finally {
2685+
rmSync(workDir, { recursive: true, force: true });
2686+
}
2687+
});
2688+
26282689
it("prints heartbeat progress for long successful Docker E2E log captures", () => {
26292690
const workDir = mkdtempSync(join(tmpdir(), "openclaw-docker-e2e-log-heartbeat-"));
26302691

0 commit comments

Comments
 (0)