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-02-09 15:35:10
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/helm-schema (Old)
 and      /work/SRC/openSUSE:Factory/.helm-schema.new.1670 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "helm-schema"

Mon Feb  9 15:35:10 2026 rev:4 rq:1331951 version:0.21.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/helm-schema/helm-schema.changes  2026-01-30 
18:26:59.345395645 +0100
+++ /work/SRC/openSUSE:Factory/.helm-schema.new.1670/helm-schema.changes        
2026-02-09 15:35:44.369637691 +0100
@@ -1,0 +2,14 @@
+Mon Feb 09 06:45:19 UTC 2026 - Johannes Kastl 
<[email protected]>
+
+- Update to version 0.21.1:
+  no code changes
+- Update to version 0.21.0:
+  * feat: Add annotate functionality
+- Update to version 0.20.3:
+  * fix(uncomment): preserve indentation and flush buffer on
+    uncommented lines
+  * chore(deps): update alpine:3.23 docker digest to 2510918
+  * chore(deps): update azure/setup-helm digest to 1a275c3
+  * chore(deps): update docker/login-action digest to c94ce9f
+
+-------------------------------------------------------------------

Old:
----
  helm-schema-0.20.2.obscpio

New:
----
  helm-schema-0.21.1.obscpio

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ helm-schema.spec ++++++
--- /var/tmp/diff_new_pack.iL16sZ/_old  2026-02-09 15:35:44.957662360 +0100
+++ /var/tmp/diff_new_pack.iL16sZ/_new  2026-02-09 15:35:44.957662360 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           helm-schema
-Version:        0.20.2
+Version:        0.21.1
 Release:        0
 Summary:        Generate jsonschemas from helm charts
 License:        MIT

++++++ _service ++++++
--- /var/tmp/diff_new_pack.iL16sZ/_old  2026-02-09 15:35:45.005664373 +0100
+++ /var/tmp/diff_new_pack.iL16sZ/_new  2026-02-09 15:35:45.009664541 +0100
@@ -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.20.2</param>
+    <param name="revision">0.21.1</param>
     <param name="versionformat">@PARENT_TAG@</param>
     <param name="changesgenerate">enable</param>
   </service>

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.iL16sZ/_old  2026-02-09 15:35:45.033665551 +0100
+++ /var/tmp/diff_new_pack.iL16sZ/_new  2026-02-09 15:35:45.037665719 +0100
@@ -1,6 +1,6 @@
 <servicedata>
 <service name="tar_scm">
                 <param name="url">https://github.com/dadav/helm-schema</param>
-              <param 
name="changesrevision">7711600f4ada6f2a71ccb81668e2637789315c7b</param></service></servicedata>
+              <param 
name="changesrevision">c0ca4c5c600f237539b2a1e5fbfcac7bb963bbbc</param></service></servicedata>
 (No newline at EOF)
 

++++++ helm-schema-0.20.2.obscpio -> helm-schema-0.21.1.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/helm-schema-0.20.2/CLAUDE.md 
new/helm-schema-0.21.1/CLAUDE.md
--- old/helm-schema-0.20.2/CLAUDE.md    2026-01-29 21:32:50.000000000 +0100
+++ new/helm-schema-0.21.1/CLAUDE.md    2026-02-09 06:52:57.000000000 +0100
@@ -61,6 +61,8 @@
 
 6. **Output** (`cmd/helm-schema/main.go`): Writes `values.schema.json` files 
to each chart directory.
 
+7. **Annotation Mode** (`pkg/schema/annotate.go`): With `--annotate` / `-A` 
flag, writes inferred `@schema` type annotation blocks into `values.yaml` files 
for keys that don't already have them. This is a separate execution mode that 
modifies values files instead of generating JSON schema. Keys that already have 
`@schema` blocks are skipped.
+
 ### Key Components
 
 #### Schema Parsing (`pkg/schema/schema.go`)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/helm-schema-0.20.2/Dockerfile 
new/helm-schema-0.21.1/Dockerfile
--- old/helm-schema-0.20.2/Dockerfile   2026-01-29 21:32:50.000000000 +0100
+++ new/helm-schema-0.21.1/Dockerfile   2026-02-09 06:52:57.000000000 +0100
@@ -1,4 +1,4 @@
-FROM 
alpine:3.23@sha256:865b95f46d98cf867a156fe4a135ad3fe50d2056aa3f25ed31662dff6da4eb62
+FROM 
alpine:3.23@sha256:25109184c71bdad752c8312a8623239686a9a2071e8825f20acb8f2198c3f659
 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.20.2/cmd/helm-schema/cli.go 
new/helm-schema-0.21.1/cmd/helm-schema/cli.go
--- old/helm-schema-0.20.2/cmd/helm-schema/cli.go       2026-01-29 
21:32:50.000000000 +0100
+++ new/helm-schema-0.21.1/cmd/helm-schema/cli.go       2026-02-09 
06:52:57.000000000 +0100
@@ -79,6 +79,8 @@
                BoolP("skip-dependencies-schema-validation", "m", false, "skip 
schema validation for dependencies by setting additionalProperties to true and 
removing from required")
        cmd.PersistentFlags().
                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")
 
        viper.AutomaticEnv()
        viper.SetEnvPrefix("HELM_SCHEMA")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/helm-schema-0.20.2/cmd/helm-schema/main.go 
new/helm-schema-0.21.1/cmd/helm-schema/main.go
--- old/helm-schema-0.20.2/cmd/helm-schema/main.go      2026-01-29 
21:32:50.000000000 +0100
+++ new/helm-schema-0.21.1/cmd/helm-schema/main.go      2026-02-09 
06:52:57.000000000 +0100
@@ -55,6 +55,7 @@
        dontAddGlobal := viper.GetBool("dont-add-global")
        skipDepsSchemaValidation := 
viper.GetBool("skip-dependencies-schema-validation")
        allowCircularDeps := viper.GetBool("allow-circular-dependencies")
+       annotate := viper.GetBool("annotate")
        for _, dep := range dependenciesFilter {
                dependenciesFilterMap[dep] = true
        }
@@ -99,6 +100,7 @@
                                helmDocsCompatibilityMode,
                                dontRemoveHelmDocsPrefix,
                                dontAddGlobal,
+                               annotate,
                                valueFileNames,
                                skipConfig,
                                outFile,
@@ -145,6 +147,28 @@
                }
        }
 
+       // In annotate mode, just report errors and return (no schema 
generation)
+       if annotate {
+               foundErrors := false
+               for _, result := range results {
+                       if len(result.Errors) > 0 {
+                               foundErrors = true
+                               if result.Chart != nil {
+                                       log.Errorf("Found %d errors while 
annotating chart %s (%s)", len(result.Errors), result.Chart.Name, 
result.ChartPath)
+                               } else {
+                                       log.Errorf("Found %d errors while 
annotating chart %s", len(result.Errors), result.ChartPath)
+                               }
+                               for _, err := range result.Errors {
+                                       log.Error(err)
+                               }
+                       }
+               }
+               if foundErrors {
+                       return errors.New("some errors were found")
+               }
+               return nil
+       }
+
        if !noDeps {
                results, err = schema.TopoSort(results, allowCircularDeps)
                if err != nil {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/helm-schema-0.20.2/cmd/helm-schema/version.go 
new/helm-schema-0.21.1/cmd/helm-schema/version.go
--- old/helm-schema-0.20.2/cmd/helm-schema/version.go   2026-01-29 
21:32:50.000000000 +0100
+++ new/helm-schema-0.21.1/cmd/helm-schema/version.go   2026-02-09 
06:52:57.000000000 +0100
@@ -1,3 +1,3 @@
 package main
 
-var version string = "0.20.2"
+var version string = "0.21.1"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/helm-schema-0.20.2/pkg/schema/annotate.go 
new/helm-schema-0.21.1/pkg/schema/annotate.go
--- old/helm-schema-0.20.2/pkg/schema/annotate.go       1970-01-01 
01:00:00.000000000 +0100
+++ new/helm-schema-0.21.1/pkg/schema/annotate.go       2026-02-09 
06:52:57.000000000 +0100
@@ -0,0 +1,194 @@
+package schema
+
+import (
+       "fmt"
+       "os"
+       "sort"
+       "strings"
+
+       log "github.com/sirupsen/logrus"
+       "gopkg.in/yaml.v3"
+)
+
+// HasSchemaAnnotation checks if a HeadComment already contains a # @schema 
block.
+// It matches exact "# @schema" lines but not "# @schema.root" lines.
+func HasSchemaAnnotation(comment string) bool {
+       for _, line := range strings.Split(comment, "\n") {
+               trimmed := strings.TrimSpace(line)
+               if trimmed == "# @schema" {
+                       return true
+               }
+       }
+       return false
+}
+
+// typeAnnotationFromTag maps a YAML tag to the annotation type string.
+// Uses the same mapping as typeFromTag.
+func typeAnnotationFromTag(tag string) string {
+       switch tag {
+       case nullTag:
+               return `"null"`
+       case boolTag:
+               return "boolean"
+       case strTag:
+               return "string"
+       case intTag:
+               return "integer"
+       case floatTag:
+               return "number"
+       case timestampTag:
+               return "string"
+       case arrayTag:
+               return "array"
+       case mapTag:
+               return "object"
+       default:
+               return ""
+       }
+}
+
+// InsertionPoint represents where to insert an annotation block in the file.
+type InsertionPoint struct {
+       Line    int    // 1-based line number of the key node
+       Indent  string // indentation string (spaces) derived from 
keyNode.Column
+       TypeStr string // type annotation value
+}
+
+// collectInsertionPoints walks the yaml.Node tree and collects InsertionPoints
+// for keys that don't already have @schema annotations.
+func collectInsertionPoints(node *yaml.Node) []InsertionPoint {
+       var points []InsertionPoint
+       collectInsertionPointsRecursive(node, &points)
+       return points
+}
+
+func collectInsertionPointsRecursive(node *yaml.Node, points 
*[]InsertionPoint) {
+       if node == nil {
+               return
+       }
+
+       switch node.Kind {
+       case yaml.DocumentNode:
+               for _, child := range node.Content {
+                       collectInsertionPointsRecursive(child, points)
+               }
+       case yaml.MappingNode:
+               for i := 0; i < len(node.Content)-1; i += 2 {
+                       keyNode := node.Content[i]
+                       valueNode := node.Content[i+1]
+
+                       if !HasSchemaAnnotation(keyNode.HeadComment) {
+                               typeStr := typeAnnotationFromTag(valueNode.Tag)
+                               if typeStr != "" {
+                                       indent := strings.Repeat(" ", 
keyNode.Column-1)
+                                       *points = append(*points, 
InsertionPoint{
+                                               Line:    keyNode.Line,
+                                               Indent:  indent,
+                                               TypeStr: typeStr,
+                                       })
+                               }
+                       }
+
+                       // Recurse into mapping values for nested keys
+                       if valueNode.Kind == yaml.MappingNode {
+                               collectInsertionPointsRecursive(valueNode, 
points)
+                       }
+
+                       // Handle alias nodes that point to mappings
+                       if valueNode.Kind == yaml.AliasNode && valueNode.Alias 
!= nil && valueNode.Alias.Kind == yaml.MappingNode {
+                               
collectInsertionPointsRecursive(valueNode.Alias, points)
+                       }
+               }
+       }
+}
+
+// AnnotateContent parses YAML content, collects insertion points for keys
+// that lack @schema annotations, and inserts type annotation blocks.
+// Returns the modified content.
+func AnnotateContent(content []byte) ([]byte, error) {
+       var doc yaml.Node
+       if err := yaml.Unmarshal(content, &doc); err != nil {
+               return nil, fmt.Errorf("failed to parse YAML: %w", err)
+       }
+
+       points := collectInsertionPoints(&doc)
+       if len(points) == 0 {
+               return content, nil
+       }
+
+       lines := strings.Split(string(content), "\n")
+
+       // Sort by line number descending so insertions don't shift earlier 
line numbers
+       sort.Slice(points, func(i, j int) bool {
+               return points[i].Line > points[j].Line
+       })
+
+       for _, pt := range points {
+               // pt.Line is 1-based; convert to 0-based index
+               targetIdx := pt.Line - 1
+               if targetIdx < 0 || targetIdx >= len(lines) {
+                       continue
+               }
+
+               // Walk backwards past any existing HeadComment lines (lines 
starting with #)
+               // to insert the annotation above existing comments
+               insertIdx := targetIdx
+               for insertIdx > 0 {
+                       candidate := strings.TrimSpace(lines[insertIdx-1])
+                       if strings.HasPrefix(candidate, "#") {
+                               insertIdx--
+                       } else {
+                               break
+                       }
+               }
+
+               // Build the 3 annotation lines
+               annotationLines := []string{
+                       pt.Indent + "# @schema",
+                       pt.Indent + "# type: " + pt.TypeStr,
+                       pt.Indent + "# @schema",
+               }
+
+               // Insert at insertIdx
+               newLines := make([]string, 0, len(lines)+3)
+               newLines = append(newLines, lines[:insertIdx]...)
+               newLines = append(newLines, annotationLines...)
+               newLines = append(newLines, lines[insertIdx:]...)
+               lines = newLines
+       }
+
+       return []byte(strings.Join(lines, "\n")), nil
+}
+
+// AnnotateValuesFile reads a values.yaml file, annotates unannotated keys
+// with @schema type blocks, and writes the result back (or prints to stdout 
if dryRun).
+func AnnotateValuesFile(valuesPath string, dryRun bool) error {
+       fileInfo, err := os.Stat(valuesPath)
+       if err != nil {
+               return fmt.Errorf("failed to stat %s: %w", valuesPath, err)
+       }
+       perm := fileInfo.Mode().Perm()
+
+       content, err := os.ReadFile(valuesPath)
+       if err != nil {
+               return fmt.Errorf("failed to read %s: %w", valuesPath, err)
+       }
+
+       annotated, err := AnnotateContent(content)
+       if err != nil {
+               return fmt.Errorf("failed to annotate %s: %w", valuesPath, err)
+       }
+
+       if dryRun {
+               log.Infof("Annotated values for %s", valuesPath)
+               fmt.Print(string(annotated))
+               return nil
+       }
+
+       if err := os.WriteFile(valuesPath, annotated, perm); err != nil {
+               return fmt.Errorf("failed to write %s: %w", valuesPath, err)
+       }
+
+       log.Infof("Annotated %s", valuesPath)
+       return nil
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/helm-schema-0.20.2/pkg/schema/annotate_test.go 
new/helm-schema-0.21.1/pkg/schema/annotate_test.go
--- old/helm-schema-0.20.2/pkg/schema/annotate_test.go  1970-01-01 
01:00:00.000000000 +0100
+++ new/helm-schema-0.21.1/pkg/schema/annotate_test.go  2026-02-09 
06:52:57.000000000 +0100
@@ -0,0 +1,248 @@
+package schema
+
+import (
+       "strings"
+       "testing"
+
+       "gopkg.in/yaml.v3"
+)
+
+func TestHasSchemaAnnotation(t *testing.T) {
+       tests := []struct {
+               name    string
+               comment string
+               want    bool
+       }{
+               {
+                       name:    "empty comment",
+                       comment: "",
+                       want:    false,
+               },
+               {
+                       name:    "no schema annotation",
+                       comment: "# This is a normal comment",
+                       want:    false,
+               },
+               {
+                       name:    "has schema annotation",
+                       comment: "# @schema\n# type: string\n# @schema",
+                       want:    true,
+               },
+               {
+                       name:    "has schema.root only",
+                       comment: "# @schema.root\n# title: foo\n# @schema.root",
+                       want:    false,
+               },
+               {
+                       name:    "has both schema and schema.root",
+                       comment: "# @schema.root\n# title: foo\n# 
@schema.root\n# @schema\n# type: string\n# @schema",
+                       want:    true,
+               },
+               {
+                       name:    "schema prefix but not exact",
+                       comment: "# @schema.something",
+                       want:    false,
+               },
+       }
+
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       got := HasSchemaAnnotation(tt.comment)
+                       if got != tt.want {
+                               t.Errorf("HasSchemaAnnotation(%q) = %v, want 
%v", tt.comment, got, tt.want)
+                       }
+               })
+       }
+}
+
+func TestTypeAnnotationFromTag(t *testing.T) {
+       tests := []struct {
+               tag  string
+               want string
+       }{
+               {"!!null", `"null"`},
+               {"!!bool", "boolean"},
+               {"!!str", "string"},
+               {"!!int", "integer"},
+               {"!!float", "number"},
+               {"!!timestamp", "string"},
+               {"!!seq", "array"},
+               {"!!map", "object"},
+               {"!!unknown", ""},
+       }
+
+       for _, tt := range tests {
+               t.Run(tt.tag, func(t *testing.T) {
+                       got := typeAnnotationFromTag(tt.tag)
+                       if got != tt.want {
+                               t.Errorf("typeAnnotationFromTag(%q) = %q, want 
%q", tt.tag, got, tt.want)
+                       }
+               })
+       }
+}
+
+func TestCollectInsertionPoints(t *testing.T) {
+       tests := []struct {
+               name       string
+               yaml       string
+               wantCount  int
+               wantTypes  []string
+       }{
+               {
+                       name:      "simple flat yaml",
+                       yaml:      "name: hello\nport: 80\nenabled: true\n",
+                       wantCount: 3,
+                       wantTypes: []string{"string", "integer", "boolean"},
+               },
+               {
+                       name:      "nested objects",
+                       yaml:      "service:\n  type: ClusterIP\n  port: 80\n",
+                       wantCount: 3,
+                       wantTypes: []string{"object", "string", "integer"},
+               },
+               {
+                       name:      "already annotated key",
+                       yaml:      "# @schema\n# type: string\n# @schema\nname: 
hello\nport: 80\n",
+                       wantCount: 1,
+                       wantTypes: []string{"integer"},
+               },
+               {
+                       name:      "null value",
+                       yaml:      "key:\n",
+                       wantCount: 1,
+                       wantTypes: []string{`"null"`},
+               },
+               {
+                       name:      "array value",
+                       yaml:      "items: []\n",
+                       wantCount: 1,
+                       wantTypes: []string{"array"},
+               },
+               {
+                       name:      "empty map value",
+                       yaml:      "config: {}\n",
+                       wantCount: 1,
+                       wantTypes: []string{"object"},
+               },
+       }
+
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       var doc yaml.Node
+                       if err := yaml.Unmarshal([]byte(tt.yaml), &doc); err != 
nil {
+                               t.Fatalf("failed to parse YAML: %v", err)
+                       }
+                       points := collectInsertionPoints(&doc)
+                       if len(points) != tt.wantCount {
+                               t.Errorf("got %d insertion points, want %d", 
len(points), tt.wantCount)
+                               for _, p := range points {
+                                       t.Logf("  line=%d type=%s", p.Line, 
p.TypeStr)
+                               }
+                       }
+                       for i, wantType := range tt.wantTypes {
+                               if i >= len(points) {
+                                       break
+                               }
+                               if points[i].TypeStr != wantType {
+                                       t.Errorf("point[%d].TypeStr = %q, want 
%q", i, points[i].TypeStr, wantType)
+                               }
+                       }
+               })
+       }
+}
+
+func TestAnnotateContent(t *testing.T) {
+       tests := []struct {
+               name    string
+               input   string
+               want    string
+               wantErr bool
+       }{
+               {
+                       name:  "simple unannotated file",
+                       input: "port: 80\n",
+                       want:  "# @schema\n# type: integer\n# @schema\nport: 
80\n",
+               },
+               {
+                       name:  "multiple keys",
+                       input: "name: hello\nport: 80\n",
+                       want:  "# @schema\n# type: string\n# @schema\nname: 
hello\n# @schema\n# type: integer\n# @schema\nport: 80\n",
+               },
+               {
+                       name:  "already fully annotated",
+                       input: "# @schema\n# type: integer\n# @schema\nport: 
80\n",
+                       want:  "# @schema\n# type: integer\n# @schema\nport: 
80\n",
+               },
+               {
+                       name:  "partially annotated",
+                       input: "# @schema\n# type: string\n# @schema\nname: 
hello\nport: 80\n",
+                       want:  "# @schema\n# type: string\n# @schema\nname: 
hello\n# @schema\n# type: integer\n# @schema\nport: 80\n",
+               },
+               {
+                       name:  "nested objects with indentation",
+                       input: "service:\n  type: ClusterIP\n  port: 80\n",
+                       want:  "# @schema\n# type: object\n# 
@schema\nservice:\n  # @schema\n  # type: string\n  # @schema\n  type: 
ClusterIP\n  # @schema\n  # type: integer\n  # @schema\n  port: 80\n",
+               },
+               {
+                       name:  "key with existing comment - annotation goes 
above comment",
+                       input: "# This is the port\nport: 80\n",
+                       want:  "# @schema\n# type: integer\n# @schema\n# This 
is the port\nport: 80\n",
+               },
+               {
+                       name:  "empty file",
+                       input: "",
+                       want:  "",
+               },
+               {
+                       name:  "document separator preserved",
+                       input: "---\nport: 80\n",
+                       want:  "---\n# @schema\n# type: integer\n# 
@schema\nport: 80\n",
+               },
+               {
+                       name:  "boolean value",
+                       input: "enabled: true\n",
+                       want:  "# @schema\n# type: boolean\n# @schema\nenabled: 
true\n",
+               },
+               {
+                       name:  "null value",
+                       input: "key:\n",
+                       want:  "# @schema\n# type: \"null\"\n# @schema\nkey:\n",
+               },
+               {
+                       name:  "array value",
+                       input: "items: []\n",
+                       want:  "# @schema\n# type: array\n# @schema\nitems: 
[]\n",
+               },
+       }
+
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       got, err := AnnotateContent([]byte(tt.input))
+                       if (err != nil) != tt.wantErr {
+                               t.Fatalf("AnnotateContent() error = %v, wantErr 
%v", err, tt.wantErr)
+                       }
+                       if string(got) != tt.want {
+                               t.Errorf("AnnotateContent() 
mismatch\ngot:\n%s\nwant:\n%s", string(got), tt.want)
+                               // Show diff line by line
+                               gotLines := strings.Split(string(got), "\n")
+                               wantLines := strings.Split(tt.want, "\n")
+                               maxLen := len(gotLines)
+                               if len(wantLines) > maxLen {
+                                       maxLen = len(wantLines)
+                               }
+                               for i := 0; i < maxLen; i++ {
+                                       var g, w string
+                                       if i < len(gotLines) {
+                                               g = gotLines[i]
+                                       }
+                                       if i < len(wantLines) {
+                                               w = wantLines[i]
+                                       }
+                                       if g != w {
+                                               t.Errorf("  line %d: got=%q 
want=%q", i, g, w)
+                                       }
+                               }
+                       }
+               })
+       }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/helm-schema-0.20.2/pkg/schema/worker.go 
new/helm-schema-0.21.1/pkg/schema/worker.go
--- old/helm-schema-0.20.2/pkg/schema/worker.go 2026-01-29 21:32:50.000000000 
+0100
+++ new/helm-schema-0.21.1/pkg/schema/worker.go 2026-02-09 06:52:57.000000000 
+0100
@@ -21,7 +21,7 @@
 }
 
 func Worker(
-       dryRun, uncomment, addSchemaReference, keepFullComment, 
helmDocsCompatibilityMode, dontRemoveHelmDocsPrefix, dontAddGlobal bool,
+       dryRun, uncomment, addSchemaReference, keepFullComment, 
helmDocsCompatibilityMode, dontRemoveHelmDocsPrefix, dontAddGlobal, annotate 
bool,
        valueFileNames []string,
        skipAutoGenerationConfig *SkipAutoGenerationConfig,
        outFile string,
@@ -86,6 +86,15 @@
                        results <- result
                        continue
                }
+
+               // Annotate mode: write @schema annotations into values.yaml 
and skip schema generation
+               if annotate {
+                       if err := AnnotateValuesFile(valuesPath, dryRun); err 
!= nil {
+                               result.Errors = append(result.Errors, err)
+                       }
+                       results <- result
+                       continue
+               }
 
                // Check if we need to add a schema reference
                if addSchemaReference {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/helm-schema-0.20.2/pkg/schema/worker_test.go 
new/helm-schema-0.21.1/pkg/schema/worker_test.go
--- old/helm-schema-0.20.2/pkg/schema/worker_test.go    2026-01-29 
21:32:50.000000000 +0100
+++ new/helm-schema-0.21.1/pkg/schema/worker_test.go    2026-02-09 
06:52:57.000000000 +0100
@@ -130,6 +130,7 @@
                                tt.helmDocsCompatibilityMode,
                                tt.dontRemoveHelmDocsPrefix,
                                tt.dontAddGlobal,
+                               false, // annotate
                                tt.valueFileNames,
                                tt.skipAutoGenerationConfig,
                                tt.outFile,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/helm-schema-0.20.2/pkg/util/file.go 
new/helm-schema-0.21.1/pkg/util/file.go
--- old/helm-schema-0.20.2/pkg/util/file.go     2026-01-29 21:32:50.000000000 
+0100
+++ new/helm-schema-0.21.1/pkg/util/file.go     2026-02-09 06:52:57.000000000 
+0100
@@ -68,12 +68,14 @@
        scanner := bufio.NewScanner(reader)
 
        commentMatcher := regexp.MustCompile(`^\s*#\s*`)
-       commentYamlMapMatcher := regexp.MustCompile(`^(\s*#\s*)[^:]+:.*$`)
+       // Capture indentation and comment marker separately
+       // Group 1: indentation (spaces/tabs before #)
+       // Group 2: comment marker (# and following space)
+       commentYamlMapMatcher := regexp.MustCompile(`^(\s*)(#\s*)([^:]+:.*)$`)
        schemaMatcher := regexp.MustCompile(`^\s*#\s@schema\s*`)
 
        var line string
        var inCode, inSchema bool
-       var codeIndention int
        var unknownYaml interface{}
 
        for scanner.Scan() {
@@ -105,10 +107,14 @@
                        continue
                }
 
+               var indentation string
+               var commentMarkerLen int
+
                // Havent found a potential yaml block yet
                if !inCode {
                        if matches := 
commentYamlMapMatcher.FindStringSubmatch(line); matches != nil {
-                               codeIndention = len(matches[1])
+                               indentation = matches[1]           // Just the 
leading whitespace
+                               commentMarkerLen = len(matches[2]) // Just "# " 
(typically 2 chars)
                                inCode = true
                        }
                }
@@ -117,7 +123,7 @@
                if inCode {
                        if commentMatcher.Match([]byte(line)) {
                                // Strip the commet away
-                               strippedLine := line[codeIndention:]
+                               strippedLine := indentation + 
line[len(indentation)+commentMarkerLen:]
                                // add it to the already parsed valid yaml
                                appendAndNLStr(&buff, strippedLine)
                                // check if the new block is still valid yaml
@@ -133,6 +139,14 @@
                                continue
                        }
 
+                       // FIX: Line is NOT a comment - we've exited the 
commented block
+                       // Flush the buffer to result and reset state
+                       if len(buff) > 0 {
+                               appendAndNL(&result, &buff)
+                               buff = make([]byte, 0)
+                       }
+                       inCode = false
+
                        // If the line is not a comment it must be yaml
                        appendAndNLStr(&buff, line)
                        continue
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/helm-schema-0.20.2/plugin.yaml 
new/helm-schema-0.21.1/plugin.yaml
--- old/helm-schema-0.20.2/plugin.yaml  2026-01-29 21:32:50.000000000 +0100
+++ new/helm-schema-0.21.1/plugin.yaml  2026-02-09 06:52:57.000000000 +0100
@@ -1,6 +1,6 @@
 ---
 name: "schema"
-version: "0.20.2"
+version: "0.21.1"
 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.20.2/tests/run.sh 
new/helm-schema-0.21.1/tests/run.sh
--- old/helm-schema-0.20.2/tests/run.sh 2026-01-29 21:32:50.000000000 +0100
+++ new/helm-schema-0.21.1/tests/run.sh 2026-02-09 06:52:57.000000000 +0100
@@ -6,6 +6,11 @@
 cp ../examples/values.schema.json test_repo_example_expected.schema.json
 
 for test_file in test_*.yaml; do
+       # Skip annotate test files from normal schema generation tests
+       case "$test_file" in
+               test_annotate_*) continue ;;
+       esac
+
        expected_file="${test_file%.yaml}_expected.schema.json"
        generated_file="${test_file%.yaml}_generated.schema.json"
        if ! ./helm-schema -f "$test_file" -o "$generated_file"; then
@@ -22,4 +27,14 @@
        fi
 done
 
+# Annotate test
+echo "Testing annotate mode"
+annotate_output=$(./helm-schema --annotate -d -f test_annotate_input.yaml 
2>/dev/null)
+if diff -y --suppress-common-lines <(echo "$annotate_output") 
test_annotate_expected.yaml; then
+       echo "✅: annotate mode"
+else
+       echo "❌: annotate mode"
+       rc=1
+fi
+
 exit "$rc"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/helm-schema-0.20.2/tests/test_annotate_expected.yaml 
new/helm-schema-0.21.1/tests/test_annotate_expected.yaml
--- old/helm-schema-0.20.2/tests/test_annotate_expected.yaml    1970-01-01 
01:00:00.000000000 +0100
+++ new/helm-schema-0.21.1/tests/test_annotate_expected.yaml    2026-02-09 
06:52:57.000000000 +0100
@@ -0,0 +1,64 @@
+# @schema
+# type: integer
+# @schema
+replicaCount: 1
+
+# @schema
+# type: object
+# @schema
+image:
+  # @schema
+  # type: string
+  # @schema
+  repository: nginx
+  # @schema
+  # type: string
+  # @schema
+  pullPolicy: IfNotPresent
+  # @schema
+  # type: string
+  # @schema
+  # Overrides the image tag whose default is the chart appVersion.
+  tag: ""
+
+# @schema
+# type: array
+# @schema
+imagePullSecrets: []
+# @schema
+# type: string
+# @schema
+nameOverride: ""
+
+# @schema
+# type: boolean
+# @schema
+alreadyAnnotated: true
+
+# @schema
+# type: object
+# @schema
+service:
+  # @schema
+  # type: string
+  # @schema
+  type: ClusterIP
+  # @schema
+  # type: integer
+  # @schema
+  port: 80
+
+# @schema
+# type: boolean
+# @schema
+enabled: false
+
+# @schema
+# type: object
+# @schema
+config: {}
+
+# @schema
+# type: "null"
+# @schema
+key:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/helm-schema-0.20.2/tests/test_annotate_input.yaml 
new/helm-schema-0.21.1/tests/test_annotate_input.yaml
--- old/helm-schema-0.20.2/tests/test_annotate_input.yaml       1970-01-01 
01:00:00.000000000 +0100
+++ new/helm-schema-0.21.1/tests/test_annotate_input.yaml       2026-02-09 
06:52:57.000000000 +0100
@@ -0,0 +1,25 @@
+replicaCount: 1
+
+image:
+  repository: nginx
+  pullPolicy: IfNotPresent
+  # Overrides the image tag whose default is the chart appVersion.
+  tag: ""
+
+imagePullSecrets: []
+nameOverride: ""
+
+# @schema
+# type: boolean
+# @schema
+alreadyAnnotated: true
+
+service:
+  type: ClusterIP
+  port: 80
+
+enabled: false
+
+config: {}
+
+key:

++++++ helm-schema.obsinfo ++++++
--- /var/tmp/diff_new_pack.iL16sZ/_old  2026-02-09 15:35:45.209672958 +0100
+++ /var/tmp/diff_new_pack.iL16sZ/_new  2026-02-09 15:35:45.217673294 +0100
@@ -1,5 +1,5 @@
 name: helm-schema
-version: 0.20.2
-mtime: 1769718770
-commit: 7711600f4ada6f2a71ccb81668e2637789315c7b
+version: 0.21.1
+mtime: 1770616377
+commit: c0ca4c5c600f237539b2a1e5fbfcac7bb963bbbc
 

++++++ vendor.tar.gz ++++++

Reply via email to