Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package helm-schema for openSUSE:Factory checked in at 2026-04-28 11:54:41 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/helm-schema (Old) and /work/SRC/openSUSE:Factory/.helm-schema.new.11940 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "helm-schema" Tue Apr 28 11:54:41 2026 rev:10 rq:1349347 version:0.23.2 Changes: -------- --- /work/SRC/openSUSE:Factory/helm-schema/helm-schema.changes 2026-04-18 21:39:22.536952605 +0200 +++ /work/SRC/openSUSE:Factory/.helm-schema.new.11940/helm-schema.changes 2026-04-28 11:57:11.915567646 +0200 @@ -1,0 +2,12 @@ +Sun Apr 26 08:03:25 UTC 2026 - Johannes Kastl <[email protected]> + +- Update to version 0.23.2: + * Bug Fixes + - Issue with dependencies by @dadav + * Chores + - chore(deps): bump helm.sh/helm/v3 from 3.20.1 to 3.20.2 + - chore(deps): update goreleaser/goreleaser-action digest to + e24998b + - chore(deps): update alpine:3.23 docker digest to 5b10f43 + +------------------------------------------------------------------- Old: ---- helm-schema-0.23.1.obscpio New: ---- helm-schema-0.23.2.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ helm-schema.spec ++++++ --- /var/tmp/diff_new_pack.jj9gEM/_old 2026-04-28 11:57:12.527592865 +0200 +++ /var/tmp/diff_new_pack.jj9gEM/_new 2026-04-28 11:57:12.531593030 +0200 @@ -17,7 +17,7 @@ Name: helm-schema -Version: 0.23.1 +Version: 0.23.2 Release: 0 Summary: Generate jsonschemas from helm charts License: MIT ++++++ _service ++++++ --- /var/tmp/diff_new_pack.jj9gEM/_old 2026-04-28 11:57:12.583595173 +0200 +++ /var/tmp/diff_new_pack.jj9gEM/_new 2026-04-28 11:57:12.591595502 +0200 @@ -3,7 +3,7 @@ <param name="url">https://github.com/dadav/helm-schema</param> <param name="scm">git</param> <param name="exclude">.git</param> - <param name="revision">0.23.1</param> + <param name="revision">0.23.2</param> <param name="versionformat">@PARENT_TAG@</param> <param name="changesgenerate">enable</param> </service> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.jj9gEM/_old 2026-04-28 11:57:12.635597316 +0200 +++ /var/tmp/diff_new_pack.jj9gEM/_new 2026-04-28 11:57:12.639597481 +0200 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/dadav/helm-schema</param> - <param name="changesrevision">050a5cc4580c56689031dc135f69d2a667fe6afc</param></service></servicedata> + <param name="changesrevision">f1760a68976034f737025d2b42e1bc46f793ae07</param></service></servicedata> (No newline at EOF) ++++++ helm-schema-0.23.1.obscpio -> helm-schema-0.23.2.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/helm-schema-0.23.1/CLAUDE.md new/helm-schema-0.23.2/CLAUDE.md --- old/helm-schema-0.23.1/CLAUDE.md 2026-04-14 14:06:44.000000000 +0200 +++ new/helm-schema-0.23.2/CLAUDE.md 2026-04-24 08:19:06.000000000 +0200 @@ -274,3 +274,5 @@ 6. **Comment parsing**: By default, descriptions are cut at the first empty line in comments. Use `-s` to keep full comments. 7. **Plugin signing**: Signing only works if GPG secrets are configured in GitHub. Missing secrets cause signing steps to be skipped gracefully. + +8. **Dependency schema regeneration**: By default every discovered chart — including those declared as dependencies of another chart — has its `values.schema.json` regenerated from its own `values.yaml`. Pass `--keep-existing-dep-schemas` (`-K`) to instead reuse a dependency chart's pre-existing `values.schema.json` (useful for third-party charts pulled via `helm dep up`, so their rich constraints and `x-*` annotations are preserved). When the flag is set, such dependency schemas are merged into the parent as-is and are not overwritten on disk. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/helm-schema-0.23.1/Dockerfile new/helm-schema-0.23.2/Dockerfile --- old/helm-schema-0.23.1/Dockerfile 2026-04-14 14:06:44.000000000 +0200 +++ new/helm-schema-0.23.2/Dockerfile 2026-04-24 08:19:06.000000000 +0200 @@ -1,4 +1,4 @@ -FROM alpine:3.23@sha256:25109184c71bdad752c8312a8623239686a9a2071e8825f20acb8f2198c3f659 +FROM alpine:3.23@sha256:5b10f432ef3da1b8d4c7eb6c487f2f5a8f096bc91145e68878dd4a5019afde11 ARG TARGETPLATFORM RUN adduser -k /dev/null -u 10001 -D helm-schema \ && chgrp 0 /home/helm-schema \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/helm-schema-0.23.1/README.md new/helm-schema-0.23.2/README.md --- old/helm-schema-0.23.1/README.md 2026-04-14 14:06:44.000000000 +0200 +++ new/helm-schema-0.23.2/README.md 2026-04-24 08:19:06.000000000 +0200 @@ -133,9 +133,10 @@ -d, --dry-run "don't actually create files just print to stdout passed" -p, --helm-docs-compatibility-mode "parse and use helm-docs comments" -h, --help "help for helm-schema" + -K, --keep-existing-dep-schemas "use dependency charts' pre-existing values.schema.json instead of regenerating from values.yaml" -s, --keep-full-comment "keep the whole leading comment (default: cut at empty line)" -l, --log-level string "level of logs that should be printed, one of (panic, fatal, error, warning, info, debug, trace) (default "info")" - -n, --no-dependencies "don't analyze dependencies" + -n, --no-dependencies "skip dependency charts: don't merge them into parents and don't generate their schemas" -o, --output-file string "jsonschema file path relative to each chart directory to which jsonschema will be written (default 'values.schema.json')" -m, --skip-dependencies-schema-validation "skip schema validation for dependencies by setting additionalProperties to true and removing from required" -f, --value-files strings "filenames to look for chart values; schema generation merges all matches in the order provided (default [values.yaml])" @@ -292,7 +293,22 @@ By default, `helm-schema` will try to also create the schemas for the dependencies in their respective chart directory. These schemas will be merged as properties in the main schema, but the `requiredProperties` field will be nullified, otherwise you would have to always overwrite all the required fields. -If you don't want to generate `jsonschema` for chart dependencies, you can use the `-n, --no-dependencies` option to only generate the `values.schema.json` for your parent chart(s) +If you don't want to generate `jsonschema` for chart dependencies, you can use the `-n, --no-dependencies` option to only generate the `values.schema.json` for your parent chart(s). With this flag, any discovered chart that is declared as a dependency of another discovered chart is skipped entirely — the dependency is not merged into its parent and its own `values.schema.json` is not generated. + +### Reusing a Dependency's Pre-existing Schema + +By default, `helm-schema` regenerates `values.schema.json` for every discovered chart — including subcharts that already ship with a hand-written `values.schema.json`. If you instead want to preserve a dependency's shipped schema (typical for third-party charts pulled via `helm dep up` that carry rich constraints such as `minimum`, `pattern`, `format`, or custom `x-*` annotations), pass `-K, --keep-existing-dep-schemas`: + +```sh +helm-schema -K +``` + +When this flag is set: + +1. A dependency chart's pre-existing `values.schema.json` is used as-is and merged into the parent. +2. That dependency's schema file is not overwritten on disk. + +Without the flag, every discovered chart's schema is regenerated from its `values.yaml`. ### Library Charts diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/helm-schema-0.23.1/cmd/helm-schema/cli.go new/helm-schema-0.23.2/cmd/helm-schema/cli.go --- old/helm-schema-0.23.1/cmd/helm-schema/cli.go 2026-04-14 14:06:44.000000000 +0200 +++ new/helm-schema-0.23.2/cmd/helm-schema/cli.go 2026-04-24 08:19:06.000000000 +0200 @@ -61,7 +61,7 @@ cmd.PersistentFlags(). BoolP("dont-strip-helm-docs-prefix", "x", false, "disable the removal of the helm-docs prefix (--)") cmd.PersistentFlags(). - BoolP("no-dependencies", "n", false, "don't analyze dependencies") + BoolP("no-dependencies", "n", false, "skip dependency charts: don't merge them into parents and don't generate their schemas") cmd.PersistentFlags(). BoolP("add-schema-reference", "r", false, "add reference to schema in values.yaml if not found") cmd.PersistentFlags().StringP("log-level", "l", "info", logLevelUsage) @@ -81,6 +81,8 @@ BoolP("allow-circular-dependencies", "w", false, "allow circular dependencies between charts (will log a warning instead of failing)") cmd.PersistentFlags(). BoolP("annotate", "A", false, "write inferred @schema annotations into values.yaml files for unannotated keys") + cmd.PersistentFlags(). + BoolP("keep-existing-dep-schemas", "K", false, "use dependency charts' pre-existing values.schema.json instead of regenerating from values.yaml") viper.AutomaticEnv() viper.SetEnvPrefix("HELM_SCHEMA") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/helm-schema-0.23.1/cmd/helm-schema/main.go new/helm-schema-0.23.2/cmd/helm-schema/main.go --- old/helm-schema-0.23.1/cmd/helm-schema/main.go 2026-04-14 14:06:44.000000000 +0200 +++ new/helm-schema-0.23.2/cmd/helm-schema/main.go 2026-04-24 08:19:06.000000000 +0200 @@ -196,6 +196,7 @@ skipDepsSchemaValidation := viper.GetBool("skip-dependencies-schema-validation") allowCircularDeps := viper.GetBool("allow-circular-dependencies") annotate := viper.GetBool("annotate") + keepExistingDepSchemas := viper.GetBool("keep-existing-dep-schemas") for _, dep := range dependenciesFilter { dependenciesFilterMap[dep] = true } @@ -321,18 +322,24 @@ } } - // For dependency charts with pre-existing schema files, load them instead of - // using the worker-generated schema from values.yaml - if !noDeps { - isDependencyChart := make(map[string]bool) - for _, result := range results { - if result.Chart == nil || len(result.Errors) > 0 { - continue - } - for _, dep := range result.Chart.Dependencies { - isDependencyChart[dep.Name] = true - } + // Identify charts that are declared as dependencies of some other discovered + // chart. Used both to skip dependency charts entirely with --no-dependencies + // and to opt-in reuse of a dependency's pre-existing schema. + isDependencyChart := make(map[string]bool) + for _, result := range results { + if result.Chart == nil || len(result.Errors) > 0 { + continue + } + for _, dep := range result.Chart.Dependencies { + isDependencyChart[dep.Name] = true } + } + + // For dependency charts with pre-existing schema files, load them instead of + // using the worker-generated schema from values.yaml. Opt-in via + // --keep-existing-dep-schemas; default is to regenerate every discovered + // chart's schema. + if !noDeps && keepExistingDepSchemas { for _, result := range results { if result.Chart == nil || len(result.Errors) > 0 { continue @@ -411,6 +418,13 @@ continue } + // With --no-dependencies, skip charts that are declared as dependencies of + // some other discovered chart. Top-level charts are still processed. + if noDeps && isDependencyChart[result.Chart.Name] { + log.Debugf("Skipping dependency chart %s (--no-dependencies)", result.Chart.Name) + continue + } + log.Debugf("Processing result for chart: %s (%s)", result.Chart.Name, result.ChartPath) if !noDeps { chartNameToResult[result.Chart.Name] = result diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/helm-schema-0.23.1/cmd/helm-schema/main_test.go new/helm-schema-0.23.2/cmd/helm-schema/main_test.go --- old/helm-schema-0.23.1/cmd/helm-schema/main_test.go 1970-01-01 01:00:00.000000000 +0100 +++ new/helm-schema-0.23.2/cmd/helm-schema/main_test.go 2026-04-24 08:19:06.000000000 +0200 @@ -0,0 +1,576 @@ +package main + +import ( + "encoding/json" + "os" + "path/filepath" + "testing" + + "github.com/spf13/viper" + "github.com/stretchr/testify/assert" +) + +type stringOrArray []string + +func (s *stringOrArray) UnmarshalJSON(value []byte) error { + if len(value) == 0 { + return nil + } + if value[0] == '"' { + var single string + if err := json.Unmarshal(value, &single); err != nil { + return err + } + *s = []string{single} + return nil + } + var multi []string + if err := json.Unmarshal(value, &multi); err != nil { + return err + } + *s = multi + return nil +} + +type schemaDoc struct { + Properties map[string]schemaProperty `json:"properties"` +} + +type schemaProperty struct { + Type stringOrArray `json:"type"` + Properties map[string]schemaProperty `json:"properties"` +} + +func TestExec_ConditionPatchingAndRootConditions(t *testing.T) { + tmpDir := t.TempDir() + + writeFile := func(relPath, content string) { + path := filepath.Join(tmpDir, relPath) + err := os.MkdirAll(filepath.Dir(path), 0o755) + assert.NoError(t, err) + err = os.WriteFile(path, []byte(content), 0o644) + assert.NoError(t, err) + } + + writeFile("dep/Chart.yaml", ` +apiVersion: v2 +name: dep +version: 1.0.0 +`) + writeFile("dep/values.yaml", ` +key: value +`) + + writeFile("dep2/Chart.yaml", ` +apiVersion: v2 +name: dep2 +version: 1.0.0 +`) + writeFile("dep2/values.yaml", ` +key: value +`) + + writeFile("parent1/Chart.yaml", ` +apiVersion: v2 +name: parent1 +version: 1.0.0 +dependencies: + - name: dep + version: 1.0.0 + condition: dep.enabled + - name: dep2 + version: 1.0.0 + condition: dep2 +`) + writeFile("parent1/values.yaml", ` +root: value +`) + + writeFile("parent2/Chart.yaml", ` +apiVersion: v2 +name: parent2 +version: 1.0.0 +dependencies: + - name: dep + version: 1.0.0 + condition: dep.extra.flag +`) + writeFile("parent2/values.yaml", ` +root: value +`) + + viper.Reset() + viper.Set("chart-search-root", tmpDir) + viper.Set("dry-run", false) + viper.Set("no-dependencies", false) + viper.Set("add-schema-reference", false) + viper.Set("keep-full-comment", false) + viper.Set("helm-docs-compatibility-mode", false) + viper.Set("uncomment", false) + viper.Set("output-file", "values.schema.json") + viper.Set("dont-strip-helm-docs-prefix", false) + viper.Set("append-newline", false) + viper.Set("dependencies-filter", []string{}) + viper.Set("dont-add-global", true) + viper.Set("skip-dependencies-schema-validation", false) + viper.Set("allow-circular-dependencies", false) + viper.Set("annotate", false) + viper.Set("keep-existing-dep-schemas", false) + viper.Set("value-files", []string{"values.yaml"}) + viper.Set("skip-auto-generation", []string{}) + viper.Set("log-level", "info") + + err := exec(nil, nil) + assert.NoError(t, err) + + depSchemaPath := filepath.Join(tmpDir, "dep", "values.schema.json") + depSchemaBytes, err := os.ReadFile(depSchemaPath) + assert.NoError(t, err) + + var depSchema schemaDoc + err = json.Unmarshal(depSchemaBytes, &depSchema) + assert.NoError(t, err) + + enabledProp, ok := depSchema.Properties["enabled"] + assert.True(t, ok) + assert.Contains(t, []string(enabledProp.Type), "boolean") + + extraProp, ok := depSchema.Properties["extra"] + assert.True(t, ok) + flagProp, ok := extraProp.Properties["flag"] + assert.True(t, ok) + assert.Contains(t, []string(flagProp.Type), "boolean") + + parent1SchemaPath := filepath.Join(tmpDir, "parent1", "values.schema.json") + parent1SchemaBytes, err := os.ReadFile(parent1SchemaPath) + assert.NoError(t, err) + + var parent1Schema schemaDoc + err = json.Unmarshal(parent1SchemaBytes, &parent1Schema) + assert.NoError(t, err) + + dep2Prop, ok := parent1Schema.Properties["dep2"] + assert.True(t, ok) + assert.Contains(t, []string(dep2Prop.Type), "object") + assert.Contains(t, []string(dep2Prop.Type), "boolean") +} + +func TestExec_DependencyFilterSkipsConditionPatching(t *testing.T) { + tmpDir := t.TempDir() + + writeFile := func(relPath, content string) { + path := filepath.Join(tmpDir, relPath) + err := os.MkdirAll(filepath.Dir(path), 0o755) + assert.NoError(t, err) + err = os.WriteFile(path, []byte(content), 0o644) + assert.NoError(t, err) + } + + writeFile("dep/Chart.yaml", ` +apiVersion: v2 +name: dep +version: 1.0.0 +`) + writeFile("dep/values.yaml", ` +key: value +`) + + writeFile("dep2/Chart.yaml", ` +apiVersion: v2 +name: dep2 +version: 1.0.0 +`) + writeFile("dep2/values.yaml", ` +key: value +`) + + writeFile("Chart.yaml", ` +apiVersion: v2 +name: parent +version: 1.0.0 +dependencies: + - name: dep + version: 1.0.0 + condition: dep.enabled + - name: dep2 + version: 1.0.0 + condition: dep2.flag +`) + writeFile("values.yaml", ` +root: value +`) + + viper.Reset() + viper.Set("chart-search-root", tmpDir) + viper.Set("dry-run", false) + viper.Set("no-dependencies", false) + viper.Set("add-schema-reference", false) + viper.Set("keep-full-comment", false) + viper.Set("helm-docs-compatibility-mode", false) + viper.Set("uncomment", false) + viper.Set("output-file", "values.schema.json") + viper.Set("dont-strip-helm-docs-prefix", false) + viper.Set("append-newline", false) + viper.Set("dependencies-filter", []string{"dep"}) + viper.Set("dont-add-global", true) + viper.Set("skip-dependencies-schema-validation", false) + viper.Set("allow-circular-dependencies", false) + viper.Set("annotate", false) + viper.Set("keep-existing-dep-schemas", false) + viper.Set("value-files", []string{"values.yaml"}) + viper.Set("skip-auto-generation", []string{}) + viper.Set("log-level", "info") + + err := exec(nil, nil) + assert.NoError(t, err) + + parentSchemaPath := filepath.Join(tmpDir, "values.schema.json") + parentSchemaBytes, err := os.ReadFile(parentSchemaPath) + assert.NoError(t, err) + + var parentSchema schemaDoc + err = json.Unmarshal(parentSchemaBytes, &parentSchema) + assert.NoError(t, err) + + _, hasDep := parentSchema.Properties["dep"] + _, hasDep2 := parentSchema.Properties["dep2"] + assert.True(t, hasDep) + assert.False(t, hasDep2) + + depSchemaPath := filepath.Join(tmpDir, "dep", "values.schema.json") + depSchemaBytes, err := os.ReadFile(depSchemaPath) + assert.NoError(t, err) + + var depSchema schemaDoc + err = json.Unmarshal(depSchemaBytes, &depSchema) + assert.NoError(t, err) + + enabledProp, ok := depSchema.Properties["enabled"] + assert.True(t, ok) + assert.Contains(t, []string(enabledProp.Type), "boolean") + + dep2SchemaPath := filepath.Join(tmpDir, "dep2", "values.schema.json") + _, err = os.Stat(dep2SchemaPath) + assert.True(t, os.IsNotExist(err)) +} + +func TestExec_DependencyAliasConditionPatching(t *testing.T) { + tmpDir := t.TempDir() + + writeFile := func(relPath, content string) { + path := filepath.Join(tmpDir, relPath) + err := os.MkdirAll(filepath.Dir(path), 0o755) + assert.NoError(t, err) + err = os.WriteFile(path, []byte(content), 0o644) + assert.NoError(t, err) + } + + writeFile("dep/Chart.yaml", ` +apiVersion: v2 +name: dep +version: 1.0.0 +`) + writeFile("dep/values.yaml", ` +key: value +`) + + writeFile("Chart.yaml", ` +apiVersion: v2 +name: parent +version: 1.0.0 +dependencies: + - name: dep + alias: depalias + version: 1.0.0 + condition: depalias.enabled +`) + writeFile("values.yaml", ` +root: value +`) + + viper.Reset() + viper.Set("chart-search-root", tmpDir) + viper.Set("dry-run", false) + viper.Set("no-dependencies", false) + viper.Set("add-schema-reference", false) + viper.Set("keep-full-comment", false) + viper.Set("helm-docs-compatibility-mode", false) + viper.Set("uncomment", false) + viper.Set("output-file", "values.schema.json") + viper.Set("dont-strip-helm-docs-prefix", false) + viper.Set("append-newline", false) + viper.Set("dependencies-filter", []string{}) + viper.Set("dont-add-global", true) + viper.Set("skip-dependencies-schema-validation", false) + viper.Set("allow-circular-dependencies", false) + viper.Set("annotate", false) + viper.Set("keep-existing-dep-schemas", false) + viper.Set("value-files", []string{"values.yaml"}) + viper.Set("skip-auto-generation", []string{}) + viper.Set("log-level", "info") + + err := exec(nil, nil) + assert.NoError(t, err) + + depSchemaPath := filepath.Join(tmpDir, "dep", "values.schema.json") + depSchemaBytes, err := os.ReadFile(depSchemaPath) + assert.NoError(t, err) + + var depSchema schemaDoc + err = json.Unmarshal(depSchemaBytes, &depSchema) + assert.NoError(t, err) + + enabledProp, ok := depSchema.Properties["enabled"] + assert.True(t, ok) + assert.Contains(t, []string(enabledProp.Type), "boolean") + + parentSchemaPath := filepath.Join(tmpDir, "values.schema.json") + parentSchemaBytes, err := os.ReadFile(parentSchemaPath) + assert.NoError(t, err) + + var parentSchema schemaDoc + err = json.Unmarshal(parentSchemaBytes, &parentSchema) + assert.NoError(t, err) + + _, ok = parentSchema.Properties["depalias"] + assert.True(t, ok) +} + +func TestExec_KeepExistingDepSchemasPreservesDependencySchema(t *testing.T) { + tmpDir := t.TempDir() + + writeFile := func(relPath, content string) { + path := filepath.Join(tmpDir, relPath) + err := os.MkdirAll(filepath.Dir(path), 0o755) + assert.NoError(t, err) + err = os.WriteFile(path, []byte(content), 0o644) + assert.NoError(t, err) + } + + writeFile("dep/Chart.yaml", ` +apiVersion: v2 +name: dep +version: 1.0.0 +`) + writeFile("dep/values.yaml", ` +port: 8080 +`) + preExistingDepSchema := `{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "port": { + "type": "integer", + "description": "The port to listen on", + "minimum": 1, + "maximum": 65535, + "x-custom-annotation": "preserve-me" + } + }, + "required": ["port"] +} +` + writeFile("dep/values.schema.json", preExistingDepSchema) + + writeFile("parent/Chart.yaml", ` +apiVersion: v2 +name: parent +version: 1.0.0 +dependencies: + - name: dep + version: 1.0.0 + repository: file://../dep +`) + writeFile("parent/values.yaml", ` +root: value +`) + + viper.Reset() + viper.Set("chart-search-root", tmpDir) + viper.Set("dry-run", false) + viper.Set("no-dependencies", false) + viper.Set("add-schema-reference", false) + viper.Set("keep-full-comment", false) + viper.Set("helm-docs-compatibility-mode", false) + viper.Set("uncomment", false) + viper.Set("output-file", "values.schema.json") + viper.Set("dont-strip-helm-docs-prefix", false) + viper.Set("append-newline", false) + viper.Set("dependencies-filter", []string{}) + viper.Set("dont-add-global", true) + viper.Set("skip-dependencies-schema-validation", false) + viper.Set("allow-circular-dependencies", false) + viper.Set("annotate", false) + viper.Set("keep-existing-dep-schemas", true) + viper.Set("value-files", []string{"values.yaml"}) + viper.Set("skip-auto-generation", []string{}) + viper.Set("log-level", "info") + + err := exec(nil, nil) + assert.NoError(t, err) + + depSchemaPath := filepath.Join(tmpDir, "dep", "values.schema.json") + depSchemaBytes, err := os.ReadFile(depSchemaPath) + assert.NoError(t, err) + assert.Equal(t, preExistingDepSchema, string(depSchemaBytes), + "dependency's pre-existing values.schema.json must not be overwritten when --keep-existing-dep-schemas is set") + + parentSchemaPath := filepath.Join(tmpDir, "parent", "values.schema.json") + parentSchemaBytes, err := os.ReadFile(parentSchemaPath) + assert.NoError(t, err) + + var parentRaw map[string]any + err = json.Unmarshal(parentSchemaBytes, &parentRaw) + assert.NoError(t, err) + + props, _ := parentRaw["properties"].(map[string]any) + depNode, ok := props["dep"].(map[string]any) + assert.True(t, ok, "parent must nest dependency schema under dep key") + depProps, _ := depNode["properties"].(map[string]any) + portNode, ok := depProps["port"].(map[string]any) + assert.True(t, ok, "parent must include port from merged dependency schema") + assert.Equal(t, "preserve-me", portNode["x-custom-annotation"], + "pre-existing x-* annotations must be carried into the merged parent schema") +} + +func TestExec_DefaultRegeneratesDependencySchema(t *testing.T) { + tmpDir := t.TempDir() + + writeFile := func(relPath, content string) { + path := filepath.Join(tmpDir, relPath) + err := os.MkdirAll(filepath.Dir(path), 0o755) + assert.NoError(t, err) + err = os.WriteFile(path, []byte(content), 0o644) + assert.NoError(t, err) + } + + writeFile("dep/Chart.yaml", ` +apiVersion: v2 +name: dep +version: 1.0.0 +`) + writeFile("dep/values.yaml", ` +port: 8080 +`) + preExistingDepSchema := `{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "port": { + "type": "integer", + "x-custom-annotation": "should-be-lost" + } + } +} +` + writeFile("dep/values.schema.json", preExistingDepSchema) + + writeFile("parent/Chart.yaml", ` +apiVersion: v2 +name: parent +version: 1.0.0 +dependencies: + - name: dep + version: 1.0.0 + repository: file://../dep +`) + writeFile("parent/values.yaml", ` +root: value +`) + + viper.Reset() + viper.Set("chart-search-root", tmpDir) + viper.Set("dry-run", false) + viper.Set("no-dependencies", false) + viper.Set("add-schema-reference", false) + viper.Set("keep-full-comment", false) + viper.Set("helm-docs-compatibility-mode", false) + viper.Set("uncomment", false) + viper.Set("output-file", "values.schema.json") + viper.Set("dont-strip-helm-docs-prefix", false) + viper.Set("append-newline", false) + viper.Set("dependencies-filter", []string{}) + viper.Set("dont-add-global", true) + viper.Set("skip-dependencies-schema-validation", false) + viper.Set("allow-circular-dependencies", false) + viper.Set("annotate", false) + viper.Set("keep-existing-dep-schemas", false) + viper.Set("value-files", []string{"values.yaml"}) + viper.Set("skip-auto-generation", []string{}) + viper.Set("log-level", "info") + + err := exec(nil, nil) + assert.NoError(t, err) + + depSchemaPath := filepath.Join(tmpDir, "dep", "values.schema.json") + depSchemaBytes, err := os.ReadFile(depSchemaPath) + assert.NoError(t, err) + assert.NotEqual(t, preExistingDepSchema, string(depSchemaBytes), + "default mode must regenerate a dependency's values.schema.json") +} + +func TestExec_NoDependenciesSkipsDependencyCharts(t *testing.T) { + tmpDir := t.TempDir() + + writeFile := func(relPath, content string) { + path := filepath.Join(tmpDir, relPath) + err := os.MkdirAll(filepath.Dir(path), 0o755) + assert.NoError(t, err) + err = os.WriteFile(path, []byte(content), 0o644) + assert.NoError(t, err) + } + + writeFile("foo/Chart.yaml", ` +apiVersion: v2 +name: foo +version: 1.0.0 +dependencies: + - name: bar + version: 1.0.0 + repository: file://./bar +`) + writeFile("foo/values.yaml", ` +top: 1 +`) + writeFile("foo/bar/Chart.yaml", ` +apiVersion: v2 +name: bar +version: 1.0.0 +`) + writeFile("foo/bar/values.yaml", ` +inside: 2 +`) + + viper.Reset() + viper.Set("chart-search-root", filepath.Join(tmpDir, "foo")) + viper.Set("dry-run", false) + viper.Set("no-dependencies", true) + viper.Set("add-schema-reference", false) + viper.Set("keep-full-comment", false) + viper.Set("helm-docs-compatibility-mode", false) + viper.Set("uncomment", false) + viper.Set("output-file", "values.schema.json") + viper.Set("dont-strip-helm-docs-prefix", false) + viper.Set("append-newline", false) + viper.Set("dependencies-filter", []string{}) + viper.Set("dont-add-global", true) + viper.Set("skip-dependencies-schema-validation", false) + viper.Set("allow-circular-dependencies", false) + viper.Set("annotate", false) + viper.Set("keep-existing-dep-schemas", false) + viper.Set("value-files", []string{"values.yaml"}) + viper.Set("skip-auto-generation", []string{}) + viper.Set("log-level", "info") + + err := exec(nil, nil) + assert.NoError(t, err) + + parentSchemaPath := filepath.Join(tmpDir, "foo", "values.schema.json") + _, err = os.Stat(parentSchemaPath) + assert.NoError(t, err, "parent chart schema must still be generated with --no-dependencies") + + depSchemaPath := filepath.Join(tmpDir, "foo", "bar", "values.schema.json") + _, err = os.Stat(depSchemaPath) + assert.True(t, os.IsNotExist(err), + "dependency chart schema must not be generated with --no-dependencies (issue #215)") +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/helm-schema-0.23.1/cmd/helm-schema/version.go new/helm-schema-0.23.2/cmd/helm-schema/version.go --- old/helm-schema-0.23.1/cmd/helm-schema/version.go 2026-04-14 14:06:44.000000000 +0200 +++ new/helm-schema-0.23.2/cmd/helm-schema/version.go 2026-04-24 08:19:06.000000000 +0200 @@ -1,3 +1,3 @@ package main -var version string = "0.23.1" +var version string = "0.23.2" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/helm-schema-0.23.1/go.mod new/helm-schema-0.23.2/go.mod --- old/helm-schema-0.23.1/go.mod 2026-04-14 14:06:44.000000000 +0200 +++ new/helm-schema-0.23.2/go.mod 2026-04-24 08:19:06.000000000 +0200 @@ -41,5 +41,5 @@ golang.org/x/sys v0.42.0 // indirect golang.org/x/text v0.35.0 // indirect gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect - helm.sh/helm/v3 v3.20.1 // indirect + helm.sh/helm/v3 v3.20.2 // indirect ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/helm-schema-0.23.1/go.sum new/helm-schema-0.23.2/go.sum --- old/helm-schema-0.23.1/go.sum 2026-04-14 14:06:44.000000000 +0200 +++ new/helm-schema-0.23.2/go.sum 2026-04-24 08:19:06.000000000 +0200 @@ -39,8 +39,6 @@ github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/norwoodj/helm-docs v1.14.2 h1:Ew3bCq1hZqMnnTopkk66Uy2mGwu/jAclAx+3JAVp1To= github.com/norwoodj/helm-docs v1.14.2/go.mod h1:qdo76rorOkPDme8nsV5e0JBAYrs56kzvZMYW83k1kgc= -github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= -github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/pelletier/go-toml/v2 v2.3.0 h1:k59bC/lIZREW0/iVaQR8nDHxVq8OVlIzYCOJf421CaM= github.com/pelletier/go-toml/v2 v2.3.0/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -75,16 +73,10 @@ github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= -golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= -golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= -golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= -golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= -golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= -golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8= golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -92,7 +84,5 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -helm.sh/helm/v3 v3.20.0 h1:2M+0qQwnbI1a2CxN7dbmfsWHg/MloeaFMnZCY56as50= -helm.sh/helm/v3 v3.20.0/go.mod h1:rTavWa0lagZOxGfdhu4vgk1OjH2UYCnrDKE2PVC4N0o= -helm.sh/helm/v3 v3.20.1 h1:T8PodUaH1UwNvE+imUA2mIKjJItY8g7CVvLVP5g4NzI= -helm.sh/helm/v3 v3.20.1/go.mod h1:Fl1kBaWCpkUrM6IYXPjQ3bdZQfFrogKArqptvueZ6Ww= +helm.sh/helm/v3 v3.20.2 h1:binM4rvPx5DcNsa1sIt7UZi55lRbu3pZUFmQkSoRh48= +helm.sh/helm/v3 v3.20.2/go.mod h1:Fl1kBaWCpkUrM6IYXPjQ3bdZQfFrogKArqptvueZ6Ww= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/helm-schema-0.23.1/plugin.yaml new/helm-schema-0.23.2/plugin.yaml --- old/helm-schema-0.23.1/plugin.yaml 2026-04-14 14:06:44.000000000 +0200 +++ new/helm-schema-0.23.2/plugin.yaml 2026-04-24 08:19:06.000000000 +0200 @@ -1,6 +1,6 @@ --- name: "schema" -version: "0.23.1" +version: "0.23.2" usage: "generate jsonschemas for your helm charts" description: "generate jsonschemas for your helm charts" command: "$HELM_PLUGIN_DIR/bin/helm-schema" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/helm-schema-0.23.1/tests/preexisting-schema/parent/values.schema.default-expected.json new/helm-schema-0.23.2/tests/preexisting-schema/parent/values.schema.default-expected.json --- old/helm-schema-0.23.1/tests/preexisting-schema/parent/values.schema.default-expected.json 1970-01-01 01:00:00.000000000 +0100 +++ new/helm-schema-0.23.2/tests/preexisting-schema/parent/values.schema.default-expected.json 2026-04-24 08:19:06.000000000 +0200 @@ -0,0 +1,45 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "appName": { + "default": "myapp", + "title": "appName", + "type": "string" + }, + "dep-with-schema": { + "description": "A dependency chart with its own schema", + "properties": { + "global": { + "description": "Global values are values that can be accessed from any chart or subchart by exactly the same name.", + "required": [], + "title": "global", + "type": "object" + }, + "host": { + "default": "localhost", + "title": "host", + "type": "string" + }, + "port": { + "default": 8080, + "title": "port", + "type": "integer" + } + }, + "required": [], + "title": "dep-with-schema", + "type": "object" + }, + "global": { + "description": "Global values are values that can be accessed from any chart or subchart by exactly the same name.", + "required": [], + "title": "global", + "type": "object" + } + }, + "required": [ + "appName" + ], + "type": "object" +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/helm-schema-0.23.1/tests/run.sh new/helm-schema-0.23.2/tests/run.sh --- old/helm-schema-0.23.1/tests/run.sh 2026-04-14 14:06:44.000000000 +0200 +++ new/helm-schema-0.23.2/tests/run.sh 2026-04-24 08:19:06.000000000 +0200 @@ -60,25 +60,50 @@ rm -f ../import-values/parent/values.schema.json ../import-values/child/values.schema.json rm -f ../import-values/parent-complex/values.schema.json ../import-values/child-complex/values.schema.json -# Pre-existing schema test -echo "Testing pre-existing dependency schema" -dep_schema_before=$(cat ../preexisting-schema/dep-with-schema/values.schema.json) -../helm-schema -c ../preexisting-schema >/dev/null 2>&1 +# Pre-existing schema test (opt-in via --keep-existing-dep-schemas) +echo "Testing pre-existing dependency schema (opt-in)" +dep_schema_backup=$(mktemp) +cp ../preexisting-schema/dep-with-schema/values.schema.json "$dep_schema_backup" +dep_schema_before=$(cat "$dep_schema_backup") +../helm-schema -c ../preexisting-schema --keep-existing-dep-schemas >/dev/null 2>&1 if diff -y --suppress-common-lines <(jq --sort-keys . ../preexisting-schema/parent/values.schema.json) <(jq --sort-keys . ../preexisting-schema/parent/values.schema.expected.json); then - echo "✅: pre-existing dependency schema" + echo "✅: pre-existing dependency schema (opt-in)" else - echo "❌: pre-existing dependency schema" + echo "❌: pre-existing dependency schema (opt-in)" rc=1 fi dep_schema_after=$(cat ../preexisting-schema/dep-with-schema/values.schema.json) if [ "$dep_schema_before" = "$dep_schema_after" ]; then - echo "✅: dependency schema not overwritten" + echo "✅: dependency schema not overwritten (opt-in)" +else + echo "❌: dependency schema was overwritten (opt-in)" + rc=1 +fi + +rm -f ../preexisting-schema/parent/values.schema.json + +# Default behavior: dependency schemas are regenerated (issue #215 regression guard) +echo "Testing dependency schema regeneration (default)" +../helm-schema -c ../preexisting-schema >/dev/null 2>&1 +if diff -y --suppress-common-lines <(jq --sort-keys . ../preexisting-schema/parent/values.schema.json) <(jq --sort-keys . ../preexisting-schema/parent/values.schema.default-expected.json); then + echo "✅: dependency schema regeneration (parent)" +else + echo "❌: dependency schema regeneration (parent)" + rc=1 +fi + +dep_schema_after_default=$(cat ../preexisting-schema/dep-with-schema/values.schema.json) +if [ "$dep_schema_before" != "$dep_schema_after_default" ]; then + echo "✅: dependency schema regenerated (default)" else - echo "❌: dependency schema was overwritten" + echo "❌: dependency schema was NOT regenerated (default)" rc=1 fi +# Restore the original pre-existing dep schema so the fixture is stable across runs +cp "$dep_schema_backup" ../preexisting-schema/dep-with-schema/values.schema.json +rm -f "$dep_schema_backup" rm -f ../preexisting-schema/parent/values.schema.json exit "$rc" ++++++ helm-schema.obsinfo ++++++ --- /var/tmp/diff_new_pack.jj9gEM/_old 2026-04-28 11:57:12.959610667 +0200 +++ /var/tmp/diff_new_pack.jj9gEM/_new 2026-04-28 11:57:12.967610996 +0200 @@ -1,5 +1,5 @@ name: helm-schema -version: 0.23.1 -mtime: 1776168404 -commit: 050a5cc4580c56689031dc135f69d2a667fe6afc +version: 0.23.2 +mtime: 1777011546 +commit: f1760a68976034f737025d2b42e1bc46f793ae07 ++++++ vendor.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/modules.txt new/vendor/modules.txt --- old/vendor/modules.txt 2026-04-14 14:06:44.000000000 +0200 +++ new/vendor/modules.txt 2026-04-24 08:19:06.000000000 +0200 @@ -142,6 +142,6 @@ # gopkg.in/yaml.v3 v3.0.1 ## explicit gopkg.in/yaml.v3 -# helm.sh/helm/v3 v3.20.1 +# helm.sh/helm/v3 v3.20.2 ## explicit; go 1.25.0 helm.sh/helm/v3/pkg/ignore
