From 0b5649614dcffbf02e275c479c933416c51d5445 Mon Sep 17 00:00:00 2001 From: Evans Mungai Date: Sat, 29 Nov 2025 15:36:02 +0000 Subject: [PATCH 1/4] feat(create): add hidden --chart-api-version flag Add --chart-api-version flag to helm create command to allow selecting chart API version (v2 or v3) when creating a new chart. - Default is v2 (existing behavior unchanged) - v3 uses internal/chart/v3 scaffold generator - Invalid versions return clear error message - Works with --starter flag Signed-off-by: Evans Mungai --- pkg/cmd/create.go | 48 ++++++++- pkg/cmd/create_test.go | 235 +++++++++++++++++++++++++++-------------- 2 files changed, 201 insertions(+), 82 deletions(-) diff --git a/pkg/cmd/create.go b/pkg/cmd/create.go index 435c8ca82..3eddd7f10 100644 --- a/pkg/cmd/create.go +++ b/pkg/cmd/create.go @@ -23,6 +23,8 @@ import ( "github.com/spf13/cobra" + chartv3 "helm.sh/helm/v4/internal/chart/v3" + chartutilv3 "helm.sh/helm/v4/internal/chart/v3/util" chart "helm.sh/helm/v4/pkg/chart/v2" chartutil "helm.sh/helm/v4/pkg/chart/v2/util" "helm.sh/helm/v4/pkg/cmd/require" @@ -51,9 +53,10 @@ will be overwritten, but other files will be left alone. ` type createOptions struct { - starter string // --starter - name string - starterDir string + starter string // --starter + name string + starterDir string + chartAPIVersion string // --chart-api-version } func newCreateCmd(out io.Writer) *cobra.Command { @@ -81,12 +84,25 @@ func newCreateCmd(out io.Writer) *cobra.Command { } cmd.Flags().StringVarP(&o.starter, "starter", "p", "", "the name or absolute path to Helm starter scaffold") + cmd.Flags().StringVar(&o.chartAPIVersion, "chart-api-version", chart.APIVersionV2, "chart API version to use (v2 or v3)") + return cmd } func (o *createOptions) run(out io.Writer) error { fmt.Fprintf(out, "Creating %s\n", o.name) + switch o.chartAPIVersion { + case chart.APIVersionV2, "": + return o.createV2Chart(out) + case chartv3.APIVersionV3: + return o.createV3Chart(out) + default: + return fmt.Errorf("unsupported chart API version: %s (supported: v2, v3)", o.chartAPIVersion) + } +} + +func (o *createOptions) createV2Chart(out io.Writer) error { chartname := filepath.Base(o.name) cfile := &chart.Metadata{ Name: chartname, @@ -111,3 +127,29 @@ func (o *createOptions) run(out io.Writer) error { _, err := chartutil.Create(chartname, filepath.Dir(o.name)) return err } + +func (o *createOptions) createV3Chart(out io.Writer) error { + chartname := filepath.Base(o.name) + cfile := &chartv3.Metadata{ + Name: chartname, + Description: "A Helm chart for Kubernetes", + Type: "application", + Version: "0.1.0", + AppVersion: "0.1.0", + APIVersion: chartv3.APIVersionV3, + } + + if o.starter != "" { + // Create from the starter + lstarter := filepath.Join(o.starterDir, o.starter) + // If path is absolute, we don't want to prefix it with helm starters folder + if filepath.IsAbs(o.starter) { + lstarter = o.starter + } + return chartutilv3.CreateFrom(cfile, filepath.Dir(o.name), lstarter) + } + + chartutilv3.Stderr = out + _, err := chartutilv3.Create(chartname, filepath.Dir(o.name)) + return err +} diff --git a/pkg/cmd/create_test.go b/pkg/cmd/create_test.go index 90ed90eff..9f1c6e5c8 100644 --- a/pkg/cmd/create_test.go +++ b/pkg/cmd/create_test.go @@ -22,6 +22,9 @@ import ( "path/filepath" "testing" + chartv3 "helm.sh/helm/v4/internal/chart/v3" + loaderv3 "helm.sh/helm/v4/internal/chart/v3/loader" + chartutilv3 "helm.sh/helm/v4/internal/chart/v3/util" "helm.sh/helm/v4/internal/test/ensure" chart "helm.sh/helm/v4/pkg/chart/v2" "helm.sh/helm/v4/pkg/chart/v2/loader" @@ -60,27 +63,142 @@ func TestCreateCmd(t *testing.T) { } func TestCreateStarterCmd(t *testing.T) { + tests := []struct { + name string + chartAPIVersion string + useAbsolutePath bool + expectedVersion string + }{ + { + name: "v2 with relative starter path", + chartAPIVersion: "", + useAbsolutePath: false, + expectedVersion: chart.APIVersionV2, + }, + { + name: "v2 with absolute starter path", + chartAPIVersion: "", + useAbsolutePath: true, + expectedVersion: chart.APIVersionV2, + }, + { + name: "v3 with relative starter path", + chartAPIVersion: "v3", + useAbsolutePath: false, + expectedVersion: chartv3.APIVersionV3, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Chdir(t.TempDir()) + ensure.HelmHome(t) + defer resetEnv()() + cname := "testchart" + + // Create a starter using the appropriate chartutil + starterchart := helmpath.DataPath("starters") + os.MkdirAll(starterchart, 0o755) + var err error + var dest string + if tt.chartAPIVersion == "v3" { + dest, err = chartutilv3.Create("starterchart", starterchart) + } else { + dest, err = chartutil.Create("starterchart", starterchart) + } + if err != nil { + t.Fatalf("Could not create chart: %s", err) + } + t.Logf("Created %s", dest) + + tplpath := filepath.Join(starterchart, "starterchart", "templates", "foo.tpl") + if err := os.WriteFile(tplpath, []byte("test"), 0o644); err != nil { + t.Fatalf("Could not write template: %s", err) + } + + // Build the command + starterArg := "starterchart" + if tt.useAbsolutePath { + starterArg = filepath.Join(starterchart, "starterchart") + } + cmd := fmt.Sprintf("create --starter=%s", starterArg) + if tt.chartAPIVersion != "" { + cmd += fmt.Sprintf(" --chart-api-version=%s", tt.chartAPIVersion) + } + cmd += " " + cname + + // Run create + if _, _, err := executeActionCommand(cmd); err != nil { + t.Fatalf("Failed to run create: %s", err) + } + + // Test that the chart is there + if fi, err := os.Stat(cname); err != nil { + t.Fatalf("no chart directory: %s", err) + } else if !fi.IsDir() { + t.Fatalf("chart is not directory") + } + + // Load and verify the chart + var chartName, apiVersion string + var templates []string + if tt.chartAPIVersion == "v3" { + c, err := loaderv3.LoadDir(cname) + if err != nil { + t.Fatal(err) + } + chartName = c.Name() + apiVersion = c.Metadata.APIVersion + for _, tpl := range c.Templates { + templates = append(templates, tpl.Name) + } + } else { + c, err := loader.LoadDir(cname) + if err != nil { + t.Fatal(err) + } + chartName = c.Name() + apiVersion = c.Metadata.APIVersion + for _, tpl := range c.Templates { + templates = append(templates, tpl.Name) + } + } + + if chartName != cname { + t.Errorf("Expected %q name, got %q", cname, chartName) + } + if apiVersion != tt.expectedVersion { + t.Errorf("Wrong API version: expected %q, got %q", tt.expectedVersion, apiVersion) + } + + // Verify custom template exists + found := false + for _, name := range templates { + if name == "templates/foo.tpl" { + found = true + break + } + } + if !found { + t.Error("Did not find foo.tpl") + } + }) + } +} + +func TestCreateFileCompletion(t *testing.T) { + checkFileCompletion(t, "create", true) + checkFileCompletion(t, "create myname", false) +} + +func TestCreateCmdChartAPIVersionV2(t *testing.T) { t.Chdir(t.TempDir()) ensure.HelmHome(t) cname := "testchart" - defer resetEnv()() - // Create a starter. - starterchart := helmpath.DataPath("starters") - os.MkdirAll(starterchart, 0o755) - if dest, err := chartutil.Create("starterchart", starterchart); err != nil { - t.Fatalf("Could not create chart: %s", err) - } else { - t.Logf("Created %s", dest) - } - tplpath := filepath.Join(starterchart, "starterchart", "templates", "foo.tpl") - if err := os.WriteFile(tplpath, []byte("test"), 0o644); err != nil { - t.Fatalf("Could not write template: %s", err) - } - // Run a create - if _, _, err := executeActionCommand(fmt.Sprintf("create --starter=starterchart %s", cname)); err != nil { - t.Errorf("Failed to run create: %s", err) - return + // Run a create with explicit v2 + if _, _, err := executeActionCommand("create --chart-api-version=v2 " + cname); err != nil { + t.Fatalf("Failed to run create: %s", err) } // Test that the chart is there @@ -99,53 +217,18 @@ func TestCreateStarterCmd(t *testing.T) { t.Errorf("Expected %q name, got %q", cname, c.Name()) } if c.Metadata.APIVersion != chart.APIVersionV2 { - t.Errorf("Wrong API version: %q", c.Metadata.APIVersion) - } - - expectedNumberOfTemplates := 10 - if l := len(c.Templates); l != expectedNumberOfTemplates { - t.Errorf("Expected %d templates, got %d", expectedNumberOfTemplates, l) - } - - found := false - for _, tpl := range c.Templates { - if tpl.Name == "templates/foo.tpl" { - found = true - if data := string(tpl.Data); data != "test" { - t.Errorf("Expected template 'test', got %q", data) - } - } - } - if !found { - t.Error("Did not find foo.tpl") + t.Errorf("Wrong API version: expected %q, got %q", chart.APIVersionV2, c.Metadata.APIVersion) } } -func TestCreateStarterAbsoluteCmd(t *testing.T) { +func TestCreateCmdChartAPIVersionV3(t *testing.T) { t.Chdir(t.TempDir()) - defer resetEnv()() ensure.HelmHome(t) cname := "testchart" - // Create a starter. - starterchart := helmpath.DataPath("starters") - os.MkdirAll(starterchart, 0o755) - if dest, err := chartutil.Create("starterchart", starterchart); err != nil { - t.Fatalf("Could not create chart: %s", err) - } else { - t.Logf("Created %s", dest) - } - tplpath := filepath.Join(starterchart, "starterchart", "templates", "foo.tpl") - if err := os.WriteFile(tplpath, []byte("test"), 0o644); err != nil { - t.Fatalf("Could not write template: %s", err) - } - - starterChartPath := filepath.Join(starterchart, "starterchart") - - // Run a create - if _, _, err := executeActionCommand(fmt.Sprintf("create --starter=%s %s", starterChartPath, cname)); err != nil { - t.Errorf("Failed to run create: %s", err) - return + // Run a create with v3 + if _, _, err := executeActionCommand("create --chart-api-version=v3 " + cname); err != nil { + t.Fatalf("Failed to run create: %s", err) } // Test that the chart is there @@ -155,7 +238,7 @@ func TestCreateStarterAbsoluteCmd(t *testing.T) { t.Fatalf("chart is not directory") } - c, err := loader.LoadDir(cname) + c, err := loaderv3.LoadDir(cname) if err != nil { t.Fatal(err) } @@ -163,30 +246,24 @@ func TestCreateStarterAbsoluteCmd(t *testing.T) { if c.Name() != cname { t.Errorf("Expected %q name, got %q", cname, c.Name()) } - if c.Metadata.APIVersion != chart.APIVersionV2 { - t.Errorf("Wrong API version: %q", c.Metadata.APIVersion) + if c.Metadata.APIVersion != chartv3.APIVersionV3 { + t.Errorf("Wrong API version: expected %q, got %q", chartv3.APIVersionV3, c.Metadata.APIVersion) } +} - expectedNumberOfTemplates := 10 - if l := len(c.Templates); l != expectedNumberOfTemplates { - t.Errorf("Expected %d templates, got %d", expectedNumberOfTemplates, l) - } +func TestCreateCmdInvalidChartAPIVersion(t *testing.T) { + t.Chdir(t.TempDir()) + ensure.HelmHome(t) + cname := "testchart" - found := false - for _, tpl := range c.Templates { - if tpl.Name == "templates/foo.tpl" { - found = true - if data := string(tpl.Data); data != "test" { - t.Errorf("Expected template 'test', got %q", data) - } - } - } - if !found { - t.Error("Did not find foo.tpl") + // Run a create with invalid version + _, _, err := executeActionCommand("create --chart-api-version=v1 " + cname) + if err == nil { + t.Fatal("Expected error for invalid API version, got nil") } -} -func TestCreateFileCompletion(t *testing.T) { - checkFileCompletion(t, "create", true) - checkFileCompletion(t, "create myname", false) + expectedErr := "unsupported chart API version: v1 (supported: v2, v3)" + if err.Error() != expectedErr { + t.Errorf("Expected error %q, got %q", expectedErr, err.Error()) + } } From bb26682b6e37c487aa00494b0a1e824ea620c002 Mon Sep 17 00:00:00 2001 From: Evans Mungai Date: Tue, 2 Dec 2025 07:06:08 +0000 Subject: [PATCH 2/4] Add HELM_EXPERIMENTAL_CHART_V3 feature gate to create command Signed-off-by: Evans Mungai --- pkg/cmd/create.go | 4 ++++ pkg/cmd/create_test.go | 8 ++++++++ pkg/gates/gates.go | 3 +++ 3 files changed, 15 insertions(+) diff --git a/pkg/cmd/create.go b/pkg/cmd/create.go index 3eddd7f10..c3c2e3c2d 100644 --- a/pkg/cmd/create.go +++ b/pkg/cmd/create.go @@ -28,6 +28,7 @@ import ( chart "helm.sh/helm/v4/pkg/chart/v2" chartutil "helm.sh/helm/v4/pkg/chart/v2/util" "helm.sh/helm/v4/pkg/cmd/require" + "helm.sh/helm/v4/pkg/gates" "helm.sh/helm/v4/pkg/helmpath" ) @@ -96,6 +97,9 @@ func (o *createOptions) run(out io.Writer) error { case chart.APIVersionV2, "": return o.createV2Chart(out) case chartv3.APIVersionV3: + if !gates.ChartV3.IsEnabled() { + return gates.ChartV3.Error() + } return o.createV3Chart(out) default: return fmt.Errorf("unsupported chart API version: %s (supported: v2, v3)", o.chartAPIVersion) diff --git a/pkg/cmd/create_test.go b/pkg/cmd/create_test.go index 9f1c6e5c8..554d5f1af 100644 --- a/pkg/cmd/create_test.go +++ b/pkg/cmd/create_test.go @@ -29,6 +29,7 @@ import ( chart "helm.sh/helm/v4/pkg/chart/v2" "helm.sh/helm/v4/pkg/chart/v2/loader" chartutil "helm.sh/helm/v4/pkg/chart/v2/util" + "helm.sh/helm/v4/pkg/gates" "helm.sh/helm/v4/pkg/helmpath" ) @@ -94,6 +95,12 @@ func TestCreateStarterCmd(t *testing.T) { t.Chdir(t.TempDir()) ensure.HelmHome(t) defer resetEnv()() + + // Enable feature gate for v3 charts + if tt.chartAPIVersion == "v3" { + t.Setenv(string(gates.ChartV3), "1") + } + cname := "testchart" // Create a starter using the appropriate chartutil @@ -224,6 +231,7 @@ func TestCreateCmdChartAPIVersionV2(t *testing.T) { func TestCreateCmdChartAPIVersionV3(t *testing.T) { t.Chdir(t.TempDir()) ensure.HelmHome(t) + t.Setenv(string(gates.ChartV3), "1") cname := "testchart" // Run a create with v3 diff --git a/pkg/gates/gates.go b/pkg/gates/gates.go index 69559219e..a6787c789 100644 --- a/pkg/gates/gates.go +++ b/pkg/gates/gates.go @@ -36,3 +36,6 @@ func (g Gate) IsEnabled() bool { func (g Gate) Error() error { return fmt.Errorf("this feature has been marked as experimental and is not enabled by default. Please set %s=1 in your environment to use this feature", g.String()) } + +// ChartV3 is the feature gate for chart API version v3. +const ChartV3 Gate = "HELM_EXPERIMENTAL_CHART_V3" From 1676abc7421fb4d5f9aece448450fa602cd703c9 Mon Sep 17 00:00:00 2001 From: Evans Mungai Date: Thu, 4 Dec 2025 17:38:22 +0000 Subject: [PATCH 3/4] make chartv3 private and use loader to load the chart Signed-off-by: Evans Mungai --- pkg/cmd/create.go | 7 ++- pkg/cmd/create_test.go | 120 +++++++++++++++++++++++++---------------- pkg/gates/gates.go | 3 -- 3 files changed, 79 insertions(+), 51 deletions(-) diff --git a/pkg/cmd/create.go b/pkg/cmd/create.go index c3c2e3c2d..263466c9f 100644 --- a/pkg/cmd/create.go +++ b/pkg/cmd/create.go @@ -60,6 +60,9 @@ type createOptions struct { chartAPIVersion string // --chart-api-version } +// ChartV3 is the feature gate for chart API version v3. +const chartV3 gates.Gate = "HELM_EXPERIMENTAL_CHART_V3" + func newCreateCmd(out io.Writer) *cobra.Command { o := &createOptions{} @@ -97,8 +100,8 @@ func (o *createOptions) run(out io.Writer) error { case chart.APIVersionV2, "": return o.createV2Chart(out) case chartv3.APIVersionV3: - if !gates.ChartV3.IsEnabled() { - return gates.ChartV3.Error() + if !chartV3.IsEnabled() { + return chartV3.Error() } return o.createV3Chart(out) default: diff --git a/pkg/cmd/create_test.go b/pkg/cmd/create_test.go index 554d5f1af..3ecbb5387 100644 --- a/pkg/cmd/create_test.go +++ b/pkg/cmd/create_test.go @@ -23,13 +23,12 @@ import ( "testing" chartv3 "helm.sh/helm/v4/internal/chart/v3" - loaderv3 "helm.sh/helm/v4/internal/chart/v3/loader" chartutilv3 "helm.sh/helm/v4/internal/chart/v3/util" "helm.sh/helm/v4/internal/test/ensure" - chart "helm.sh/helm/v4/pkg/chart/v2" - "helm.sh/helm/v4/pkg/chart/v2/loader" + chart "helm.sh/helm/v4/pkg/chart" + chartloader "helm.sh/helm/v4/pkg/chart/loader" + chartv2 "helm.sh/helm/v4/pkg/chart/v2" chartutil "helm.sh/helm/v4/pkg/chart/v2/util" - "helm.sh/helm/v4/pkg/gates" "helm.sh/helm/v4/pkg/helmpath" ) @@ -50,16 +49,26 @@ func TestCreateCmd(t *testing.T) { t.Fatalf("chart is not directory") } - c, err := loader.LoadDir(cname) + c, err := chartloader.LoadDir(cname) if err != nil { t.Fatal(err) } - if c.Name() != cname { - t.Errorf("Expected %q name, got %q", cname, c.Name()) + acc, err := chart.NewAccessor(c) + if err != nil { + t.Fatal(err) + } + + if acc.Name() != cname { + t.Errorf("Expected %q name, got %q", cname, acc.Name()) } - if c.Metadata.APIVersion != chart.APIVersionV2 { - t.Errorf("Wrong API version: %q", c.Metadata.APIVersion) + metadata := acc.MetadataAsMap() + apiVersion, ok := metadata["APIVersion"].(string) + if !ok { + t.Fatal("APIVersion not found in metadata") + } + if apiVersion != chartv2.APIVersionV2 { + t.Errorf("Wrong API version: %q", apiVersion) } } @@ -74,13 +83,13 @@ func TestCreateStarterCmd(t *testing.T) { name: "v2 with relative starter path", chartAPIVersion: "", useAbsolutePath: false, - expectedVersion: chart.APIVersionV2, + expectedVersion: chartv2.APIVersionV2, }, { name: "v2 with absolute starter path", chartAPIVersion: "", useAbsolutePath: true, - expectedVersion: chart.APIVersionV2, + expectedVersion: chartv2.APIVersionV2, }, { name: "v3 with relative starter path", @@ -98,7 +107,7 @@ func TestCreateStarterCmd(t *testing.T) { // Enable feature gate for v3 charts if tt.chartAPIVersion == "v3" { - t.Setenv(string(gates.ChartV3), "1") + t.Setenv(string(chartV3), "1") } cname := "testchart" @@ -129,8 +138,10 @@ func TestCreateStarterCmd(t *testing.T) { starterArg = filepath.Join(starterchart, "starterchart") } cmd := fmt.Sprintf("create --starter=%s", starterArg) - if tt.chartAPIVersion != "" { - cmd += fmt.Sprintf(" --chart-api-version=%s", tt.chartAPIVersion) + if tt.chartAPIVersion == "v3" { + cmd += fmt.Sprintf(" --chart-api-version=%s", chartv3.APIVersionV3) + } else { + cmd += fmt.Sprintf(" --chart-api-version=%s", chartv2.APIVersionV2) } cmd += " " + cname @@ -147,28 +158,25 @@ func TestCreateStarterCmd(t *testing.T) { } // Load and verify the chart - var chartName, apiVersion string + c, err := chartloader.LoadDir(cname) + if err != nil { + t.Fatal(err) + } + + acc, err := chart.NewAccessor(c) + if err != nil { + t.Fatal(err) + } + + chartName := acc.Name() + metadata := acc.MetadataAsMap() + apiVersion, ok := metadata["APIVersion"].(string) + if !ok { + t.Fatal("APIVersion not found in metadata") + } var templates []string - if tt.chartAPIVersion == "v3" { - c, err := loaderv3.LoadDir(cname) - if err != nil { - t.Fatal(err) - } - chartName = c.Name() - apiVersion = c.Metadata.APIVersion - for _, tpl := range c.Templates { - templates = append(templates, tpl.Name) - } - } else { - c, err := loader.LoadDir(cname) - if err != nil { - t.Fatal(err) - } - chartName = c.Name() - apiVersion = c.Metadata.APIVersion - for _, tpl := range c.Templates { - templates = append(templates, tpl.Name) - } + for _, tpl := range acc.Templates() { + templates = append(templates, tpl.Name) } if chartName != cname { @@ -215,23 +223,33 @@ func TestCreateCmdChartAPIVersionV2(t *testing.T) { t.Fatalf("chart is not directory") } - c, err := loader.LoadDir(cname) + c, err := chartloader.LoadDir(cname) if err != nil { t.Fatal(err) } - if c.Name() != cname { - t.Errorf("Expected %q name, got %q", cname, c.Name()) + acc, err := chart.NewAccessor(c) + if err != nil { + t.Fatal(err) } - if c.Metadata.APIVersion != chart.APIVersionV2 { - t.Errorf("Wrong API version: expected %q, got %q", chart.APIVersionV2, c.Metadata.APIVersion) + + if acc.Name() != cname { + t.Errorf("Expected %q name, got %q", cname, acc.Name()) + } + metadata := acc.MetadataAsMap() + apiVersion, ok := metadata["APIVersion"].(string) + if !ok { + t.Fatal("APIVersion not found in metadata") + } + if apiVersion != chartv2.APIVersionV2 { + t.Errorf("Wrong API version: expected %q, got %q", chartv2.APIVersionV2, apiVersion) } } func TestCreateCmdChartAPIVersionV3(t *testing.T) { t.Chdir(t.TempDir()) ensure.HelmHome(t) - t.Setenv(string(gates.ChartV3), "1") + t.Setenv(string(chartV3), "1") cname := "testchart" // Run a create with v3 @@ -246,16 +264,26 @@ func TestCreateCmdChartAPIVersionV3(t *testing.T) { t.Fatalf("chart is not directory") } - c, err := loaderv3.LoadDir(cname) + c, err := chartloader.LoadDir(cname) if err != nil { t.Fatal(err) } - if c.Name() != cname { - t.Errorf("Expected %q name, got %q", cname, c.Name()) + acc, err := chart.NewAccessor(c) + if err != nil { + t.Fatal(err) + } + + if acc.Name() != cname { + t.Errorf("Expected %q name, got %q", cname, acc.Name()) + } + metadata := acc.MetadataAsMap() + apiVersion, ok := metadata["APIVersion"].(string) + if !ok { + t.Fatal("APIVersion not found in metadata") } - if c.Metadata.APIVersion != chartv3.APIVersionV3 { - t.Errorf("Wrong API version: expected %q, got %q", chartv3.APIVersionV3, c.Metadata.APIVersion) + if apiVersion != chartv3.APIVersionV3 { + t.Errorf("Wrong API version: expected %q, got %q", chartv3.APIVersionV3, apiVersion) } } diff --git a/pkg/gates/gates.go b/pkg/gates/gates.go index a6787c789..69559219e 100644 --- a/pkg/gates/gates.go +++ b/pkg/gates/gates.go @@ -36,6 +36,3 @@ func (g Gate) IsEnabled() bool { func (g Gate) Error() error { return fmt.Errorf("this feature has been marked as experimental and is not enabled by default. Please set %s=1 in your environment to use this feature", g.String()) } - -// ChartV3 is the feature gate for chart API version v3. -const ChartV3 Gate = "HELM_EXPERIMENTAL_CHART_V3" From ed22747448a123f6dd7a67faee1672d7387ab944 Mon Sep 17 00:00:00 2001 From: Evans Mungai Date: Thu, 4 Dec 2025 17:43:24 +0000 Subject: [PATCH 4/4] Hide chart-api-version flag until chart v3 is officially released Signed-off-by: Evans Mungai --- pkg/cmd/create.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/cmd/create.go b/pkg/cmd/create.go index 263466c9f..b12f1cf29 100644 --- a/pkg/cmd/create.go +++ b/pkg/cmd/create.go @@ -89,6 +89,8 @@ func newCreateCmd(out io.Writer) *cobra.Command { cmd.Flags().StringVarP(&o.starter, "starter", "p", "", "the name or absolute path to Helm starter scaffold") cmd.Flags().StringVar(&o.chartAPIVersion, "chart-api-version", chart.APIVersionV2, "chart API version to use (v2 or v3)") + // Hide the flag until chart v3 is officially released + cmd.Flags().MarkHidden("chart-api-version") return cmd }