ci(msan): retry transient network failures while building the MSan image - #2048
Merged
Conversation
The test-msan lane dies whenever the buildx layer cache misses and the
builder's resolver hiccups. PR-CI runs 33816056229 and 33818108315 both
failed in "Build MSan image (cached layers)" with:
#7 26.77 Could not resolve 'apt.llvm.org'
#7 27.34 W: Failed to fetch http://apt.llvm.org/noble/dists/\
llvm-toolchain-noble-22/InRelease Could not resolve 'apt.llvm.org'
ERROR: failed to build: failed to solve: process "/bin/sh -c apt-get \
update && ..." did not complete successfully
The wget of the signing key from that SAME host had succeeded seconds
earlier in the same layer, so this is a transient DNS failure inside
buildkit, not a wrong URL or a dead mirror. 2 of the last 15 PR runs.
Every network-touching step in Dockerfile.msan now runs under a small
POSIX-sh helper written into the image before the first layer that needs
it: /usr/local/bin/retry makes 5 attempts with growing backoff
(5s/10s/20s/40s) and still exits non-zero once they are exhausted, so a
genuine breakage keeps failing the build instead of being swallowed.
Wrapped: both apt-get update/install pairs (also given
-o Acquire::Retries=3), the wget of the LLVM signing key, and the
llvm-project and zlib clones. Two shapes needed care:
- the key is fetched with `wget -O <file>` instead of `-qO- > <file>`,
because a redirect is opened once for all attempts and a partial write
from a failed attempt would be prepended to a later successful one;
- each clone clears its destination first, or a half-finished clone makes
every later attempt fail on "destination path already exists".
The pinned base digest, the pinned llvmorg-22.1.0 / v1.3.1 tags,
--no-install-recommends and the layer structure are unchanged; on a
healthy network the image is byte-for-byte the same work as before.
Verified on Colima:
- `docker buildx build --check -f test-infrastructure/Dockerfile.msan
test-infrastructure/` -> "Check complete, no warnings found."
- scratch image = FROM + helper + the real apt.llvm.org layer, built
--no-cache: layer completes, clang-22/llvm-22 installed.
- scratch image where the wrapped command fails twice then succeeds:
attempts 1 and 2 logged with 5s/10s backoff, attempt 3 succeeds,
build exit 0.
- scratch image where the wrapped command always fails: 5 attempts,
"retry: giving up after 5 attempts", retry_exit=1, build exit 1.
The full MSan image was deliberately not built locally (it compiles
libc++ with MSan); CI builds it on the branch.
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The defect
test-msandies on PR CI whenever the buildx layer cache misses and the builder's resolver hiccups. It fails in step "Build MSan image (cached layers)" (scripts/ci/msan-lane.sh build→ buildx build oftest-infrastructure/Dockerfile.msan), 2 of the last 15 PR runs — runs 33816056229 and 33818108315:The
wgetof the signing key from that same host had succeeded seconds earlier in the same layer, so this is a transient DNS failure inside buildkit — not a wrong URL, not a dead mirror. One unlucky packet and the whole lane is red.The fix
A small POSIX-sh helper is written into the image (
/usr/local/bin/retry) in its own layer before anything touches the network: 5 attempts with growing backoff (5s/10s/20s/40s), and it still exits non-zero once they are exhausted — a real breakage keeps failing the build rather than being swallowed.Wrapped with it:
apt-get update/apt-get installpairs (also given-o Acquire::Retries=3),wgetof the LLVM signing key,git cloneofllvm-project,git cloneofzlib.Two shapes needed care:
wget -O <file>instead of-qO- > <file>: underretrythe redirect is opened once for all attempts, so a partial write from a failed attempt would be prepended to the output of a later successful one;destination path already exists.Unchanged: the pinned base digest, the pinned
llvmorg-22.1.0/v1.3.1tags,--no-install-recommends, and the layer structure and its comments. No behaviour change on a healthy network — every wrapped command succeeds on attempt 1,retryreturns immediately and never sleeps (confirmed below: the real apt layer built with zero retry lines).Verification (Colima, arm64)
The full MSan image was deliberately not built locally — it compiles libc++ with MSan. Instead the changed pieces were exercised directly.
1. Lint
2. The real
apt.llvm.orglayer — scratch image = theFROMline + the retry helper + the first apt layer, taken verbatim out of this Dockerfile, built with--no-cache:Zero
retry: attempt ... failedlines in that log — the healthy path costs nothing.3. The retry path fires — wrapped command fails twice, then succeeds:
4. Exhausted retries still fail the build — wrapped command always fails:
That third case is the one that matters for honesty: a retry helper that swallowed the final failure would hide real breakage behind a green lane.
Scratch images removed afterwards.
Scope
Only
test-infrastructure/Dockerfile.msanis touched —scripts/ci/msan-lane.sh, the workflow and everything else are untouched.Not implemented, offered as a follow-up decision: the lane builds on a
buildx created builder (msan-builder, docker-container driver), which resolves through its own container network — that is where the hiccup lives. Adding--network=hostto the buildx invocation would sidestep the builder's resolver entirely, but it needs thenetwork.hostentitlement on the builder and changes the lane script, so it is out of this PR's scope. Retries help regardless of which resolver is in play.