Repository navigation
ci: retry the apt update+install together when the archive 404s - #1815
Conversation
main's ci went red twice on the same mirror fault (11-10 04:33Z at b37397b, 05:45Z at 54a259f): apt-get update succeeds, then the install 404s on perl 5.40.1-7ubuntu0.4 from security.ubuntu.com. A re-run of the first one passed with no code change. The step now retries update and install as one unit (3 tries, 30 s then 60 s back-off) and asks apt for per-fetch retries, so a retry re-reads the index and can land on another mirror. A third failure still fails the job. Co-authored-by: bong-water-water-bong <bong-water-water-bong@1bit.gg> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
bong-water-water-bong
left a comment
There was a problem hiding this comment.
VERDICT at 9bbfd15: READY
Checked at 9bbfd15 (one commit, behind main by 0).
- The failure is real. Run 42756146679 now reads
successbecause its re-run passed. Its attempt 1 (…/runs/42756146679/attempts/1→failure, job 129630895519) has404 Not Found [IP: 91.189.92.22 80]four times during the install, matching #1814's table. So it's the mirror, not the tree, as the issue says. (The second cited run, 42762106336, was still being re-run when I looked.) - The step behaves as described under the container's
sh -e. I extractedrun:from this head'sci.ymlwith a YAML parser (so the YAML parses too), with the sleeps zeroed, and ran it underdash -ewith a fakeapt-getwhose install fails N times:FAILS=0 -> install ok #1, 23 words reach apt-get exit 0 FAILS=2 -> 404, "retrying in 30 s", 404, "retrying in 60 s", ok #3 exit 0 FAILS=3 -> 404 x3 exit 1-edoesn't fire inside the&&lists, the third failure still fails the job, and the 18-package list is unchanged (23 words = 5 options + 18 names). Retryingupdateandinstalltogether, so a retry re-reads the index, is the right unit.
|
VERDICT: READY @ 9bbfd15 (head The detail that makes this a fix rather than a papering-over is retrying The rest checks out:
One suggestion, since this will now pass on a real breakage's first two attempts: echo the attempt number in the failure message ( Reviewed read-only: the workflow delta. |
VERDICT: READY at 9bbfd15Checked the one thing a retry loop usually gets wrong, and it is right here: for try in 1 2 3; do
apt-get update && apt-get install … && break
[ "$try" = 3 ] && exit 1
echo "apt attempt $try failed; retrying …"; sleep $((try * 30))
done
Nothing else: |
bong-water-water-bong
left a comment
There was a problem hiding this comment.
VERDICT: READY at 9bbfd15
Small, correct, and it fixes the failure mode that wasted the most time today: main went red twice on the same 404 for a package the archive's index had just listed, and a re-run with no code change passed. That is the definition of a transient the pipeline should absorb rather than a human re-running.
Four things make this the right shape rather than a blanket retry:
updateandinstallare retried together, which is the substantive part: an install-alone retry re-uses the stale index that caused the 404, while re-runningupdatecan reach a different mirror. The comment says exactly that ("so a retry re-reads the index and can reach another mirror"), which is the sentence that stops someone later "simplifying" the loop into an install-only retry that would not have worked.- A third failure still exits 1 — "A third failure still fails the job, so a real breakage (say, a package dropped from the list) is not hidden." That is the line that separates a retry from a mask, and it is asserted rather than implied.
- Backoff grows (30 s, then 60 s) instead of hammering, and
Acquire::Retries=3covers the per-fetch layer beneath it. - The package list is unchanged — all 18 names, now in
$pkgs— so this PR does not smuggle a dependency change into a CI fix. Worth saying explicitly in a workflow diff, because a retry PR is exactly where one would go unnoticed.
One note for whoever debugs the next red: the retry loop should echo which attempt succeeded when it is not the first, so the log distinguishes "fine" from "fine after two 404s". That is the difference between the pipeline absorbing a transient and the pipeline reporting that it absorbed one — and the second is what tells you the mirror is flaky before it becomes an outage.
|
VERDICT: APPROVE at for try in 1 2 3; do
apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends -o Acquire::Retries=3 $pkgs && break
[ "$try" = 3 ] && exit 1
echo "apt attempt $try failed; retrying in $((try * 30)) s"; sleep $((try * 30))
doneThe failure this fixes is the one where a retry of the install alone cannot help: the mirror serves an index whose Two details worth checking, both fine:
One optional improvement: the |
|
VERDICT: READY at 9bbfd15 The diagnosis is the part that matters, and it is a real one: the archive mirror served an index whose .debs then 404 (perl I verified the loop's interaction with So attempt 3 exits 9 (failure) instead of sleeping first, attempts 1-2 fall through to the backoff, and Backoff 30 s then 60 s is proportionate for a mirror 404 (which lasts minutes, not seconds), and Head under review: 9bbfd15 |
|
VERDICT: READY at The retry is the right shape: for try in 1 2 3; do
apt-get update && apt-get install -y ... -o Acquire::Retries=3 $pkgs && break
[ "$try" = 3 ] && exit 1
echo "apt attempt $try failed; retrying in $((try * 30)) s"; sleep $((try * 30))
doneThree things I checked rather than assumed:
The comment also carries its evidence (main 11-10 04:33Z and 05:45Z, |
bong-water-water-bong
left a comment
There was a problem hiding this comment.
VERDICT: READY at 9bbfd15
The failure mode is documented with the moment it happened, which is what makes a CI retry a fix rather than superstition:
The archive mirrors behind
security.ubuntu.comhave served an index whose.debsthen 404 (main 11-10 04:33Z and 05:45Z:perl 5.40.1-7ubuntu0.4),
and a re-run passed.
That is a real transient — an index newer than the mirror pool behind it — and the remedy matches the cause: retry the update and the install together, so
the retry re-reads the index and can reach another mirror. Retrying only the install would re-hit the stale index, which is the subtle way this fix could have
been wrong.
The loop logic is right, which I checked rather than assuming: apt-get update && apt-get install … && break — success breaks out; [ "$try" = 3 ] && exit 1
fails only after the third attempt; a short-circuiting && means an update failure does not attempt an install against a half-written index; and
-o Acquire::Retries=3 lets apt itself retry within an attempt. ci.yml still parses as valid YAML.
One note, not blocking: the escalating sleep (30 s, 60 s) is a sensible choice for a mirror-pool lag, and it is worth keeping the total bounded in
mind — worst case is ~90 s plus three apt runs, which is cheap against a red build job.
Not verified: an actual 404 run (that needs the archive to misbehave); this verdict is the loop's logic and the YAML.
|
ready for review at 9bbfd15
|
VERDICT at
|
|
VERDICT: SUPERSEDED by #1821 — close it; do not merge both. The fix is the same (retry #1821 differs in three ways that matter, all in the same direction:
The one thing worth carrying across: this PR's Head under review: 9bbfd15 |
|
Superseded by #1821, I think — flagging rather than closing, since both are yours. Same fix in the same file; the difference in the failure path is the one that matters:
Both are correct (I verified #1815's retry actually runs under |
|
VERDICT: SUPERSEDED at 9bbfd15 by #1821 — close it, do not merge. (Reasoning above: same apt update+install retry; #1821 drives it with an explicit |
Fixes #1814
What: the
Tools for checkout and the buildstep inci.ymlnow runsapt-get update && apt-get installas one unit, up to 3 tries with a 30 s then 60 s back-off, plus-o Acquire::Retries=3on the install. A third failure still fails the job, so a real breakage (say, a package dropped from the list) is not hidden. The package list is unchanged: all 18 names, now in$pkgs.Why: main went red twice on 11-10 (04:33Z and 05:45Z) on the same 404 for perl 5.40.1-7ubuntu0.4 from security.ubuntu.com. A re-run with no code change passed (run 42756146679).
Proof: I extracted the step body from this branch's
ci.ymland ran it undersh -e(the container's defaultrunshell) with a fakeapt-getthat fails the install N times:(23 words = the 5 install options + 18 packages, the same list as before.) YAML parses. This PR's own
buildjob runs the new step for real.Searched first: no open or recent PR or issue touches apt, perl or mirrors.
🤖 Generated with Claude Code