From 21b9aa3d942bc96df9be7cd8996b5730c49b0ccb Mon Sep 17 00:00:00 2001 From: Zach Burgess Date: Thu, 26 Jun 2025 14:07:54 -0700 Subject: [PATCH 01/19] Lint the `crds/` directory. This checks that the `crds/` dir only contains YAML files that define K8s resources with `kind: CustomResourceDefinition`. Checking that the YAML files are not templates will be done in a separate commit. Signed-off-by: Zach Burgess --- pkg/lint/lint.go | 1 + pkg/lint/lint_test.go | 11 +++ pkg/lint/rules/crds.go | 96 +++++++++++++++++++ pkg/lint/rules/crds_test.go | 51 ++++++++++ pkg/lint/rules/testdata/badcrdfile/Chart.yaml | 6 ++ .../testdata/badcrdfile/crds/bad-crd.yaml | 2 + .../rules/testdata/badcrdfile/values.yaml | 1 + .../rules/testdata/invalidcrdsdir/Chart.yaml | 6 ++ pkg/lint/rules/testdata/invalidcrdsdir/crds | 0 .../rules/testdata/invalidcrdsdir/values.yaml | 1 + pkg/lint/rules/testdata/withcrd/Chart.yaml | 5 + .../rules/testdata/withcrd/crds/test-crd.yaml | 19 ++++ 12 files changed, 199 insertions(+) create mode 100644 pkg/lint/rules/crds.go create mode 100644 pkg/lint/rules/crds_test.go create mode 100644 pkg/lint/rules/testdata/badcrdfile/Chart.yaml create mode 100644 pkg/lint/rules/testdata/badcrdfile/crds/bad-crd.yaml create mode 100644 pkg/lint/rules/testdata/badcrdfile/values.yaml create mode 100644 pkg/lint/rules/testdata/invalidcrdsdir/Chart.yaml create mode 100644 pkg/lint/rules/testdata/invalidcrdsdir/crds create mode 100644 pkg/lint/rules/testdata/invalidcrdsdir/values.yaml create mode 100644 pkg/lint/rules/testdata/withcrd/Chart.yaml create mode 100644 pkg/lint/rules/testdata/withcrd/crds/test-crd.yaml diff --git a/pkg/lint/lint.go b/pkg/lint/lint.go index a61d5e43f..64b2a6057 100644 --- a/pkg/lint/lint.go +++ b/pkg/lint/lint.go @@ -60,6 +60,7 @@ func RunAll(baseDir string, values map[string]interface{}, namespace string, opt rules.ValuesWithOverrides(&result, values) rules.TemplatesWithSkipSchemaValidation(&result, values, namespace, lo.KubeVersion, lo.SkipSchemaValidation) rules.Dependencies(&result) + rules.Crds(&result) return result } diff --git a/pkg/lint/lint_test.go b/pkg/lint/lint_test.go index 888d3dfe6..45e24f533 100644 --- a/pkg/lint/lint_test.go +++ b/pkg/lint/lint_test.go @@ -32,6 +32,7 @@ const namespace = "testNamespace" const badChartDir = "rules/testdata/badchartfile" const badValuesFileDir = "rules/testdata/badvaluesfile" const badYamlFileDir = "rules/testdata/albatross" +const badCrdFileDir = "rules/testdata/badcrdfile" const goodChartDir = "rules/testdata/goodone" const subChartValuesDir = "rules/testdata/withsubchart" const malformedTemplate = "rules/testdata/malformed-template" @@ -111,6 +112,16 @@ func TestBadValues(t *testing.T) { } } +func TestBadCrdFile(t *testing.T) { + m := RunAll(badCrdFileDir, values, namespace).Messages + if len(m) < 1 { + t.Fatalf("All didn't fail with expected errors, got %#v", m) + } + if !strings.Contains(m[0].Err.Error(), "object kind is not 'CustomResourceDefinition'") { + t.Errorf("All didn't have the error for invalid CRD: %s", m[0].Err) + } +} + func TestGoodChart(t *testing.T) { m := RunAll(goodChartDir, values, namespace).Messages if len(m) != 0 { diff --git a/pkg/lint/rules/crds.go b/pkg/lint/rules/crds.go new file mode 100644 index 000000000..bba06ddc3 --- /dev/null +++ b/pkg/lint/rules/crds.go @@ -0,0 +1,96 @@ +/* +Copyright The Helm Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package rules + +import ( + "bytes" + "errors" + "fmt" + "io" + "os" + "path/filepath" + + "k8s.io/apimachinery/pkg/util/yaml" + + "helm.sh/helm/v4/pkg/chart/v2/loader" + "helm.sh/helm/v4/pkg/lint/support" +) + +// Crds lints the CRDs in the Linter. +func Crds(linter *support.Linter) { + fpath := "crds/" + crdsPath := filepath.Join(linter.ChartDir, fpath) + + crdsDirExist := linter.RunLinterRule(support.WarningSev, fpath, validateCrdsDir(crdsPath)) + + // crds directory is optional + if !crdsDirExist { + return + } + + // Load chart and parse CRDs + chart, err := loader.Load(linter.ChartDir) + + chartLoaded := linter.RunLinterRule(support.ErrorSev, fpath, err) + + if !chartLoaded { + return + } + + /* Iterate over all the CRDs to check: + - It is a YAML file + - The kind is CustomResourceDefinition + */ + for _, crd := range chart.CRDObjects() { + fileName := crd.Name + fpath = fileName + + decoder := yaml.NewYAMLOrJSONDecoder(bytes.NewReader(crd.File.Data), 4096) + for { + var yamlStruct *K8sYamlStruct + + err := decoder.Decode(&yamlStruct) + if err == io.EOF { + break + } + + // If YAML linting fails here, it will always fail in the next block as well, so we should return here. + if !linter.RunLinterRule(support.ErrorSev, fpath, validateYamlContent(err)) { + return + } + + linter.RunLinterRule(support.ErrorSev, fpath, validateCrdKind(yamlStruct)) + } + } +} + +// Validation functions +func validateCrdsDir(crdsPath string) error { + if fi, err := os.Stat(crdsPath); err == nil { + if !fi.IsDir() { + return errors.New("not a directory") + } + } + return nil +} + +func validateCrdKind(obj *K8sYamlStruct) error { + if obj.Kind != "CustomResourceDefinition" { + return fmt.Errorf("object kind is not 'CustomResourceDefinition'") + } + return nil +} diff --git a/pkg/lint/rules/crds_test.go b/pkg/lint/rules/crds_test.go new file mode 100644 index 000000000..52432a130 --- /dev/null +++ b/pkg/lint/rules/crds_test.go @@ -0,0 +1,51 @@ +/* +Copyright The Helm Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package rules + +import ( + "strings" + "testing" + + "helm.sh/helm/v4/pkg/lint/support" +) + +const crdsTestBasedir = "./testdata/withcrd" +const invalidCrdsDir = "./testdata/invalidcrdsdir" + +func TestCrdsDir(t *testing.T) { + linter := support.Linter{ChartDir: crdsTestBasedir} + Crds(&linter) + res := linter.Messages + + if len(res) > 0 { + t.Fatalf("Expected no errors, got %d, %v", len(res), res) + } +} + +func TestInvalidCrdsDir(t *testing.T) { + linter := support.Linter{ChartDir: invalidCrdsDir} + Crds(&linter) + res := linter.Messages + + if len(res) != 1 { + t.Fatalf("Expected one error, got %d, %v", len(res), res) + } + + if !strings.Contains(res[0].Err.Error(), "not a directory") { + t.Errorf("Unexpected error: %s", res[0]) + } +} diff --git a/pkg/lint/rules/testdata/badcrdfile/Chart.yaml b/pkg/lint/rules/testdata/badcrdfile/Chart.yaml new file mode 100644 index 000000000..08c4b61ac --- /dev/null +++ b/pkg/lint/rules/testdata/badcrdfile/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +description: A Helm chart for Kubernetes +version: 0.1.0 +name: badcrdfile +type: application +icon: http://riverrun.io diff --git a/pkg/lint/rules/testdata/badcrdfile/crds/bad-crd.yaml b/pkg/lint/rules/testdata/badcrdfile/crds/bad-crd.yaml new file mode 100644 index 000000000..523b97f85 --- /dev/null +++ b/pkg/lint/rules/testdata/badcrdfile/crds/bad-crd.yaml @@ -0,0 +1,2 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: NotACustomResourceDefinition diff --git a/pkg/lint/rules/testdata/badcrdfile/values.yaml b/pkg/lint/rules/testdata/badcrdfile/values.yaml new file mode 100644 index 000000000..2fffc7715 --- /dev/null +++ b/pkg/lint/rules/testdata/badcrdfile/values.yaml @@ -0,0 +1 @@ +# Default values for badcrdfile. diff --git a/pkg/lint/rules/testdata/invalidcrdsdir/Chart.yaml b/pkg/lint/rules/testdata/invalidcrdsdir/Chart.yaml new file mode 100644 index 000000000..18e30f70f --- /dev/null +++ b/pkg/lint/rules/testdata/invalidcrdsdir/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +description: A Helm chart for Kubernetes +version: 0.1.0 +name: invalidcrdsdir +type: application +icon: http://riverrun.io diff --git a/pkg/lint/rules/testdata/invalidcrdsdir/crds b/pkg/lint/rules/testdata/invalidcrdsdir/crds new file mode 100644 index 000000000..e69de29bb diff --git a/pkg/lint/rules/testdata/invalidcrdsdir/values.yaml b/pkg/lint/rules/testdata/invalidcrdsdir/values.yaml new file mode 100644 index 000000000..2fffc7715 --- /dev/null +++ b/pkg/lint/rules/testdata/invalidcrdsdir/values.yaml @@ -0,0 +1 @@ +# Default values for badcrdfile. diff --git a/pkg/lint/rules/testdata/withcrd/Chart.yaml b/pkg/lint/rules/testdata/withcrd/Chart.yaml new file mode 100644 index 000000000..58e3a0c27 --- /dev/null +++ b/pkg/lint/rules/testdata/withcrd/Chart.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +name: withcrd +description: testing chart with a CRD +version: 199.44.12345-Alpha.1+cafe009 +icon: http://riverrun.io diff --git a/pkg/lint/rules/testdata/withcrd/crds/test-crd.yaml b/pkg/lint/rules/testdata/withcrd/crds/test-crd.yaml new file mode 100644 index 000000000..1d7350f1d --- /dev/null +++ b/pkg/lint/rules/testdata/withcrd/crds/test-crd.yaml @@ -0,0 +1,19 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: tests.test.io +spec: + group: test.io + names: + kind: Test + listKind: TestList + plural: tests + singular: test + scope: Namespaced + versions: + - name : v1alpha2 + served: true + storage: true + - name : v1alpha1 + served: true + storage: false From bc35ea5ad749653e744ab50d32fa5bbc98be0187 Mon Sep 17 00:00:00 2001 From: Zach Burgess Date: Fri, 27 Jun 2025 11:13:34 -0700 Subject: [PATCH 02/19] Fix comment in pkg/lint/rules/testdata/invalidcrdsdir/values.yaml Signed-off-by: Zach Burgess --- pkg/lint/rules/testdata/invalidcrdsdir/values.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/lint/rules/testdata/invalidcrdsdir/values.yaml b/pkg/lint/rules/testdata/invalidcrdsdir/values.yaml index 2fffc7715..6b1611a64 100644 --- a/pkg/lint/rules/testdata/invalidcrdsdir/values.yaml +++ b/pkg/lint/rules/testdata/invalidcrdsdir/values.yaml @@ -1 +1 @@ -# Default values for badcrdfile. +# Default values for invalidcrdsdir. From e4c88faeff8b3b5752a49dbb1e3bd54306462d55 Mon Sep 17 00:00:00 2001 From: Zach Burgess Date: Fri, 27 Jun 2025 11:54:39 -0700 Subject: [PATCH 03/19] Update test assertions Signed-off-by: Zach Burgess --- .../output/lint-chart-with-bad-subcharts-with-subcharts.txt | 2 ++ pkg/cmd/testdata/output/lint-chart-with-bad-subcharts.txt | 1 + pkg/cmd/testdata/output/lint-quiet-with-error.txt | 1 + pkg/lint/lint_test.go | 2 +- 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkg/cmd/testdata/output/lint-chart-with-bad-subcharts-with-subcharts.txt b/pkg/cmd/testdata/output/lint-chart-with-bad-subcharts-with-subcharts.txt index 6e2efcecd..2432563f5 100644 --- a/pkg/cmd/testdata/output/lint-chart-with-bad-subcharts-with-subcharts.txt +++ b/pkg/cmd/testdata/output/lint-chart-with-bad-subcharts-with-subcharts.txt @@ -3,6 +3,7 @@ [ERROR] templates/: error unpacking subchart bad-subchart in chart-with-bad-subcharts: validation: chart.metadata.name is required [ERROR] : unable to load chart error unpacking subchart bad-subchart in chart-with-bad-subcharts: validation: chart.metadata.name is required +[ERROR] crds/: error unpacking subchart bad-subchart in chart-with-bad-subcharts: validation: chart.metadata.name is required ==> Linting testdata/testcharts/chart-with-bad-subcharts/charts/bad-subchart [ERROR] Chart.yaml: name is required @@ -12,6 +13,7 @@ [ERROR] templates/: validation: chart.metadata.name is required [ERROR] : unable to load chart validation: chart.metadata.name is required +[ERROR] crds/: validation: chart.metadata.name is required ==> Linting testdata/testcharts/chart-with-bad-subcharts/charts/good-subchart [INFO] Chart.yaml: icon is recommended diff --git a/pkg/cmd/testdata/output/lint-chart-with-bad-subcharts.txt b/pkg/cmd/testdata/output/lint-chart-with-bad-subcharts.txt index af533797b..c514a100a 100644 --- a/pkg/cmd/testdata/output/lint-chart-with-bad-subcharts.txt +++ b/pkg/cmd/testdata/output/lint-chart-with-bad-subcharts.txt @@ -3,5 +3,6 @@ [ERROR] templates/: error unpacking subchart bad-subchart in chart-with-bad-subcharts: validation: chart.metadata.name is required [ERROR] : unable to load chart error unpacking subchart bad-subchart in chart-with-bad-subcharts: validation: chart.metadata.name is required +[ERROR] crds/: error unpacking subchart bad-subchart in chart-with-bad-subcharts: validation: chart.metadata.name is required Error: 1 chart(s) linted, 1 chart(s) failed diff --git a/pkg/cmd/testdata/output/lint-quiet-with-error.txt b/pkg/cmd/testdata/output/lint-quiet-with-error.txt index e3d29a5a3..f8ae55eb3 100644 --- a/pkg/cmd/testdata/output/lint-quiet-with-error.txt +++ b/pkg/cmd/testdata/output/lint-quiet-with-error.txt @@ -4,5 +4,6 @@ [ERROR] templates/: cannot load Chart.yaml: error converting YAML to JSON: yaml: line 6: did not find expected '-' indicator [ERROR] : unable to load chart cannot load Chart.yaml: error converting YAML to JSON: yaml: line 6: did not find expected '-' indicator +[ERROR] crds/: cannot load Chart.yaml: error converting YAML to JSON: yaml: line 6: did not find expected '-' indicator Error: 2 chart(s) linted, 1 chart(s) failed diff --git a/pkg/lint/lint_test.go b/pkg/lint/lint_test.go index 45e24f533..6c380409c 100644 --- a/pkg/lint/lint_test.go +++ b/pkg/lint/lint_test.go @@ -40,7 +40,7 @@ const invalidChartFileDir = "rules/testdata/invalidchartfile" func TestBadChart(t *testing.T) { m := RunAll(badChartDir, values, namespace).Messages - if len(m) != 8 { + if len(m) != 9 { t.Errorf("Number of errors %v", len(m)) t.Errorf("All didn't fail with expected errors, got %#v", m) } From d6ddd8e6618e132fc43eaa56c0c26b903b6c9693 Mon Sep 17 00:00:00 2001 From: Zach Burgess Date: Fri, 27 Jun 2025 14:49:49 -0700 Subject: [PATCH 04/19] Document that attempting to parse YAML checks that the CRD is not a template Signed-off-by: Zach Burgess --- pkg/lint/rules/crds.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/lint/rules/crds.go b/pkg/lint/rules/crds.go index bba06ddc3..c978bfc53 100644 --- a/pkg/lint/rules/crds.go +++ b/pkg/lint/rules/crds.go @@ -52,7 +52,7 @@ func Crds(linter *support.Linter) { } /* Iterate over all the CRDs to check: - - It is a YAML file + - It is a YAML file and not a template - The kind is CustomResourceDefinition */ for _, crd := range chart.CRDObjects() { @@ -68,7 +68,8 @@ func Crds(linter *support.Linter) { break } - // If YAML linting fails here, it will always fail in the next block as well, so we should return here. + // If YAML parsing fails here, it will always fail in the next block as well, so we should return here. + // This also confirms the YAML is not a template, since templates can't be decoded into a K8sYamlStruct. if !linter.RunLinterRule(support.ErrorSev, fpath, validateYamlContent(err)) { return } From 562ff982cb37aada7b98a755c8c37563c1e45577 Mon Sep 17 00:00:00 2001 From: Zach Burgess Date: Tue, 1 Jul 2025 13:52:15 -0700 Subject: [PATCH 05/19] Early return if the `/crds` directory does not exist and don't silently discard the error from `os.Stat`. Signed-off-by: Zach Burgess --- pkg/lint/lint_test.go | 2 +- pkg/lint/rules/crds.go | 17 ++++++++++------- pkg/lint/rules/crds_test.go | 4 ++-- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/pkg/lint/lint_test.go b/pkg/lint/lint_test.go index 6c380409c..45e24f533 100644 --- a/pkg/lint/lint_test.go +++ b/pkg/lint/lint_test.go @@ -40,7 +40,7 @@ const invalidChartFileDir = "rules/testdata/invalidchartfile" func TestBadChart(t *testing.T) { m := RunAll(badChartDir, values, namespace).Messages - if len(m) != 9 { + if len(m) != 8 { t.Errorf("Number of errors %v", len(m)) t.Errorf("All didn't fail with expected errors, got %#v", m) } diff --git a/pkg/lint/rules/crds.go b/pkg/lint/rules/crds.go index c978bfc53..4740157b3 100644 --- a/pkg/lint/rules/crds.go +++ b/pkg/lint/rules/crds.go @@ -21,6 +21,7 @@ import ( "errors" "fmt" "io" + "io/fs" "os" "path/filepath" @@ -35,13 +36,13 @@ func Crds(linter *support.Linter) { fpath := "crds/" crdsPath := filepath.Join(linter.ChartDir, fpath) - crdsDirExist := linter.RunLinterRule(support.WarningSev, fpath, validateCrdsDir(crdsPath)) - // crds directory is optional - if !crdsDirExist { + if _, err := os.Stat(crdsPath); errors.Is(err, fs.ErrNotExist) { return } + linter.RunLinterRule(support.WarningSev, fpath, validateCrdsDir(crdsPath)) + // Load chart and parse CRDs chart, err := loader.Load(linter.ChartDir) @@ -81,10 +82,12 @@ func Crds(linter *support.Linter) { // Validation functions func validateCrdsDir(crdsPath string) error { - if fi, err := os.Stat(crdsPath); err == nil { - if !fi.IsDir() { - return errors.New("not a directory") - } + fi, err := os.Stat(crdsPath) + if err != nil { + return err + } + if !fi.IsDir() { + return errors.New("not a directory") } return nil } diff --git a/pkg/lint/rules/crds_test.go b/pkg/lint/rules/crds_test.go index 52432a130..a84b62a50 100644 --- a/pkg/lint/rules/crds_test.go +++ b/pkg/lint/rules/crds_test.go @@ -23,11 +23,11 @@ import ( "helm.sh/helm/v4/pkg/lint/support" ) -const crdsTestBasedir = "./testdata/withcrd" +const crdsTestBaseDir = "./testdata/withcrd" const invalidCrdsDir = "./testdata/invalidcrdsdir" func TestCrdsDir(t *testing.T) { - linter := support.Linter{ChartDir: crdsTestBasedir} + linter := support.Linter{ChartDir: crdsTestBaseDir} Crds(&linter) res := linter.Messages From a99c3700f0484c3fabca2f191ebe23db9d32d67c Mon Sep 17 00:00:00 2001 From: Zach Burgess Date: Tue, 1 Jul 2025 13:52:15 -0700 Subject: [PATCH 06/19] Return early if the `/crds` directory does not exist. Don't silently discard the error from `os.Stat`. Signed-off-by: Zach Burgess --- .../output/lint-chart-with-bad-subcharts-with-subcharts.txt | 2 -- pkg/cmd/testdata/output/lint-chart-with-bad-subcharts.txt | 1 - pkg/cmd/testdata/output/lint-quiet-with-error.txt | 1 - 3 files changed, 4 deletions(-) diff --git a/pkg/cmd/testdata/output/lint-chart-with-bad-subcharts-with-subcharts.txt b/pkg/cmd/testdata/output/lint-chart-with-bad-subcharts-with-subcharts.txt index 2432563f5..6e2efcecd 100644 --- a/pkg/cmd/testdata/output/lint-chart-with-bad-subcharts-with-subcharts.txt +++ b/pkg/cmd/testdata/output/lint-chart-with-bad-subcharts-with-subcharts.txt @@ -3,7 +3,6 @@ [ERROR] templates/: error unpacking subchart bad-subchart in chart-with-bad-subcharts: validation: chart.metadata.name is required [ERROR] : unable to load chart error unpacking subchart bad-subchart in chart-with-bad-subcharts: validation: chart.metadata.name is required -[ERROR] crds/: error unpacking subchart bad-subchart in chart-with-bad-subcharts: validation: chart.metadata.name is required ==> Linting testdata/testcharts/chart-with-bad-subcharts/charts/bad-subchart [ERROR] Chart.yaml: name is required @@ -13,7 +12,6 @@ [ERROR] templates/: validation: chart.metadata.name is required [ERROR] : unable to load chart validation: chart.metadata.name is required -[ERROR] crds/: validation: chart.metadata.name is required ==> Linting testdata/testcharts/chart-with-bad-subcharts/charts/good-subchart [INFO] Chart.yaml: icon is recommended diff --git a/pkg/cmd/testdata/output/lint-chart-with-bad-subcharts.txt b/pkg/cmd/testdata/output/lint-chart-with-bad-subcharts.txt index c514a100a..af533797b 100644 --- a/pkg/cmd/testdata/output/lint-chart-with-bad-subcharts.txt +++ b/pkg/cmd/testdata/output/lint-chart-with-bad-subcharts.txt @@ -3,6 +3,5 @@ [ERROR] templates/: error unpacking subchart bad-subchart in chart-with-bad-subcharts: validation: chart.metadata.name is required [ERROR] : unable to load chart error unpacking subchart bad-subchart in chart-with-bad-subcharts: validation: chart.metadata.name is required -[ERROR] crds/: error unpacking subchart bad-subchart in chart-with-bad-subcharts: validation: chart.metadata.name is required Error: 1 chart(s) linted, 1 chart(s) failed diff --git a/pkg/cmd/testdata/output/lint-quiet-with-error.txt b/pkg/cmd/testdata/output/lint-quiet-with-error.txt index f8ae55eb3..e3d29a5a3 100644 --- a/pkg/cmd/testdata/output/lint-quiet-with-error.txt +++ b/pkg/cmd/testdata/output/lint-quiet-with-error.txt @@ -4,6 +4,5 @@ [ERROR] templates/: cannot load Chart.yaml: error converting YAML to JSON: yaml: line 6: did not find expected '-' indicator [ERROR] : unable to load chart cannot load Chart.yaml: error converting YAML to JSON: yaml: line 6: did not find expected '-' indicator -[ERROR] crds/: cannot load Chart.yaml: error converting YAML to JSON: yaml: line 6: did not find expected '-' indicator Error: 2 chart(s) linted, 1 chart(s) failed From b703d5b4bb109c6ec679fc3327021eb7b90c3bc1 Mon Sep 17 00:00:00 2001 From: Zach Burgess Date: Tue, 1 Jul 2025 14:29:29 -0700 Subject: [PATCH 07/19] Return early when linting if the `templates/` dir does not exist The `vaildateTemplatesDir` function would still return `nil` if the directory doesn't exist, so the early return that was documented never occurs. Signed-off-by: Zach Burgess --- ...t-chart-with-bad-subcharts-with-subcharts.txt | 2 -- .../output/lint-chart-with-bad-subcharts.txt | 1 - .../testdata/output/lint-quiet-with-error.txt | 1 - pkg/lint/lint_test.go | 2 +- pkg/lint/rules/template.go | 16 +++++++++------- 5 files changed, 10 insertions(+), 12 deletions(-) diff --git a/pkg/cmd/testdata/output/lint-chart-with-bad-subcharts-with-subcharts.txt b/pkg/cmd/testdata/output/lint-chart-with-bad-subcharts-with-subcharts.txt index 6e2efcecd..2a84d8739 100644 --- a/pkg/cmd/testdata/output/lint-chart-with-bad-subcharts-with-subcharts.txt +++ b/pkg/cmd/testdata/output/lint-chart-with-bad-subcharts-with-subcharts.txt @@ -1,6 +1,5 @@ ==> Linting testdata/testcharts/chart-with-bad-subcharts [INFO] Chart.yaml: icon is recommended -[ERROR] templates/: error unpacking subchart bad-subchart in chart-with-bad-subcharts: validation: chart.metadata.name is required [ERROR] : unable to load chart error unpacking subchart bad-subchart in chart-with-bad-subcharts: validation: chart.metadata.name is required @@ -9,7 +8,6 @@ [ERROR] Chart.yaml: apiVersion is required. The value must be either "v1" or "v2" [ERROR] Chart.yaml: version is required [INFO] Chart.yaml: icon is recommended -[ERROR] templates/: validation: chart.metadata.name is required [ERROR] : unable to load chart validation: chart.metadata.name is required diff --git a/pkg/cmd/testdata/output/lint-chart-with-bad-subcharts.txt b/pkg/cmd/testdata/output/lint-chart-with-bad-subcharts.txt index af533797b..0cba1c52b 100644 --- a/pkg/cmd/testdata/output/lint-chart-with-bad-subcharts.txt +++ b/pkg/cmd/testdata/output/lint-chart-with-bad-subcharts.txt @@ -1,6 +1,5 @@ ==> Linting testdata/testcharts/chart-with-bad-subcharts [INFO] Chart.yaml: icon is recommended -[ERROR] templates/: error unpacking subchart bad-subchart in chart-with-bad-subcharts: validation: chart.metadata.name is required [ERROR] : unable to load chart error unpacking subchart bad-subchart in chart-with-bad-subcharts: validation: chart.metadata.name is required diff --git a/pkg/cmd/testdata/output/lint-quiet-with-error.txt b/pkg/cmd/testdata/output/lint-quiet-with-error.txt index e3d29a5a3..2711d9397 100644 --- a/pkg/cmd/testdata/output/lint-quiet-with-error.txt +++ b/pkg/cmd/testdata/output/lint-quiet-with-error.txt @@ -1,7 +1,6 @@ ==> Linting testdata/testcharts/chart-bad-requirements [ERROR] Chart.yaml: unable to parse YAML error converting YAML to JSON: yaml: line 6: did not find expected '-' indicator -[ERROR] templates/: cannot load Chart.yaml: error converting YAML to JSON: yaml: line 6: did not find expected '-' indicator [ERROR] : unable to load chart cannot load Chart.yaml: error converting YAML to JSON: yaml: line 6: did not find expected '-' indicator diff --git a/pkg/lint/lint_test.go b/pkg/lint/lint_test.go index 888d3dfe6..6e7f40ef6 100644 --- a/pkg/lint/lint_test.go +++ b/pkg/lint/lint_test.go @@ -39,7 +39,7 @@ const invalidChartFileDir = "rules/testdata/invalidchartfile" func TestBadChart(t *testing.T) { m := RunAll(badChartDir, values, namespace).Messages - if len(m) != 8 { + if len(m) != 7 { t.Errorf("Number of errors %v", len(m)) t.Errorf("All didn't fail with expected errors, got %#v", m) } diff --git a/pkg/lint/rules/template.go b/pkg/lint/rules/template.go index 72b81f191..55bc0ec89 100644 --- a/pkg/lint/rules/template.go +++ b/pkg/lint/rules/template.go @@ -54,13 +54,13 @@ func TemplatesWithSkipSchemaValidation(linter *support.Linter, values map[string fpath := "templates/" templatesPath := filepath.Join(linter.ChartDir, fpath) - templatesDirExist := linter.RunLinterRule(support.WarningSev, fpath, validateTemplatesDir(templatesPath)) - // Templates directory is optional for now - if !templatesDirExist { + if _, err := os.Stat(templatesPath); errors.Is(err, os.ErrNotExist) { return } + linter.RunLinterRule(support.WarningSev, fpath, validateTemplatesDir(templatesPath)) + // Load chart and parse templates chart, err := loader.Load(linter.ChartDir) @@ -195,10 +195,12 @@ func validateTopIndentLevel(content string) error { // Validation functions func validateTemplatesDir(templatesPath string) error { - if fi, err := os.Stat(templatesPath); err == nil { - if !fi.IsDir() { - return errors.New("not a directory") - } + fi, err := os.Stat(templatesPath) + if err != nil { + return err + } + if !fi.IsDir() { + return errors.New("not a directory") } return nil } From 357957b0d38cdf8119c7bb0e4fd1b587abf6486c Mon Sep 17 00:00:00 2001 From: Zach Burgess Date: Mon, 7 Jul 2025 11:04:24 -0700 Subject: [PATCH 08/19] Use testify and add a CRD to the `goodone` test case. Signed-off-by: Zach Burgess --- pkg/lint/lint_test.go | 11 +++++------ pkg/lint/rules/crds.go | 19 ++++++++++++++++--- pkg/lint/rules/crds_test.go | 18 ++++++------------ .../badcrdfile/crds/bad-apiversion.yaml | 2 ++ .../{withcrd => goodone}/crds/test-crd.yaml | 0 pkg/lint/rules/testdata/withcrd/Chart.yaml | 5 ----- 6 files changed, 29 insertions(+), 26 deletions(-) create mode 100644 pkg/lint/rules/testdata/badcrdfile/crds/bad-apiversion.yaml rename pkg/lint/rules/testdata/{withcrd => goodone}/crds/test-crd.yaml (100%) delete mode 100644 pkg/lint/rules/testdata/withcrd/Chart.yaml diff --git a/pkg/lint/lint_test.go b/pkg/lint/lint_test.go index 45e24f533..2b591f516 100644 --- a/pkg/lint/lint_test.go +++ b/pkg/lint/lint_test.go @@ -21,6 +21,8 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" + chartutil "helm.sh/helm/v4/pkg/chart/v2/util" "helm.sh/helm/v4/pkg/lint/support" ) @@ -114,12 +116,9 @@ func TestBadValues(t *testing.T) { func TestBadCrdFile(t *testing.T) { m := RunAll(badCrdFileDir, values, namespace).Messages - if len(m) < 1 { - t.Fatalf("All didn't fail with expected errors, got %#v", m) - } - if !strings.Contains(m[0].Err.Error(), "object kind is not 'CustomResourceDefinition'") { - t.Errorf("All didn't have the error for invalid CRD: %s", m[0].Err) - } + assert.Lenf(t, m, 2, "All didn't fail with expected errors, got %#v", m) + assert.ErrorContains(t, m[0].Err, "apiVersion is not in 'apiextensions.k8s.io'") + assert.ErrorContains(t, m[1].Err, "object kind is not 'CustomResourceDefinition'") } func TestGoodChart(t *testing.T) { diff --git a/pkg/lint/rules/crds.go b/pkg/lint/rules/crds.go index 4740157b3..dd3e145fc 100644 --- a/pkg/lint/rules/crds.go +++ b/pkg/lint/rules/crds.go @@ -24,6 +24,7 @@ import ( "io/fs" "os" "path/filepath" + "strings" "k8s.io/apimachinery/pkg/util/yaml" @@ -41,7 +42,10 @@ func Crds(linter *support.Linter) { return } - linter.RunLinterRule(support.WarningSev, fpath, validateCrdsDir(crdsPath)) + crdsDirValid := linter.RunLinterRule(support.WarningSev, fpath, validateCrdsDir(crdsPath)) + if !crdsDirValid { + return + } // Load chart and parse CRDs chart, err := loader.Load(linter.ChartDir) @@ -53,8 +57,9 @@ func Crds(linter *support.Linter) { } /* Iterate over all the CRDs to check: - - It is a YAML file and not a template - - The kind is CustomResourceDefinition + 1. It is a YAML file and not a template + 2. The API version is apiextensions.k8s.io + 3. The kind is CustomResourceDefinition */ for _, crd := range chart.CRDObjects() { fileName := crd.Name @@ -75,6 +80,7 @@ func Crds(linter *support.Linter) { return } + linter.RunLinterRule(support.ErrorSev, fpath, validateCrdApiVersion(yamlStruct)) linter.RunLinterRule(support.ErrorSev, fpath, validateCrdKind(yamlStruct)) } } @@ -92,6 +98,13 @@ func validateCrdsDir(crdsPath string) error { return nil } +func validateCrdApiVersion(obj *K8sYamlStruct) error { + if !strings.HasPrefix(obj.APIVersion, "apiextensions.k8s.io") { + return fmt.Errorf("apiVersion is not in 'apiextensions.k8s.io'") + } + return nil +} + func validateCrdKind(obj *K8sYamlStruct) error { if obj.Kind != "CustomResourceDefinition" { return fmt.Errorf("object kind is not 'CustomResourceDefinition'") diff --git a/pkg/lint/rules/crds_test.go b/pkg/lint/rules/crds_test.go index a84b62a50..66da06121 100644 --- a/pkg/lint/rules/crds_test.go +++ b/pkg/lint/rules/crds_test.go @@ -17,13 +17,14 @@ limitations under the License. package rules import ( - "strings" "testing" + "github.com/stretchr/testify/assert" + "helm.sh/helm/v4/pkg/lint/support" ) -const crdsTestBaseDir = "./testdata/withcrd" +const crdsTestBaseDir = "./testdata/goodone" const invalidCrdsDir = "./testdata/invalidcrdsdir" func TestCrdsDir(t *testing.T) { @@ -31,9 +32,7 @@ func TestCrdsDir(t *testing.T) { Crds(&linter) res := linter.Messages - if len(res) > 0 { - t.Fatalf("Expected no errors, got %d, %v", len(res), res) - } + assert.Emptyf(t, res, "Expected no errors, got %v", res) } func TestInvalidCrdsDir(t *testing.T) { @@ -41,11 +40,6 @@ func TestInvalidCrdsDir(t *testing.T) { Crds(&linter) res := linter.Messages - if len(res) != 1 { - t.Fatalf("Expected one error, got %d, %v", len(res), res) - } - - if !strings.Contains(res[0].Err.Error(), "not a directory") { - t.Errorf("Unexpected error: %s", res[0]) - } + assert.Lenf(t, res, 1, "Expected one error, got %d, %v", len(res), res) + assert.ErrorContains(t, res[0].Err, "not a directory") } diff --git a/pkg/lint/rules/testdata/badcrdfile/crds/bad-apiversion.yaml b/pkg/lint/rules/testdata/badcrdfile/crds/bad-apiversion.yaml new file mode 100644 index 000000000..468916053 --- /dev/null +++ b/pkg/lint/rules/testdata/badcrdfile/crds/bad-apiversion.yaml @@ -0,0 +1,2 @@ +apiVersion: bad.k8s.io/v1beta1 +kind: CustomResourceDefinition diff --git a/pkg/lint/rules/testdata/withcrd/crds/test-crd.yaml b/pkg/lint/rules/testdata/goodone/crds/test-crd.yaml similarity index 100% rename from pkg/lint/rules/testdata/withcrd/crds/test-crd.yaml rename to pkg/lint/rules/testdata/goodone/crds/test-crd.yaml diff --git a/pkg/lint/rules/testdata/withcrd/Chart.yaml b/pkg/lint/rules/testdata/withcrd/Chart.yaml deleted file mode 100644 index 58e3a0c27..000000000 --- a/pkg/lint/rules/testdata/withcrd/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -name: withcrd -description: testing chart with a CRD -version: 199.44.12345-Alpha.1+cafe009 -icon: http://riverrun.io From bf9084a16a1a8b084b15bdb36fc4bca42edcba7c Mon Sep 17 00:00:00 2001 From: Zach Burgess Date: Mon, 7 Jul 2025 11:09:11 -0700 Subject: [PATCH 09/19] Rename `validateCrdApiVersion` to `validateCrdAPIVersion` Signed-off-by: Zach Burgess --- pkg/lint/rules/crds.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/lint/rules/crds.go b/pkg/lint/rules/crds.go index dd3e145fc..cb867684e 100644 --- a/pkg/lint/rules/crds.go +++ b/pkg/lint/rules/crds.go @@ -80,7 +80,7 @@ func Crds(linter *support.Linter) { return } - linter.RunLinterRule(support.ErrorSev, fpath, validateCrdApiVersion(yamlStruct)) + linter.RunLinterRule(support.ErrorSev, fpath, validateCrdAPIVersion(yamlStruct)) linter.RunLinterRule(support.ErrorSev, fpath, validateCrdKind(yamlStruct)) } } @@ -98,7 +98,7 @@ func validateCrdsDir(crdsPath string) error { return nil } -func validateCrdApiVersion(obj *K8sYamlStruct) error { +func validateCrdAPIVersion(obj *K8sYamlStruct) error { if !strings.HasPrefix(obj.APIVersion, "apiextensions.k8s.io") { return fmt.Errorf("apiVersion is not in 'apiextensions.k8s.io'") } From c59a0972097fb87c49361347009adda8887a8ee4 Mon Sep 17 00:00:00 2001 From: Zach Burgess Date: Mon, 7 Jul 2025 14:19:35 -0700 Subject: [PATCH 10/19] Remove duplicate test case from crds_test.go The "good" test case for CRDs is done in `TestGoodChart` in lint_test.go. Signed-off-by: Zach Burgess --- pkg/lint/rules/crds_test.go | 9 --------- 1 file changed, 9 deletions(-) diff --git a/pkg/lint/rules/crds_test.go b/pkg/lint/rules/crds_test.go index 66da06121..563392377 100644 --- a/pkg/lint/rules/crds_test.go +++ b/pkg/lint/rules/crds_test.go @@ -24,17 +24,8 @@ import ( "helm.sh/helm/v4/pkg/lint/support" ) -const crdsTestBaseDir = "./testdata/goodone" const invalidCrdsDir = "./testdata/invalidcrdsdir" -func TestCrdsDir(t *testing.T) { - linter := support.Linter{ChartDir: crdsTestBaseDir} - Crds(&linter) - res := linter.Messages - - assert.Emptyf(t, res, "Expected no errors, got %v", res) -} - func TestInvalidCrdsDir(t *testing.T) { linter := support.Linter{ChartDir: invalidCrdsDir} Crds(&linter) From cc85352a0eb03c118f8e899fd9f398dfae17054e Mon Sep 17 00:00:00 2001 From: Zach Burgess Date: Mon, 7 Jul 2025 14:28:19 -0700 Subject: [PATCH 11/19] Use `assert.Len` instead of `assert.Lenf` The default message from testify is descriptive enough. Signed-off-by: Zach Burgess --- pkg/lint/rules/crds_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/lint/rules/crds_test.go b/pkg/lint/rules/crds_test.go index 563392377..d497b29ba 100644 --- a/pkg/lint/rules/crds_test.go +++ b/pkg/lint/rules/crds_test.go @@ -31,6 +31,6 @@ func TestInvalidCrdsDir(t *testing.T) { Crds(&linter) res := linter.Messages - assert.Lenf(t, res, 1, "Expected one error, got %d, %v", len(res), res) + assert.Len(t, res, 1) assert.ErrorContains(t, res[0].Err, "not a directory") } From 3a318c2fa3dcaf46d7eeca97fa5677cbddc6ba76 Mon Sep 17 00:00:00 2001 From: Zach Burgess Date: Mon, 7 Jul 2025 14:42:08 -0700 Subject: [PATCH 12/19] Update crds.go after https://github.com/helm/helm/pull/31029 Signed-off-by: Zach Burgess --- pkg/lint/rules/crds.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/lint/rules/crds.go b/pkg/lint/rules/crds.go index cb867684e..3f5822cc4 100644 --- a/pkg/lint/rules/crds.go +++ b/pkg/lint/rules/crds.go @@ -67,7 +67,7 @@ func Crds(linter *support.Linter) { decoder := yaml.NewYAMLOrJSONDecoder(bytes.NewReader(crd.File.Data), 4096) for { - var yamlStruct *K8sYamlStruct + var yamlStruct *k8sYamlStruct err := decoder.Decode(&yamlStruct) if err == io.EOF { @@ -98,14 +98,14 @@ func validateCrdsDir(crdsPath string) error { return nil } -func validateCrdAPIVersion(obj *K8sYamlStruct) error { +func validateCrdAPIVersion(obj *k8sYamlStruct) error { if !strings.HasPrefix(obj.APIVersion, "apiextensions.k8s.io") { return fmt.Errorf("apiVersion is not in 'apiextensions.k8s.io'") } return nil } -func validateCrdKind(obj *K8sYamlStruct) error { +func validateCrdKind(obj *k8sYamlStruct) error { if obj.Kind != "CustomResourceDefinition" { return fmt.Errorf("object kind is not 'CustomResourceDefinition'") } From eea2d4577bf08d5cac2bf8f054439db01e0cf97d Mon Sep 17 00:00:00 2001 From: Zach Burgess Date: Mon, 7 Jul 2025 20:31:41 -0700 Subject: [PATCH 13/19] Raise an error if the `templates/` dir is not valid and return early. Signed-off-by: Zach Burgess --- pkg/lint/rules/template.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkg/lint/rules/template.go b/pkg/lint/rules/template.go index 55bc0ec89..06a5a2994 100644 --- a/pkg/lint/rules/template.go +++ b/pkg/lint/rules/template.go @@ -59,7 +59,10 @@ func TemplatesWithSkipSchemaValidation(linter *support.Linter, values map[string return } - linter.RunLinterRule(support.WarningSev, fpath, validateTemplatesDir(templatesPath)) + validTemplatesDir := linter.RunLinterRule(support.ErrorSev, fpath, validateTemplatesDir(templatesPath)) + if !validTemplatesDir { + return + } // Load chart and parse templates chart, err := loader.Load(linter.ChartDir) From fe114387155af63f63133899779c0dc71fcb2c85 Mon Sep 17 00:00:00 2001 From: Zach Burgess Date: Mon, 7 Jul 2025 20:39:22 -0700 Subject: [PATCH 14/19] Raise error instead of warning if `crds/` is not a valid directory Signed-off-by: Zach Burgess --- pkg/lint/rules/crds.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/lint/rules/crds.go b/pkg/lint/rules/crds.go index 3f5822cc4..1b8a73139 100644 --- a/pkg/lint/rules/crds.go +++ b/pkg/lint/rules/crds.go @@ -42,7 +42,7 @@ func Crds(linter *support.Linter) { return } - crdsDirValid := linter.RunLinterRule(support.WarningSev, fpath, validateCrdsDir(crdsPath)) + crdsDirValid := linter.RunLinterRule(support.ErrorSev, fpath, validateCrdsDir(crdsPath)) if !crdsDirValid { return } From 35434947a36d8859e16a81c0d4349266d35f0314 Mon Sep 17 00:00:00 2001 From: Zach Burgess Date: Mon, 7 Jul 2025 21:02:11 -0700 Subject: [PATCH 15/19] Return a lint warning if `templates/` does not exist. Signed-off-by: Zach Burgess --- pkg/action/lint_test.go | 6 +++--- .../lint-chart-with-bad-subcharts-with-subcharts.txt | 3 +++ .../testdata/output/lint-chart-with-bad-subcharts.txt | 1 + pkg/cmd/testdata/output/lint-quiet-with-error.txt | 1 + pkg/cmd/testdata/output/lint-quiet-with-warning.txt | 4 ++++ pkg/lint/rules/template.go | 11 ++++++++++- 6 files changed, 22 insertions(+), 4 deletions(-) diff --git a/pkg/action/lint_test.go b/pkg/action/lint_test.go index a01580b0a..613149a4d 100644 --- a/pkg/action/lint_test.go +++ b/pkg/action/lint_test.go @@ -154,12 +154,12 @@ func TestLint_ChartWithWarnings(t *testing.T) { } }) - t.Run("should pass with no errors when strict", func(t *testing.T) { + t.Run("should fail with one error when strict", func(t *testing.T) { testCharts := []string{chartWithNoTemplatesDir} testLint := NewLint() testLint.Strict = true - if result := testLint.Run(testCharts, values); len(result.Errors) != 0 { - t.Error("expected no errors, but got", len(result.Errors)) + if result := testLint.Run(testCharts, values); len(result.Errors) != 1 { + t.Error("expected one error, but got", len(result.Errors)) } }) } diff --git a/pkg/cmd/testdata/output/lint-chart-with-bad-subcharts-with-subcharts.txt b/pkg/cmd/testdata/output/lint-chart-with-bad-subcharts-with-subcharts.txt index 2a84d8739..7b445a69a 100644 --- a/pkg/cmd/testdata/output/lint-chart-with-bad-subcharts-with-subcharts.txt +++ b/pkg/cmd/testdata/output/lint-chart-with-bad-subcharts-with-subcharts.txt @@ -1,5 +1,6 @@ ==> Linting testdata/testcharts/chart-with-bad-subcharts [INFO] Chart.yaml: icon is recommended +[WARNING] templates/: directory does not exist [ERROR] : unable to load chart error unpacking subchart bad-subchart in chart-with-bad-subcharts: validation: chart.metadata.name is required @@ -8,10 +9,12 @@ [ERROR] Chart.yaml: apiVersion is required. The value must be either "v1" or "v2" [ERROR] Chart.yaml: version is required [INFO] Chart.yaml: icon is recommended +[WARNING] templates/: directory does not exist [ERROR] : unable to load chart validation: chart.metadata.name is required ==> Linting testdata/testcharts/chart-with-bad-subcharts/charts/good-subchart [INFO] Chart.yaml: icon is recommended +[WARNING] templates/: directory does not exist Error: 3 chart(s) linted, 2 chart(s) failed diff --git a/pkg/cmd/testdata/output/lint-chart-with-bad-subcharts.txt b/pkg/cmd/testdata/output/lint-chart-with-bad-subcharts.txt index 0cba1c52b..5a1c388bb 100644 --- a/pkg/cmd/testdata/output/lint-chart-with-bad-subcharts.txt +++ b/pkg/cmd/testdata/output/lint-chart-with-bad-subcharts.txt @@ -1,5 +1,6 @@ ==> Linting testdata/testcharts/chart-with-bad-subcharts [INFO] Chart.yaml: icon is recommended +[WARNING] templates/: directory does not exist [ERROR] : unable to load chart error unpacking subchart bad-subchart in chart-with-bad-subcharts: validation: chart.metadata.name is required diff --git a/pkg/cmd/testdata/output/lint-quiet-with-error.txt b/pkg/cmd/testdata/output/lint-quiet-with-error.txt index 2711d9397..0731a07d1 100644 --- a/pkg/cmd/testdata/output/lint-quiet-with-error.txt +++ b/pkg/cmd/testdata/output/lint-quiet-with-error.txt @@ -1,6 +1,7 @@ ==> Linting testdata/testcharts/chart-bad-requirements [ERROR] Chart.yaml: unable to parse YAML error converting YAML to JSON: yaml: line 6: did not find expected '-' indicator +[WARNING] templates/: directory does not exist [ERROR] : unable to load chart cannot load Chart.yaml: error converting YAML to JSON: yaml: line 6: did not find expected '-' indicator diff --git a/pkg/cmd/testdata/output/lint-quiet-with-warning.txt b/pkg/cmd/testdata/output/lint-quiet-with-warning.txt index e69de29bb..ebf6c1989 100644 --- a/pkg/cmd/testdata/output/lint-quiet-with-warning.txt +++ b/pkg/cmd/testdata/output/lint-quiet-with-warning.txt @@ -0,0 +1,4 @@ +==> Linting testdata/testcharts/chart-with-only-crds +[WARNING] templates/: directory does not exist + +1 chart(s) linted, 0 chart(s) failed diff --git a/pkg/lint/rules/template.go b/pkg/lint/rules/template.go index ef355e193..b36153ec6 100644 --- a/pkg/lint/rules/template.go +++ b/pkg/lint/rules/template.go @@ -55,7 +55,8 @@ func TemplatesWithSkipSchemaValidation(linter *support.Linter, values map[string templatesPath := filepath.Join(linter.ChartDir, fpath) // Templates directory is optional for now - if _, err := os.Stat(templatesPath); errors.Is(err, os.ErrNotExist) { + templatesDirExists := linter.RunLinterRule(support.WarningSev, fpath, templatesDirExists(templatesPath)) + if !templatesDirExists { return } @@ -197,6 +198,14 @@ func validateTopIndentLevel(content string) error { } // Validation functions +func templatesDirExists(templatesPath string) error { + _, err := os.Stat(templatesPath) + if errors.Is(err, os.ErrNotExist) { + return errors.New("directory does not exist") + } + return nil +} + func validateTemplatesDir(templatesPath string) error { fi, err := os.Stat(templatesPath) if err != nil { From 1002ec5ae981b5dd4517b8a75bd4d088efab0bbd Mon Sep 17 00:00:00 2001 From: Zach Burgess Date: Mon, 7 Jul 2025 21:11:05 -0700 Subject: [PATCH 16/19] Update tests in lint_test.go Signed-off-by: Zach Burgess --- pkg/lint/lint_test.go | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/pkg/lint/lint_test.go b/pkg/lint/lint_test.go index 6e7f40ef6..63cf017e4 100644 --- a/pkg/lint/lint_test.go +++ b/pkg/lint/lint_test.go @@ -39,18 +39,23 @@ const invalidChartFileDir = "rules/testdata/invalidchartfile" func TestBadChart(t *testing.T) { m := RunAll(badChartDir, values, namespace).Messages - if len(m) != 7 { + if len(m) != 8 { t.Errorf("Number of errors %v", len(m)) t.Errorf("All didn't fail with expected errors, got %#v", m) } - // There should be one INFO, and 2 ERROR messages, check for them - var i, e, e2, e3, e4, e5, e6 bool + // There should be one INFO, one WARNING, and 2 ERROR messages, check for them + var i, w, e, e2, e3, e4, e5, e6 bool for _, msg := range m { if msg.Severity == support.InfoSev { if strings.Contains(msg.Err.Error(), "icon is recommended") { i = true } } + if msg.Severity == support.WarningSev { + if strings.Contains(msg.Err.Error(), "does not exist") { + w = true + } + } if msg.Severity == support.ErrorSev { if strings.Contains(msg.Err.Error(), "version '0.0.0.0' is not a valid SemVer") { e = true @@ -76,7 +81,7 @@ func TestBadChart(t *testing.T) { } } } - if !e || !e2 || !e3 || !e4 || !e5 || !i || !e6 { + if !e || !e2 || !e3 || !e4 || !e5 || !i || !e6 || !w { t.Errorf("Didn't find all the expected errors, got %#v", m) } } @@ -93,7 +98,7 @@ func TestInvalidYaml(t *testing.T) { func TestInvalidChartYaml(t *testing.T) { m := RunAll(invalidChartFileDir, values, namespace).Messages - if len(m) != 1 { + if len(m) != 2 { t.Fatalf("All didn't fail with expected errors, got %#v", m) } if !strings.Contains(m[0].Err.Error(), "failed to strictly parse chart metadata file") { From 46b1a41631a01fd85011710646157f96d458ed4d Mon Sep 17 00:00:00 2001 From: Yuriy Losev Date: Fri, 27 Jun 2025 13:51:24 +0400 Subject: [PATCH 17/19] Add release labels to the release Metadata Signed-off-by: Yuriy Losev --- pkg/action/get_metadata.go | 14 +++++--- pkg/action/get_metadata_test.go | 42 +++++++++++++++++++++++ pkg/cmd/get_metadata.go | 1 + pkg/cmd/get_metadata_test.go | 8 ++--- pkg/cmd/testdata/output/get-metadata.json | 2 +- pkg/cmd/testdata/output/get-metadata.txt | 1 + pkg/cmd/testdata/output/get-metadata.yaml | 2 ++ pkg/release/v1/mock.go | 6 ++++ 8 files changed, 66 insertions(+), 10 deletions(-) create mode 100644 pkg/action/get_metadata_test.go diff --git a/pkg/action/get_metadata.go b/pkg/action/get_metadata.go index e760ae4d1..4cb77361a 100644 --- a/pkg/action/get_metadata.go +++ b/pkg/action/get_metadata.go @@ -34,11 +34,14 @@ type GetMetadata struct { } type Metadata struct { - Name string `json:"name" yaml:"name"` - Chart string `json:"chart" yaml:"chart"` - Version string `json:"version" yaml:"version"` - AppVersion string `json:"appVersion" yaml:"appVersion"` - Annotations map[string]string `json:"annotations,omitempty" yaml:"annotations,omitempty"` + Name string `json:"name" yaml:"name"` + Chart string `json:"chart" yaml:"chart"` + Version string `json:"version" yaml:"version"` + AppVersion string `json:"appVersion" yaml:"appVersion"` + // Annotations are fetched from the Chart.yaml file + 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"` Dependencies []*chart.Dependency `json:"dependencies,omitempty" yaml:"dependencies,omitempty"` Namespace string `json:"namespace" yaml:"namespace"` Revision int `json:"revision" yaml:"revision"` @@ -71,6 +74,7 @@ func (g *GetMetadata) Run(name string) (*Metadata, error) { AppVersion: rel.Chart.Metadata.AppVersion, Dependencies: rel.Chart.Metadata.Dependencies, Annotations: rel.Chart.Metadata.Annotations, + Labels: rel.Labels, Namespace: rel.Namespace, Revision: rel.Version, Status: rel.Info.Status.String(), diff --git a/pkg/action/get_metadata_test.go b/pkg/action/get_metadata_test.go new file mode 100644 index 000000000..08e99d8d6 --- /dev/null +++ b/pkg/action/get_metadata_test.go @@ -0,0 +1,42 @@ +/* +Copyright The Helm Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package action + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + release "helm.sh/helm/v4/pkg/release/v1" +) + +func TestGetMetadata_Labels(t *testing.T) { + rel := releaseStub() + rel.Info.Status = release.StatusDeployed + customLabels := map[string]string{"key1": "value1", "key2": "value2"} + rel.Labels = customLabels + + metaGetter := NewGetMetadata(actionConfigFixture(t)) + err := metaGetter.cfg.Releases.Create(rel) + assert.NoError(t, err) + + metadata, err := metaGetter.Run(rel.Name) + assert.NoError(t, err) + + assert.Equal(t, metadata.Name, rel.Name) + assert.Equal(t, metadata.Labels, customLabels) +} diff --git a/pkg/cmd/get_metadata.go b/pkg/cmd/get_metadata.go index 9f58e0f4e..aea149f5e 100644 --- a/pkg/cmd/get_metadata.go +++ b/pkg/cmd/get_metadata.go @@ -80,6 +80,7 @@ func (w metadataWriter) WriteTable(out io.Writer) error { _, _ = fmt.Fprintf(out, "VERSION: %v\n", w.metadata.Version) _, _ = fmt.Fprintf(out, "APP_VERSION: %v\n", w.metadata.AppVersion) _, _ = fmt.Fprintf(out, "ANNOTATIONS: %v\n", k8sLabels.Set(w.metadata.Annotations).String()) + _, _ = fmt.Fprintf(out, "LABELS: %v\n", k8sLabels.Set(w.metadata.Labels).String()) _, _ = fmt.Fprintf(out, "DEPENDENCIES: %v\n", w.metadata.FormattedDepNames()) _, _ = fmt.Fprintf(out, "NAMESPACE: %v\n", w.metadata.Namespace) _, _ = fmt.Fprintf(out, "REVISION: %v\n", w.metadata.Revision) diff --git a/pkg/cmd/get_metadata_test.go b/pkg/cmd/get_metadata_test.go index a2ab2cba1..59fc3b82c 100644 --- a/pkg/cmd/get_metadata_test.go +++ b/pkg/cmd/get_metadata_test.go @@ -27,23 +27,23 @@ func TestGetMetadataCmd(t *testing.T) { name: "get metadata with a release", cmd: "get metadata thomas-guide", golden: "output/get-metadata.txt", - rels: []*release.Release{release.Mock(&release.MockReleaseOptions{Name: "thomas-guide"})}, + rels: []*release.Release{release.Mock(&release.MockReleaseOptions{Name: "thomas-guide", Labels: map[string]string{"key1": "value1"}})}, }, { name: "get metadata requires release name arg", cmd: "get metadata", golden: "output/get-metadata-args.txt", - rels: []*release.Release{release.Mock(&release.MockReleaseOptions{Name: "thomas-guide"})}, + rels: []*release.Release{release.Mock(&release.MockReleaseOptions{Name: "thomas-guide", Labels: map[string]string{"key1": "value1"}})}, wantError: true, }, { name: "get metadata to json", cmd: "get metadata thomas-guide --output json", golden: "output/get-metadata.json", - rels: []*release.Release{release.Mock(&release.MockReleaseOptions{Name: "thomas-guide"})}, + rels: []*release.Release{release.Mock(&release.MockReleaseOptions{Name: "thomas-guide", Labels: map[string]string{"key1": "value1"}})}, }, { name: "get metadata to yaml", cmd: "get metadata thomas-guide --output yaml", golden: "output/get-metadata.yaml", - rels: []*release.Release{release.Mock(&release.MockReleaseOptions{Name: "thomas-guide"})}, + rels: []*release.Release{release.Mock(&release.MockReleaseOptions{Name: "thomas-guide", Labels: map[string]string{"key1": "value1"}})}, }} runTestCmd(t, tests) } diff --git a/pkg/cmd/testdata/output/get-metadata.json b/pkg/cmd/testdata/output/get-metadata.json index 4c015b977..9166f87ac 100644 --- a/pkg/cmd/testdata/output/get-metadata.json +++ b/pkg/cmd/testdata/output/get-metadata.json @@ -1 +1 @@ -{"name":"thomas-guide","chart":"foo","version":"0.1.0-beta.1","appVersion":"1.0","annotations":{"category":"web-apps","supported":"true"},"dependencies":[{"name":"cool-plugin","version":"1.0.0","repository":"https://coolplugin.io/charts","condition":"coolPlugin.enabled","enabled":true},{"name":"crds","version":"2.7.1","repository":"","condition":"crds.enabled"}],"namespace":"default","revision":1,"status":"deployed","deployedAt":"1977-09-02T22:04:05Z"} +{"name":"thomas-guide","chart":"foo","version":"0.1.0-beta.1","appVersion":"1.0","annotations":{"category":"web-apps","supported":"true"},"labels":{"key1":"value1"},"dependencies":[{"name":"cool-plugin","version":"1.0.0","repository":"https://coolplugin.io/charts","condition":"coolPlugin.enabled","enabled":true},{"name":"crds","version":"2.7.1","repository":"","condition":"crds.enabled"}],"namespace":"default","revision":1,"status":"deployed","deployedAt":"1977-09-02T22:04:05Z"} diff --git a/pkg/cmd/testdata/output/get-metadata.txt b/pkg/cmd/testdata/output/get-metadata.txt index 01083b333..5744083dd 100644 --- a/pkg/cmd/testdata/output/get-metadata.txt +++ b/pkg/cmd/testdata/output/get-metadata.txt @@ -3,6 +3,7 @@ CHART: foo VERSION: 0.1.0-beta.1 APP_VERSION: 1.0 ANNOTATIONS: category=web-apps,supported=true +LABELS: key1=value1 DEPENDENCIES: cool-plugin,crds NAMESPACE: default REVISION: 1 diff --git a/pkg/cmd/testdata/output/get-metadata.yaml b/pkg/cmd/testdata/output/get-metadata.yaml index 6298436c9..98f567837 100644 --- a/pkg/cmd/testdata/output/get-metadata.yaml +++ b/pkg/cmd/testdata/output/get-metadata.yaml @@ -14,6 +14,8 @@ dependencies: repository: "" version: 2.7.1 deployedAt: "1977-09-02T22:04:05Z" +labels: + key1: value1 name: thomas-guide namespace: default revision: 1 diff --git a/pkg/release/v1/mock.go b/pkg/release/v1/mock.go index 9ca57284c..3d3b0c2e2 100644 --- a/pkg/release/v1/mock.go +++ b/pkg/release/v1/mock.go @@ -46,6 +46,7 @@ type MockReleaseOptions struct { Chart *chart.Chart Status Status Namespace string + Labels map[string]string } // Mock creates a mock release object based on options set by MockReleaseOptions. This function should typically not be used outside of testing. @@ -66,6 +67,10 @@ func Mock(opts *MockReleaseOptions) *Release { if namespace == "" { namespace = "default" } + var labels map[string]string + if len(opts.Labels) > 0 { + labels = opts.Labels + } ch := opts.Chart if opts.Chart == nil { @@ -130,5 +135,6 @@ func Mock(opts *MockReleaseOptions) *Release { }, }, Manifest: MockManifest, + Labels: labels, } } From 57e84877d226f3c929993ad4b808755ec478a10b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 16 Jul 2025 22:07:31 +0000 Subject: [PATCH 18/19] chore(deps): bump the k8s-io group with 7 updates Bumps the k8s-io group with 7 updates: | Package | From | To | | --- | --- | --- | | [k8s.io/api](https://github.com/kubernetes/api) | `0.33.2` | `0.33.3` | | [k8s.io/apiextensions-apiserver](https://github.com/kubernetes/apiextensions-apiserver) | `0.33.2` | `0.33.3` | | [k8s.io/apimachinery](https://github.com/kubernetes/apimachinery) | `0.33.2` | `0.33.3` | | [k8s.io/apiserver](https://github.com/kubernetes/apiserver) | `0.33.2` | `0.33.3` | | [k8s.io/cli-runtime](https://github.com/kubernetes/cli-runtime) | `0.33.2` | `0.33.3` | | [k8s.io/client-go](https://github.com/kubernetes/client-go) | `0.33.2` | `0.33.3` | | [k8s.io/kubectl](https://github.com/kubernetes/kubectl) | `0.33.2` | `0.33.3` | Updates `k8s.io/api` from 0.33.2 to 0.33.3 - [Commits](https://github.com/kubernetes/api/compare/v0.33.2...v0.33.3) Updates `k8s.io/apiextensions-apiserver` from 0.33.2 to 0.33.3 - [Release notes](https://github.com/kubernetes/apiextensions-apiserver/releases) - [Commits](https://github.com/kubernetes/apiextensions-apiserver/compare/v0.33.2...v0.33.3) Updates `k8s.io/apimachinery` from 0.33.2 to 0.33.3 - [Commits](https://github.com/kubernetes/apimachinery/compare/v0.33.2...v0.33.3) Updates `k8s.io/apiserver` from 0.33.2 to 0.33.3 - [Commits](https://github.com/kubernetes/apiserver/compare/v0.33.2...v0.33.3) Updates `k8s.io/cli-runtime` from 0.33.2 to 0.33.3 - [Commits](https://github.com/kubernetes/cli-runtime/compare/v0.33.2...v0.33.3) Updates `k8s.io/client-go` from 0.33.2 to 0.33.3 - [Changelog](https://github.com/kubernetes/client-go/blob/master/CHANGELOG.md) - [Commits](https://github.com/kubernetes/client-go/compare/v0.33.2...v0.33.3) Updates `k8s.io/kubectl` from 0.33.2 to 0.33.3 - [Commits](https://github.com/kubernetes/kubectl/compare/v0.33.2...v0.33.3) --- updated-dependencies: - dependency-name: k8s.io/api dependency-version: 0.33.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-io - dependency-name: k8s.io/apiextensions-apiserver dependency-version: 0.33.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-io - dependency-name: k8s.io/apimachinery dependency-version: 0.33.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-io - dependency-name: k8s.io/apiserver dependency-version: 0.33.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-io - dependency-name: k8s.io/cli-runtime dependency-version: 0.33.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-io - dependency-name: k8s.io/client-go dependency-version: 0.33.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-io - dependency-name: k8s.io/kubectl dependency-version: 0.33.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-io ... Signed-off-by: dependabot[bot] --- go.mod | 16 ++++++++-------- go.sum | 32 ++++++++++++++++---------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/go.mod b/go.mod index e19d71e77..f04a9767c 100644 --- a/go.mod +++ b/go.mod @@ -35,14 +35,14 @@ require ( golang.org/x/term v0.33.0 golang.org/x/text v0.27.0 gopkg.in/yaml.v3 v3.0.1 - k8s.io/api v0.33.2 - k8s.io/apiextensions-apiserver v0.33.2 - k8s.io/apimachinery v0.33.2 - k8s.io/apiserver v0.33.2 - k8s.io/cli-runtime v0.33.2 - k8s.io/client-go v0.33.2 + k8s.io/api v0.33.3 + k8s.io/apiextensions-apiserver v0.33.3 + k8s.io/apimachinery v0.33.3 + k8s.io/apiserver v0.33.3 + k8s.io/cli-runtime v0.33.3 + k8s.io/client-go v0.33.3 k8s.io/klog/v2 v2.130.1 - k8s.io/kubectl v0.33.2 + k8s.io/kubectl v0.33.3 oras.land/oras-go/v2 v2.6.0 sigs.k8s.io/controller-runtime v0.21.0 sigs.k8s.io/kustomize/kyaml v0.20.0 @@ -171,7 +171,7 @@ require ( gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - k8s.io/component-base v0.33.2 // indirect + k8s.io/component-base v0.33.3 // indirect k8s.io/kube-openapi v0.0.0-20250701173324-9bd5c66d9911 // indirect k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 // indirect sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect diff --git a/go.sum b/go.sum index 4fff82bcc..63da08b70 100644 --- a/go.sum +++ b/go.sum @@ -506,26 +506,26 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.33.2 h1:YgwIS5jKfA+BZg//OQhkJNIfie/kmRsO0BmNaVSimvY= -k8s.io/api v0.33.2/go.mod h1:fhrbphQJSM2cXzCWgqU29xLDuks4mu7ti9vveEnpSXs= -k8s.io/apiextensions-apiserver v0.33.2 h1:6gnkIbngnaUflR3XwE1mCefN3YS8yTD631JXQhsU6M8= -k8s.io/apiextensions-apiserver v0.33.2/go.mod h1:IvVanieYsEHJImTKXGP6XCOjTwv2LUMos0YWc9O+QP8= -k8s.io/apimachinery v0.33.2 h1:IHFVhqg59mb8PJWTLi8m1mAoepkUNYmptHsV+Z1m5jY= -k8s.io/apimachinery v0.33.2/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM= -k8s.io/apiserver v0.33.2 h1:KGTRbxn2wJagJowo29kKBp4TchpO1DRO3g+dB/KOJN4= -k8s.io/apiserver v0.33.2/go.mod h1:9qday04wEAMLPWWo9AwqCZSiIn3OYSZacDyu/AcoM/M= -k8s.io/cli-runtime v0.33.2 h1:koNYQKSDdq5AExa/RDudXMhhtFasEg48KLS2KSAU74Y= -k8s.io/cli-runtime v0.33.2/go.mod h1:gnhsAWpovqf1Zj5YRRBBU7PFsRc6NkEkwYNQE+mXL88= -k8s.io/client-go v0.33.2 h1:z8CIcc0P581x/J1ZYf4CNzRKxRvQAwoAolYPbtQes+E= -k8s.io/client-go v0.33.2/go.mod h1:9mCgT4wROvL948w6f6ArJNb7yQd7QsvqavDeZHvNmHo= -k8s.io/component-base v0.33.2 h1:sCCsn9s/dG3ZrQTX/Us0/Sx2R0G5kwa0wbZFYoVp/+0= -k8s.io/component-base v0.33.2/go.mod h1:/41uw9wKzuelhN+u+/C59ixxf4tYQKW7p32ddkYNe2k= +k8s.io/api v0.33.3 h1:SRd5t//hhkI1buzxb288fy2xvjubstenEKL9K51KBI8= +k8s.io/api v0.33.3/go.mod h1:01Y/iLUjNBM3TAvypct7DIj0M0NIZc+PzAHCIo0CYGE= +k8s.io/apiextensions-apiserver v0.33.3 h1:qmOcAHN6DjfD0v9kxL5udB27SRP6SG/MTopmge3MwEs= +k8s.io/apiextensions-apiserver v0.33.3/go.mod h1:oROuctgo27mUsyp9+Obahos6CWcMISSAPzQ77CAQGz8= +k8s.io/apimachinery v0.33.3 h1:4ZSrmNa0c/ZpZJhAgRdcsFcZOw1PQU1bALVQ0B3I5LA= +k8s.io/apimachinery v0.33.3/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM= +k8s.io/apiserver v0.33.3 h1:Wv0hGc+QFdMJB4ZSiHrCgN3zL3QRatu56+rpccKC3J4= +k8s.io/apiserver v0.33.3/go.mod h1:05632ifFEe6TxwjdAIrwINHWE2hLwyADFk5mBsQa15E= +k8s.io/cli-runtime v0.33.3 h1:Dgy4vPjNIu8LMJBSvs8W0LcdV0PX/8aGG1DA1W8lklA= +k8s.io/cli-runtime v0.33.3/go.mod h1:yklhLklD4vLS8HNGgC9wGiuHWze4g7x6XQZ+8edsKEo= +k8s.io/client-go v0.33.3 h1:M5AfDnKfYmVJif92ngN532gFqakcGi6RvaOF16efrpA= +k8s.io/client-go v0.33.3/go.mod h1:luqKBQggEf3shbxHY4uVENAxrDISLOarxpTKMiUuujg= +k8s.io/component-base v0.33.3 h1:mlAuyJqyPlKZM7FyaoM/LcunZaaY353RXiOd2+B5tGA= +k8s.io/component-base v0.33.3/go.mod h1:ktBVsBzkI3imDuxYXmVxZ2zxJnYTZ4HAsVj9iF09qp4= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20250701173324-9bd5c66d9911 h1:gAXU86Fmbr/ktY17lkHwSjw5aoThQvhnstGGIYKlKYc= k8s.io/kube-openapi v0.0.0-20250701173324-9bd5c66d9911/go.mod h1:GLOk5B+hDbRROvt0X2+hqX64v/zO3vXN7J78OUmBSKw= -k8s.io/kubectl v0.33.2 h1:7XKZ6DYCklu5MZQzJe+CkCjoGZwD1wWl7t/FxzhMz7Y= -k8s.io/kubectl v0.33.2/go.mod h1:8rC67FB8tVTYraovAGNi/idWIK90z2CHFNMmGJZJ3KI= +k8s.io/kubectl v0.33.3 h1:r/phHvH1iU7gO/l7tTjQk2K01ER7/OAJi8uFHHyWSac= +k8s.io/kubectl v0.33.3/go.mod h1:euj2bG56L6kUGOE/ckZbCoudPwuj4Kud7BR0GzyNiT0= k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y= k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= oras.land/oras-go/v2 v2.6.0 h1:X4ELRsiGkrbeox69+9tzTu492FMUu7zJQW6eJU+I2oc= From 846bb53f721343a53f6a8482ed39a330c2568521 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 16 Jul 2025 22:07:35 +0000 Subject: [PATCH 19/19] chore(deps): bump github.com/spf13/pflag from 1.0.6 to 1.0.7 Bumps [github.com/spf13/pflag](https://github.com/spf13/pflag) from 1.0.6 to 1.0.7. - [Release notes](https://github.com/spf13/pflag/releases) - [Commits](https://github.com/spf13/pflag/compare/v1.0.6...v1.0.7) --- updated-dependencies: - dependency-name: github.com/spf13/pflag dependency-version: 1.0.7 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index e19d71e77..7d40d29a6 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/rubenv/sql-migrate v1.8.0 github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 github.com/spf13/cobra v1.9.1 - github.com/spf13/pflag v1.0.6 + github.com/spf13/pflag v1.0.7 github.com/stretchr/testify v1.10.0 golang.org/x/crypto v0.40.0 golang.org/x/term v0.33.0 diff --git a/go.sum b/go.sum index 4fff82bcc..6ba9f4b69 100644 --- a/go.sum +++ b/go.sum @@ -303,8 +303,9 @@ github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w= github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= -github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M= +github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=