Files
FabledCurator/.forgejo
bvandeusenandClaude Opus 5 815268418e
CI / lint (push) Successful in 3s
CI / extension-version (push) Successful in 3s
Build images / sign-extension (push) Successful in 4s
Build images / build-agent (push) Successful in 6s
Build images / build-web (push) Successful in 5s
CI / frontend-build (push) Successful in 23s
extension / lint (push) Successful in 23s
CI / backend-lint-and-test (push) Successful in 32s
Build images / build-ml (push) Successful in 22s
Build images / smoke-web (push) Successful in 30s
Build images / promote (push) Skipped
CI / integration (push) Successful in 2m17s
perf: stop building the same image twice under two names (4311)
`fabledcurator-ml` has been the SAME IMAGE as `fabledcurator` since milestone
422 step 6 merged the ML layers into the one Dockerfile. `build-ml` was still
running `file: Dockerfile, context: .` — byte for byte what `build-web`
builds — and publishing the result under a second name. So CI did the whole
build twice. Measured on run 7282, cold cache: build-web 1m54s, build-ml
1m55s, for identical output, plus a second push of a few hundred MB.

Operator, 2026-09-22: *"please fix the CI so it doesn't do this superfluous
work."*

build-ml now publishes nothing of its own. It pulls the manifest build-web
just pushed, re-tags it, and pushes that — so the second name goes on working
for the operator's Swarm stack, which still references it, while CI stops
compiling anything twice. 437 lines of duplicated build machinery go with it:
its own buildx setup, its own reuse check, its own version derivation, its
own tag repoint.

It now `needs: [build-web]` rather than running in parallel. That is the one
cost, and it is seconds: there is nothing to copy until build-web has decided
what this run publishes, and the layers are already on the runner.

Deliberately NOT `imagetools create`, which would have been the obvious
one-liner. That wraps its source in an INDEX and `.Image.Config.Labels` does
not resolve through one (#3183, run 4751) — and it would bite harder here
than it did there, because `promote` asks the registry for IMAGE manifest
media types ONLY, so an index at :refresh-candidate would fail its
`test -n "$CT"` and break the weekly refresh for this name. Plain
pull/tag/push keeps a plain manifest, which rule 40 also asks for. The step
reads the tag back and fails if `fc.revision` stops resolving, so a future
change that reintroduces index-wrapping says so instead of quietly costing
the refresh.

The tag list mirrors build-web's exactly, refresh included: a refresh writes
:refresh-candidate alone and `promote` moves it to :latest after smoke-web
passes. So this name keeps the gate it has today and `promote` needs no
change — it already loops over all three image names.

Source is build-web's `digest` when it built, else its `published_digest` on
a reuse hit — the digest its channel tag already names, which is what a hit
MEANS. With neither, the job fails with a reason rather than publishing
something arbitrary.

This does not retire the name; #4311 still does that, and is still gated on
the operator's stack pointing ml-worker at `fabledcurator:latest` with
`command: ["ml-worker"]`. Until then nothing of theirs changes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LVjrnpQjRgHdvq95rASoiR
2026-09-23 07:20:30 -04:00
..