fix(ci): decouple build-cache export so a registry stall can't hang the job #96

Merged
nrupard merged 2 commits from fix/mapps-131-cache-export-stall into main 2026-06-09 19:12:38 +02:00
Owner

Problem

MAPPS-131: the main-branch OCI build (build-oci-image.yml) ran docker buildx build --push together with --cache-to type=registry,mode=max against dev.a8n.run in a single step. The registry's cache-export PUT can stall indefinitely and never returns an error, so buildx's ignore-error=true never fires. In run #331 the image and both tags (v0.2.0, latest) were pushed at 05:43, then the job hung in exporting cache to registry for ~3h until the runner's max-runtime cancelled it. A build that had actually succeeded was reported as failed.

This is the same flaky registry-cache-export endpoint behind MAPPS-121 (which fixed the redundant export on tag builds); MAPPS-131 is the main-build export itself stalling.

Fix

Split cache export into its own best-effort step that runs after push:

  • Build + push step now passes --cache-from only. Push can no longer be coupled to a cache-export stall.
  • New Warm build cache (best effort) step does --cache-to mode=max with timeout-minutes: 20 (caps a stall) and continue-on-error: true (keeps the job green if the export times out or fails). The image is already pushed, so a missed export only slows the next build.
  • The docker-container buildx builder still holds this commit's build state from the push step, so the re-invocation reuses local cache and only performs the registry export. Build-args and platforms are identical to the push step so the cache key matches and nothing rebuilds.
  • Step is skipped on tag builds via !startsWith(github.ref, 'refs/tags/'), preserving the MAPPS-121 behavior.

Verification

  • python3 -c "import yaml; yaml.safe_load(...)" parses clean.
  • Forgejo runner step-level timeout-minutes + continue-on-error confirmed supported per Forgejo Actions docs.
  • Real validation is the next main-branch build: image+tags push, and a stalled cache export now times out at 20m and the job stays green instead of burning ~3h to red.

#MAPPS-131

## Problem MAPPS-131: the main-branch OCI build (`build-oci-image.yml`) ran `docker buildx build --push` together with `--cache-to type=registry,mode=max` against dev.a8n.run in a single step. The registry's cache-export PUT can stall indefinitely and never returns an error, so buildx's `ignore-error=true` never fires. In run #331 the image and both tags (`v0.2.0`, `latest`) were pushed at 05:43, then the job hung in `exporting cache to registry` for ~3h until the runner's max-runtime cancelled it. A build that had actually succeeded was reported as failed. This is the same flaky registry-cache-export endpoint behind MAPPS-121 (which fixed the redundant export on tag builds); MAPPS-131 is the main-build export itself stalling. ## Fix Split cache export into its own best-effort step that runs after push: - Build + push step now passes `--cache-from` only. Push can no longer be coupled to a cache-export stall. - New `Warm build cache (best effort)` step does `--cache-to mode=max` with `timeout-minutes: 20` (caps a stall) and `continue-on-error: true` (keeps the job green if the export times out or fails). The image is already pushed, so a missed export only slows the next build. - The docker-container buildx builder still holds this commit's build state from the push step, so the re-invocation reuses local cache and only performs the registry export. Build-args and platforms are identical to the push step so the cache key matches and nothing rebuilds. - Step is skipped on tag builds via `!startsWith(github.ref, 'refs/tags/')`, preserving the MAPPS-121 behavior. ## Verification - `python3 -c "import yaml; yaml.safe_load(...)"` parses clean. - Forgejo runner step-level `timeout-minutes` + `continue-on-error` confirmed supported per Forgejo Actions docs. - Real validation is the next main-branch build: image+tags push, and a stalled cache export now times out at 20m and the job stays green instead of burning ~3h to red. #MAPPS-131
fix(ci): decouple build-cache export so a registry stall can't hang the job
All checks were successful
Check / clippy + fmt + tests (pull_request) Successful in 1m14s
0d447c54e7
The main-branch OCI build ran `docker buildx build --push` with `--cache-to type=registry,mode=max` against dev.a8n.run in a single step. The registry's cache-export PUT can stall indefinitely with no error returned, so buildx's `ignore-error=true` never fires; in MAPPS-131 (run #331) the image and both tags were pushed at 05:43 but the cache export then hung ~3h until the runner's max-runtime cancelled the job, marking a build that had actually succeeded as failed.

Cache export is now its own best-effort step after push: `timeout-minutes: 20` caps a stall instead of letting it consume the whole runtime, and `continue-on-error: true` keeps the job green when the export times out or fails. The image is already pushed by then, so a missed export only slows the next build rather than losing work. The docker-container builder still holds this commit's build state, so the re-invocation reuses local cache and only performs the registry export; build-args and platforms are kept identical so the cache key matches and nothing rebuilds.

The export step is skipped on tag builds (`!startsWith(github.ref, 'refs/tags/')`), preserving the MAPPS-121 fix that avoids re-exporting a cache the prior main build already populated.

#MAPPS-131

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
fix(ci): run cache-warm step last so a stall can't delay the mirror
All checks were successful
Create release / Create release from merged PR (pull_request) Has been skipped
Check / clippy + fmt + tests (pull_request) Successful in 1m12s
f25be878d2
The best-effort cache-export step sat between the build-and-push and the public-mirror steps, so a stalled export (up to the new 20m timeout) would delay publishing the user-facing mirrored image by that long. Move it to the end of the job, after the mirror and the image-URL print, so the critical path is push then mirror and cache warming runs last where a stall affects nothing downstream.

#MAPPS-131

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
nrupard deleted branch fix/mapps-131-cache-export-stall 2026-06-09 19:12:38 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
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
psa-systems/mokosh-apps!96
No description provided.