From 2211752b25b75c52b22d608110a01ec1b403e0f5 Mon Sep 17 00:00:00 2001 From: Marcel Wege Date: Wed, 19 Aug 2026 17:43:20 +0200 Subject: [PATCH] fix(ci): the decoupling ratchet was timing out before it ran MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `core decoupling ratchet (#470)` reported `cancelled` on two PRs in a row, which reads like a transient. It was not. Measured on the job's own step timings: Ensure ripgrep 15:35:47 -> 15:40:54 (5:07) cancelled Check core is ... skipped The job's `timeout-minutes: 5` fired inside the install step, so the step that does the actual checking never executed. On the run that DID pass, the same install took 3:28 — the job routinely had about ninety seconds of headroom. A timed-out job reports as `cancelled` and skips its remaining steps, so a REQUIRED check was silently not running: not red, not passing, just absent. Same failure family as a permanently-green guard-skip. Two changes: - `apt-get update` is the expensive half. It refetches every package index to install one small binary. Try the cached indices first and only refresh when that actually fails; worst case costs a few seconds more than today. `rg` is genuinely required — `check-core-decoupling.mjs` shells out to it via `execFileSync('rg', …)`, so the step cannot simply be dropped. - Timeout 5 -> 10, so a slow mirror cannot take out a required check. The guard is an explicit `if` rather than `cmd && exit 0`: whether `set -e` aborts on the first half of an `&&` list is exactly the kind of shell subtlety that produced a silent CI failure in this repo before. Both branches verified under `bash -e`. --- .github/workflows/ci.yml | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9f29ffeae..2b9221989 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,7 +41,13 @@ jobs: decoupling: name: core decoupling ratchet (#470) runs-on: ubuntu-latest - timeout-minutes: 5 + # Was 5. `Ensure ripgrep` alone took 3:28 on a good run and 5:07 on a bad + # one, so this job routinely had ~90 seconds of headroom and intermittently + # blew the budget. A timed-out job reports as `cancelled`, and its remaining + # steps are `skipped` — so the ratchet was a REQUIRED check that silently + # did not run, which is the same failure family as a permanently-green + # guard-skip: not red, not passing, just absent. + timeout-minutes: 10 steps: - uses: actions/checkout@v7 @@ -50,7 +56,15 @@ jobs: node-version: '22' - name: Ensure ripgrep - run: command -v rg >/dev/null || (sudo apt-get update && sudo apt-get install -y ripgrep) + # `apt-get update` is the expensive half — it refetches every package + # index to install one small binary. Try the cached indices first and + # only refresh when that actually fails. `rg` is genuinely needed: + # `check-core-decoupling.mjs` shells out to it (`execFileSync('rg', …)`). + run: | + if ! command -v rg >/dev/null; then + sudo apt-get install -y ripgrep \ + || (sudo apt-get update && sudo apt-get install -y ripgrep) + fi - name: Check core is not re-coupling to the Dev Platform run: node scripts/check-core-decoupling.mjs