Repository navigation
ci: retry transient dependency installs + skip native rebuild in typecheck - #49286
Conversation
`npm ci` / `uv sync` / toolchain header fetches occasionally die on transient network blips — e.g. node-pty's node-gyp fetching Node headers (an undici assert) during the typecheck job's `npm ci`, which killed the job before `tsc` ever ran. "Re-run and it goes green" is exactly what CI should do itself. - New reusable `.github/actions/retry` composite action wraps a command and retries on failure (3x / 10s, command passed via env so it can't inject). Applied to every PR-path network install: npm ci (typecheck, desktop build, docs site), uv sync (tests, e2e), uv tool install (lint), pip install (docs site). - typecheck now runs `npm ci --ignore-scripts`: `tsc` needs only sources + type defs, so skipping install scripts drops node-pty's native rebuild (whose header fetch was the flake) and is faster. Validated locally — tsc passes for ui-tui, apps/shared, and apps/desktop with scripts skipped. - ripgrep download uses `curl --retry`. Docker (main-only) and the release/windows workflows are intentionally left for a follow-up.
|
Related: #49227 (closed) — this PR supersedes that earlier "skip native rebuild in typecheck" attempt and broadens it into a reusable |
teknium1
left a comment
There was a problem hiding this comment.
Clean, well-scoped CI hardening. Approving.
Security: the composite action passes the command through env._CMD and runs bash -c "$_CMD" rather than interpolating it into the script body, so a command with quotes/specials can't break or inject into the runner. Correct pattern.
set -uo pipefail without -e is right here — the loop captures the command's exit code manually via the if bash -c, and -e would abort the retry on the first failed attempt.
--ignore-scripts on typecheck: sound. tsc only needs TS sources + type defs, so dropping the node-pty node-gyp rebuild removes the actual flake source rather than just papering over it with retry — and it's faster. Keeping scripts on desktop-build (its production build may need the native binary) + relying on retry there is the right split.
Two notes, neither blocking:
- Stacked on #49272 (base =
bb/ci-affected-only) — merge that first, then this auto-retargets tomain. - Because #49272 makes CI affected-only and this PR only touches
.github/workflow files, the touched lanes (typecheck/lint/tests) didn't actually run here — only the four always-on guard jobs are green. Thenpm ci --ignore-scripts+tscpath was validated locally per the PR body; first real CI exercise lands on the next frontend/python PR after merge.
LGTM.
Problem
The most common "red, re-run, green" CI failures here aren't test bugs — they're transient network/toolchain flakes during dependency install. The reported case: the
typecheck (ui-tui)job died innpm ciwhilenode-gyprebuiltnode-pty's native binary and choked fetching Node headers (anundici assert(!this.paused)). It never reachedtsc.Fix
1. Auto-retry every PR-path network install — a reusable
.github/actions/retrycomposite action wraps a command and retries on non-zero exit (3× / 10s). The command is passed via env (never interpolated into the script body) so it can't break or inject. Applied to:npm ciuv syncuv tool install ruff/typip installripgrepdownload switched tocurl --retry 3 --retry-delay 5(curl-native retry).2. Root-cause the typecheck flake — typecheck now runs
npm ci --ignore-scripts.tsconly needs TS sources + type defs, not compiled native binaries, so skipping install scripts removes the node-pty rebuild entirely (eliminating the header-fetch flake) and is faster.desktop-buildkeeps scripts (its production build may need the native binary) and relies on retry.Validation
npm ci --ignore-scripts+tscpasses for ui-tui, apps/shared, apps/desktop (~17s, no native build).Out of scope (deliberate)
docker-publish(uv pip install) is main-only after ci: run only the lanes a PR affects + build Docker on main only #49272, lower flake exposure — follow-up.build-windows-installer/upload_to_pypi/deploy-sitenpm ci— release/dispatch flows, low frequency — follow-up.