build: make the compile stages cacheable across machines - #21
build: make the compile stages cacheable across machines#21kmannislands wants to merge 1 commit into
Conversation
Exclude .git from the build context and take REVISION as a build arg instead of shelling out to git inside the buildkit-version stage. Three stages mount the build context: buildkit-version, buildctl and buildkitd. A git checkout is not byte-reproducible -- .git/index carries mtimes, logs/HEAD carries timestamps, packed-refs ordering varies -- so the context digest differed from machine to machine and all three missed the layer cache anywhere they had not already been built. runc, the one compile stage that mounts from runc-src rather than the context, was correspondingly the only one that reused a shared cache. Measured downstream in EarthBuild/earthbuild CI, where every test job builds this image in a fresh buildkitd: of the ~136s spent before any test runs, ~96s was the buildctl and buildkitd compile, and it did not improve when a registry cache was added (155s -> 151s with mode=min, 136s with --max-remote-cache; runc started hitting, the other two never did). buildkit-version was the only consumer of .git, so dropping its git usage lets the context exclude .git entirely, which is what makes the two expensive stages cacheable. Also removes a dead assignment: `VERSION=$(git describe ...)` has been unused since #18 changed the ldflags line to use ${RELEASE_VERSION}. REVISION defaults to "unknown". Callers wanting a real revision should pass the buildkit git sha they are pinning -- it is known statically at the call site, which is a better source for it than a git command run inside the build. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
| Branch | Total Count |
|---|---|
| main | 217 |
| This PR | 221 |
| Difference | +4 (1.84%) |
Keep up the great work migrating from Earthly to Earthbuild! 🚀
💡 Tips for finding more occurrences
Run locally to see detailed breakdown:
./.github/scripts/count-earthly.shNote that the goal is not to reach 0.
There is anticipated to be at least some occurences of earthly in the source code due to backwards compatibility with config files and language constructs.
Not for merge. Repoints BUILDKIT_BASE_IMAGE at the registry-cache-buildkit-version branch so CI here can measure whether excluding .git from the buildkit build context makes the buildctl and buildkitd compile stages cacheable across machines. Baseline to beat, from the Docker +test-no-qemu-group7 job: 155s prelude with no cache, 136s with --max-remote-cache, of which ~96s is those two compile stages. If the change works the prelude should drop towards ~40s. Revert to 51fe8fb974fd27cac120487c04948bd3295683c9 before merge, or bump to the squashed sha once EarthBuild/buildkit#21 lands. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Measured result from EarthBuild/earthbuild#731 CI (Docker
So this PR does what it claims for But an important caveat on the ignore-file part of this PR, which I got wrong. The reason is on the earthly side: for remote/git targets, ignore files are not applied at all — Making
Option 2 is self-contained to this repo. Happy to add it here if that is the preferred direction — flagging rather than assuming, since it changes the shape of the build. Separately, the downstream cache work has hit a reliability problem (GHCR blob fetch timeouts failing builds under ~45 concurrent importers), so the overall approach is under review. This PR does not depend on that. |
Not for merge. Repoints BUILDKIT_BASE_IMAGE at the registry-cache-buildkit-version branch so CI here can measure whether excluding .git from the buildkit build context makes the buildctl and buildkitd compile stages cacheable across machines. Baseline to beat, from the Docker +test-no-qemu-group7 job: 155s prelude with no cache, 136s with --max-remote-cache, of which ~96s is those two compile stages. If the change works the prelude should drop towards ~40s. Revert to 51fe8fb974fd27cac120487c04948bd3295683c9 before merge, or bump to the squashed sha once EarthBuild/buildkit#21 lands. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Test PR to measure whether this unblocks registry-cache reuse for the buildkitd/buildctl compile. Context: EarthBuild/earthbuild#731.
Problem
Three Dockerfile stages mount the build context —
buildkit-version,buildctl,buildkitd— and all three miss the layer cache on any machine that has not already built them.runc, the one compile stage that mounts fromrunc-srcrather than the context, is the only one that reuses a shared cache. That correlation is exact.The cause is
.git. A git checkout is not byte-reproducible:.git/indexcarries mtimes,logs/HEADcarries timestamps, packed-refs ordering varies. Including it makes the context digest differ per machine, so every stage keyed on the context misses.buildkit-versionwas the only stage that actually needed.git, forREVISION=$(git rev-parse HEAD).Measured impact downstream
In EarthBuild/earthbuild CI every test job builds this image in a fresh buildkitd. Of ~136s spent before any test runs, ~96s is the
buildctl+buildkitdcompile — and adding a registry cache barely moved it:--max-remote-cacheruncstarted hitting;buildkit-version,buildctlandbuildkitdnever did, in any configuration.Change
.gitfrom the build context.buildkit-versiontakesREVISIONas a build arg instead of shelling out to git, so nothing needs.gitany more.REVISIONthrough the Earthfile+buildtarget.VERSION=$(git describe ...)has been unused since build: bake version.Package as github.com/EarthBuild/buildkit #18 switched the ldflags line to${RELEASE_VERSION}.Notes for review
.earthlyignoreas well as.dockerignore. The Earthfile here isVERSION 0.6, and earthly only falls back to.dockerignorefrom 0.8 (theuse-docker-ignorefeature)..earthlyignoreis honoured at every version, so it is the one that actually takes effect forFROM DOCKERFILE..dockerignoreis kept in sync for plain docker builds.REVISIONdefaults tounknown, sobuildkitd --versionloses its revision unless a caller passes one. The value is known statically at the call site (the pinned buildkit sha), which is a better source than a git command inside the build — but this is a real behaviour change and the main thing worth pushing back on.🤖 Generated with Claude Code