Repository navigation
Open
Description
What is the issue?
If you place an OCI annotation on a container that is used for publishing multiple platform variants, for example,
container
.withAnnotation("org.opencontainers.image.description", "asdf")
.publish("...", platformVariants: variants)You will find the the annotation is dropped and does not appear in any of: the image index, index manifests, nor the image manifests. For example,
# Used `.withAnnotation` on the multiarch image, annotations dropped
oras manifest fetch ghcr.io/cbochs/gift-exchange:v1.0.1
# Used `.withAnnotation` on the image variants, annotations kept
oras manifest fetch ghcr.io/cbochs/gift-exchange:v1.0.2In the past (#10330 (comment)) the index manifests and image manifests were annotated. This is not the case anymore. If the variants themselves are annotated individually with .withAnnotation then an annotation appears (see repro).
Dagger version
v1.0.0-beta.25
Steps to reproduce
Example repro module
"""
Reproduce annotation placement on multi-platform image publishes.
"""
type AnnotationRepro {
publishAndInspect: String! {
let registry = container
.from("registry:2.8.3")
.withExposedPort(5000)
.asService
let annotatedVariants = ["linux/amd64", "linux/arm64"].map { platform =>
container(platform: platform :: Platform!)
.withNewFile("/platform.txt", platform)
.withAnnotation("org.opencontainers.image.description", "variant-" + platform)
}
let plainVariants = ["linux/amd64", "linux/arm64"].map { platform =>
container(platform: platform :: Platform!)
.withNewFile("/platform.txt", platform)
}
let variantImage = container
.publish(
"registry:5000/repro/variant-annotations:latest",
platformVariants: annotatedVariants,
registryService: registry,
protocol: HTTP,
)
let parentImage = container
.withAnnotation("org.opencontainers.image.description", "parent-only")
.publish(
"registry:5000/repro/parent-annotation:latest",
platformVariants: plainVariants,
registryService: registry,
protocol: HTTP,
)
let oras = container
.from("ghcr.io/oras-project/oras:v1.2.3")
.withServiceBinding("registry", registry)
let indexTemplate = "index={{if .content.annotations}}{{index .content.annotations \"org.opencontainers.image.description\"}}{{else}}(none){{end}}; descriptors={{range .content.manifests}}{{.platform.architecture}}={{if .annotations}}{{index .annotations \"org.opencontainers.image.description\"}}{{else}}(none){{end}} {{end}}"
let manifestTemplate = "{{if .content.annotations}}{{index .content.annotations \"org.opencontainers.image.description\"}}{{else}}(none){{end}}"
let variantIndex = oras.withExec(["/bin/oras", "manifest", "fetch", "--plain-http", "--format", "go-template", "--template", indexTemplate, variantImage]).stdout
let variantAMD64 = oras.withExec(["/bin/oras", "manifest", "fetch", "--plain-http", "--platform", "linux/amd64", "--format", "go-template", "--template", manifestTemplate, variantImage]).stdout
let variantARM64 = oras.withExec(["/bin/oras", "manifest", "fetch", "--plain-http", "--platform", "linux/arm64", "--format", "go-template", "--template", manifestTemplate, variantImage]).stdout
let parentIndex = oras.withExec(["/bin/oras", "manifest", "fetch", "--plain-http", "--format", "go-template", "--template", indexTemplate, parentImage]).stdout
let parentAMD64 = oras.withExec(["/bin/oras", "manifest", "fetch", "--plain-http", "--platform", "linux/amd64", "--format", "go-template", "--template", manifestTemplate, parentImage]).stdout
let parentARM64 = oras.withExec(["/bin/oras", "manifest", "fetch", "--plain-http", "--platform", "linux/arm64", "--format", "go-template", "--template", manifestTemplate, parentImage]).stdout
```text
Annotation on platform variants (org.opencontainers.image.description)
index + descriptors: ${variantIndex}
linux/amd64 image manifest: ${variantAMD64}
linux/arm64 image manifest: ${variantARM64}
Annotation only on parent multi-platform container
index + descriptors: ${parentIndex}
linux/amd64 image manifest: ${parentAMD64}
linux/arm64 image manifest: ${parentARM64}
```
}
}Log output
Annotation on platform variants (org.opencontainers.image.description)
index + descriptors: index=(none); descriptors=amd64=variant-linux/amd64 arm64=variant-linux/arm64
linux/amd64 image manifest: variant-linux/amd64
linux/arm64 image manifest: variant-linux/arm64
Annotation only on parent multi-platform container
index + descriptors: index=(none); descriptors=amd64=(none) arm64=(none)
linux/amd64 image manifest: (none)
linux/arm64 image manifest: (none)
Metadata
Metadata
Assignees
Labels
No labels
Activity
cbochs commentedon Nov 5, 2026
I want to take a moment to bring back the issue originally discussed in #10330. If possible, annotations on a multiarch image should be added to an image index. Registries (like ghcr.io) look for annotations like
org.opencontainers.image.descriptionto be on the image index to render image details (example). Today, I don't think that is possible using Dagger natively.dajiaohuang commentedon Nov 6, 2026
I'd like to investigate and work on this. I'll trace how parent-container annotations flow into multi-platform publish metadata, then add a focused regression test for the expected OCI index/descriptors. If there is an existing in-flight fix or a specific annotation-placement expectation beyond the reproducer, please let me know.