Skip to content

ci: bound the Linux apt install so a stalled mirror fails fast - #1887

Merged
thymikee merged 1 commit into
mainfrom
claude/bound-linux-apt-install
Aug 20, 2026
Merged

ci: bound the Linux apt install so a stalled mirror fails fast#1887
thymikee merged 1 commit into
mainfrom
claude/bound-linux-apt-install

Conversation

@thymikee

Copy link
Copy Markdown
Member

Problem

The Install Linux desktop dependencies step in .github/workflows/linux.yml had no bound of its own, so it could not fail — only stall.

On 2026-08-19, PR #1856 run 32268264207 was cancelled at this step on both attempts (30m24s each). Everything downstream — Setup toolchain, Start Xvfb and D-Bus, Run Linux replay smoke test — reported as skipped. In the same window, three Linux runs on unrelated branches (agent/wave4-get, test/1781-b1-daemon-leak-oracle, claude/1832-c3-residues) were stuck at the identical step and four main-branch runs were cancelled. Environmental, not branch-specific.

The result is a red check on branches that never executed a line of project code, and a 30-minute runner burn per attempt.

Change

Two bounds, 18 lines, package list untouched:

  • timeout-minutes: 6 — a stall now surfaces as a named step failure in six minutes instead of a cancelled job at thirty, leaving the job 24 of its 30 minutes for the smoke test it exists to run. A healthy install takes about a minute.
  • apt optionsAcquire::http[s]::Timeout=15 bounds a mirror that connects and then goes quiet, Acquire::Retries=2 absorbs a transient blip, and DPkg::Lock::Timeout=60 bounds the runner's own unattended-upgrades timer, which stalls identically and is a plausible alternate cause of the same symptom.

Notes on what this deliberately does not do

An earlier draft added a bash retry loop with per-attempt timeout wrappers and an archive.ubuntu.com mirror fallback (~80 lines). Dropped: Acquire::Retries already retries inside apt, the timeout wrappers existed only to make the outer loop work during a stall, and the mirror fallback was ~25 lines of sed across two sources formats to salvage a job that now just fails clearly. It also can't be made unconditional — archive.ubuntu.com is slower from Azure-hosted runners.

Caching the apt packages or baking them into a prebuilt image would remove the network from the hot path entirely, but caching .debs still needs apt-get update for dependency resolution, so only the image approach actually delivers that — and that's a CI-infrastructure change, not a hardening of this step. Worth a separate issue if stalls recur.

Tradeoff: a fast transient failure that apt's own retries miss now fails the job rather than self-healing, traded against carrying a bash retry loop in CI.

Verification

Locally: YAML parses, shellcheck -s bash clean on the extracted script, and the APT_OPTS array verified to expand onto both apt calls with all 10 packages intact.

The 6-minute fast-fail can only be confirmed by a real run, since a stall depends on mirror conditions that aren't reproducible locally. This PR's own Linux job exercises the happy path.

Unbounded, the desktop-dependency install could not fail, only stall. On
2026-08-19 a slow package mirror held apt past the job's 30-minute budget on
four main-branch runs and several unrelated PRs, cancelling each job before
Setup toolchain, Xvfb/D-Bus, or the replay smoke test ran — a red check on
branches that never executed a line of project code.

timeout-minutes: 6 turns that into a named step failure in six minutes
instead of a cancelled job at thirty; a healthy install takes about a minute.
The apt options cover the transient cases without a retry loop layered on top
of them: socket timeouts bound a mirror that connects and then goes quiet,
Acquire::Retries absorbs a blip, and DPkg::Lock::Timeout bounds the runner's
own unattended-upgrades timer, which stalls identically and is a plausible
alternate cause of the same symptom.

Tradeoff: a fast transient failure that apt's own retries miss now fails the
job rather than self-healing, traded against carrying a bash retry loop in CI.
@github-actions

Copy link
Copy Markdown

Size Report

Metric Base Current Diff
JS raw 2.33 MB 2.33 MB -1.3 kB
JS gzip 765.3 kB 765.0 kB -293 B
npm tarball 890.0 kB 888.6 kB -1.4 kB
npm unpacked 3.10 MB 3.10 MB -5.1 kB

Startup median (7 runs, lower is better):

Scenario Base Current Diff
CLI --version 20.7 ms 21.2 ms +0.4 ms
CLI --help 51.4 ms 51.6 ms +0.2 ms

Top changed chunks:

Chunk Raw diff Gzip diff
dist/src/internal/daemon.js +97 B +311 B
dist/src/agent-device-client.js -152 B -77 B
dist/src/registry.js -176 B -66 B
dist/src/cli-help.js -164 B -62 B
dist/src/snapshot.js -21 B -51 B

@thymikee
thymikee merged commit e65443d into main Aug 20, 2026
28 checks passed
@thymikee
thymikee deleted the claude/bound-linux-apt-install branch August 20, 2026 09:01
@github-actions

Copy link
Copy Markdown
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-08-20 09:01 UTC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant