Repository navigation
Description
W3.6 — one BuildKit build path: an engine-neutral OCI-layout image store
Part of opencharly/opencharly#481 (BuildKit as charly's one image builder).
Measured gap
The build drive still produces an engine-specific artefact and bridges it with a tag step:
candy/plugin-build/buildkit.goexportstype=oci,dest=<stage tar>with no name annotation, then
buildkitdrive.LoadExportdoesload→tag <id> <ref>→inspectagainst the run engine. The tag step is
only needed because the archive carries noio.containerd.image.name.- There is no engine-neutral image store: a box-on-box build resolves its parent through the local registry
mirror (DaemonOptions.RegistryMirror), which is the path Adopt BuildKit as charly's ONE image builder — 13 legs, retiring the podman/buildah + docker/buildx build drivers opencharly#481 describes as the #481 403,
and the build registry mirror is read by the drive but only reaches a buildkitd that starts AFTER it is set #35 measures the daemon-order defect in it. spec.BuildRequesthas noenginefield andcandy/plugin-build/ensure.gostill execs the literalpodman
(podman pull,podman tag) instead of the engine capability table.
Spike (measured on a, 2026-10-23, buildkit 0.34.1 / podman 6.1.4)
buildctl ... --output type=oci,name=<full-ref>,dest=x.tarwrites, inindex.json:
io.containerd.image.name=<full-ref>,org.opencontainers.image.ref.name=<tag only>,
org.opencontainers.image.created=<rfc3339>.podman load -i x.tarlands it tagged, no tag step.- The negative control — the same build without
name=— landsLoaded image: sha256:…untagged/dangling. - A child solved with
--oci-layout charly=<store> --opt context:<base-ref>=oci-layout://charly@sha256:<manifest>
succeeds while the base ref's registry is unreachable; the same child without the override fails with
dial tcp: lookup ghcr.invalid: no such host. That is the box-on-box proof: the layout, not the registry,
supplies the parent.
Scope of this change (plugin-build)
- Export each built image with
name=<FullTag>; write the archive into the charly image store — one OCI
layout at$XDG_DATA_HOME/charly/images/, oneindex.json, each manifest annotated
io.containerd.image.name=<FullTag>andorg.opencontainers.image.created— and keep it as the canonical
artefact. - Materialise from the annotated archive into the run engine without a tag step, verifying the ref resolves
through the engine capability table (no engine word literals in the code path). - Wire
buildkitdrive.Build.OCILayouts(sdk#433, tagv0.2026296.803) plus the named-context option so a
parent present in the charly store is solved fromoci-layout://charly@<digest>; the registry is a fallback
only when the parent is absent locally. - Keep
--pushas the second output (type=image,push=true).
Out of scope here, filed separately (cross-repo)
charly box build --engineneedsspec.BuildRequest.Engine+ aplugin-boxflag — filed in plugin-box/spec.--tag > box tag > defaults.tag > autocannot be implemented in the drive alone:plugin-boxpre-fills
req.Tagwith the computed CalVer, so an explicit--tagcannot be distinguished fromauto— filed in plugin-box.charly clean(keep_images) pruning of the charly image store lives inplugin-clean— filed there.- The
ResolvePodEngine/ResolveContainerdTargetresolver is feat(deploykit): the W3.1 selection resolvers — engine, VM backend, containerd target sdk#457 (open, untagged); this change
keeps the existing resolved-run-engine selection path and does not add a second selector.
Acceptance
- OCI annotation proven with its negative control (both directions).
- A box-on-box build with the parent in the charly store and the registry unreachable.
- The layout imports into at least one engine.
Metadata
Metadata
Assignees
Labels
No labels
Activity
aitrawog commentedon Oct 23, 2026
CLAIM — W3.6 (
containerd-crabbox-program/w36).Starting on
feat/w36-buildkit-image-storeofforigin/main(1f3c659). Spike already proves the twomechanisms this change rests on (OCI
io.containerd.image.namenaming with its negative control; aregistry-unreachable box-on-box solve through
--oci-layout+ a named context). Cross-repo gaps(
--engine,--tagprecedence,keep_imagespruning, sdkRootData) are being filed separately andlinked here.
Agent:
containerd-crabbox-program/w36· session8b1c01cf-7f79-4a75-bff8-240415a06208Assisted-by: Claude Code deepseek-v4.1-flash:cloud (analysed on a live system)
feat(build): the charly image store, annotated exports, and oci-layou…
fix(build): stream blobs into the store, and prove WHERE the annotati…
aitrawog commentedon Oct 23, 2026
RESOLVED — W3.6 landed. #37 merged as
c79ee55(headf2ecf3b, tagv2026.296.1100), with the review-round polish carried in #38; the build-skilldoc leg landed as opencharly/plugin-box#63.
Delivered: the charly image store (engine-neutral OCI layout at
$XDG_DATA_HOME/charly/images,io.containerd.image.name=<FullTag>+org.opencontainers.image.createdper manifest), a tag-freeengine import verified through the capability table,
Build.OCILayoutswired as a named-context parentbinding (registry-unreachable box-on-box proven with its failing control), and the removal of every
engine word literal from the build path.
Remaining cross-repo legs, filed: opencharly/sdk#458 (storekit data root), opencharly/plugin-box#61
(
--engine,--tagprecedence), opencharly/plugin-clean#21 (keep_imagespruning of the store),opencharly/sdk#457 (W3.1 resolvers; no second selector added).
Agent:
containerd-crabbox-program/w36· session8b1c01cf-7f79-4a75-bff8-240415a06208Assisted-by: Claude Code deepseek-v4.1-flash:cloud (fully tested and validated)
fix(build): stream blobs into the store, and prove WHERE the annotati…