Repository: helm/chart-testing
Pull request #725 (2025-03-20 13:18:22)

Fix chart_schema.yaml import-values rule
**What this PR does / why we need it**:

The existing rule for validating dependency import-values worked well for either of these two cases:

**1. Importing exports**

```yaml
dependencies:
- name: dep1
  version: 0.14.1
  repository: oci://myrepo
  import-values:
    - data
```

**2. Importing child values into the parent**

```yaml
dependencies:
- name: dep1
  version: 0.14.1
  repository: oci://myrepo
  import-values:
    - child: default.data
      parent: myimports
```

However, it failed on the following valid usecase:

```yaml
dependencies:
- name: dep1
  version: 0.14.1
  repository: oci://myrepo
  import-values:
    - data
    - child: default.data
      parent: myimports
```

Giving the following error:

```
dependencies.0.import-values.1: '{'parent': 'myimports', 'child': 'default.data'}' is not a str.
dependencies.0.import-values.0 : 'data' is not a map
```

This is because the Yamale is validating on a list of strings *or* a list of `import-value`, where a list containing both is also valid.

This commit changes the rule to allow both methods to be in the `import-values` list.

github-actions[bot]: This PR is stale because it has been open 45 days with no activity. Remove stale label or comment or this will be closed in 10 days.
forquare: Today I have posted in the #helm-chart-testing Slack channel hoping to make some progress with the PR and to remove the `stale` label.

Patch:
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index fd0d6fc..2178216 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -20,7 +20,7 @@ jobs:
         uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 # v2.0.0
 
       - name: Setup go
-        uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
+        uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
         with:
           go-version-file: './go.mod'
           check-latest: true
@@ -36,7 +36,7 @@ jobs:
         uses: sigstore/cosign-installer@3454372f43399081ed03b604cb2d021dabca52bb # v3.8.2
 
       - name: Install syft
-        uses: anchore/sbom-action/download-syft@9f7302141466aa6482940f15371237e9d9f4c34a # v0.19.0
+        uses: anchore/sbom-action/download-syft@e11c554f704a0b820cbf8c51673f6945e0731532 # v0.20.0
 
       - name: Install k8s Kind
         uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.3.0
@@ -81,7 +81,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
-      - uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
+      - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
         with:
           go-version-file: './go.mod'
           check-latest: true
@@ -102,7 +102,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
-      - uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
+      - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
         with:
           go-version-file: './go.mod'
           check-latest: true
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index 60d9941..f1559e0 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -25,7 +25,7 @@ jobs:
         uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 # v2.0.0
 
       - name: Setup go
-        uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
+        uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
         with:
           go-version-file: './go.mod'
           check-latest: true
@@ -39,7 +39,7 @@ jobs:
         uses: sigstore/cosign-installer@3454372f43399081ed03b604cb2d021dabca52bb # v3.8.2
 
       - name: Install syft
-        uses: anchore/sbom-action/download-syft@9f7302141466aa6482940f15371237e9d9f4c34a # v0.19.0
+        uses: anchore/sbom-action/download-syft@e11c554f704a0b820cbf8c51673f6945e0731532 # v0.20.0
 
       - name: Install tools
         run: |
diff --git a/etc/chart_schema.yaml b/etc/chart_schema.yaml
index 2a26d9b..e3cd46a 100644
--- a/etc/chart_schema.yaml
+++ b/etc/chart_schema.yaml
@@ -29,7 +29,7 @@ dependency:
   condition: str(required=False)
   tags: list(str(), required=False)
   enabled: bool(required=False)
-  import-values: any(list(str()), list(include('import-value')), required=False)
+  import-values: list(any(str(), include('import-value')), required=False)
   alias: str(required=False)
 ---
 import-value:
diff --git a/go.mod b/go.mod
index 5a2f717..f03d07e 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
 module github.com/helm/chart-testing/v3
 
-go 1.23
+go 1.24.0
 
 require (
 	github.com/MakeNowJust/heredoc v1.0.0
@@ -14,7 +14,7 @@ require (
 	github.com/spf13/viper v1.20.1
 	github.com/stretchr/testify v1.10.0
 	gopkg.in/yaml.v2 v2.4.0
-	helm.sh/helm/v3 v3.16.4
+	helm.sh/helm/v3 v3.18.0
 )
 
 require (
@@ -37,8 +37,8 @@ require (
 	github.com/subosito/gotenv v1.6.0 // indirect
 	go.uber.org/atomic v1.9.0 // indirect
 	go.uber.org/multierr v1.9.0 // indirect
-	golang.org/x/sys v0.29.0 // indirect
-	golang.org/x/text v0.21.0 // indirect
+	golang.org/x/sys v0.33.0 // indirect
+	golang.org/x/text v0.24.0 // indirect
 	gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 )
diff --git a/go.sum b/go.sum
index 0e4e7da..a57ea59 100644
--- a/go.sum
+++ b/go.sum
@@ -16,8 +16,8 @@ github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/
 github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
 github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
 github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
-github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
-github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
+github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
 github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
 github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
 github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
@@ -83,10 +83,10 @@ go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
 go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
 go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
 go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
-golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
-golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
-golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
+golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
+golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
+golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
@@ -94,5 +94,5 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-helm.sh/helm/v3 v3.16.4 h1:rBn/h9MACw+QlhxQTjpl8Ifx+VTWaYsw3rguGBYBzr0=
-helm.sh/helm/v3 v3.16.4/go.mod h1:k8QPotUt57wWbi90w3LNmg3/MWcLPigVv+0/X4B8BzA=
+helm.sh/helm/v3 v3.18.0 h1:ItOAm3Quo0dus3NUHjs+lluqWWEIO7xrSW+zKWCrvlw=
+helm.sh/helm/v3 v3.18.0/go.mod h1:43QHS1W97RcoFJRk36ZBhHdTfykqBlJdsWp3yhzdq8w=
diff --git a/pkg/chart/chart.go b/pkg/chart/chart.go
index 227ecc7..bf58b27 100644
--- a/pkg/chart/chart.go
+++ b/pkg/chart/chart.go
@@ -79,7 +79,8 @@ type Git interface {
 // InstallWithValues runs `helm install` for the given chart using the specified values file.
 // Pass a zero value for valuesFile in order to run install without specifying a values file.
 //
-// Upgrade runs `helm upgrade` against an existing release, and re-uses the previously computed values.
+// UpgradeWithValues runs `helm upgrade` against an existing release using the specified values file.
+// Pass a zero value for valuesFile in order to run install without specifying a values file.
 //
 // Test runs `helm test` against an existing release. Set the cleanup argument to true in order
 // to clean up test pods created by helm after the test command completes.
@@ -91,7 +92,7 @@ type Helm interface {
 	BuildDependenciesWithArgs(chart string, extraArgs []string) error
 	LintWithValues(chart string, valuesFile string) error
 	InstallWithValues(chart string, valuesFile string, namespace string, release string) error
-	Upgrade(chart string, namespace string, release string) error
+	UpgradeWithValues(chart string, valuesFile string, namespace string, release string) error
 	Test(namespace string, release string) error
 	DeleteRelease(namespace string, release string)
 	Version() (string, error)
@@ -660,7 +661,7 @@ func (t *Testing) doUpgrade(oldChart, newChart *Chart, oldChartMustPass bool) er
 				return nil
 			}
 
-			if err := t.helm.Upgrade(newChart.Path(), namespace, release); err != nil {
+			if err := t.helm.UpgradeWithValues(newChart.Path(), valuesFile, namespace, release); err != nil {
 				return err
 			}
 
diff --git a/pkg/tool/helm.go b/pkg/tool/helm.go
index 42724b0..024934a 100644
--- a/pkg/tool/helm.go
+++ b/pkg/tool/helm.go
@@ -75,9 +75,14 @@ func (h Helm) InstallWithValues(chart string, valuesFile string, namespace strin
 		"--wait", values, h.extraArgs, h.extraSetArgs)
 }
 
-func (h Helm) Upgrade(chart string, namespace string, release string) error {
+func (h Helm) UpgradeWithValues(chart string, valuesFile string, namespace string, release string) error {
+	var values []string
+	if valuesFile != "" {
+		values = []string{"--values", valuesFile}
+	}
+
 	return h.exec.RunProcess("helm", "upgrade", release, chart, "--namespace", namespace,
-		"--reuse-values", "--wait", h.extraArgs, h.extraSetArgs)
+		"--wait", values, h.extraArgs, h.extraSetArgs)
 }
 
 func (h Helm) Test(namespace string, release string) error {


Test patch:
diff --git a/pkg/chart/chart_test.go b/pkg/chart/chart_test.go
index 901677c..b95dd9e 100644
--- a/pkg/chart/chart_test.go
+++ b/pkg/chart/chart_test.go
@@ -111,7 +111,7 @@ func (h *fakeHelm) LintWithValues(_ string, _ string) error { return nil }
 func (h *fakeHelm) InstallWithValues(_ string, _ string, _ string, _ string) error {
 	return nil
 }
-func (h *fakeHelm) Upgrade(_ string, _ string, _ string) error {
+func (h *fakeHelm) UpgradeWithValues(_ string, _ string, _ string, _ string) error {
 	return nil
 }
 func (h *fakeHelm) Test(_ string, _ string) error {