Skip to content

Speed up docs publishes by reusing the previously built CI image - #70650

Merged
potiuk merged 1 commit into
mainfrom
seed-ci-image-cache-from-stashed-image
Jul 29, 2026
Merged

Speed up docs publishes by reusing the previously built CI image#70650
potiuk merged 1 commit into
mainfrom
seed-ci-image-cache-from-stashed-image

Conversation

@potiuk

@potiuk potiuk commented Jul 28, 2026

Copy link
Copy Markdown
Member

Docs publishes rebuild the CI image from scratch whenever the ref being documented was cut before the last Dockerfile.ci change on main. The registry cache the build reads is main's, so #70285 (Node.js/pnpm baked into the image) breaks the cache chain at layer 3 of 26 and the ~20 minute Python build runs again. Measured on run 30398809294: 1 of 26 layers CACHED, install_os_dependencies.sh 1173.7s, build step 25m24s. A canary main build, whose sources match its cache, is 6m42s.

The image the previous publish of that same ref stashed matches those layers exactly, so this seeds the build from it.

  • ci-image-build.yml gains seed-cache-from-stashed-image (default off). When on, it restores the stashed image, republishes it to a registry:2 on localhost and passes it to the build as an extra --cache-from.
  • The registry hop is required, not incidental. BuildKit imports the cache manifest of a docker loaded image and then discards every record whose layers it cannot pull from a registry. Verified locally with the same image, same builder and same args: through docker load every layer re-ran, through localhost:5000 every layer came back CACHED.
  • Images are now built with BUILDKIT_INLINE_CACHE=1 so they carry those records at all. Also verified that this arg does not participate in layer cache keys, so it does not invalidate the existing registry cache when it lands.
  • image-stash-suffix keeps a per-ref copy of the image stash, retained 6 days because the same ref is rebuilt at least three days apart. Seeding prefers that copy and falls back to the shared per-branch stash, which Tests AMD keeps warm for main.

Only publish-docs-to-s3.yml opts in. Tests AMD is unchanged apart from the inline cache record in the images it produces.

Expected effect: re-publishing the same ref should build in a couple of minutes instead of 25; a different ref that shares the image-defining files should skip the 20 minute layer; a genuine miss costs about 6 minutes of seeding once, and that run then writes its own per-ref slot.


Was generative AI tooling used to co-author this PR?
  • Yes — Claude Code (Opus 5)

Generated-by: Claude Code (Opus 5) following the guidelines

Publishing docs for a ref cut before main pays for a from-scratch CI image
build. The registry cache the build reads is main's, and the first
Dockerfile.ci change made since the ref was cut breaks the cache chain at the
third layer - #70285, which bakes Node.js and pnpm into the image, is by
itself enough to make the twenty-minute Python build run again. Nothing
caches those layers for the ref being documented except the image the
previous publish of that same ref already built.

That image could not serve as a cache until now. BuildKit imports the cache
manifest of an image loaded from a tarball and then discards every record
whose layers it cannot pull from a registry, so a docker load contributes
nothing at all; serving the image from a registry on localhost is what makes
its records usable. Recording those records in the first place needs inline
cache metadata, which no image carried before.
@potiuk
potiuk force-pushed the seed-ci-image-cache-from-stashed-image branch from 58b4fad to 5269813 Compare July 29, 2026 08:08
@potiuk
potiuk requested review from kaxil and shahar1 July 29, 2026 08:13
@potiuk
potiuk merged commit d9d8fdb into main Jul 29, 2026
157 checks passed
@potiuk
potiuk deleted the seed-ci-image-cache-from-stashed-image branch July 29, 2026 09:32
@github-actions

Copy link
Copy Markdown
Contributor

Backport failed to create: v3-3-test. View the failure log Run details

Note: As of Merging PRs targeted for Airflow 3.X
the committer who merges the PR is responsible for backporting the PRs that are bug fixes (generally speaking) to the maintenance branches.

In matter of doubt please ask in #release-management Slack channel.

Status Branch Result
v3-3-test Commit Link

You can attempt to backport this manually by running:

cherry_picker d9d8fdb v3-3-test

This should apply the commit to the v3-3-test branch and leave the commit in conflict state marking
the files that need manual conflict resolution.

After you have resolved the conflicts, you can continue the backport process by running:

cherry_picker --continue

If you don't have cherry-picker installed, see the installation guide.

potiuk added a commit that referenced this pull request Jul 29, 2026
Docs for a ref are published more than once - an RC, then the final docs
after the vote - and the second publish rebuilds an image the first one
already built from the very same commit. Seeding the build cache with that
image, as #70650 does, still pays for a docker load, a registry push, a
build that hits cache on every layer, an export and two multi-gigabyte
stash uploads, none of which can produce anything the first publish did not
already produce.

Reusing the image outright rather than as a cache turns on knowing it was
built from this commit. A ref does not say that: a branch documented twice
moves between the two publishes, so its image is a good cache and a wrong
answer. The commit each image is stashed with is what tells those apart,
and it is stashed on its own so that deciding costs a few bytes rather than
the image the decision may make unnecessary.

Reusing it also means publishing nothing, which the shared per-branch stash
could not support: it is written by every build on this branch, so whoever
restores it next would get sources they never asked for. The ref's own
stash is the one this run's docs and registry jobs now read, so a run with
nothing to build leaves them reading what the previous publish left there.
The mount cache moves with it for the same reason - it holds the dependency
set the sources resolve to, and a ref's and the branch tip's are exactly
what differ.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants