Every job has a timeout, and superseded runs for the same branch are cancelled
A hung job holds a runner until the platform’s default timeout expires, which is six hours on GitHub. Queued runs for commits nobody will merge burn the same minutes.
Observable check
every job sets timeout-minutes (GitHub) or timeout (GitLab), and the configuration sets concurrency with cancel-in-progress: true for change-request runs (GitHub) or marks jobs interruptible: true with auto-cancel enabled (GitLab).
Where this comes from
- https://docs.github.com/en/actions/reference/limits
- https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax
- https://docs.gitlab.com/ci/yaml/
Last read against these sources on 2026-07-28.
Limits confirms the 6-hour job ceiling the rule cites. Workflow syntax confirms concurrency and cancel-in-progress, and jobs.<job_id>.timeout-minutes carries 'Default: 360'. That default matters to the check: 360 is simultaneously GitHub's default and its hosted ceiling, so every job already has an effective timeout and only an explicit key in the file is observable evidence. Step-level timeout-minutes is a separate key with a maximum of 360 and no default; do not conflate them. GitLab's YAML reference confirms the analogues, timeout as 'a custom job-level timeout that takes precedence over the project-wide setting' and interruptible as whether a job 'can be canceled when made redundant by a newer run'; their defaults were not readable in the fetched excerpt.