From 921998b9429dbdf5aebe5ffcb1086de8e258758f Mon Sep 17 00:00:00 2001 From: Bill Wallace Date: Wed, 2 Sep 2026 16:56:00 -0400 Subject: [PATCH] ci: bound every pr-checks job with timeout-minutes `build (big-endian)` wedged on PR #70 and sat in_progress for over 80 minutes while its nine sibling matrix legs finished in 58-239s. Nothing bounded it, so it was headed for GitHub's 6-hour default. fail-fast is off for that matrix by design, so one wedged leg keeps the entire run -- and test, dist-size, browser-smoke and codspeed-walltime, which all need it -- pending that whole time. bench.yml also waits on this workflow's dist artifacts, so its runs stall too. A PR looks like it is "just being slow" the entire time. browser-smoke (15) and codspeed-walltime (30) already carried timeouts; this gives the other four the same treatment, sized off a green run on main: job typical limit detect-changes 13s 10m build (slowest) 239s 20m (libjxl; leaves room for a cold image pull) test 53s 15m dist-size 47s 10m Additions only -- no existing line changes. release.yml's build matrix has the same gap and the same 6-hour exposure, but it is left for a follow-up: PR #63 is currently editing that job's `if:` and touching it here would conflict. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/pr-checks.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml index 252326f0..64b63b87 100644 --- a/.github/workflows/pr-checks.yml +++ b/.github/workflows/pr-checks.yml @@ -78,6 +78,11 @@ jobs: # simulation bench in bench.yml computes the same scope from the # PR's changed-file list — keep TOOLCHAIN_PATHS below in sync with # the path lists in bench.yml's gate job. + # + # Bounded like every other job here: without an explicit timeout a job that + # wedges runs to GitHub's 6-hour default. 13s typical, so 10 is ~45x + # headroom — this job's only slow part is the fetch-depth: 0 checkout. + timeout-minutes: 10 runs-on: ubuntu-latest outputs: packages: ${{ steps.list.outputs.packages }} @@ -179,6 +184,16 @@ jobs: fail-fast: false matrix: package: ${{ fromJson(needs.detect-changes.outputs.packages) }} + # The matrix leg that motivated this: `build (big-endian)` wedged on PR #70 + # and sat in_progress for 80+ minutes while its nine siblings finished in + # 58-239s, because nothing bounded it. fail-fast is off (deliberately — one + # package's failure should not hide another's), so a wedged leg keeps the + # whole run, and every job downstream of it, pending until GitHub's 6-hour + # default fires. + # + # 20 is ~5x the slowest observed leg (libjxl, 239s) and leaves room for a + # cold emsdk image pull. + timeout-minutes: 20 runs-on: ubuntu-latest container: image: emscripten/emsdk:3.1.74 @@ -292,6 +307,9 @@ jobs: # missing dist FAILS its suite instead of silently skipping. needs: [detect-changes, build] if: needs.detect-changes.outputs.any == 'true' + # 53s typical. Generous enough for the openjpeg corpus suite on a slow + # runner without letting a hung vitest worker burn six hours. + timeout-minutes: 15 runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -378,6 +396,8 @@ jobs: # a visible, reviewed diff. needs: [detect-changes, build] if: needs.detect-changes.outputs.any == 'true' + # 47s typical: download the dist artifacts, measure, compare. + timeout-minutes: 10 runs-on: ubuntu-latest steps: - uses: actions/checkout@v4