diff --git a/pkg/action/get_metadata.go b/pkg/action/get_metadata.go index cc5705143..ab407592d 100644 --- a/pkg/action/get_metadata.go +++ b/pkg/action/get_metadata.go @@ -69,7 +69,10 @@ type Metadata struct { // or chart reference), recorded via the meta.helm.sh/release-source // annotation. Empty for releases created before this was recorded. Source string `json:"source,omitempty" yaml:"source,omitempty"` - // Annotations are fetched from the Chart.yaml file + // Annotations are the chart metadata annotations from Chart.yaml. For a + // release installed or upgraded with a recorded source, this map also + // includes the meta.helm.sh/release-source annotation Helm adds at + // install/upgrade time (also surfaced separately via Source above). Annotations map[string]string `json:"annotations,omitempty" yaml:"annotations,omitempty"` // Labels of the release which are stored in driver metadata fields storage Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"` diff --git a/pkg/action/install_test.go b/pkg/action/install_test.go index 723600ffa..52d8a34e9 100644 --- a/pkg/action/install_test.go +++ b/pkg/action/install_test.go @@ -251,6 +251,41 @@ func TestInstallReleaseRecordsChartSourceAfterRender(t *testing.T) { is.Equal("https://charts.example.com/repo", rel.Chart.Metadata.Annotations[ReleaseSourceAnnotation]) } +func TestUpgradeReleaseRecordsChartSourceAfterRender(t *testing.T) { + is := assert.New(t) + req := require.New(t) + + upAction := upgradeAction(t) + rel := releaseStub() + rel.Name = "previous-release" + rel.Info.Status = rcommon.StatusDeployed + req.NoError(upAction.cfg.Releases.Create(rel)) + + upAction.ChartSource = "https://charts.example.com/repo" + + // Same probe as the install path: a template that renders the chart's + // annotations. If the source were recorded before rendering, it would leak + // into the manifest via .Chart.Annotations. + tmpl := []*common.File{ + {Name: "templates/cfg", ModTime: time.Now(), Data: []byte("annotations: {{ .Chart.Annotations }}")}, + } + resi, err := upAction.RunWithContext(t.Context(), rel.Name, buildChartWithTemplates(tmpl), map[string]any{}) + req.NoError(err) + res, err := releaserToV1Release(resi) + req.NoError(err) + + // The recorded source must not appear in the rendered manifest. + is.NotContains(res.Manifest, "https://charts.example.com/repo") + is.NotContains(res.Manifest, ReleaseSourceAnnotation) + + // The persisted upgraded release must carry the source annotation. + stored, err := upAction.cfg.Releases.Last(rel.Name) + req.NoError(err) + last, err := releaserToV1Release(stored) + req.NoError(err) + is.Equal("https://charts.example.com/repo", last.Chart.Metadata.Annotations[ReleaseSourceAnnotation]) +} + func TestInstallReleaseWithTakeOwnership_ResourceNotOwned(t *testing.T) { // This test will test checking ownership of a resource // returned by the fake client. If the resource is not