Give bake a registry-backed layer cache #46

Merged
geusebio merged 1 commit from ci/registry-layer-cache into main 2026-08-09 00:50:16 +00:00
Owner

Scoping (#44) cut how many images a push rebuilds. This cuts what rebuilding one of them costs: every bake target gets a cache ref of its own on git.grey.ooo, so a cold builder can import layers instead of redoing multi-arch work under QEMU.

56 targets, 56 distinct refs, checked for collisions (45 in default, 11 in ubuntu; none missing cache-from or cache-to).

Who writes it

main writes, every branch only reads. A branch that could write would let unreviewed code poison every later build, and branch runs have no business holding those credentials.

It cannot fail a build

The cache is an optimisation, so it is wired so a registry that is down -- or credentials a branch run cannot see -- costs time, not a red build:

  • the git.grey.ooo login step is continue-on-error
  • cache-from import failures are already non-fatal in buildx
  • cache-to carries ignore-error=true, so a hiccup cannot break a publish on main

An unauthenticated run just builds cold, exactly as today.

Off by default

CACHE_REF defaults to empty, so ./bake on a laptop needs no credentials and behaves as before. Only CI sets it. Verified all three modes resolve: off, read-only (branch), read+write (main).

Interaction with scoped builds

changed-targets now strips cache-from/cache-to before comparing resolved bake config -- where the layer cache lives says nothing about what an image contains, so retargeting it must not rebuild all 56. Verified both directions:

change scoped to
cache config added to all 56 targets (nothing)
same, plus a real change to the node target node-22 node-24

Not covered here

The test job builds through compose, a separate path that bake's cache config does not reach, and its build.target names do not line up 1:1 with bake target names (bake alpine-15 vs compose target alpine-15-base). Since build needs test, that is where the rest of the wall clock is -- it needs its own change.

Rebased onto main after #45 so this run queues in the single concurrency lane rather than racing whatever else is in flight.

🤖 Generated with Claude Code

Scoping (#44) cut how many images a push rebuilds. This cuts what rebuilding one of them costs: every bake target gets a cache ref of its own on git.grey.ooo, so a cold builder can import layers instead of redoing multi-arch work under QEMU. **56 targets, 56 distinct refs**, checked for collisions (45 in `default`, 11 in `ubuntu`; none missing `cache-from` or `cache-to`). ### Who writes it `main` writes, every branch only reads. A branch that could write would let unreviewed code poison every later build, and branch runs have no business holding those credentials. ### It cannot fail a build The cache is an optimisation, so it is wired so a registry that is down -- or credentials a branch run cannot see -- costs time, not a red build: - the git.grey.ooo login step is `continue-on-error` - `cache-from` import failures are already non-fatal in buildx - `cache-to` carries `ignore-error=true`, so a hiccup cannot break a publish on `main` An unauthenticated run just builds cold, exactly as today. ### Off by default `CACHE_REF` defaults to empty, so `./bake` on a laptop needs no credentials and behaves as before. Only CI sets it. Verified all three modes resolve: off, read-only (branch), read+write (main). ### Interaction with scoped builds `changed-targets` now strips `cache-from`/`cache-to` before comparing resolved bake config -- where the layer cache lives says nothing about what an image contains, so retargeting it must not rebuild all 56. Verified both directions: | change | scoped to | |---|---| | cache config added to all 56 targets | *(nothing)* | | same, plus a real change to the `node` target | `node-22 node-24` | ### Not covered here The test job builds through **compose**, a separate path that bake's cache config does not reach, and its `build.target` names do not line up 1:1 with bake target names (bake `alpine-15` vs compose target `alpine-15-base`). Since `build` needs `test`, that is where the rest of the wall clock is -- it needs its own change. Rebased onto main after #45 so this run queues in the single concurrency lane rather than racing whatever else is in flight. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
ci: give bake a registry-backed layer cache
All checks were successful
Build / Run container tests (push) Successful in 7m48s
Build / Build (push) Successful in 13m48s
04ec56a284
Scoping cut how many images a push rebuilds; this cuts what rebuilding one
of them costs. Every target gets a cache ref of its own on git.grey.ooo --
56 targets, 56 distinct refs, checked for collisions -- so a cold builder
can import layers instead of redoing multi-arch work under QEMU.

main writes the cache, every branch only reads it. A branch that could
write would let unreviewed code poison every later build, and branch runs
have no business holding those credentials.

The cache is an optimisation and is wired so it can never fail a build:
the login step is continue-on-error, cache-from import failures are
already non-fatal in buildx, and cache-to carries ignore-error so a
registry hiccup cannot break a publish on main. An unauthenticated run
just builds cold, exactly as it does today.

Off by default (CACHE_REF is empty), so `./bake` on a laptop needs no
credentials and behaves as before. CI sets it.

changed-targets strips cache-from/cache-to before comparing resolved bake
config: where the layer cache lives says nothing about what an image
contains, so retargeting it must not rebuild all 56. Verified both ways --
adding cache config to every target scopes to nothing, while a real change
to the node target alongside it still scopes to node-22 node-24.

Not covered here: the test job builds through compose, a separate path
that bake's cache config does not reach, and its build.target names do not
line up 1:1 with bake target names. That is where the rest of the wall
clock is; it needs its own change.

Co-Authored-By: Claude <noreply@anthropic.com>
Sign in to join this conversation.
No reviewers
No labels
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Grey.ooo/docker!46
No description provided.