feat(plugin-oci): oci_load tags every image by content - #381
Open
raphaelvigee wants to merge 1 commit into
Open
Conversation
`tag` was required, and a tag written in a BUILD file is a moving target:
it names whichever image was loaded *last*, so two branches, two people,
or a rebuild after a change all collide on it and `docker run app:dev`
silently runs the wrong thing. It is also unusable from a script, which
has to read the log to learn what happened.
Every load now applies a content-addressed tag as well — the image
target's address as a repository, this load's input hash as the tag:
$ heph run //app:load
app/img:9f2c4e1b7a0d3856
It changes when and only when the image changes, two people on the same
commit get the same string, and it can be predicted from the graph rather
than discovered after the fact.
`tag` is now optional and is applied *in addition*, never instead, so the
pinned name is always there to fall back to. The pinned one is applied
first, so an image is never briefly reachable only under a moving name.
The repository follows the **image** target, not the load target: it names
what you are about to run, and nobody names their load target after the
image it loads.
Deriving it is not a formatting exercise. A docker reference is much
narrower than a heph address — each path component is
`[a-z0-9]+([._]|__|[-]+[a-z0-9]+)*` — so everything outside `[a-z0-9]`
becomes `-` and each component is trimmed. Dots are mapped away rather
than kept, because docker reads a first component containing one as a
*registry host*: a package called `example.com` would turn `docker run`
into a pull from a registry that does not exist. `localhost` is a host by
name alone and gets a prefix. Variants keep their args in the name, so
`//app:img@v=linux_amd64` and its arm64 sibling do not land on one
repository with nothing in `docker images` to tell them apart.
The name is resolved in `parse`, so an address with nothing a repository
can hold is a BUILD-file error naming the way out, rather than a reference
-format complaint from the daemon much later. `hashin` is only known at
run time — the engine computes it after `parse` — so only the repository
is in the def.
OCI_LOAD_FORMAT_VERSION 3 -> 4.
Drive-by: `test_real_skopeo_loads_an_oci_archive_into_the_daemon` had
described skopeo since skopeo stopped being involved. Renamed and
re-documented to say what it actually covers — that the OCI-to-docker
archive conversion is accepted by a real daemon.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WqQZxsTqanJRWLWdPSchBo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Based on #159 (
oci_loadonly exists there). Independent of #378 — a sibling, not a link in that stack.What
tagwas required. Now every load also applies a content-addressed tag — the image target's address as a repository, this load's input hash as the tag:tagbecomes optional and is applied in addition, never instead.Why
A tag written in a BUILD file is a moving target. It names whichever image was loaded last, so two branches, two people, or a rebuild after a change all collide on it and
docker run app:devsilently runs the wrong thing. It is also unusable from a script, which has to read the log to find out what happened.The derived tag can't do that: it changes when and only when the image changes, two people on the same commit get the same string, and it can be predicted from the graph instead of discovered after the fact.
The pinned tag is applied first, so an image is never briefly reachable only under a moving name.
The repository follows the image, not the load
//app:loadloading//svc/api:imggivessvc/api/img, notapp/load. The repository names what you are about to run, and nobody names their load target after the image it loads.Deriving it is not a formatting exercise
A docker reference is much narrower than a heph address — each path component is
[a-z0-9]+([._]|__|[-]+[a-z0-9]+)*://cmd/server:imgcmd/server/img//Cmd/My_Server:Imgcmd/my-server/img//example.com/svc:imgexample-com/svc/imgdocker runbecomes a network pull from a registry that does not exist//localhost:imgheph/localhost/img//app:img@v=linux_amd64app/img-v-linux-amd64docker imageswith nothing to tell them apart//app:___give an explicit tag) rather than a reference-format complaint from the daemon laterThe repository is resolved in
parse.hashinis only known at run time — the engine computes it afterparse— so only the repository is in the def.OCI_LOAD_FORMAT_VERSION3 → 4.Tests
9 unit tests covering the mapping table above, plus
tagbeing genuinely optional and the repo tracking the image rather than the load. The daemon-gated test now asserts both tags land in the daemon and that the derived one is a hex hash — with a per-process package so its repository is unique, since the daemon is shared state. That assertion needs a real daemon: the archive carriesRepoTags, but a containerd-backed daemon ignores them in favour of the OCI path, so the explicit tagging afterwards is invisible to a fake.Drive-by:
test_real_skopeo_loads_an_oci_archive_into_the_daemonhad described skopeo since skopeo stopped being involved. Renamed and re-documented to what it actually covers.🤖 Generated with Claude Code
https://claude.ai/code/session_01WqQZxsTqanJRWLWdPSchBo