fix(show): resolve OCI tag from chart version for annotations

Build the manifest reference from the concrete version of the downloaded chart instead of recombining with client.Version, which can be a range such as ">0.0.0-0" when --devel is used and is not a valid tag. Show.Run now appends the resolved chart version when the reference has no explicit tag or digest, so annotations also work without an explicit --version. Adds a regression test.

Signed-off-by: Arnav Nagzirkar <113314200+arnavnagzirkar@users.noreply.github.com>
pull/32198/head
Arnav Nagzirkar 1 month ago
parent 544e3ba3d4
commit 3cbd4a7903

@ -19,6 +19,7 @@ package action
import (
"bytes"
"fmt"
"path"
"strings"
"k8s.io/cli-runtime/pkg/printers"
@ -100,7 +101,16 @@ func (s *Show) Run(chartpath string) (string, error) {
if s.OutputFormat == ShowChart || s.OutputFormat == ShowAll {
fmt.Fprintf(&out, "%s\n", cf)
if s.OCIRef != "" && s.registryClient != nil {
annotations, err := s.registryClient.GetManifestAnnotations(s.OCIRef)
ref := s.OCIRef
// When the reference has no explicit tag or digest, fall back to the
// resolved chart version. Helm stores an OCI chart under a tag that
// matches its version, and s.chart.Metadata.Version is the concrete
// version actually downloaded (the requested version may be a range).
if s.chart.Metadata != nil && s.chart.Metadata.Version != "" &&
!strings.Contains(path.Base(ref), ":") && !strings.Contains(ref, "@") {
ref = fmt.Sprintf("%s:%s", ref, s.chart.Metadata.Version)
}
annotations, err := s.registryClient.GetManifestAnnotations(ref)
if err == nil && len(annotations) > 0 {
annotationsYAML, marshalErr := yaml.Marshal(annotations)
if marshalErr == nil {

@ -254,3 +254,60 @@ func TestShowOCIAnnotationsNoRegistry(t *testing.T) {
// No annotations section, no "---" separator
assert.NotContains(t, output, "---")
}
func TestShowOCIAnnotationsResolvesVersion(t *testing.T) {
const manifestJSON = `{
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"config": {
"mediaType": "application/vnd.cncf.helm.config.v1+json",
"digest": "sha256:abc123",
"size": 100
},
"layers": [],
"annotations": {
"org.opencontainers.image.created": "2025-04-11T20:12:25Z"
}
}`
var requestedManifest string
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/v2/" {
w.WriteHeader(http.StatusOK)
return
}
if strings.Contains(r.URL.Path, "/manifests/") {
requestedManifest = r.URL.Path
w.Header().Set("Content-Type", "application/vnd.oci.image.manifest.v1+json")
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte(manifestJSON))
return
}
http.NotFound(w, r)
}))
defer srv.Close()
host := strings.TrimPrefix(srv.URL, "http://")
registryClient, err := registry.NewClient(
registry.ClientOptWriter(io.Discard),
registry.ClientOptPlainHTTP(),
)
require.NoError(t, err)
config := actionConfigFixture(t)
client := NewShow(ShowChart, config)
client.SetRegistryClient(registryClient)
// OCIRef has no explicit tag; the concrete tag is taken from the chart version.
client.OCIRef = host + "/test/chart"
client.chart = &chart.Chart{
Metadata: &chart.Metadata{Name: "test-chart", Version: "1.0.0"},
}
output, err := client.Run("")
require.NoError(t, err)
assert.Contains(t, output, "org.opencontainers.image.created")
assert.Contains(t, output, "2025-04-11T20:12:25Z")
assert.Contains(t, requestedManifest, "/manifests/1.0.0")
}

@ -21,7 +21,6 @@ import (
"io"
"log"
"log/slog"
"path"
"strings"
"github.com/spf13/cobra"
@ -222,11 +221,11 @@ func runShow(args []string, client *action.Show) (string, error) {
}
if registry.IsOCI(args[0]) {
ref := strings.TrimPrefix(args[0], registry.OCIScheme+"://")
if client.Version != "" && !strings.Contains(path.Base(ref), ":") {
ref = fmt.Sprintf("%s:%s", ref, client.Version)
}
client.OCIRef = ref
// Store the bare OCI reference (without the oci:// scheme). The concrete
// tag is resolved from the downloaded chart version in Show.Run, because
// client.Version may be a range (for example ">0.0.0-0" with --devel)
// rather than an exact tag.
client.OCIRef = strings.TrimPrefix(args[0], registry.OCIScheme+"://")
}
cp, err := client.LocateChart(args[0], settings)

Loading…
Cancel
Save