Skip to content

fix: add timeout-minutes to remaining workflows - #166

Merged
steipete merged 1 commit into
openclaw:mainfrom
SebTardif:fix/workflow-timeouts
Sep 5, 2026
Merged

fix: add timeout-minutes to remaining workflows#166
steipete merged 1 commit into
openclaw:mainfrom
SebTardif:fix/workflow-timeouts

Conversation

@SebTardif

Copy link
Copy Markdown
Contributor

What Problem This Solves

Fixes an issue where four docs workflows could occupy a GitHub-hosted runner until the six-hour default if a step hung. update-skills, Translate Incremental, Stale, and CodeQL had no timeout-minutes. Sibling workflows (r2-pages, pages, docs-code-ci, llms-full, translate-locale) already set one.

Why This Change Was Made

Each local job in those four files now sets timeout-minutes. Short jobs use 15. CodeQL uses 30, matching Docs Code CI. Incremental prepare uses 70 so the default 3600-second debounce can finish. GitHub does not allow timeout-minutes on a job that only uses: a reusable workflow, so incremental validate-workflow-shell and finalize are bounded in the callee files (15 and 60). The locale worker already had 360.

User Impact

A hung skills update, incremental debounce, stale scan, or CodeQL run now fails on a job budget instead of holding a runner for up to six hours. Healthy runs are unchanged. Incremental translation still waits up to one hour for main to settle.

Evidence

Live node reading the four workflow files (plus the two incremental callees). The reader walks jobs: and reports each job's timeout-minutes. It was first run against origin/main copies written to a temp dir (production files left in place), then against the patched files.

Before, every job in the four files reports timeout: null:

$ node C:\Users\sebta\AppData\Local\Temp\docs-f004-live-read.mjs C:\Users\sebta\AppData\Local\Temp\docs-f004-main-wf\update-skills.yml C:\Users\sebta\AppData\Local\Temp\docs-f004-main-wf\translate-incremental.yml C:\Users\sebta\AppData\Local\Temp\docs-f004-main-wf\stale.yml C:\Users\sebta\AppData\Local\Temp\docs-f004-main-wf\codeql.yml
[
  { "workflow": "update-skills.yml", "jobs": [ { "name": "update", "timeout": null } ], "hasTimeoutString": false },
  { "workflow": "translate-incremental.yml", "jobs": [
      { "name": "validate-workflow-shell", "timeout": null },
      { "name": "prepare", "timeout": null },
      { "name": "plan", "timeout": null },
      { "name": "translate", "timeout": null },
      { "name": "provider-preflight", "timeout": null },
      { "name": "finalize", "timeout": null }
    ], "hasTimeoutString": false },
  { "workflow": "stale.yml", "jobs": [ { "name": "stale", "timeout": null } ], "hasTimeoutString": false },
  { "workflow": "codeql.yml", "jobs": [ { "name": "analyze", "timeout": null } ], "hasTimeoutString": false }
]

After the patch, local jobs report a positive timeout. Reusable-call jobs stay unset on the caller (GitHub restriction). Their callees now report 15 and 60:

$ node C:\Users\sebta\AppData\Local\Temp\docs-f004-live-read.mjs .github/workflows/update-skills.yml .github/workflows/translate-incremental.yml .github/workflows/stale.yml .github/workflows/codeql.yml .github/workflows/translate-shell-check-reusable.yml .github/workflows/translate-finalize-reusable.yml
[
  { "workflow": "update-skills.yml", "jobs": [ { "name": "update", "timeout": 15 } ] },
  { "workflow": "translate-incremental.yml", "jobs": [
      { "name": "validate-workflow-shell", "timeout": null },
      { "name": "prepare", "timeout": 70 },
      { "name": "plan", "timeout": 15 },
      { "name": "translate", "timeout": null },
      { "name": "provider-preflight", "timeout": 15 },
      { "name": "finalize", "timeout": null }
    ] },
  { "workflow": "stale.yml", "jobs": [ { "name": "stale", "timeout": 15 } ] },
  { "workflow": "codeql.yml", "jobs": [ { "name": "analyze", "timeout": 30 } ] },
  { "workflow": "translate-shell-check-reusable.yml", "jobs": [ { "name": "check", "timeout": 15 } ] },
  { "workflow": "translate-finalize-reusable.yml", "jobs": [ { "name": "finalize", "timeout": 60 } ] }
]

rg -L timeout-minutes .github/workflows/ now lists only docs-live-smoke.yml (sibling #164). The four files from this finding are no longer in that list. r2-upload.mjs and docs-live-smoke.yml are not in this diff.

Related: #164, #69, #70, #61.

Real behavior proof

  • Behavior or issue addressed: Four docs workflows had no job timeout, so a hang could occupy a runner until GitHub's six-hour default.
  • Real environment tested: Windows 11, Node v24.19.0, repo checkout at C:\Users\sebta.grok\tmp\pr-gate-batch\docs-f004 on branch fix/workflow-timeouts. origin/main copies were written to a temp dir; production files were left in place.
  • Exact steps or command run after this patch: node C:\Users\sebta\AppData\Local\Temp\docs-f004-live-read.mjs on the origin/main copies, then the same reader on the patched workflow files.
  • Evidence after fix: terminal output above. update=15, prepare=70, plan=15, provider-preflight=15, stale=15, analyze=30. Incremental shell-check callee=15, finalize callee=60. Caller jobs that only uses: a reusable workflow stay unset.
  • Observed result after fix: A hung update-skills, incremental prepare, stale, or CodeQL job is now killed by timeout-minutes instead of the six-hour default. Incremental debounce still has 70 minutes so the default 3600-second wait can finish.
  • What was not tested: A live scheduled run of update-skills, Stale, CodeQL, or Translate Incremental. This change only adds job budgets; it does not change what those workflows do when they complete.

Summary

Audit finding F004. Sibling hang bounds are #161, #163, #164, and #165.

Jobs in update-skills, translate-incremental, stale, and codeql had
no timeout-minutes, so a hang could occupy a runner until GitHub's
six-hour default. Short jobs use 15. CodeQL uses 30.

prepare uses 70 so the default 3600s debounce can finish. GitHub
rejects timeout-minutes on reusable-call jobs, so incremental
shell-check and finalize are bounded in the callee (15 and 60).

Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
@SebTardif
SebTardif requested a review from a team as a code owner September 5, 2026 11:04
@steipete

steipete commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Verified head ed6a045f6ebe786f61f8d2dc04c69fa2a178b64c.

actionlint passed for all six changed workflow files. All three node --test scripts/docs-site/workflow-timeouts.test.mjs regressions passed; the same tests fail against the main-branch workflow files. workflow_shell_check.py --check-bash and budget_check.py also passed.

The 70-minute preparation budget accommodates the existing one-hour debounce. Reusable workflow limits are on the callee jobs, avoiding GitHub's prohibition on job timeouts at reusable call sites. Branch autoreview against origin/main, through P2, returned scoped-clean.

All exact-head CI workflows succeeded after approval:

Ready for the orchestrator's squash merge. The shared changelog update will be in #167.

@steipete
steipete merged commit 7440c95 into openclaw:main Sep 5, 2026
6 checks passed
steipete pushed a commit that referenced this pull request Sep 5, 2026
Apply configurable request deadlines to hostname cutover API calls and reject malformed or overflowing budgets before requests begin.

Document both request-timeout controls and consolidate the prepared dependency and publishing changelog entries. Land after PRs #132, #152, #161, #163, #164, #165, and #166.

Co-authored-by: Sebastien Tardif <SebTardif@ncf.ca>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants