From 088959aae9be561214070b93abd8b4d17059fc07 Mon Sep 17 00:00:00 2001 From: Benoit Tigeot Date: Wed, 25 Feb 2026 01:17:28 +0100 Subject: [PATCH] fix(schema): enable $ref resolution for directory charts Set ChartDir only for directory-based charts to enable $ref resolution in JSON schemas. Archived charts (.tgz) are loaded into memory without filesystem extraction, so $ref resolution is not supported for them. This fixes the original issue where `helm template .` and `helm install .` failed to validate schemas with relative $ref references. Fixes #31260 Signed-off-by: Benoit Tigeot --- pkg/cmd/install.go | 7 +++++++ pkg/cmd/install_test.go | 5 +++++ pkg/cmd/template_test.go | 5 +++++ pkg/cmd/testdata/output/schema-ref.txt | 7 +++++++ pkg/cmd/testdata/output/template-schema-ref.txt | 1 + pkg/cmd/testdata/output/upgrade-schema-ref.txt | 8 ++++++++ .../testdata/testcharts/chart-with-schema-ref/Chart.yaml | 3 +++ .../testcharts/chart-with-schema-ref/name.schema.json | 4 ++++ .../testcharts/chart-with-schema-ref/values.schema.json | 7 +++++++ .../testdata/testcharts/chart-with-schema-ref/values.yaml | 1 + pkg/cmd/upgrade.go | 7 +++++++ pkg/cmd/upgrade_test.go | 6 ++++++ 12 files changed, 61 insertions(+) create mode 100644 pkg/cmd/testdata/output/schema-ref.txt create mode 100644 pkg/cmd/testdata/output/template-schema-ref.txt create mode 100644 pkg/cmd/testdata/output/upgrade-schema-ref.txt create mode 100644 pkg/cmd/testdata/testcharts/chart-with-schema-ref/Chart.yaml create mode 100644 pkg/cmd/testdata/testcharts/chart-with-schema-ref/name.schema.json create mode 100644 pkg/cmd/testdata/testcharts/chart-with-schema-ref/values.schema.json create mode 100644 pkg/cmd/testdata/testcharts/chart-with-schema-ref/values.yaml diff --git a/pkg/cmd/install.go b/pkg/cmd/install.go index d36cd9e34..10473c5d9 100644 --- a/pkg/cmd/install.go +++ b/pkg/cmd/install.go @@ -248,6 +248,13 @@ func runInstall(args []string, client *action.Install, valueOpts *values.Options return nil, err } + // Only set ChartDir for directory-based charts to enable $ref resolution. + // Archived charts (.tgz) are loaded into memory without filesystem extraction, + // so $ref resolution is not supported for them. + if fi, err := os.Stat(cp); err == nil && fi.IsDir() { + client.ChartDir = cp + } + slog.Debug("Chart path", "path", cp) p := getter.All(settings) diff --git a/pkg/cmd/install_test.go b/pkg/cmd/install_test.go index 5fa3c1340..3a88a9aa6 100644 --- a/pkg/cmd/install_test.go +++ b/pkg/cmd/install_test.go @@ -231,6 +231,11 @@ func TestInstall(t *testing.T) { cmd: "install schema testdata/testcharts/chart-with-schema-and-subchart --set lastname=doe --set subchart-with-schema.age=-25 --skip-schema-validation", golden: "output/schema.txt", }, + { + name: "install with schema file containing $ref", + cmd: "install reftest testdata/testcharts/chart-with-schema-ref", + golden: "output/schema-ref.txt", + }, // Install deprecated chart { name: "install with warning about deprecated chart", diff --git a/pkg/cmd/template_test.go b/pkg/cmd/template_test.go index 5bcccf5d0..6bfa29743 100644 --- a/pkg/cmd/template_test.go +++ b/pkg/cmd/template_test.go @@ -166,6 +166,11 @@ func TestTemplateCmd(t *testing.T) { cmd: fmt.Sprintf("template '%s' -f %s/extra_values.yaml", chartPath, chartPath), golden: "output/template-subchart-cm-set-file.txt", }, + { + name: "template with schema file containing $ref", + cmd: "template reftest testdata/testcharts/chart-with-schema-ref", + golden: "output/template-schema-ref.txt", + }, } runTestCmd(t, tests) } diff --git a/pkg/cmd/testdata/output/schema-ref.txt b/pkg/cmd/testdata/output/schema-ref.txt new file mode 100644 index 000000000..fa6015315 --- /dev/null +++ b/pkg/cmd/testdata/output/schema-ref.txt @@ -0,0 +1,7 @@ +NAME: reftest +LAST DEPLOYED: Fri Sep 2 22:04:05 1977 +NAMESPACE: default +STATUS: deployed +REVISION: 1 +DESCRIPTION: Install complete +TEST SUITE: None diff --git a/pkg/cmd/testdata/output/template-schema-ref.txt b/pkg/cmd/testdata/output/template-schema-ref.txt new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/pkg/cmd/testdata/output/template-schema-ref.txt @@ -0,0 +1 @@ + diff --git a/pkg/cmd/testdata/output/upgrade-schema-ref.txt b/pkg/cmd/testdata/output/upgrade-schema-ref.txt new file mode 100644 index 000000000..cceed6919 --- /dev/null +++ b/pkg/cmd/testdata/output/upgrade-schema-ref.txt @@ -0,0 +1,8 @@ +Release "reftest" has been upgraded. Happy Helming! +NAME: reftest +LAST DEPLOYED: Fri Sep 2 22:04:05 1977 +NAMESPACE: default +STATUS: deployed +REVISION: 2 +DESCRIPTION: Upgrade complete +TEST SUITE: None diff --git a/pkg/cmd/testdata/testcharts/chart-with-schema-ref/Chart.yaml b/pkg/cmd/testdata/testcharts/chart-with-schema-ref/Chart.yaml new file mode 100644 index 000000000..c344a04d9 --- /dev/null +++ b/pkg/cmd/testdata/testcharts/chart-with-schema-ref/Chart.yaml @@ -0,0 +1,3 @@ +apiVersion: v2 +name: chart-with-schema-ref +version: 0.1.0 diff --git a/pkg/cmd/testdata/testcharts/chart-with-schema-ref/name.schema.json b/pkg/cmd/testdata/testcharts/chart-with-schema-ref/name.schema.json new file mode 100644 index 000000000..290e9cca5 --- /dev/null +++ b/pkg/cmd/testdata/testcharts/chart-with-schema-ref/name.schema.json @@ -0,0 +1,4 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "string" +} diff --git a/pkg/cmd/testdata/testcharts/chart-with-schema-ref/values.schema.json b/pkg/cmd/testdata/testcharts/chart-with-schema-ref/values.schema.json new file mode 100644 index 000000000..e253c4c7e --- /dev/null +++ b/pkg/cmd/testdata/testcharts/chart-with-schema-ref/values.schema.json @@ -0,0 +1,7 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "name": { "$ref": "name.schema.json" } + } +} diff --git a/pkg/cmd/testdata/testcharts/chart-with-schema-ref/values.yaml b/pkg/cmd/testdata/testcharts/chart-with-schema-ref/values.yaml new file mode 100644 index 000000000..0b9fc7e3a --- /dev/null +++ b/pkg/cmd/testdata/testcharts/chart-with-schema-ref/values.yaml @@ -0,0 +1 @@ +name: "test" diff --git a/pkg/cmd/upgrade.go b/pkg/cmd/upgrade.go index b71c4ae2d..386107c52 100644 --- a/pkg/cmd/upgrade.go +++ b/pkg/cmd/upgrade.go @@ -187,6 +187,13 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { return err } + // Only set ChartDir for directory-based charts to enable $ref resolution. + // Archived charts (.tgz) are loaded into memory without filesystem extraction, + // so $ref resolution is not supported for them. + if fi, err := os.Stat(chartPath); err == nil && fi.IsDir() { + client.ChartDir = chartPath + } + p := getter.All(settings) vals, err := valueOpts.MergeValues(p) if err != nil { diff --git a/pkg/cmd/upgrade_test.go b/pkg/cmd/upgrade_test.go index 0ae1e3561..0c7ef5671 100644 --- a/pkg/cmd/upgrade_test.go +++ b/pkg/cmd/upgrade_test.go @@ -190,6 +190,12 @@ func TestUpgradeCmd(t *testing.T) { golden: "output/upgrade-uninstalled-with-keep-history.txt", rels: []*release.Release{relWithStatusMock("funny-bunny", 2, ch, rcommon.StatusUninstalled)}, }, + { + name: "upgrade with schema file containing $ref", + cmd: "upgrade reftest testdata/testcharts/chart-with-schema-ref", + golden: "output/upgrade-schema-ref.txt", + rels: []*release.Release{relMock("reftest", 1, ch)}, + }, } runTestCmd(t, tests) }