From c38b5033e64b71c141a2926f50b77f020b4cdcf0 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Tue, 26 May 2026 15:40:44 +0200 Subject: [PATCH] fix(ci): kill timed workflow process groups --- .github/workflows/full-release-validation.yml | 2 +- .../openclaw-live-and-e2e-checks-reusable.yml | 30 +++++++++---------- scripts/ci-docker-pull-retry.sh | 2 +- scripts/docker/install-sh-smoke/run.sh | 6 ++-- .../package-acceptance-workflow.test.ts | 16 +++++----- test/scripts/test-install-sh-docker.test.ts | 2 +- 6 files changed, 29 insertions(+), 29 deletions(-) diff --git a/.github/workflows/full-release-validation.yml b/.github/workflows/full-release-validation.yml index 74b52293344..085948641b1 100644 --- a/.github/workflows/full-release-validation.yml +++ b/.github/workflows/full-release-validation.yml @@ -245,7 +245,7 @@ jobs: DOCKER_BUILDKIT: "1" run: | set -euo pipefail - timeout --foreground --kill-after=30s 35m docker build \ + timeout --kill-after=30s 35m docker build \ --target runtime-assets \ --build-arg OPENCLAW_EXTENSIONS="diagnostics-otel,codex" \ . diff --git a/.github/workflows/openclaw-live-and-e2e-checks-reusable.yml b/.github/workflows/openclaw-live-and-e2e-checks-reusable.yml index ed7d91f5727..ab9a425f9a7 100644 --- a/.github/workflows/openclaw-live-and-e2e-checks-reusable.yml +++ b/.github/workflows/openclaw-live-and-e2e-checks-reusable.yml @@ -521,7 +521,7 @@ jobs: set -euo pipefail for attempt in 1 2; do echo "live-cache attempt ${attempt}/2" - if timeout --foreground --kill-after=30s 8m pnpm test:live:cache; then + if timeout --kill-after=30s 8m pnpm test:live:cache; then exit 0 fi if [[ "$attempt" == "2" ]]; then @@ -1434,7 +1434,7 @@ jobs: fi echo "Validating Docker E2E package tarball: $target" started_at="$(date +%s)" - timeout --foreground 5m node scripts/check-openclaw-package-tarball.mjs "$target" + timeout --kill-after=30s 5m node scripts/check-openclaw-package-tarball.mjs "$target" finished_at="$(date +%s)" echo "Docker E2E package tarball validation finished in $((finished_at - started_at))s." digest="$(sha256sum "$target" | awk '{print $1}')" @@ -1778,7 +1778,7 @@ jobs: - name: Run Docker live model sweep if: contains(matrix.profiles, inputs.release_test_profile) - run: OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --foreground --kill-after=30s 35m bash .release-harness/scripts/test-live-models-docker.sh + run: OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --kill-after=30s 35m bash .release-harness/scripts/test-live-models-docker.sh validate_live_models_docker_targeted: name: Docker live models (selected providers) @@ -1953,7 +1953,7 @@ jobs: done - name: Run Docker live model sweep - run: OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --foreground --kill-after=30s 35m bash .release-harness/scripts/test-live-models-docker.sh + run: OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --kill-after=30s 35m bash .release-harness/scripts/test-live-models-docker.sh validate_live_provider_suites: needs: validate_selected_ref @@ -2289,32 +2289,32 @@ jobs: include: - suite_id: live-gateway-docker label: Docker live gateway OpenAI - command: OPENCLAW_LIVE_GATEWAY_THINKING=low OPENCLAW_LIVE_GATEWAY_PROVIDERS=openai OPENCLAW_LIVE_GATEWAY_MODELS=openai/gpt-5.5 OPENCLAW_LIVE_GATEWAY_MAX_MODELS=1 OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=90000 OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=600000 OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --foreground --kill-after=30s 35m bash .release-harness/scripts/test-live-gateway-models-docker.sh + command: OPENCLAW_LIVE_GATEWAY_THINKING=low OPENCLAW_LIVE_GATEWAY_PROVIDERS=openai OPENCLAW_LIVE_GATEWAY_MODELS=openai/gpt-5.5 OPENCLAW_LIVE_GATEWAY_MAX_MODELS=1 OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=90000 OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=600000 OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --kill-after=30s 35m bash .release-harness/scripts/test-live-gateway-models-docker.sh timeout_minutes: 40 profile_env_only: false profiles: beta minimum stable full - suite_id: live-gateway-anthropic-docker label: Docker live gateway Anthropic - command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=anthropic OPENCLAW_LIVE_GATEWAY_MAX_MODELS=2 OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=90000 OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=180000 OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --foreground --kill-after=30s 35m bash .release-harness/scripts/test-live-gateway-models-docker.sh + command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=anthropic OPENCLAW_LIVE_GATEWAY_MAX_MODELS=2 OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=90000 OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=180000 OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --kill-after=30s 35m bash .release-harness/scripts/test-live-gateway-models-docker.sh timeout_minutes: 40 profile_env_only: false profiles: stable full - suite_id: live-gateway-google-docker label: Docker live gateway Google - command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=google OPENCLAW_LIVE_GATEWAY_MODELS=google/gemini-3.1-pro-preview,google/gemini-3-flash-preview OPENCLAW_LIVE_GATEWAY_MAX_MODELS=2 OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=90000 OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=180000 OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --foreground --kill-after=30s 35m bash .release-harness/scripts/test-live-gateway-models-docker.sh + command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=google OPENCLAW_LIVE_GATEWAY_MODELS=google/gemini-3.1-pro-preview,google/gemini-3-flash-preview OPENCLAW_LIVE_GATEWAY_MAX_MODELS=2 OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=90000 OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=180000 OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --kill-after=30s 35m bash .release-harness/scripts/test-live-gateway-models-docker.sh timeout_minutes: 40 profile_env_only: false profiles: stable full - suite_id: live-gateway-minimax-docker label: Docker live gateway MiniMax - command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=minimax,minimax-portal OPENCLAW_LIVE_GATEWAY_MAX_MODELS=1 OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=90000 OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=180000 OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --foreground --kill-after=30s 35m bash .release-harness/scripts/test-live-gateway-models-docker.sh + command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=minimax,minimax-portal OPENCLAW_LIVE_GATEWAY_MAX_MODELS=1 OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=90000 OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=180000 OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --kill-after=30s 35m bash .release-harness/scripts/test-live-gateway-models-docker.sh timeout_minutes: 40 profile_env_only: false profiles: stable full - suite_id: live-gateway-advisory-docker-deepseek-fireworks suite_group: live-gateway-advisory-docker label: Docker live gateway advisory DeepSeek/Fireworks - command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=deepseek,fireworks OPENCLAW_LIVE_GATEWAY_MAX_MODELS=2 OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=90000 OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=180000 OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --foreground --kill-after=30s 35m bash .release-harness/scripts/test-live-gateway-models-docker.sh + command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=deepseek,fireworks OPENCLAW_LIVE_GATEWAY_MAX_MODELS=2 OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=90000 OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=180000 OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --kill-after=30s 35m bash .release-harness/scripts/test-live-gateway-models-docker.sh timeout_minutes: 40 profile_env_only: false advisory: true @@ -2322,7 +2322,7 @@ jobs: - suite_id: live-gateway-advisory-docker-opencode-openrouter suite_group: live-gateway-advisory-docker label: Docker live gateway advisory OpenCode/OpenRouter - command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=opencode-go,openrouter OPENCLAW_LIVE_GATEWAY_MAX_MODELS=2 OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=90000 OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=180000 OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --foreground --kill-after=30s 35m bash .release-harness/scripts/test-live-gateway-models-docker.sh + command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=opencode-go,openrouter OPENCLAW_LIVE_GATEWAY_MAX_MODELS=2 OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=90000 OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=180000 OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --kill-after=30s 35m bash .release-harness/scripts/test-live-gateway-models-docker.sh timeout_minutes: 40 profile_env_only: false advisory: true @@ -2330,32 +2330,32 @@ jobs: - suite_id: live-gateway-advisory-docker-xai-zai suite_group: live-gateway-advisory-docker label: Docker live gateway advisory xAI/Z.ai - command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=xai,zai OPENCLAW_LIVE_GATEWAY_MAX_MODELS=2 OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=90000 OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=180000 OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --foreground --kill-after=30s 35m bash .release-harness/scripts/test-live-gateway-models-docker.sh + command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=xai,zai OPENCLAW_LIVE_GATEWAY_MAX_MODELS=2 OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=90000 OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=180000 OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --kill-after=30s 35m bash .release-harness/scripts/test-live-gateway-models-docker.sh timeout_minutes: 40 profile_env_only: false advisory: true profiles: full - suite_id: live-cli-backend-docker label: Docker live CLI backend - command: OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --foreground --kill-after=30s 45m bash .release-harness/scripts/test-live-cli-backend-docker.sh + command: OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --kill-after=30s 45m bash .release-harness/scripts/test-live-cli-backend-docker.sh timeout_minutes: 50 profile_env_only: false profiles: stable full - suite_id: live-acp-bind-docker label: Docker live ACP bind - command: OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --foreground --kill-after=30s 45m bash .release-harness/scripts/test-live-acp-bind-docker.sh + command: OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --kill-after=30s 45m bash .release-harness/scripts/test-live-acp-bind-docker.sh timeout_minutes: 50 profile_env_only: false profiles: stable full - suite_id: live-codex-harness-docker label: Docker live Codex harness - command: OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --foreground --kill-after=30s 35m bash .release-harness/scripts/test-live-codex-harness-docker.sh + command: OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --kill-after=30s 35m bash .release-harness/scripts/test-live-codex-harness-docker.sh timeout_minutes: 40 profile_env_only: false profiles: stable full - suite_id: live-subagent-announce-docker label: Docker live subagent announce - command: OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --foreground --kill-after=30s 20m bash .release-harness/scripts/test-live-subagent-announce-docker.sh + command: OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --kill-after=30s 20m bash .release-harness/scripts/test-live-subagent-announce-docker.sh timeout_minutes: 25 profile_env_only: false profiles: stable full diff --git a/scripts/ci-docker-pull-retry.sh b/scripts/ci-docker-pull-retry.sh index c699f1f569c..65d23435e42 100644 --- a/scripts/ci-docker-pull-retry.sh +++ b/scripts/ci-docker-pull-retry.sh @@ -29,7 +29,7 @@ fi last_status=1 for attempt in $(seq 1 "$attempts"); do echo "==> Pull Docker image attempt ${attempt}/${attempts}: ${image}" - if timeout --foreground --kill-after=30s "${timeout_seconds}s" docker pull "$image"; then + if timeout --kill-after=30s "${timeout_seconds}s" docker pull "$image"; then exit 0 fi last_status="$?" diff --git a/scripts/docker/install-sh-smoke/run.sh b/scripts/docker/install-sh-smoke/run.sh index ab8f4a2fbe0..1611df66044 100755 --- a/scripts/docker/install-sh-smoke/run.sh +++ b/scripts/docker/install-sh-smoke/run.sh @@ -194,7 +194,7 @@ npm_install_global() { local label="$1" shift run_with_heartbeat "$label" \ - timeout --foreground "${INSTALL_COMMAND_TIMEOUT}s" \ + timeout --kill-after=30s "${INSTALL_COMMAND_TIMEOUT}s" \ npm \ --loglevel=error \ --logs-max=0 \ @@ -223,7 +223,7 @@ run_installer_for_package_spec() { local install_url="$1" local package_spec="$2" - timeout --foreground "${INSTALL_COMMAND_TIMEOUT}s" \ + timeout --kill-after=30s "${INSTALL_COMMAND_TIMEOUT}s" \ bash -c "curl -fsSL \"\$1\" | bash -s -- --install-method npm --version \"\$2\" --no-prompt --no-onboard" \ _ "$install_url" "$package_spec" } @@ -520,7 +520,7 @@ run_freshness_smoke() { echo "==> Verify user npm freshness policy blocks plain npm install" set +e HOME="$policy_home" NPM_CONFIG_USERCONFIG="${policy_home}/.npmrc" \ - timeout --foreground "${INSTALL_COMMAND_TIMEOUT}s" \ + timeout --kill-after=30s "${INSTALL_COMMAND_TIMEOUT}s" \ npm \ --loglevel=error \ --logs-max=0 \ diff --git a/test/scripts/package-acceptance-workflow.test.ts b/test/scripts/package-acceptance-workflow.test.ts index 4fe75341780..d9f739fd946 100644 --- a/test/scripts/package-acceptance-workflow.test.ts +++ b/test/scripts/package-acceptance-workflow.test.ts @@ -421,7 +421,7 @@ describe("package artifact reuse", () => { 'retry_delay_seconds="${OPENCLAW_DOCKER_PULL_RETRY_DELAY_SECONDS:-5}"', ); expect(pullHelper).toContain( - 'timeout --foreground --kill-after=30s "${timeout_seconds}s" docker pull "$image"', + 'timeout --kill-after=30s "${timeout_seconds}s" docker pull "$image"', ); }); @@ -539,7 +539,7 @@ describe("package artifact reuse", () => { expect(workflow).toContain( "OPENCLAW_LIVE_GATEWAY_THINKING=low OPENCLAW_LIVE_GATEWAY_PROVIDERS=openai OPENCLAW_LIVE_GATEWAY_MODELS=openai/gpt-5.5 OPENCLAW_LIVE_GATEWAY_MAX_MODELS=1 OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=90000 OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=600000", ); - expect(workflow).toContain("timeout --foreground --kill-after=30s 35m"); + expect(workflow).toContain("timeout --kill-after=30s 35m"); expect(workflow).toMatch(/suite_id: live-gateway-docker[\s\S]*?timeout_minutes: 40/u); expect(workflow).toContain("suite_id: native-live-extensions-a-k"); expect(workflow).toContain("suite_id: native-live-extensions-l-n"); @@ -609,22 +609,22 @@ describe("package artifact reuse", () => { const stage = readFileSync("scripts/lib/live-docker-stage.sh", "utf8"); expect(workflow).toContain( - 'run: OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --foreground --kill-after=30s 35m bash .release-harness/scripts/test-live-models-docker.sh', + 'run: OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --kill-after=30s 35m bash .release-harness/scripts/test-live-models-docker.sh', ); expect(workflow).toContain( "command: OPENCLAW_LIVE_GATEWAY_THINKING=low OPENCLAW_LIVE_GATEWAY_PROVIDERS=openai OPENCLAW_LIVE_GATEWAY_MODELS=openai/gpt-5.5 OPENCLAW_LIVE_GATEWAY_MAX_MODELS=1", ); expect(workflow).toContain( - 'command: OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --foreground --kill-after=30s 45m bash .release-harness/scripts/test-live-cli-backend-docker.sh', + 'command: OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --kill-after=30s 45m bash .release-harness/scripts/test-live-cli-backend-docker.sh', ); expect(workflow).toContain( - 'command: OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --foreground --kill-after=30s 45m bash .release-harness/scripts/test-live-acp-bind-docker.sh', + 'command: OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --kill-after=30s 45m bash .release-harness/scripts/test-live-acp-bind-docker.sh', ); expect(workflow).toContain( - 'command: OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --foreground --kill-after=30s 35m bash .release-harness/scripts/test-live-codex-harness-docker.sh', + 'command: OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --kill-after=30s 35m bash .release-harness/scripts/test-live-codex-harness-docker.sh', ); expect(workflow).toContain( - 'command: OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --foreground --kill-after=30s 20m bash .release-harness/scripts/test-live-subagent-announce-docker.sh', + 'command: OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --kill-after=30s 20m bash .release-harness/scripts/test-live-subagent-announce-docker.sh', ); expect(scenarios).toContain("function liveDockerScriptCommand"); expect(scenarios).toContain( @@ -1287,7 +1287,7 @@ describe("package artifact reuse", () => { expect(crossOs.jobs?.cross_os_release_checks?.["timeout-minutes"]).toBe(60); expect(liveE2e.jobs?.validate_release_live_cache?.["timeout-minutes"]).toBe(20); expect(readFileSync(LIVE_E2E_WORKFLOW, "utf8")).toContain( - "timeout --foreground --kill-after=30s 8m pnpm test:live:cache", + "timeout --kill-after=30s 8m pnpm test:live:cache", ); expect(readFileSync(LIVE_E2E_WORKFLOW, "utf8")).toContain("live-cache attempt ${attempt}/2"); }); diff --git a/test/scripts/test-install-sh-docker.test.ts b/test/scripts/test-install-sh-docker.test.ts index 0799842e8e0..4a73263dd76 100644 --- a/test/scripts/test-install-sh-docker.test.ts +++ b/test/scripts/test-install-sh-docker.test.ts @@ -245,7 +245,7 @@ describe("install-sh smoke runner", () => { ); expect(script).toContain("run_with_heartbeat"); expect(script).toContain("npm_install_global"); - expect(script).toContain('timeout --foreground "${INSTALL_COMMAND_TIMEOUT}s"'); + expect(script).toContain('timeout --kill-after=30s "${INSTALL_COMMAND_TIMEOUT}s"'); expect(script).toContain("==> Still running"); expect(script).toContain("print_install_audit"); expect(script).toContain('install -g "$@"');