mirror of
https://github.com/anthropics/claude-code-action.git
synced 2026-11-10 17:10:00 +08:00
The download_job_log MCP tool called client.actions.downloadJobLogsForWorkflowRun() with no timeout and no AbortController. @octokit/rest@21 runs on Node's native fetch, which has no default timeout, and Octokit only cancels a request when the caller passes request.signal. If the log blob fetch stalls, that await never resolves and never rejects. This tool is always enabled in tag mode (src/modes/tag/index.ts), so a "fix the failing CI" run that calls get_ci_status -> get_workflow_run_details -> download_job_log can hang on this one await with nothing to recover it. It's headless, so the run only ends when the Actions job-level timeout-minutes kills it, burning the whole job budget with the tracking comment stuck at "Claude Code is working...". Sibling fetch in src/github/utils/image-downloader.ts (fetchImage) already got this treatment in #1625 via a timeout-driven AbortController. Same shape of call: fetch a GitHub-hosted resource by ID from untrusted PR/CI content. This mirrors that fix for github-actions-server.ts. Extracted the download+write logic into an exported downloadJobLog() function (with an injectable timeoutMs) so the timeout path is directly testable, and guarded the module's entrypoint side effects with import.meta.main, matching the pattern already used by the other entrypoints in src/entrypoints/.