feat(hip): OCI Artifact Selection and Referrers Support - #424
Conversation
This HIP proposes enabling Helm to: 1. Select chart manifests from OCI Image Index by artifactType 2. Set artifactType field when pushing charts 3. Support Referrers API via --subject flag Addresses helm/helm#31582 Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: Aleksei Sviridkin <f@lex.la>
|
|
||
| When `helm pull`, `helm install`, or `helm dependency update` encounters an OCI reference that resolves to an Image Index (`application/vnd.oci.image.index.v1+json`), Helm MUST select a chart manifest using the following algorithm: | ||
|
|
||
| 1. **First pass**: Iterate through descriptors in `manifests[]` and check for `artifactType: application/vnd.cncf.helm.config.v1+json` |
There was a problem hiding this comment.
I wasn't around for the helm OCI implementation, so I don't know the thinking, but I assumed application/vnd.cncf.helm.config.v1+json represented the format of the config blob. If that is the case, it is almost as if there would need to be a new type something like application/vnd.cncf.helm.manifest.v1+json
There was a problem hiding this comment.
You're correct that application/vnd.cncf.helm.config.v1+json represents the config blob format. However, using the same value for artifactType is intentional per OCI spec.
The OCI Image Spec (descriptor.md) explicitly defines artifactType in Index descriptors as:
"This is the value of the config descriptor
mediaTypewhen the descriptor references an image manifest."
This design allows clients to select manifests from an Image Index without fetching them first - the artifactType in the descriptor tells you what kind of artifact it is by exposing the config.mediaType value at the Index level.
So the equality artifactType == config.mediaType is by design, not a naming collision:
- In Image Index descriptor:
artifactType= identifier for selection - In Image Manifest:
config.mediaType= format of the config blob
Both happen to have the same value because OCI spec defines it that way. Creating a separate type like application/vnd.cncf.helm.manifest.v1+json would contradict the OCI artifact model and require IANA registration for no functional benefit.
Reference: https://github.com/opencontainers/image-spec/blob/main/descriptor.md#properties
| 2. **Second pass** (fallback): If no match in first pass, iterate through descriptors WITHOUT a `platform` field: | ||
| - Fetch the referenced manifest | ||
| - Check if `config.mediaType` equals `application/vnd.cncf.helm.config.v1+json` | ||
| - If exactly one manifest matches, select it |
There was a problem hiding this comment.
I would think this would search for the first layer mediaType that is application/vnd.cncf.helm.chart.content.v1.tar+gzip
There was a problem hiding this comment.
Layer mediaTypes are not exposed in Image Index descriptors - only these fields are available at the Index level:
mediaType(of the manifest itself, alwaysapplication/vnd.oci.image.manifest.v1+json)digest,sizeplatform(for container images)artifactType(for artifacts, OCI 1.1+)annotations
To check layers[].mediaType, we would need to fetch every manifest in the Index first, then inspect each one. This defeats the purpose of efficient artifact selection.
The OCI artifact model specifically uses artifactType (derived from config.mediaType) because it's available at the Index level without additional round-trips.
Example Index descriptor:
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:def456...",
"size": 567,
"artifactType": "application/vnd.cncf.helm.config.v1+json"
// layers[] is NOT here - it's inside the manifest
}The fallback path (checking config.mediaType when artifactType is absent) already requires fetching the manifest. Adding layer inspection would not improve selection accuracy but would add complexity.
Address review feedback from TerryHowe: - Explain why artifactType equals config.mediaType (per OCI spec) - Explain why layer mediaType cannot be used for selection Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: Aleksei Sviridkin <f@lex.la>
sabre1041
left a comment
There was a problem hiding this comment.
There are a number of concerns related to this proposal, both in complexity as well as desire as a feature within Helm. Support for this feature would not only impact all Helm users given there may need to be additional logic implemented to traverse OCI manifests which could slow down the performance of Helm, but require the use of multiple tools outside the helm ecosystem just to implement it.
In addition, since Helm, by nature uses templating languages and parameters, the Image that is actually utilized within the chart may not be the same as the image the chart is attached to. Also, many charts contain references to multiple images. What logic can be employed to suggest whether a chart should be associated to one image or another.
I am very interested in the desire for others in the community to support such a feature. Until there is a marked need, I would recommend holding off until such a time where demand does grow.
|
|
||
| ## Abstract | ||
|
|
||
| This proposal enables Helm to select chart manifests from OCI Image Index manifests and adds support for the OCI Referrers API. Currently, `helm pull` fails when encountering an OCI Image Index containing multiple artifacts. This HIP introduces artifact selection logic based on the `artifactType` field (with fallback to `config.mediaType`), sets `artifactType` during `helm push`, and optionally allows charts to be associated with container images via the `subject` field and Referrers API. |
There was a problem hiding this comment.
| This proposal enables Helm to select chart manifests from OCI Image Index manifests and adds support for the OCI Referrers API. Currently, `helm pull` fails when encountering an OCI Image Index containing multiple artifacts. This HIP introduces artifact selection logic based on the `artifactType` field (with fallback to `config.mediaType`), sets `artifactType` during `helm push`, and optionally allows charts to be associated with container images via the `subject` field and Referrers API. | |
| This proposal enables Helm to select chart manifests from OCI Image Index manifests and adds support for the OCI Referrers API. Currently, `helm pull` fails when encountering an OCI Image Index containing multiple artifacts. This HIP introduces artifact selection logic based on the `artifactType` field (with fallback to `config.mediaType`), sets `artifactType` during `helm push`, and optionally allows charts to be associated with container images via the `subject` field and the Referrers API. |
| - Separate repository paths (e.g., `registry/app` for image, `registry/app-chart` for chart) | ||
| - Completely separate registries | ||
|
|
||
| These workarounds introduce unnecessary complexity in CI/CD pipelines, break atomic versioning guarantees, and require additional tooling to keep artifacts synchronized. Tools like ArtifactHub, ArgoCD, and GitOps workflows would benefit from a single source of truth for versioned artifacts. |
There was a problem hiding this comment.
| These workarounds introduce unnecessary complexity in CI/CD pipelines, break atomic versioning guarantees, and require additional tooling to keep artifacts synchronized. Tools like ArtifactHub, ArgoCD, and GitOps workflows would benefit from a single source of truth for versioned artifacts. | |
| These workarounds introduce unnecessary complexity in CI/CD pipelines, break atomic versioning guarantees, and require additional tooling to keep artifacts synchronized. Tools like ArtifactHub, Argo CD, and GitOps workflows would benefit from a single source of truth for versioned artifacts. |
| - If exactly one descriptor matches, select it | ||
| - If multiple descriptors match, select the first one (per OCI spec) | ||
|
|
||
| 2. **Second pass** (fallback): If no match in first pass, iterate through descriptors WITHOUT a `platform` field: |
There was a problem hiding this comment.
This has the potential to be resource intensive iterating through all of the associated manifests associated within an index
There was a problem hiding this comment.
It should not be an issue because manifest index are fetch ether by digest (sha256:abcdef12345678...) or by tag (that are just alias of direct manifest or manifests index)
in any case manifest index should contain artifact for the same version so:
- container image (we can consider that it don't go over 10 architectures)
- deployment artifact (docker-compose, helm, ...)
- the package application (npm, go package, dpkg, ...)
We have a maximum of 20 manifests that have a max size 4MB (defined in OCI 1.1 spec) this make the worse scenario 80MB of download. This is quite big but the worse case scenario.
Note that OCI 1.0 artifacts are usually link by tag. example for cosign:
An image with manifest sha256:abcdef12345678 will have it's sbom
at the tag sha256-abcdef12345678.sbom and it's signature at sha256-abcdef12345678.sig
|
|
||
| This enables efficient selection from Image Index without fetching manifest content. | ||
|
|
||
| ### 3. Referrers API Support |
There was a problem hiding this comment.
What happens if theres a chart associated within the index image as well as in the referrers API? Since its found in the list of manifests within the index, is the associated artifact via the referrers ignored (ie first found wins)?
There was a problem hiding this comment.
I don't think that we should add referrers API support.
The main use case is to link a helm chart to a container image but:
- helm chart can use multiple images and multiple tag of the same image and the OCI spec allow only one referrers, making referrers support at lease wonky
- Multiple helm chart version can use the same image (repo/tag/digest). If we use referrers the image will have references to multiple helm chart. The OCI spec don't define any order in witch the referrers API should send manifests making choosing the "right" (probably the latest) helm chart at lease slow, if not conflicting.
|
|
||
| When `helm pull`, `helm install`, or `helm dependency update` encounters an OCI reference that resolves to an Image Index (`application/vnd.oci.image.index.v1+json`), Helm MUST select a chart manifest using the following algorithm: | ||
|
|
||
| 1. **First pass**: Iterate through descriptors in `manifests[]` and check for `artifactType: application/vnd.cncf.helm.config.v1+json` |
There was a problem hiding this comment.
I agree that no changes should be made to the internal structure of the Helm chart itself (necessitating the need to register additional IANA types). This would require a HIP of its own
| # Create Image Index combining both | ||
| crane index append \ | ||
| --manifest registry.example.com/myapp:v1.0.0 \ | ||
| --manifest registry.example.com/myapp:v1.0.0-helm \ |
There was a problem hiding this comment.
this manifest reference does not align with the helm push command mentioned previously
There was a problem hiding this comment.
helm chart use semver version without any v in front of it:
| --manifest registry.example.com/myapp:v1.0.0-helm \ | |
| --manifest registry.example.com/myapp:1.0.0 \ |
|
I have a question that this HIP don't answer: In case an image index or an other manifest already exist for the given tag
helm currently just override the tag but having a "smarter" logic don't seems to far fetch. In case we don't want to implement this logic inside helm, helm should be able to push manifest without tag (As |
Rework the proposal around the real gap. Since the index-pull regression was fixed (helm/helm#31776) Helm traverses an index but selects the chart by last-match-wins over hardcoded media types, which is order-dependent and names the output from the reference rather than the selected chart, so it can return a mislabeled chart. Specify selection by descriptor artifactType with name/version disambiguation via org.opencontainers.image.title/version, erroring on genuine ambiguity instead of guessing. Keep the Referrers/subject half optional and separable from selection, clarify push-into-existing-tag behavior, and add a real-world motivation and an offline reproduction. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Aleksei Sviridkin <f@lex.la>
|
@sabre1041 Fair concerns — and a couple come from the original framing, which I've reworked in the latest push. The "helm pull fails on an index" premise is gone: that was a regression, already fixed in v3.20.2/v4.2 (helm/helm#31776). The real gap is that selection is order-dependent and name-blind — for an index with more than one chart-shaped manifest, reversing the manifest order changes which chart you get, and the file is named from the reference rather than the selected chart, so you can end up with On performance: selection reads Concerns 3 and 4 are exactly why On demand: concrete need from a CNCF Sandbox project — Cozystack ships ~158 charts as one OCI artifact and 30+ images separately, with no per-component chart+image unit, which makes air-gapped mirroring two disjoint flows. Happy to gather more signal if that helps. |
|
@JulesdeCube Good question, and a real gap — added a section for it (§4 "Push into an existing tag"). Short version: v1 keeps today's tag-overwrite behavior; Helm won't merge into or auto-create an index — assembling a multi-artifact index stays with external tooling (oras/crane) for now. Pushing by digest / without a tag is a clean enhancement (pull already works by digest), so I've listed it as an open issue rather than baking implicit index logic into |
Align the Referrers section with the reference implementation: --subject takes a digest that must already exist in the chart's target repository (the Referrers API is per-repository), and Helm resolves it there to a complete descriptor so the manifest carries a spec-valid subject rather than a digest-only stub. Cross-repository subjects move to Open Issues. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Aleksei Sviridkin <f@lex.la>
Add OCI 1.1 artifact support for charts (HIP: helm/community#424): - Select a chart from an OCI Image Index by descriptor artifactType, disambiguating multiple charts by the requested name then version, and falling back to the chart config for legacy indexes without annotations. An unresolvable choice errors with the candidate list instead of returning a position-dependent, mislabeled match. - Set artifactType (and chart name/version annotations) on helm push so charts are identifiable at the Index level without fetching each manifest. - Add a --subject flag to helm push that associates the chart with an existing artifact in the same repository via the OCI Referrers API; the digest is validated and resolved against the target repository to a full descriptor. Closes helm#31582 Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Aleksei Sviridkin <f@lex.la>
Implementing the selection rules showed the wording under-specified in three places, each of which allowed a wrong-chart pick: - an explicit chart artifactType now wins over a platform stamp; the platform filter applies only to entries with no declared type, since tooling stamps platform onto non-image entries (BuildKit attestation manifests carry platform unknown/unknown) - the config.mediaType fallback runs whenever the annotated candidates do not announce the requested chart, not only for fully legacy indexes, so a mixed index cannot hide the requested legacy chart - name and version must be announced by one descriptor, with a per-attribute fallback to Chart.yaml; matching them independently across candidates could fabricate an identity no candidate has The motivation now cites the measured behavior on released Helm (helm/helm#32539): selection varies between runs of one command against one digest, and the output file always keeps the requested name. Backwards compatibility gains the digest consequence of setting artifactType on push. References add the standalone selection fix (helm/helm#32540). Signed-off-by: Aleksei Sviridkin <3811295@gmail.com>
Accepted HIPs carry a helm-version field and sentence-case section headings; this proposal targets Helm 4, so say so, and match the heading style of the HIPs that passed review. Signed-off-by: Aleksei Sviridkin <3811295@gmail.com>
Proofreading the spec against the running selection code found five places where the text and the code disagreed: - the config.mediaType fallback does not skip platform-stamped entries; excluding them would hide exactly the legacy charts the fallback exists for, and the text said otherwise twice - repeated index entries count as one candidate, not an ambiguity - single-manifest pulls are not free: selection resolves the reference first, one extra manifest HEAD per pull - the spec cannot require registries not to error on artifactType; pre-OCI-1.1 registry behaviour has not been surveyed Signed-off-by: Aleksei Sviridkin <3811295@gmail.com>
Add OCI 1.1 artifact support for charts (HIP: helm/community#424): - Select a chart from an OCI Image Index by descriptor artifactType, disambiguating multiple charts by the requested name then version, and falling back to the chart config for legacy indexes without annotations. An unresolvable choice errors with the candidate list instead of returning a position-dependent, mislabeled match. - Set artifactType (and chart name/version annotations) on helm push so charts are identifiable at the Index level without fetching each manifest. - Add a --subject flag to helm push that associates the chart with an existing artifact in the same repository via the OCI Referrers API; the digest is validated and resolved against the target repository to a full descriptor. Closes helm#31582 Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Aleksei Sviridkin <f@lex.la>
Both came out of implementing them. Ambiguity is only detected among candidates that were examined, so a duplicate identity hiding in an entry with no artifactType goes unnoticed when a declared entry already announces what was asked for; catching it costs a fetch per undeclared entry on every index pull. And the requested version picks between candidates rather than validating one, matching what a plain reference already does with a tag. Signed-off-by: Aleksei Sviridkin <3811295@gmail.com>
…sent An index entry can fail to read, either its manifest or the config blob consulted when annotations omit the identity. A pass that could not read everything has not established what the index lacks, so an answer that rests on nothing else matching has to say what it could not see. A lone candidate now confirms the requested identity before it is returned, and errors reporting no match name the entries that were unreadable. Signed-off-by: Aleksei Sviridkin <3811295@gmail.com>
|
Since the June rework this stopped being theoretical. The selection gap this HIP describes turned out to be a live bug: on released 4.2.3, pulling from an index holding two charts can return the wrong one, same command, same digest, numbers and commands in helm/helm#32539. A fix for the selection half is up at helm/helm#32540. Implementing it forced three corrections to the wording of section 1 here, all pushed. An explicitly declared chart artifactType now wins over a platform stamp, because the tooling that stamps a platform onto every entry is the tooling least likely to set artifactType. The config.mediaType fallback also runs on mixed indexes, not only fully legacy ones, since finding a chart is not finding the requested chart. And name and version have to be announced by one descriptor, because matching them independently can fabricate an identity no candidate has. Two limits are now stated rather than left implicit: ambiguity is only detected among candidates that were examined, and the requested version chooses between candidates rather than validating a single one. @sabre1041 your December points were answered in the June push and the premise you flagged is gone from the text. The CHANGES_REQUESTED is still standing, so a re-review would help. @JulesdeCube section 4 answers the tag-overwrite part of your question. The two halves are independent, and the selection half now has running code and a demonstrated bug behind it. Per HIP-1 the next step is a review; drafts get merged with a number and iterate from there. Anything I can do to help one happen? |
Summary
This HIP proposes three related enhancements to Helm's OCI support:
Artifact Selection from Image Index - Enable
helm pull/install/dependencyto select chart manifests from OCI Image Index byartifactType(withconfig.mediaTypefallback)Set
artifactTypeon Push - Havehelm pushset theartifactTypefield in manifests for efficient selectionReferrers API Support - Add
--subjectflag tohelm pushfor associating charts with container imagesMotivation
Current workarounds for publishing charts and images together (tag suffixes like
:v1.0.0-helm, separate paths) are unnecessary complexity. OCI 1.1 provides native artifact bundling - Helm should leverage it.Related
Checklist