Repository navigation
test+fix: red tests and fixes for v0.14.1 merge (stacked on #41) - #48
kmannislands wants to merge 8 commits into
Conversation
Red test for the progress duplication EarthBuild hit after the v0.14.1 merge (earthbuild#1004). Two jobs build vertices with different digests but the same cache key, so the scheduler merges j1's edge into j0's. Since upstream e1da8b7 ("solver: fix printing progress messages after merged edges", first shipped in v0.13), state.setEdge adds the merge source's MultiWriter to the target and MultiWriter.Add replays history, so j1 also receives j0's log line. TestEarthlyMergedEdgeLogsDeliveredOnce passes on old main (f0b332c) and fails here. TestEarthlySharedVertexLogsDeliveredToEveryJob is a control: identical-digest vertices have always fanned logs out to every job, on both old main and this branch. This is upstream behaviour pulled in by the merge, not a conflict resolution mistake; per AGENTS.md dedupe belongs in EarthBuild. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
runExporters skips verifier.CheckInvalidPlatforms for the whole solve as soon as any exporter has Type() == client.ExporterEarthly. A non-EarthBuild exporter in the same solve therefore loses the upstream v0.14 result validation and is run on a multi-ref result without a platforms mapping. The control case (image exporter alone) still errors as upstream does. The earthlyoutputs exporter only builds a per-image platforms mapping from "platform" metadata; it does not compare requested and produced platforms, so the "handled per-image inside the Earthly exporter" comment is inaccurate. Linux only (llbsolver imports cache -> overlayutils). Old main had no exporter/verifier package and no ExporterInstance.Type(), so this is a divergence from upstream v0.14.1, not a regression from old main. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
⛔ Files ignored due to path filters (4)
📒 Files selected for processing (6)
Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review. 📝 WalkthroughWalkthroughThe pull request updates the fsutil replacement, changes execution mount dependency handling, refines exporter platform validation, and adds tests for concurrent job log delivery and exporter and mount behavior. ChangesProgress log fanout
Execution mount dependencies
Exporter platform validation
fsutil replacement update
Priority: ➖ Normal Estimated code review effort: 3 (Moderate) | ~20 minutes Change: Bug fix Suggested reviewers: Merge Risk: ⚪ Minimal · up to No confirmed issue prevents merging after normal checks. Pre-merge checks |
|
Turn TestEarthlyMergedEdgeLogsDeliveredOnce into the green characterisation test TestEarthlyMergedEdgeLogsReachMergedJob, which asserts that a job whose edge is merged into another job's edge receives the replayed log line. This is upstream behaviour from e1da8b7 ("solver: fix printing progress messages after merged edges", v0.13), not a regression introduced while resolving the v0.14.1 merge. AGENTS.md says BuildKit must not be patched to dedupe progress logs across concurrent solves, so no solver code changes here. EarthBuild relies on this fan-out contract and must dedupe on its side (earthbuild#1004). The test comment says so, so that an upstream change to the contract shows up as a test failure instead of a silent behaviour change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
runExporters skipped verifier.CheckInvalidPlatforms for the whole solve as soon as any exporter was the EarthBuild exporter. A non-EarthBuild exporter in the same solve then lost the upstream v0.14 validation and ran on a multi-ref result with no platforms mapping. All exporters share one input result, so a per-exporter check is not possible. The EarthBuild frontend always returns named Refs and never sets refs.platforms, so CheckInvalidPlatforms always rejects an EarthBuild-shaped result. The narrowest correct rule is to skip the check only when every exporter is the EarthBuild exporter. A mixed solve is then checked for the other exporter's sake and is rejected with the upstream error, as the red test expects. EarthBuild never issues mixed solves: every SolveOpt it builds has exactly one export entry. A solve with no exporters still runs the check, as upstream does. Also correct the comment, which claimed that platform verification was handled per image inside the EarthBuild exporter. It is not: earthlyoutputs only groups refs into images by their "platform" metadata and never compares requested and produced platforms. The test keeps its original expectations and adds an earthly-only case, so the skip cannot be removed without the test noticing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Picks up the fsutil merge fixes: send progress is counted once, and verbose progress callbacks report native paths on both sides. fsutil#4 is unmerged; go.mod carries a TODO to advance the replace to the merged earthly-main commit once fsutil#3 and #4 land. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every EarthBuild RUN carries, alongside the rootfs, a secret mount (/run/secrets/earthly_debugger_settings) and two socket mounts (/var/run/earthly_interactive, /var/run/earthly_save). They arrive with Input:0 and no selector. getMountDeps treats them as whole-source mounts of input 0 and, because the ContentBasedHash flag is last-mount-wins, overrides the rootfs mount's "no content cache on /" decision. The rootfs dep of every RUN therefore gets a content-based cache key (daemon logs show dep_has_slow_cache=true). A RUN after a `RUN --no-cache` that did not change the filesystem then matches its previous record and is reported as *cached* (functional test T8). The content-hash behaviour came in with the v0.13.2 merge (upstream 98bfcf4, ab17c1d). Old main did not have it. Linux only (ops imports cache -> overlayutils). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Secret, SSH and Tmpfs mounts never have an input vertex and zero value for input should not be considered and input at index 0 . Currently, if for example secret mount had a input=0, it caused content based checksum from first input(rootfs), that could take quite a lot of time when image was big and had lots of files. The computation result was cached but if there was a cache invalidation in previous commands it caused checksum to recomputed again for the command with the secret mount. Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com> (cherry picked from commit 3c87ba1) Cherry-picked from moby/buildkit#5251 for the T8 regression (`RUN --no-cache` no longer invalidates the following RUN). This alone does not fix it: TestExecOpEarthlySpecialMountsNotContentHashed still fails because EarthBuild's two socket mounts (MountType_SOCKET, /var/run/earthly_interactive and /var/run/earthly_save) also arrive with Input:0 and still mark the rootfs input as content-hashed. Skipping SOCKET follows in the next commit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
EarthBuild's socket mounts (MountType_SOCKET, used for /var/run/earthly_interactive and /var/run/earthly_save) have no input vertex, like the secret/SSH/tmpfs mounts upstream 3c87ba1 already skips, but arrive with Input:0. getMountDeps counted them as whole-source mounts of the rootfs input and, last-mount-wins, turned on ContentBasedHash for it. Every RUN's rootfs dep then got a content-based cache key, so a RUN after a `RUN --no-cache` that left the filesystem unchanged was reported as *cached* (T8). Skip SOCKET too, on its own case line so the upstream line stays unchanged. TestExecOpEarthlySpecialMountsNotContentHashed now passes; TestExecOpContentCache and TestDedupePaths still pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Stacking
This PR is stacked on #41 (
chore-merge-v0.14.1, itself based onchore-merge-v0.14.1-unresolved). It targetschore-merge-v0.14.1so the diff shows only the review additions. Merge #41 first, or fold these commits into it.Commit structure: red, then green
The first two commits add red tests that fail on #41's head (
a653104a) and pin down each finding. The next two are green fixes that make those tests pass, so each fix can be reviewed against the test that motivated it.2d63eacbtest(solver): merged-edge logs now reach every attached jobfd768dc5test(llbsolver): platform check skipped for non-earthly exporters08c7a4e5test(solver): pin merged-edge log fan-out as upstream behaviour. Test-only, no BuildKit change.f821ecf1fix(llbsolver): only skip platform check when every exporter is earthlyThe T8 regression commits (
2cd6cbcc,4f8b3685,1f6ea531) follow the same red-then-green pattern. See the T8 section below.Findings
1. Progress duplication across concurrent solves (earthbuild#1004)
Tests:
TestEarthlyMergedEdgeLogsDeliveredOnce(red) and the controlTestEarthlySharedVertexLogsDeliveredToEveryJob(passes on old main and here), insolver/earthly_progress_fanout_test.go.go test ./solver/ -run TestEarthly -count=1 -vTwo jobs build vertices with different digests but the same cache key, so the scheduler merges j1's edge into j0's active edge and the operation runs once. On old EarthBuild main (BuildKit v0.12 base) the log line went only to the job that ran it. Since upstream e1da8b7 ("solver: fix printing progress messages after merged edges", first shipped in v0.13 and so part of this merge),
state.setEdgeadds the merge source's progress writer to the target, andMultiWriter.Addreplays history. j1 therefore also receives j0's log line, and EarthBuild, which prints every log line from every Status stream, prints it twice.This is upstream behaviour pulled in by the merge, not a conflict-resolution mistake. Per this repo's AGENTS.md, BuildKit must not be patched to dedupe progress logs across concurrent solves; that belongs in EarthBuild (avoid redundant solve requests in
earthfile2llb/converter.go, or dedupe on the client side). The green commit for this finding therefore does not change BuildKit. It turns the red test into a characterisation test that asserts the upstream behaviour, so EarthBuild's dedupe has a pinned contract to rely on.2. Platform validation skipped for every exporter if any is earthly
Test:
TestRunExportersValidatesNonEarthlyExporterAlongsideEarthlyinsolver/llbsolver/earthly_exporters_test.go. It is Linux-only, because llbsolver imports cache, which imports overlayutils:runExportersskipsverifier.CheckInvalidPlatformsfor the whole solve as soon as any exporter hasType() == client.ExporterEarthly. A non-EarthBuild exporter in the same solve loses the upstream v0.14 validation and runs on a multi-ref result with no platforms mapping. The accompanying comment says platform verification is "handled per-image inside the Earthly exporter", but it is not:earthlyoutputsonly builds a per-image platforms mapping fromplatformmetadata and never compares requested platforms with produced ones.Old main had no
exporter/verifierpackage and noExporterInstance.Type(), so this is a divergence from upstream v0.14.1, not a regression from old main.Resolution of finding 1
TestEarthlyMergedEdgeLogsDeliveredOncebecameTestEarthlyMergedEdgeLogsReachMergedJob, which asserts that the merged job does receive the replayed line (j0 = 1, j1 = 1). Its comment cites e1da8b7 and says EarthBuild relies on this contract and must dedupe concurrent solves on its side. If an upstream bump changes the fan-out, this test fails and signals that EarthBuild's dedupe must be revisited.Resolution of finding 2
Every exporter receives the same
inp, so a per-exporter check is not possible. The EarthBuild frontend always returns namedRefsand never setsrefs.platforms, soCheckInvalidPlatformsalways rejects an EarthBuild-shaped result. The fix skips the check only when every exporter is earthly (and at least one exporter exists, so the zero-exporter warnings path still runs as upstream). A mixed solve is checked for the non-earthly exporter's sake, which rejects an EarthBuild-shaped result with the upstream error. EarthBuild never issues mixed solves: everySolveOptinbuilder/has exactly one export entry. The misleading comment is corrected and the block is marked// earthly-specific. The red test's expectations are unchanged. An earthly-only case was added so the skip cannot be removed without the test noticing.T8:
RUN --no-cacheno longer invalidates the following RUNFunctional test T8 (earthbuild#1004) found a regression. After a
RUN --no-cache echo …, the nextRUNin the same target, or in a target that doesFROM +common, was reported as*cached*on the second run. On old main it re-executed.Root cause
Every EarthBuild RUN carries three mounts besides the rootfs: a secret mount (
/run/secrets/earthly_debugger_settings) and two socket mounts (/var/run/earthly_interactiveand/var/run/earthly_save,MountType_SOCKET). None of them consumes an input, but all three arrive withInput: 0and no selector.getMountDepsinsolver/llbsolver/ops/exec.gotreated them as whole-source mounts of input 0. ItsContentBasedHashflag is last-mount-wins per input, so they overrode the rootfs mount's "no content cache on/" decision. As a result, the rootfs dep of every RUN got a content-based cache key, and the daemon logs showeddep_has_slow_cache=true. Anecho-only--no-cacheRUN does not change the filesystem, so the next RUN's content key matched its old record.That content-hash logic came from upstream 98bfcf4 ("exec: refactor content-based cache detection") and ab17c1d ("exec: allow content-cache for root selected mounts"), both pulled in by the v0.13.2 merge. Upstream fixed the same issue for secret, SSH and tmpfs mounts in 3c87ba1 (moby/buildkit#5251, "exec: fix incorrect deps computation for special mounts"). That fix alone is not enough here, because EarthBuild's socket mounts still hit the rootfs branch.
Commit map
2cd6cbcctest(llbsolver/ops):TestExecOpEarthlySpecialMountsNotContentHashedinsolver/llbsolver/ops/earthly_exec_mounts_test.gouses the exact mount shape EarthBuild sends (root + host-bind debugger + secret + 2 sockets) and asserts that the rootfs dep is not content-hashed4f8b3685git cherry-pick -x 3c87ba1b, which skips SECRET/SSH/TMPFS. Applied cleanly. The red test still fails at this commit because of the socket mounts1f6ea531fix(llbsolver/ops): skip earthly socket mounts in getMountDeps. Addspb.MountType_SOCKETon its owncaseline, marked// earthly-specific, so the upstream line stays unchangedLinux only (ops imports cache, which imports overlayutils):
Verification
Unit: the red test fails on
dd17522aand on4f8b3685(rootfs input must not be content-hashed) and passes on1f6ea531.TestExecOpContentCache,TestDedupePathsand the rest of./solver/llbsolver/ops/...pass.End to end: I built a buildkitd image from this branch with
earth ./buildkitd+buildkitd --BUILDKIT_PROJECT=<this tree>(earthbuild pr1004 Earthfile) and ran the PR earth binary against it, twice per target:buildkitd-dev-pr-1004image (BuildKit97a1abd8;ops/is unchanged up todd17522a)1f6ea531+single(RUN --no-cache echothenRUN echo T8AFTER)*cached* --> RUN echo T8AFTER-$((3+4))--> RUN echo T8AFTER-$((3+4))/T8AFTER-7(re-executed)+child(FROM +common, where+commonhas the--no-cacheRUN)*cached* --> RUN echo T8CHILD-$((5+5))--> RUN echo T8CHILD-$((5+5))/T8CHILD-10(re-executed)+plain(two RUNs, no--no-cache, control)*cached* --> RUN echo T8PLAIN-…and*cached* --> RUN echo T8PLAIN2-…(normal cache still works)Follow-up
dd17522achore(deps): bump earthbuild/fsutil toe66a226(EarthBuild/fsutil#4: send progress counted once, native paths in verbose progress). fsutil#4 is unmerged; a TODO ingo.modmarks the replace to advance to the mergedearthly-maincommit once EarthBuild/fsutil#3, #6 and #4 land.🤖 Generated with Claude Code
Summary by CodeRabbit