mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-06 05:51:15 +08:00
fix(ci): trim docker e2e heartbeat latency
This commit is contained in:
@@ -49,6 +49,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Release/CI/E2E: fail early when Crabbox sparse-sync full checkouts do not have enough local disk, with guidance for moving the sync root.
|
||||
- Release/CI/E2E: reset shared Crabbox pnpm hydrate state before installs so stale `/var/tmp` stores cannot leave `pnpm install` spinning after completion.
|
||||
- Release/CI/E2E: print heartbeat progress during centralized Docker builds while keeping successful build logs quiet.
|
||||
- Release/CI/E2E: avoid heartbeat-tail delays in Docker E2E log wrappers while reporting captured log bytes during long runs.
|
||||
- Build: render independent CLI startup metadata help snapshots concurrently to cut cold build-all metadata time.
|
||||
- Plugins: stop timed-out package-boundary prep steps by process group so descendant TypeScript/helper processes do not survive local check cleanup.
|
||||
- Control UI: serve static assets asynchronously after safe-open checks so large UI files do not block Gateway request handling.
|
||||
|
||||
@@ -76,7 +76,7 @@ docker_build_timeout_required() {
|
||||
docker_build_heartbeat_seconds() {
|
||||
local configured="${OPENCLAW_DOCKER_BUILD_HEARTBEAT_SECONDS:-30}"
|
||||
if [[ "$configured" =~ ^[0-9]+$ ]] && [ "$configured" -ge 1 ]; then
|
||||
echo "$configured"
|
||||
echo "$((10#$configured))"
|
||||
return
|
||||
fi
|
||||
echo 30
|
||||
|
||||
@@ -35,19 +35,29 @@ run_logged_print_heartbeat() {
|
||||
local label="$1"
|
||||
local interval_seconds="$2"
|
||||
shift 2
|
||||
if ! [[ "$interval_seconds" =~ ^[0-9]+$ ]] || [ "$interval_seconds" -lt 1 ]; then
|
||||
interval_seconds="30"
|
||||
else
|
||||
interval_seconds="$((10#$interval_seconds))"
|
||||
fi
|
||||
local log_file
|
||||
log_file="$(docker_e2e_run_log "$label")"
|
||||
"$@" >"$log_file" 2>&1 &
|
||||
local command_pid=$!
|
||||
local started_at
|
||||
started_at="$(date +%s)"
|
||||
local started_at="$SECONDS"
|
||||
local next_heartbeat=$interval_seconds
|
||||
local status=0
|
||||
while kill -0 "$command_pid" 2>/dev/null; do
|
||||
sleep "$interval_seconds"
|
||||
if kill -0 "$command_pid" 2>/dev/null; then
|
||||
local now
|
||||
now="$(date +%s)"
|
||||
echo "still running $label ($((now - started_at))s elapsed)"
|
||||
/bin/sleep 1
|
||||
local elapsed_seconds=$((SECONDS - started_at))
|
||||
if [ "$elapsed_seconds" -ge "$next_heartbeat" ] && kill -0 "$command_pid" 2>/dev/null; then
|
||||
local log_bytes="0"
|
||||
if [ -f "$log_file" ]; then
|
||||
log_bytes="$(wc -c <"$log_file" 2>/dev/null || echo 0)"
|
||||
log_bytes="${log_bytes//[[:space:]]/}"
|
||||
fi
|
||||
echo "still running $label (${elapsed_seconds}s elapsed, ${log_bytes} log bytes captured)"
|
||||
next_heartbeat=$((elapsed_seconds + interval_seconds))
|
||||
fi
|
||||
done
|
||||
set +e
|
||||
|
||||
@@ -339,6 +339,22 @@ output="$(docker_build_run e2e-build -t demo-image .)"
|
||||
}
|
||||
});
|
||||
|
||||
it("normalizes zero-padded centralized Docker build heartbeat intervals", () => {
|
||||
const rootDir = process.cwd();
|
||||
const script = `
|
||||
set -euo pipefail
|
||||
ROOT_DIR=${shellQuote(rootDir)}
|
||||
export ROOT_DIR
|
||||
export OPENCLAW_DOCKER_BUILD_HEARTBEAT_SECONDS=08
|
||||
|
||||
source "$ROOT_DIR/scripts/lib/docker-build.sh"
|
||||
|
||||
[[ "$(docker_build_heartbeat_seconds)" = "8" ]]
|
||||
`;
|
||||
|
||||
execFileSync("bash", ["-lc", script], { encoding: "utf8" });
|
||||
});
|
||||
|
||||
it("fails centralized Docker builds fast when timeout is unavailable", () => {
|
||||
const workDir = mkdtempSync(join(tmpdir(), "openclaw-docker-build-timeout-required-"));
|
||||
|
||||
@@ -1555,6 +1571,82 @@ test -f "$TMPDIR/docker-cmd-seen"
|
||||
expect(runner).not.toContain("docker_e2e_run_logged_with_harness plugins-run");
|
||||
});
|
||||
|
||||
it("prints heartbeat progress for long successful Docker E2E log captures", () => {
|
||||
const workDir = mkdtempSync(join(tmpdir(), "openclaw-docker-e2e-log-heartbeat-"));
|
||||
|
||||
try {
|
||||
const rootDir = process.cwd();
|
||||
const script = `
|
||||
set -euo pipefail
|
||||
ROOT_DIR=${shellQuote(rootDir)}
|
||||
TMPDIR=${shellQuote(workDir)}
|
||||
export ROOT_DIR TMPDIR
|
||||
|
||||
source "$ROOT_DIR/scripts/lib/docker-e2e-logs.sh"
|
||||
|
||||
output="$(run_logged_print_heartbeat plugins-run 1 bash -c 'printf "captured container log\\\\n"; /bin/sleep 2')"
|
||||
[[ "$output" = *"still running plugins-run ("* ]]
|
||||
[[ "$output" = *"log bytes captured"* ]]
|
||||
[[ "$output" = *"captured container log"* ]]
|
||||
`;
|
||||
|
||||
execFileSync("bash", ["-lc", script], { encoding: "utf8" });
|
||||
} finally {
|
||||
rmSync(workDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
it("does not delay fast successful Docker E2E log captures until the next heartbeat", () => {
|
||||
const workDir = mkdtempSync(join(tmpdir(), "openclaw-docker-e2e-log-fast-heartbeat-"));
|
||||
|
||||
try {
|
||||
const rootDir = process.cwd();
|
||||
const script = `
|
||||
set -euo pipefail
|
||||
ROOT_DIR=${shellQuote(rootDir)}
|
||||
TMPDIR=${shellQuote(workDir)}
|
||||
export ROOT_DIR TMPDIR
|
||||
|
||||
source "$ROOT_DIR/scripts/lib/docker-e2e-logs.sh"
|
||||
|
||||
output="$(run_logged_print_heartbeat plugins-run 30 bash -c 'printf "quick container log\\\\n"')"
|
||||
[[ "$output" = "quick container log" ]]
|
||||
`;
|
||||
const startedAt = Date.now();
|
||||
|
||||
execFileSync("bash", ["-lc", script], { encoding: "utf8" });
|
||||
|
||||
expect(Date.now() - startedAt).toBeLessThan(5_000);
|
||||
} finally {
|
||||
rmSync(workDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
it("normalizes zero-padded Docker E2E log heartbeat intervals", () => {
|
||||
const workDir = mkdtempSync(join(tmpdir(), "openclaw-docker-e2e-log-zero-heartbeat-"));
|
||||
|
||||
try {
|
||||
const rootDir = process.cwd();
|
||||
const script = `
|
||||
set -euo pipefail
|
||||
ROOT_DIR=${shellQuote(rootDir)}
|
||||
TMPDIR=${shellQuote(workDir)}
|
||||
export ROOT_DIR TMPDIR
|
||||
|
||||
source "$ROOT_DIR/scripts/lib/docker-e2e-logs.sh"
|
||||
|
||||
output="$(run_logged_print_heartbeat plugins-run 08 bash -c 'printf "captured container log\\\\n"; /bin/sleep 9')"
|
||||
[[ "$output" = *"still running plugins-run (8s elapsed,"* ]]
|
||||
[[ "$output" = *"log bytes captured"* ]]
|
||||
[[ "$output" = *"captured container log"* ]]
|
||||
`;
|
||||
|
||||
execFileSync("bash", ["-lc", script], { encoding: "utf8" });
|
||||
} finally {
|
||||
rmSync(workDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
it("includes procps in the shared Docker E2E image for process watchdogs", () => {
|
||||
const dockerfile = readFileSync("scripts/e2e/Dockerfile", "utf8");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user