fix(ci): bound apt so a stalled mirror cannot hang the snapshot refresh - #102
Conversation
apt applies no timeout to package acquisition, so a mirror that accepts the connection and then stops responding blocks forever rather than failing. Run 32269308335 printed "Installing dependencies..." then the first mirror Get line and then nothing for twenty minutes; the same signature stalled an unrelated apt-get in another repo's validate workflow. playwright install --with-deps owns that apt call, so the bound goes into /etc/apt/apt.conf.d where the child process picks it up. A bounded retry around the step catches whatever survives that, and the step no longer discards its output — the silent stall is what made this take three runs to diagnose. Closes #99 Assisted-by: claude-code:claude-opus-5 Agent-Session: https://claude.ai/code/session_01GSptxPLHWsttu9FuqVkvYZ Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
|
|
Verification dispatch on this branch: 32289956430, job green end to end, The interesting part is that this run hit the stall and recovered from it, so it is evidence rather than a lucky pass: The mirror fetch is issued, goes quiet for nearly two minutes, and is issued again — that second The install step took 4m15s against a 73–80 second baseline, so the stall cost real time — and then finished. Zero To be precise about what this shows: one run that stalled and recovered demonstrates the bound works under the failure condition. It does not prove every future stall stays under 300s — that is what the retry and the job timeout are for. Assisted by claude-code:claude-opus-5 — Session |



Closes #99, this time with the cause rather than a bound on the symptom.
The cause
apt-get. Log of the hung run 32269308335, last two lines before twenty minutes of silence:playwright install --with-depsshells out toapt-get updatefor the browser system libraries, and it stalled on the first mirror fetch. The identical signature stalled a completely unrelated step in another repository the same afternoon —sudo apt-get update -qq … && sudo apt-get install -y -qq shellcheckin the sharedvalidateworkflow, 37 minutes, different repo, different tool.apt applies no timeout to package acquisition by default, so a mirror that accepts the connection and then stops responding blocks forever instead of failing. That is also the only hypothesis that explains the intermittency: the same command finished in 73 seconds on one run and never on the next, which is mirror state rather than invocation shape.
Three earlier hypotheses are retired by this:
npxresolution, Playwright flakiness, and the missingharden-runnerstep. None of them touch apt, and the second hang happened in a job that hasharden-runner.The fix
/etc/apt/apt.conf.d/99-ci-timeoutssetsAcquire::Retriesand per-scheme timeouts. Playwright owns theapt-getinvocation, so bounding apt through its own configuration is what reaches the child process — passing flags is not an option here.A
timeout 300plus three attempts wraps the step for whatever survives that, and the step no longer discards its output. Worst case is 15 minutes, inside the job's 20-minute bound from #101. A retry emits::warning::so the flake stays visible instead of being silently absorbed.What this does not claim
An intermittent fault cannot be proven gone by one green run. What is verifiable here is that the failure mode is now bounded at every level — apt fails instead of hanging, the step ends instead of the job, the job ends instead of the runner — and that the diagnosis rests on log evidence from two independent hangs rather than on elimination.
Assisted by claude-code:claude-opus-5 — Session