diff --git a/pkg/cmd/push.go b/pkg/cmd/push.go index da7c07b64..31b03ac15 100644 --- a/pkg/cmd/push.go +++ b/pkg/cmd/push.go @@ -34,10 +34,12 @@ If the chart has an associated provenance file, it will also be uploaded. Remote target formats: - oci://REGISTRY/REPO +- oci://REGISTRY/REPO:VERSION - oci://REGISTRY/REPO/CHART - oci://REGISTRY/REPO/CHART:VERSION -When CHART is omitted, the chart name is derived from the package. When VERSION is omitted, +When CHART is omitted, the chart name is derived from the package (and must match the +repo basename when using oci://REGISTRY/REPO:VERSION). When VERSION is omitted, it comes from Chart.yaml. Use --ensure-version as an optional verification. If set, it must match Chart.yaml or the command fails. diff --git a/pkg/pusher/ocipusher.go b/pkg/pusher/ocipusher.go index 753657d19..4490c6d0c 100644 --- a/pkg/pusher/ocipusher.go +++ b/pkg/pusher/ocipusher.go @@ -59,7 +59,7 @@ func (pusher *OCIPusher) push(chartRef, href string) error { return err } - // If an expected version is specified via --version, enforce it matches Chart.yaml + // If an expected version is specified via --ensure-version, enforce it matches Chart.yaml if pusher.opts.expectedVersion != "" && pusher.opts.expectedVersion != meta.Metadata.Version { return fmt.Errorf("specified --ensure-version %q does not match chart version %q", pusher.opts.expectedVersion, meta.Metadata.Version) } diff --git a/pkg/pusher/ocipusher_test.go b/pkg/pusher/ocipusher_test.go index 27f6e075c..18f936f1d 100644 --- a/pkg/pusher/ocipusher_test.go +++ b/pkg/pusher/ocipusher_test.go @@ -443,7 +443,7 @@ func TestOCIPusher_Push_InvalidChartVersion(t *testing.T) { err = pusher.Push(chartPath, "oci://localhost:5000/test:0.2.0") if err == nil { - t.Fatal("Expected error when pushing without a valid registry") + t.Fatal("Expected error due to tag/chart version mismatch") } if !strings.Contains(err.Error(), "does not match provided chart version") { t.Error("Expected error to mention tag mismatch") @@ -469,7 +469,7 @@ func TestOCIPusher_Push_ExpectedVersionMismatch(t *testing.T) { ) if err == nil { - t.Fatal("Expected error when --version does not match chart version") + t.Fatal("Expected error when --ensure-version does not match chart version") } if !strings.Contains(err.Error(), "specified --ensure-version") { diff --git a/pkg/registry/pushref.go b/pkg/registry/pushref.go index eaa85d60b..86689d111 100644 --- a/pkg/registry/pushref.go +++ b/pkg/registry/pushref.go @@ -51,6 +51,9 @@ func BuildPushRef(href, chartName, chartVersion string) (string, error) { last = finalRepo } if last != chartName { + if ref.Tag != "" { + return "", fmt.Errorf("repository %q does not match chart name %q; the tagged reference %q indicates an explicit push target", finalRepo, chartName, href) + } finalRepo = path.Join(finalRepo, chartName) } } diff --git a/pkg/registry/pushref_test.go b/pkg/registry/pushref_test.go index 0bd29ae26..5408baf3b 100644 --- a/pkg/registry/pushref_test.go +++ b/pkg/registry/pushref_test.go @@ -85,10 +85,17 @@ func TestBuildPushRef(t *testing.T) { version: "1.0.0", want: "my-registry.io/namespace/my-repo:1.0.0", }, + { + name: "tagged href with mismatched chart name should error", + registry: "oci://my-registry.io/repo/other:1.2.3", + chart: "mychart", + version: "1.2.3", + want: "", + wantErr: true, + }, } for _, tt := range tests { - if tt.wantErr { t.Run(tt.name, func(t *testing.T) { _, err := BuildPushRef(tt.registry, tt.chart, tt.version)