From 77205eab41314999197fd5b105d094ec446413e1 Mon Sep 17 00:00:00 2001 From: Jonathan Pollert Date: Tue, 17 Mar 2026 18:15:21 +0100 Subject: [PATCH 01/10] Reapply "feat: make strict mode work with new style comments on values" This reverts commit b9f76efc72b972e4072914527e5ab14f94632179. --- pkg/helm/chart_info.go | 57 +++++++++++++++++-- pkg/helm/chart_info_test.go | 15 ++++- .../test-fixtures/full-template/values.yaml | 4 +- .../fully-documented-new-style/Chart.yaml | 15 +++++ .../fully-documented-new-style/README.md | 34 +++++++++++ .../fully-documented-new-style/values.yaml | 10 ++++ 6 files changed, 126 insertions(+), 9 deletions(-) create mode 100644 pkg/helm/test-fixtures/fully-documented-new-style/Chart.yaml create mode 100644 pkg/helm/test-fixtures/fully-documented-new-style/README.md create mode 100644 pkg/helm/test-fixtures/fully-documented-new-style/values.yaml diff --git a/pkg/helm/chart_info.go b/pkg/helm/chart_info.go index 424afb4f..4cf6c45b 100644 --- a/pkg/helm/chart_info.go +++ b/pkg/helm/chart_info.go @@ -7,6 +7,7 @@ import ( "os" "path/filepath" "regexp" + "slices" "sort" "strings" @@ -251,15 +252,23 @@ func parseChartValuesFileComments(chartDirectory string, values *yaml.Node, lint foundValuesComment := false commentLines := make([]string, 0) currentLineIdx := -1 + currentValueKeySegments := make([]string, 0) for scanner.Scan() { currentLineIdx++ currentLine := scanner.Text() - // If we've not yet found a values comment with a key name, try and find one on each line + if currentLine == "" { + continue + } + + // For value comments without keys we need to track previous keys to exactly know where we are at. + currentValueKeySegments = updateCurrentValueKeySegments(currentLine, currentValueKeySegments) + + // If we've not yet found a values comment, try and find one on each line if !foundValuesComment { match := valuesDescriptionRegex.FindStringSubmatch(currentLine) - if len(match) < 3 || match[1] == "" { + if len(match) < 3 { continue } foundValuesComment = true @@ -286,9 +295,10 @@ func parseChartValuesFileComments(chartDirectory string, values *yaml.Node, lint // If we haven't continued by this point, we didn't match any of the comment formats we want, so we need to add // the in progress value to the map, and reset to looking for a new key key, description := ParseComment(commentLines) - if key != "" { - keyToDescriptions[key] = description + if key == "" { + key = strings.Join(currentValueKeySegments, ".") } + keyToDescriptions[key] = description commentLines = make([]string, 0) foundValuesComment = false @@ -302,6 +312,45 @@ func parseChartValuesFileComments(chartDirectory string, values *yaml.Node, lint return keyToDescriptions, nil } +func updateCurrentValueKeySegments(currentLine string, currentValueKeySegments []string) []string { + valueKeyRegex := regexp.MustCompile("^(\\s*)(-?)\\s*(.+):\\s*.*$") + valueKeyMatch := valueKeyRegex.FindStringSubmatch(currentLine) + + if len(valueKeyMatch) == 4 { + // line is value key or group. + indentation := len(valueKeyMatch[1]) + valueKey := valueKeyMatch[3] + isArrayElement := valueKeyMatch[2] != "" + + // if current indentation is less than elements in list, we need to remove some elements. + if indentation/2 < len(currentValueKeySegments) { + currentValueKeySegments = slices.Delete(currentValueKeySegments, indentation/2, len(currentValueKeySegments)) + } + + // For yaml arrays we need the current index in the key + if isArrayElement { + previousValueKeySegment := currentValueKeySegments[len(currentValueKeySegments)-1] + currentValueKeySegments = slices.Delete(currentValueKeySegments, len(currentValueKeySegments)-1, len(currentValueKeySegments)) + keyRegex := regexp.MustCompile("^(\\w+)\\[?(\\d+)?\\]?$") + keyMatches := keyRegex.FindStringSubmatch(previousValueKeySegment) + index := "0" + if keyMatches[2] != "" { + index = keyMatches[2] + } + valueKey = keyMatches[1] + "[" + index + "]" + } + + // We need to quote the key if value key contains special characters + if strings.ContainsAny(valueKey, "-./") { + valueKey = "\"" + valueKey + "\"" + } + + currentValueKeySegments = append(currentValueKeySegments, valueKey) + } + + return currentValueKeySegments +} + func ParseChartInformation(chartDirectory string, documentationParsingConfig ChartValuesDocumentationParsingConfig) (ChartDocumentationInfo, error) { var chartDocInfo ChartDocumentationInfo var err error diff --git a/pkg/helm/chart_info_test.go b/pkg/helm/chart_info_test.go index 3d9197b6..4f0586de 100644 --- a/pkg/helm/chart_info_test.go +++ b/pkg/helm/chart_info_test.go @@ -1,12 +1,13 @@ package helm_test import ( - "github.com/norwoodj/helm-docs/pkg/helm" - "github.com/spf13/viper" - "github.com/stretchr/testify/suite" "path/filepath" "regexp" "testing" + + "github.com/norwoodj/helm-docs/pkg/helm" + "github.com/spf13/viper" + "github.com/stretchr/testify/suite" ) type ChartParsingTestSuite struct { @@ -94,3 +95,11 @@ func (suite *ChartParsingTestSuite) TestFullyDocumentedChartStrictModeOn() { }) suite.NoError(err) } + +func (suite *ChartParsingTestSuite) TestFullyDocumentedChartNewStyleStrictModeOn() { + chartPath := filepath.Join("test-fixtures", "fully-documented-new-style") + _, err := helm.ParseChartInformation(chartPath, helm.ChartValuesDocumentationParsingConfig{ + StrictMode: true, + }) + suite.NoError(err) +} diff --git a/pkg/helm/test-fixtures/full-template/values.yaml b/pkg/helm/test-fixtures/full-template/values.yaml index ea87b8e9..b5d35227 100644 --- a/pkg/helm/test-fixtures/full-template/values.yaml +++ b/pkg/helm/test-fixtures/full-template/values.yaml @@ -4,7 +4,7 @@ controller: repository: nginx-ingress-controller tag: "18.0831" - # controller.persistentVolumeClaims -- List of persistent volume claims to create. + # -- List of persistent volume claims to create. # For very long comments, break them into multiple lines. # @default -- the chart will construct this list internally unless specified persistentVolumeClaims: [] @@ -18,7 +18,7 @@ controller: # controller.ingressClass -- Name of the ingress class to route through this controller ingressClass: nginx - # controller.podLabels -- The labels to be applied to instances of the controller pod + # -- The labels to be applied to instances of the controller pod podLabels: {} publishService: diff --git a/pkg/helm/test-fixtures/fully-documented-new-style/Chart.yaml b/pkg/helm/test-fixtures/fully-documented-new-style/Chart.yaml new file mode 100644 index 00000000..fbd50ebc --- /dev/null +++ b/pkg/helm/test-fixtures/fully-documented-new-style/Chart.yaml @@ -0,0 +1,15 @@ +apiVersion: v2 +name: nginx-ingress +description: A simple wrapper around the stable/nginx-ingress chart that adds a few of our conventions +version: "0.2.0" +home: "https://github.com/norwoodj/helm-docs/tree/master/example-charts/nginx-ingress" +sources: ["https://github.com/norwoodj/helm-docs/tree/master/example-charts/nginx-ingress"] +engine: gotpl +type: application +maintainers: + - email: norwood.john.m@gmail.com + name: John Norwood +dependencies: + - name: nginx-ingress + version: "0.22.1" + repository: "@stable" diff --git a/pkg/helm/test-fixtures/fully-documented-new-style/README.md b/pkg/helm/test-fixtures/fully-documented-new-style/README.md new file mode 100644 index 00000000..30119375 --- /dev/null +++ b/pkg/helm/test-fixtures/fully-documented-new-style/README.md @@ -0,0 +1,34 @@ +# nginx-ingress + +![Version: 0.2.0](https://img.shields.io/badge/Version-0.2.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) + +A simple wrapper around the stable/nginx-ingress chart that adds a few of our conventions + +**Homepage:** + +## Maintainers + +| Name | Email | Url | +| ---- | ------ | --- | +| John Norwood | | | + +## Source Code + +* + +## Requirements + +| Repository | Name | Version | +|------------|------|---------| +| @stable | nginx-ingress | 0.22.1 | + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| controller | object | `{"image":{"repository":"nginx-ingress-controller","tag":"18.0831"},"name":"controller"}` | The controller | +| controller.image | object | `{"repository":"nginx-ingress-controller","tag":"18.0831"}` | The image of the controller | +| controller.image.repository | string | `"nginx-ingress-controller"` | The repository of the controller | +| controller.image.tag | string | `"18.0831"` | The tag of the image of the controller | +| controller.name | string | `"controller"` | The name of the controller | + diff --git a/pkg/helm/test-fixtures/fully-documented-new-style/values.yaml b/pkg/helm/test-fixtures/fully-documented-new-style/values.yaml new file mode 100644 index 00000000..f75295f4 --- /dev/null +++ b/pkg/helm/test-fixtures/fully-documented-new-style/values.yaml @@ -0,0 +1,10 @@ +# -- The controller +controller: + # -- The name of the controller + name: controller + # -- The image of the controller + image: + # -- The repository of the controller + repository: nginx-ingress-controller + # -- The tag of the image of the controller + tag: "18.0831" From 0392a6659fb88a76fffbc541101e6bd07c4e7d46 Mon Sep 17 00:00:00 2001 From: Jonathan Pollert Date: Fri, 20 Mar 2026 19:33:06 +0100 Subject: [PATCH 02/10] feat: make strict mode work with new style comments on values --- pkg/helm/chart_info.go | 15 ++++++++++----- .../fully-documented-new-style/values.yaml | 6 ++++++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/pkg/helm/chart_info.go b/pkg/helm/chart_info.go index 4cf6c45b..ab9b8a62 100644 --- a/pkg/helm/chart_info.go +++ b/pkg/helm/chart_info.go @@ -9,6 +9,7 @@ import ( "regexp" "slices" "sort" + "strconv" "strings" log "github.com/sirupsen/logrus" @@ -313,17 +314,20 @@ func parseChartValuesFileComments(chartDirectory string, values *yaml.Node, lint } func updateCurrentValueKeySegments(currentLine string, currentValueKeySegments []string) []string { - valueKeyRegex := regexp.MustCompile("^(\\s*)(-?)\\s*(.+):\\s*.*$") + valueKeyRegex := regexp.MustCompile("^(\\s*)(-?)\\s*([^:]+):?\\s*.*$") valueKeyMatch := valueKeyRegex.FindStringSubmatch(currentLine) if len(valueKeyMatch) == 4 { // line is value key or group. indentation := len(valueKeyMatch[1]) valueKey := valueKeyMatch[3] + if strings.HasPrefix(valueKey, "#") { + return currentValueKeySegments + } isArrayElement := valueKeyMatch[2] != "" // if current indentation is less than elements in list, we need to remove some elements. - if indentation/2 < len(currentValueKeySegments) { + if !isArrayElement && indentation/2 < len(currentValueKeySegments) { currentValueKeySegments = slices.Delete(currentValueKeySegments, indentation/2, len(currentValueKeySegments)) } @@ -333,11 +337,12 @@ func updateCurrentValueKeySegments(currentLine string, currentValueKeySegments [ currentValueKeySegments = slices.Delete(currentValueKeySegments, len(currentValueKeySegments)-1, len(currentValueKeySegments)) keyRegex := regexp.MustCompile("^(\\w+)\\[?(\\d+)?\\]?$") keyMatches := keyRegex.FindStringSubmatch(previousValueKeySegment) - index := "0" + index := 0 if keyMatches[2] != "" { - index = keyMatches[2] + valueInt, _ := strconv.Atoi(keyMatches[2]) + index = valueInt + 1 } - valueKey = keyMatches[1] + "[" + index + "]" + valueKey = keyMatches[1] + "[" + strconv.Itoa(index) + "]" } // We need to quote the key if value key contains special characters diff --git a/pkg/helm/test-fixtures/fully-documented-new-style/values.yaml b/pkg/helm/test-fixtures/fully-documented-new-style/values.yaml index f75295f4..699a7ee5 100644 --- a/pkg/helm/test-fixtures/fully-documented-new-style/values.yaml +++ b/pkg/helm/test-fixtures/fully-documented-new-style/values.yaml @@ -8,3 +8,9 @@ controller: repository: nginx-ingress-controller # -- The tag of the image of the controller tag: "18.0831" + # -- tags for the image to use + tags: + # -- the first tag to use + - number one + # -- the second tag to use + - number two From 0eb875fc5aba86d0b4a006ec8d2f314305da6ae4 Mon Sep 17 00:00:00 2001 From: Jonathan Pollert Date: Sun, 31 May 2026 20:57:08 +0200 Subject: [PATCH 03/10] feat: make strict mode work with new style comments on values --- .../custom-value-notation-type/README.md | 127 ++++----- .../README.md.gotmpl | 1 + pkg/helm/chart_info_test.go | 6 +- .../fully-documented-new-style/values.yaml | 243 ++++++++++++++++-- .../fully-documented/values.yaml | 7 + 5 files changed, 306 insertions(+), 78 deletions(-) diff --git a/example-charts/custom-value-notation-type/README.md b/example-charts/custom-value-notation-type/README.md index 400af82d..aa1a85b0 100644 --- a/example-charts/custom-value-notation-type/README.md +++ b/example-charts/custom-value-notation-type/README.md @@ -138,7 +138,15 @@ extraConfigMap: | tpl/array -
+
- name: DJANGO_SETTINGS_MODULE + value: "django.settings" +- name: DEBUG + value: {{ .Values.global.debug | quote }} +- name: ROOT_URLCONF + value: {{ .Values.global.rootURLConf | quote }} +- name: MAIN_APP_NAME + value: {{ .Values.global.mainAppName | quote }} +
 extraPodEnv: |
   - name: DJANGO_SETTINGS_MODULE
@@ -221,7 +229,7 @@ extraVolumeMounts: |
 object
 
 			
-				
+
`{"adminEmail":"admin@localhost","adminPassword":{"value":null,"valueFrom":{"secretKeyRef":{"key":"admin-password","name":null}}},"adminUser":"admin","databaseHost":"postgis","databaseName":"django","databasePassword":{"value":null,"valueFrom":{"secretKeyRef":{"key":"database-password","name":null}}},"databasePort":5432,"databaseUsername":"django_db_user","debug":"False","djangoArgs":"[\"uwsgi\",\"--chdir=${REPO_ROOT}\",\"--module=${MAIN_APP_NAME}.wsgi\",\"--socket=:8000\",\"--http=0.0.0.0:8080\",\"--processes=5\",\"--buffer-size=8192\"]\n","djangoCommand":"[\"/opt/django/scripts/docker-entrypoint.sh\"]\n","djangoSecretKey":{"value":null,"valueFrom":{"secretKeyRef":{"key":"django-secret","name":null}}},"djangoSettingsModule":"django.settings","existingSecret":"","mainAppName":"django","mediaRoot":"/opt/django/media","nameOverride":"django","rootURLConf":"django.urls","sharedSecretName":"django-shared-secret","siteName":"django","staticRoot":"/opt/django/static"}`
 {
   "adminEmail": "admin@localhost",
@@ -282,7 +290,7 @@ object
 This value type is for a valid email address format. Such as owner@somedomain.org.">string/email
 
 			
-				
+
admin@localhost "admin@localhost"
@@ -294,7 +302,7 @@ This value type is for a valid email address format. Such as owner@somedomain.or string -
+
`nil`
 null
 
@@ -308,7 +316,7 @@ null string -
+
`"admin"`
 "admin"
 
@@ -322,7 +330,7 @@ string string -
+
`"postgis"`
 "postgis"
 
@@ -336,7 +344,7 @@ string string -
+
`"django"`
 "django"
 
@@ -350,7 +358,7 @@ string string -
+
`nil`
 null
 
@@ -364,7 +372,7 @@ null int -
+
`5432`
 5432
 
@@ -378,7 +386,7 @@ int string -
+
`"django_db_user"`
 "django_db_user"
 
@@ -392,7 +400,7 @@ string string -
+
`"False"`
 "False"
 
@@ -406,7 +414,8 @@ string tpl/array -
+
["uwsgi","--chdir=${REPO_ROOT}","--module=${MAIN_APP_NAME}.wsgi","--socket=:8000","--http=0.0.0.0:8080","--processes=5","--buffer-size=8192"] +
 global.djangoArgs: |
   ["uwsgi","--chdir=${REPO_ROOT}","--module=${MAIN_APP_NAME}.wsgi","--socket=:8000","--http=0.0.0.0:8080","--processes=5","--buffer-size=8192"]
@@ -422,7 +431,8 @@ global.djangoArgs: |
 tpl/array
 
 			
-				
+
["/opt/django/scripts/docker-entrypoint.sh"] +
 global.djangoCommand: |
   ["/opt/django/scripts/docker-entrypoint.sh"]
@@ -438,7 +448,7 @@ global.djangoCommand: |
 string
 
 			
-				
+
`nil`
 null
 
@@ -452,7 +462,7 @@ null string -
+
`"django.settings"`
 "django.settings"
 
@@ -481,7 +491,7 @@ global.existingSecret: | string -
+
`"django"`
 "django"
 
@@ -495,7 +505,7 @@ string path -
+
`"/opt/django/media"`
 "/opt/django/media"
 
@@ -509,7 +519,7 @@ path string -
+
`"django.urls"`
 "django.urls"
 
@@ -523,7 +533,7 @@ string string -
+
`"django-shared-secret"`
 "django-shared-secret"
 
@@ -537,7 +547,7 @@ string string -
+
`"django"`
 "django"
 
@@ -551,7 +561,7 @@ string path -
+
`"/opt/django/static"`
 "/opt/django/static"
 
@@ -565,7 +575,7 @@ path object -
+
`{"pullPolicy":"IfNotPresent","registry":"docker.io","repository":"lucernae/django-sample","tag":"3.1"}`
 {
   "pullPolicy": "IfNotPresent",
@@ -584,7 +594,7 @@ object
 string
 
 			
-				
+
`"IfNotPresent"`
 "IfNotPresent"
 
@@ -598,7 +608,7 @@ string string -
+
`"docker.io"`
 "docker.io"
 
@@ -612,7 +622,7 @@ string string -
+
`"lucernae/django-sample"`
 "lucernae/django-sample"
 
@@ -626,7 +636,7 @@ string string -
+
`"3.1"`
 "3.1"
 
@@ -640,7 +650,7 @@ string dict -
+
`{}`
 {}
 
@@ -654,7 +664,7 @@ dict bool -
+
`false`
 false
 
@@ -683,7 +693,7 @@ ingress.host: | dict -
+
`{}`
 {}
 
@@ -697,7 +707,7 @@ dict bool -
+
`false`
 false
 
@@ -711,7 +721,7 @@ false string -
+
`"django-tls"`
 "django-tls"
 
@@ -725,12 +735,9 @@ string map -
+
map[client-name:my-boss project-name:awesome-project user/workload:true]
-user/workload: "true"
-client-name: "my-boss"
-project-name: "awesome-project"
-
+map[client-name:my-boss project-name:awesome-project user/workload:true]
 
@@ -742,7 +749,7 @@ project-name: "awesome-project" string -
+
`"ReadWriteOnce"`
 "ReadWriteOnce"
 
@@ -756,7 +763,7 @@ string object -
+
`{}`
 {}
 
@@ -770,7 +777,7 @@ object bool -
+
`true`
 true
 
@@ -784,7 +791,7 @@ true bool -
+
`false`
 false
 
@@ -798,7 +805,7 @@ false string -
+
`"/opt/django/media"`
 "/opt/django/media"
 
@@ -812,7 +819,7 @@ string string -
+
`"8Gi"`
 "8Gi"
 
@@ -826,7 +833,7 @@ string string -
+
`"media"`
 "media"
 
@@ -842,10 +849,9 @@ string >k8s/storage/persistent-volume/access-modes -
+
[ReadWriteOnce]
-- ReadWriteOnce
-
+[ReadWriteOnce]
 
@@ -857,7 +863,7 @@ string object -
+
`{}`
 {}
 
@@ -871,7 +877,7 @@ object bool -
+
`true`
 true
 
@@ -885,7 +891,7 @@ true bool -
+
`false`
 false
 
@@ -899,7 +905,7 @@ false string -
+
`"/opt/django/static"`
 "/opt/django/static"
 
@@ -913,7 +919,7 @@ string string -
+
`"8Gi"`
 "8Gi"
 
@@ -927,7 +933,7 @@ string string -
+
`"static"`
 "static"
 
@@ -941,7 +947,7 @@ string bool -
+
`true`
 true
 
@@ -955,7 +961,8 @@ true tpl/string -
+
{{ include "common.sharedSecretName" . | quote -}} +
 postgis.existingSecret: |
   {{ include "common.sharedSecretName" . | quote -}}
@@ -986,7 +993,7 @@ probe: |
 dict
 
 			
-				
+
`{}`
 {}
 
@@ -1022,7 +1029,7 @@ execute some command dict -
+
`{}`
 {}
 
@@ -1036,7 +1043,7 @@ dict string -
+
`""`
 ""
 
@@ -1065,7 +1072,7 @@ service.externalIPs: | int -
+
`nil`
 null
 
@@ -1079,7 +1086,7 @@ null int -
+
`80`
 80
 
@@ -1093,7 +1100,7 @@ int string -
+
`"ClusterIP"`
 "ClusterIP"
 
diff --git a/example-charts/custom-value-notation-type/README.md.gotmpl b/example-charts/custom-value-notation-type/README.md.gotmpl index 2b76d843..6a105697 100644 --- a/example-charts/custom-value-notation-type/README.md.gotmpl +++ b/example-charts/custom-value-notation-type/README.md.gotmpl @@ -104,6 +104,7 @@ uses HTML `` tag to collapse some part of the comments. {{ define "chart.valueDefaultColumnRender" }} {{- $defaultValue := (default .Default .AutoDefault) -}} {{- $notationType := .NotationType }} +{{- $defaultValue }} {{- if (and (hasPrefix "`" $defaultValue) (hasSuffix "`" $defaultValue) ) -}} {{- $defaultValue = (toPrettyJson (fromJson (trimAll "`" (default .Default .AutoDefault) ) ) ) -}} {{- $notationType = "json" }} diff --git a/pkg/helm/chart_info_test.go b/pkg/helm/chart_info_test.go index 4f0586de..11f23491 100644 --- a/pkg/helm/chart_info_test.go +++ b/pkg/helm/chart_info_test.go @@ -90,16 +90,18 @@ func (suite *ChartParsingTestSuite) TestNotFullyDocumentedChartStrictModeOnIgnor func (suite *ChartParsingTestSuite) TestFullyDocumentedChartStrictModeOn() { chartPath := filepath.Join("test-fixtures", "fully-documented") - _, err := helm.ParseChartInformation(chartPath, helm.ChartValuesDocumentationParsingConfig{ + asd, err := helm.ParseChartInformation(chartPath, helm.ChartValuesDocumentationParsingConfig{ StrictMode: true, }) + print(asd.ApiVersion) suite.NoError(err) } func (suite *ChartParsingTestSuite) TestFullyDocumentedChartNewStyleStrictModeOn() { chartPath := filepath.Join("test-fixtures", "fully-documented-new-style") - _, err := helm.ParseChartInformation(chartPath, helm.ChartValuesDocumentationParsingConfig{ + asd, err := helm.ParseChartInformation(chartPath, helm.ChartValuesDocumentationParsingConfig{ StrictMode: true, }) + print(asd.ApiVersion) suite.NoError(err) } diff --git a/pkg/helm/test-fixtures/fully-documented-new-style/values.yaml b/pkg/helm/test-fixtures/fully-documented-new-style/values.yaml index 699a7ee5..ec771784 100644 --- a/pkg/helm/test-fixtures/fully-documented-new-style/values.yaml +++ b/pkg/helm/test-fixtures/fully-documented-new-style/values.yaml @@ -1,16 +1,227 @@ -# -- The controller -controller: - # -- The name of the controller - name: controller - # -- The image of the controller - image: - # -- The repository of the controller - repository: nginx-ingress-controller - # -- The tag of the image of the controller - tag: "18.0831" - # -- tags for the image to use - tags: - # -- the first tag to use - - number one - # -- the second tag to use - - number two +# -- Image map +image: + # -- Image registry + registry: docker.io + # -- Image repository + repository: lucernae/django-sample + # -- Image tag + tag: "3.1" + # -- Image pullPolicy + pullPolicy: IfNotPresent + + +# -- This key name is used for service interconnection between subcharts and parent charts. +global: + nameOverride: django + # -- (tpl/string) Name of existing secret + # @notationType -- tpl + existingSecret: | + # -- (string) Name of shared secret store that will be generated + sharedSecretName: django-shared-secret + # generic values + # -- (string) The site name. It will be used to construct url such as http://django/ + siteName: django + # -- (tpl/array) The django entrypoint command to execute + # @notationType -- tpl + djangoCommand: | + ["/opt/django/scripts/docker-entrypoint.sh"] + # -- (tpl/array) The django command args to be passed to entrypoint command + # @notationType -- tpl + djangoArgs: | + ["uwsgi","--chdir=${REPO_ROOT}","--module=${MAIN_APP_NAME}.wsgi","--socket=:8000","--http=0.0.0.0:8080","--processes=5","--buffer-size=8192"] + # -- (string) Default super user admin username + adminUser: admin + adminPassword: + # -- (string) Specify this password value. If not, it will be autogenerated everytime chart upgraded + value: + valueFrom: + secretKeyRef: + name: + key: admin-password + # -- (string/email) Default admin email sender + # @notationType -- email + adminEmail: admin@localhost + djangoSecretKey: + # -- (string) Specify this Django Secret string value. If not, it will be autogenerated everytime chart upgraded + value: + valueFrom: + secretKeyRef: + name: + key: django-secret + # -- (string) Database username backend to connect to. If you use external backend, provide the value + databaseUsername: django_db_user + databasePassword: + # -- (string) Specify this password value. If not, it will be autogenerated everytime chart upgraded. If you use external backend, you must provide the value + value: + valueFrom: + secretKeyRef: + name: + key: database-password + # -- (string) Django database name + databaseName: django + # -- (string) Django database host location. By default this chart can generate standard postgres chart. So you can leave it as default. If you use external backend, you must provide the value + databaseHost: postgis + # -- (int) Django database port. By default this chart can generate standard postgres chart. So you can leave it as default. If you use external backend, you must provide the value + databasePort: 5432 + # -- (string) Python boolean literal, this will correspond to `DEBUG` environment variable inside the Django container. Useful as a debug switch. + debug: "False" + # -- (string) The main app name to execute. Affects which settings, wsgi, and rootURL to use. + mainAppName: django + # -- (string) Django settings module to be used + djangoSettingsModule: django.settings + # -- (string) Django root URL conf to be used + rootURLConf: django.urls + # -- (path) Location to the static directory + staticRoot: /opt/django/static + # -- (path) Location to the media directory + mediaRoot: /opt/django/media + +# -- (map) The deployment label +# @notationType -- yaml +labels: + user/workload: "true" + client-name: "my-boss" + project-name: "awesome-project" + +# -- (tpl/array) Define this for extra Django environment variables +# @notationType -- tpl +extraPodEnv: | + - name: DJANGO_SETTINGS_MODULE + value: "django.settings" + - name: DEBUG + value: {{ .Values.global.debug | quote }} + - name: ROOT_URLCONF + value: {{ .Values.global.rootURLConf | quote }} + - name: MAIN_APP_NAME + value: {{ .Values.global.mainAppName | quote }} + +# -- (tpl/object) This will be evaluated as pod spec +# @notationType -- tpl +extraPodSpec: | +# nodeSelector: +# a.label: value + +# -- (tpl/dict) Define this for extra secrets to be included in django-shared-secret secret +# @notationType -- tpl +extraSecret: | +# key_1: value_1 + +# -- (tpl/dict) Define this for extra config map to be included in django-shared-config +# @notationType -- tpl +extraConfigMap: | +# file_1: conf content + +# -- (tpl/array) Define this for extra volume mounts in the pod +# @notationType -- tpl +extraVolumeMounts: | +# You may potentially mount a config map/secret +# - name: custom-config +# mountPath: /docker-entrypoint.sh +# subPath: docker-entrypoint.sh +# readOnly: true + +# -- (tpl/array) Define this for extra volume (in pair with extraVolumeMounts) +# @notationType -- tpl +extraVolume: | +# You may potentially mount a config map/secret +# - name: custom-config +# configMap: +# name: geonode-config + +service: + # -- (string) Define k8s service for Django. + type: ClusterIP + # -- (string) Specify `None` for headless service. Otherwise, leave them be. + clusterIP: "" + # -- (tpl/array) Specify for LoadBalancer service type + # @notationType -- tpl + externalIPs: | + # -- (int) Specify service port + port: 80 + + # -- (int) Specify node port, for NodePort service type + nodePort: + + # -- (dict) Extra service annotations + annotations: {} + +ingress: + # -- (bool) Set to true to generate Ingress resource + enabled: false + # -- (tpl/string) Set custom host name. (DNS name convention) + # @notationType -- tpl + host: | + # -- (dict) Custom Ingress annotations + annotations: {} + # -- (dict) Custom Ingress labels + labels: {} + tls: + # -- (bool) Set to true to enable HTTPS + enabled: false + # -- (string) You must provide a secret name where the TLS cert is stored + secretName: django-tls + +# -- (tpl/object) Probe can be overridden +# @notationType -- tpl +probe: | + +postgis: + # -- (bool) Enable postgis as database backend by default. Set to false if using different external backend. + enabled: true + + # -- (tpl/string) Existing secret to be used + # @notationType -- tpl + existingSecret: | + {{ include "common.sharedSecretName" . | quote -}} + + +persistence: + staticDir: + # -- (bool) Allow persistence + enabled: true + existingClaim: false + mountPath: /opt/django/static + subPath: "static" + size: 8Gi + # -- (k8s/storage/persistent-volume/access-modes) Static Dir access modes + # @notationType -- yaml + accessModes: + - ReadWriteOnce + annotations: {} + mediaDir: + # -- (bool) Allow persistence + enabled: true + existingClaim: false + mountPath: /opt/django/media + subPath: "media" + size: 8Gi + accessModes: + - ReadWriteOnce + annotations: {} + + +# -- (dict) Values with long description +# @raw +# Sometimes you need a very long description +# for your values. +# +# Any comment section for a given key with **@raw** attribute +# will be treated as raw string and stored as is. +# Since it generates in Markdown format, you can do something like this: +# +# ```yaml +# hello: +# bar: true +# ``` +# +# Markdown also accept subset of HTML tags. So you can also do this: +# +#
+# +Expand +# +# ```bash +# execute some command +# ``` +# +#
+sampleYaml: {} \ No newline at end of file diff --git a/pkg/helm/test-fixtures/fully-documented/values.yaml b/pkg/helm/test-fixtures/fully-documented/values.yaml index d57a32d6..0a747782 100644 --- a/pkg/helm/test-fixtures/fully-documented/values.yaml +++ b/pkg/helm/test-fixtures/fully-documented/values.yaml @@ -8,3 +8,10 @@ controller: repository: nginx-ingress-controller # controller.image.tag -- The tag of the image of the controller tag: "18.0831" + # controller.image.tags -- (tpl/array) tags for the image to use + # @notationType -- tpl + tags: + # controller.image.tags[0]-- the first tag to use + - number one + # controller.image.tags[1] -- the second tag to use + - number two From e4d321e9dbab24aebaa4f8de2b0a58137cfe8f24 Mon Sep 17 00:00:00 2001 From: Jonathan Pollert <38696668+jnt0r@users.noreply.github.com> Date: Sun, 31 May 2026 21:20:18 +0200 Subject: [PATCH 04/10] feat: make strict mode work with new style comments on values --- .../custom-value-notation-type/README.md | 119 ++++++++---------- .../README.md.gotmpl | 1 - 2 files changed, 54 insertions(+), 66 deletions(-) diff --git a/example-charts/custom-value-notation-type/README.md b/example-charts/custom-value-notation-type/README.md index aa1a85b0..4190d89b 100644 --- a/example-charts/custom-value-notation-type/README.md +++ b/example-charts/custom-value-notation-type/README.md @@ -138,15 +138,7 @@ extraConfigMap: | tpl/array -
- name: DJANGO_SETTINGS_MODULE - value: "django.settings" -- name: DEBUG - value: {{ .Values.global.debug | quote }} -- name: ROOT_URLCONF - value: {{ .Values.global.rootURLConf | quote }} -- name: MAIN_APP_NAME - value: {{ .Values.global.mainAppName | quote }} - +
 extraPodEnv: |
   - name: DJANGO_SETTINGS_MODULE
@@ -229,7 +221,7 @@ extraVolumeMounts: |
 object
 
 			
-				
`{"adminEmail":"admin@localhost","adminPassword":{"value":null,"valueFrom":{"secretKeyRef":{"key":"admin-password","name":null}}},"adminUser":"admin","databaseHost":"postgis","databaseName":"django","databasePassword":{"value":null,"valueFrom":{"secretKeyRef":{"key":"database-password","name":null}}},"databasePort":5432,"databaseUsername":"django_db_user","debug":"False","djangoArgs":"[\"uwsgi\",\"--chdir=${REPO_ROOT}\",\"--module=${MAIN_APP_NAME}.wsgi\",\"--socket=:8000\",\"--http=0.0.0.0:8080\",\"--processes=5\",\"--buffer-size=8192\"]\n","djangoCommand":"[\"/opt/django/scripts/docker-entrypoint.sh\"]\n","djangoSecretKey":{"value":null,"valueFrom":{"secretKeyRef":{"key":"django-secret","name":null}}},"djangoSettingsModule":"django.settings","existingSecret":"","mainAppName":"django","mediaRoot":"/opt/django/media","nameOverride":"django","rootURLConf":"django.urls","sharedSecretName":"django-shared-secret","siteName":"django","staticRoot":"/opt/django/static"}` +
 {
   "adminEmail": "admin@localhost",
@@ -290,7 +282,7 @@ object
 This value type is for a valid email address format. Such as owner@somedomain.org.">string/email
 
 			
-				
admin@localhost + @@ -302,7 +294,7 @@ This value type is for a valid email address format. Such as owner@somedomain.or string -
`nil` +
 null
 
@@ -316,7 +308,7 @@ null string -
`"admin"` +
 "admin"
 
@@ -330,7 +322,7 @@ string string -
`"postgis"` +
 "postgis"
 
@@ -344,7 +336,7 @@ string string -
`"django"` +
 "django"
 
@@ -358,7 +350,7 @@ string string -
`nil` +
 null
 
@@ -372,7 +364,7 @@ null int -
`5432` +
 5432
 
@@ -386,7 +378,7 @@ int string -
`"django_db_user"` +
 "django_db_user"
 
@@ -400,7 +392,7 @@ string string -
`"False"` +
 "False"
 
@@ -414,8 +406,7 @@ string tpl/array -
["uwsgi","--chdir=${REPO_ROOT}","--module=${MAIN_APP_NAME}.wsgi","--socket=:8000","--http=0.0.0.0:8080","--processes=5","--buffer-size=8192"] - +
 global.djangoArgs: |
   ["uwsgi","--chdir=${REPO_ROOT}","--module=${MAIN_APP_NAME}.wsgi","--socket=:8000","--http=0.0.0.0:8080","--processes=5","--buffer-size=8192"]
@@ -431,8 +422,7 @@ global.djangoArgs: |
 tpl/array
 
 			
-				
["/opt/django/scripts/docker-entrypoint.sh"] - +
 global.djangoCommand: |
   ["/opt/django/scripts/docker-entrypoint.sh"]
@@ -448,7 +438,7 @@ global.djangoCommand: |
 string
 
 			
-				
`nil` +
 null
 
@@ -462,7 +452,7 @@ null string -
`"django.settings"` +
 "django.settings"
 
@@ -491,7 +481,7 @@ global.existingSecret: | string -
`"django"` +
 "django"
 
@@ -505,7 +495,7 @@ string path -
`"/opt/django/media"` +
 "/opt/django/media"
 
@@ -519,7 +509,7 @@ path string -
`"django.urls"` +
 "django.urls"
 
@@ -533,7 +523,7 @@ string string -
`"django-shared-secret"` +
 "django-shared-secret"
 
@@ -547,7 +537,7 @@ string string -
`"django"` +
 "django"
 
@@ -561,7 +551,7 @@ string path -
`"/opt/django/static"` +
 "/opt/django/static"
 
@@ -575,7 +565,7 @@ path object -
`{"pullPolicy":"IfNotPresent","registry":"docker.io","repository":"lucernae/django-sample","tag":"3.1"}` +
 {
   "pullPolicy": "IfNotPresent",
@@ -594,7 +584,7 @@ object
 string
 
 			
-				
`"IfNotPresent"` +
 "IfNotPresent"
 
@@ -608,7 +598,7 @@ string string -
`"docker.io"` +
 "docker.io"
 
@@ -622,7 +612,7 @@ string string -
`"lucernae/django-sample"` +
 "lucernae/django-sample"
 
@@ -636,7 +626,7 @@ string string -
`"3.1"` +
 "3.1"
 
@@ -650,7 +640,7 @@ string dict -
`{}` +
 {}
 
@@ -664,7 +654,7 @@ dict bool -
`false` +
 false
 
@@ -693,7 +683,7 @@ ingress.host: | dict -
`{}` +
 {}
 
@@ -707,7 +697,7 @@ dict bool -
`false` +
 false
 
@@ -721,7 +711,7 @@ false string -
`"django-tls"` +
 "django-tls"
 
@@ -735,7 +725,7 @@ string map -
map[client-name:my-boss project-name:awesome-project user/workload:true] +
 map[client-name:my-boss project-name:awesome-project user/workload:true]
 
@@ -749,7 +739,7 @@ map[client-name:my-boss project-name:awesome-project user/workload:true] string -
`"ReadWriteOnce"` +
 "ReadWriteOnce"
 
@@ -763,7 +753,7 @@ string object -
`{}` +
 {}
 
@@ -777,7 +767,7 @@ object bool -
`true` +
 true
 
@@ -791,7 +781,7 @@ true bool -
`false` +
 false
 
@@ -805,7 +795,7 @@ false string -
`"/opt/django/media"` +
 "/opt/django/media"
 
@@ -819,7 +809,7 @@ string string -
`"8Gi"` +
 "8Gi"
 
@@ -833,7 +823,7 @@ string string -
`"media"` +
 "media"
 
@@ -849,7 +839,7 @@ string >k8s/storage/persistent-volume/access-modes -
[ReadWriteOnce] +
 [ReadWriteOnce]
 
@@ -863,7 +853,7 @@ string object -
`{}` +
 {}
 
@@ -877,7 +867,7 @@ object bool -
`true` +
 true
 
@@ -891,7 +881,7 @@ true bool -
`false` +
 false
 
@@ -905,7 +895,7 @@ false string -
`"/opt/django/static"` +
 "/opt/django/static"
 
@@ -919,7 +909,7 @@ string string -
`"8Gi"` +
 "8Gi"
 
@@ -933,7 +923,7 @@ string string -
`"static"` +
 "static"
 
@@ -947,7 +937,7 @@ string bool -
`true` +
 true
 
@@ -961,8 +951,7 @@ true tpl/string -
{{ include "common.sharedSecretName" . | quote -}} - +
 postgis.existingSecret: |
   {{ include "common.sharedSecretName" . | quote -}}
@@ -993,7 +982,7 @@ probe: |
 dict
 
 			
-				
`{}` +
 {}
 
@@ -1029,7 +1018,7 @@ execute some command dict -
`{}` +
 {}
 
@@ -1043,7 +1032,7 @@ dict string -
`""` +
 ""
 
@@ -1072,7 +1061,7 @@ service.externalIPs: | int -
`nil` +
 null
 
@@ -1086,7 +1075,7 @@ null int -
`80` +
 80
 
@@ -1100,7 +1089,7 @@ int string -
`"ClusterIP"` +
 "ClusterIP"
 
diff --git a/example-charts/custom-value-notation-type/README.md.gotmpl b/example-charts/custom-value-notation-type/README.md.gotmpl index 6a105697..2b76d843 100644 --- a/example-charts/custom-value-notation-type/README.md.gotmpl +++ b/example-charts/custom-value-notation-type/README.md.gotmpl @@ -104,7 +104,6 @@ uses HTML `` tag to collapse some part of the comments. {{ define "chart.valueDefaultColumnRender" }} {{- $defaultValue := (default .Default .AutoDefault) -}} {{- $notationType := .NotationType }} -{{- $defaultValue }} {{- if (and (hasPrefix "`" $defaultValue) (hasSuffix "`" $defaultValue) ) -}} {{- $defaultValue = (toPrettyJson (fromJson (trimAll "`" (default .Default .AutoDefault) ) ) ) -}} {{- $notationType = "json" }} From 7018b7a875c859312380e83bc7af6fd715c15276 Mon Sep 17 00:00:00 2001 From: Jonathan Pollert Date: Sun, 6 Sep 2026 11:31:23 +0200 Subject: [PATCH 05/10] feat: make strict mode work with new style comments on values --- cmd/helm-docs/main_test.go | 24 ++ pkg/helm/chart_info.go | 11 +- pkg/helm/chart_info_test.go | 14 +- pkg/helm/comment_test.go | 28 +++ .../test-fixtures/full-template/README.md | 19 +- .../full-template/README.md.gotmpl | 1 - .../fully-documented-new-style/README.md | 13 +- .../fully-documented-new-style/values.yaml | 210 ------------------ .../test-fixtures/fully-documented/README.md | 13 +- .../fully-documented/values.yaml | 34 +-- 10 files changed, 102 insertions(+), 265 deletions(-) create mode 100644 pkg/helm/comment_test.go diff --git a/cmd/helm-docs/main_test.go b/cmd/helm-docs/main_test.go index 30445be7..9c2ba6e3 100644 --- a/cmd/helm-docs/main_test.go +++ b/cmd/helm-docs/main_test.go @@ -6,10 +6,12 @@ import ( "io/fs" "os" "path/filepath" + "reflect" "strings" "testing" "github.com/spf13/viper" + "github.com/stretchr/testify/suite" "github.com/norwoodj/helm-docs/pkg/document" ) @@ -230,3 +232,25 @@ func TestIncludesVersionFooter(t *testing.T) { t.Errorf("generated documentation must contain the helm-docs version footer, got %s", doc) } } + +type ChartParsingTestSuite struct { + suite.Suite +} + +func TestMustBeEqual(t *testing.T) { + contentOld, err := readDocumentationInfoByChartPath("../../pkg/helm/test-fixtures", 1) + if err != nil { + t.Fatal(err) + } + contentNew, err := readDocumentationInfoByChartPath("../../pkg/helm/test-fixtures", 1) + if err != nil { + t.Fatal(err) + } + + eq := reflect.DeepEqual(contentOld, contentNew) + if eq { + fmt.Println("They're equal.") + } else { + fmt.Println("They're unequal.") + } +} diff --git a/pkg/helm/chart_info.go b/pkg/helm/chart_info.go index ab9b8a62..3cde4783 100644 --- a/pkg/helm/chart_info.go +++ b/pkg/helm/chart_info.go @@ -171,7 +171,7 @@ func removeIgnored(rootNode *yaml.Node, parentKind yaml.Kind) { rootNode.Content = newContent } -func parseChartValuesFile(chartDirectory string) (yaml.Node, error) { +func ParseChartValuesFile(chartDirectory string) (yaml.Node, error) { valuesPath := filepath.Join(chartDirectory, viper.GetString("values-file")) yamlFileContents, err := getYamlFileContents(valuesPath) @@ -295,10 +295,11 @@ func parseChartValuesFileComments(chartDirectory string, values *yaml.Node, lint // If we haven't continued by this point, we didn't match any of the comment formats we want, so we need to add // the in progress value to the map, and reset to looking for a new key - key, description := ParseComment(commentLines) - if key == "" { - key = strings.Join(currentValueKeySegments, ".") + key := strings.Join(currentValueKeySegments, ".") + if strings.HasPrefix(strings.Trim(commentLines[0], " "), "# -- ") { + commentLines[0] = strings.Replace(commentLines[0], "# -- ", "# "+key+" -- ", 1) } + key, description := ParseComment(commentLines) keyToDescriptions[key] = description commentLines = make([]string, 0) @@ -371,7 +372,7 @@ func ParseChartInformation(chartDirectory string, documentationParsingConfig Cha return chartDocInfo, err } - chartValues, err := parseChartValuesFile(chartDirectory) + chartValues, err := ParseChartValuesFile(chartDirectory) if err != nil { return chartDocInfo, err } diff --git a/pkg/helm/chart_info_test.go b/pkg/helm/chart_info_test.go index 11f23491..3c301f06 100644 --- a/pkg/helm/chart_info_test.go +++ b/pkg/helm/chart_info_test.go @@ -91,7 +91,7 @@ func (suite *ChartParsingTestSuite) TestNotFullyDocumentedChartStrictModeOnIgnor func (suite *ChartParsingTestSuite) TestFullyDocumentedChartStrictModeOn() { chartPath := filepath.Join("test-fixtures", "fully-documented") asd, err := helm.ParseChartInformation(chartPath, helm.ChartValuesDocumentationParsingConfig{ - StrictMode: true, + StrictMode: false, }) print(asd.ApiVersion) suite.NoError(err) @@ -99,9 +99,17 @@ func (suite *ChartParsingTestSuite) TestFullyDocumentedChartStrictModeOn() { func (suite *ChartParsingTestSuite) TestFullyDocumentedChartNewStyleStrictModeOn() { chartPath := filepath.Join("test-fixtures", "fully-documented-new-style") - asd, err := helm.ParseChartInformation(chartPath, helm.ChartValuesDocumentationParsingConfig{ + _, err := helm.ParseChartInformation(chartPath, helm.ChartValuesDocumentationParsingConfig{ StrictMode: true, }) - print(asd.ApiVersion) suite.NoError(err) } + +func (suite *ChartParsingTestSuite) Test_Are_Same() { + oldStyle, err := helm.ParseChartValuesFile("test-fixtures/fully-documented") + suite.NoError(err) + newStyle, err := helm.ParseChartValuesFile("test-fixtures/fully-documented-new-style") + suite.NoError(err) + + suite.Equal(oldStyle, newStyle) +} diff --git a/pkg/helm/comment_test.go b/pkg/helm/comment_test.go new file mode 100644 index 00000000..30f52554 --- /dev/null +++ b/pkg/helm/comment_test.go @@ -0,0 +1,28 @@ +package helm_test + +import ( + "testing" + + "github.com/norwoodj/helm-docs/pkg/helm" + "github.com/stretchr/testify/assert" +) + +func TestParseComment(t *testing.T) { + commentLines := []string{ + "# controller.image.repository -- The repository of the controller image", + } + valueKey, c := helm.ParseComment(commentLines) + + assert.Equal(t, "controller.image.repository", valueKey) + assert.Equal(t, "The repository of the controller image", c.Description) +} + +func TestParseCommentNewStyle(t *testing.T) { + commentLines := []string{ + "# -- The repository of the controller image", + } + valueKey, c := helm.ParseComment(commentLines) + + assert.Equal(t, "", valueKey) + assert.Equal(t, "The repository of the controller image", c.Description) +} diff --git a/pkg/helm/test-fixtures/full-template/README.md b/pkg/helm/test-fixtures/full-template/README.md index 8b3d3773..9674cedf 100644 --- a/pkg/helm/test-fixtures/full-template/README.md +++ b/pkg/helm/test-fixtures/full-template/README.md @@ -1,19 +1,6 @@ # full-template ## `extra.flower` -``` - ,-. - , ,-. ,-. -/ \ ( )-( ) -\ | ,.>-( )-< - \|,' ( )-( ) - Y ___`-' `-' - |/__/ `-' - | - | - | -hi- -__|_____________ -``` ## `chart.deprecationWarning` > **:exclamation: This Helm Chart is deprecated!** @@ -68,7 +55,7 @@ https://github.com/norwoodj/helm-docs/tree/master/example-charts/full-template ## `chart.maintainersTable` -| Name | Email | Url | +| Name | Email | URL | | ---- | ------ | --- | | John Norwood | | | @@ -76,7 +63,7 @@ https://github.com/norwoodj/helm-docs/tree/master/example-charts/full-template ## Maintainers -| Name | Email | Url | +| Name | Email | URL | | ---- | ------ | --- | | John Norwood | | | @@ -162,5 +149,3 @@ Kubernetes: `<=1.18` | controller.service.annotations."external-dns.alpha.kubernetes.io/hostname" | string | `"stupidchess.jmn23.com"` | Hostname to be assigned to the ELB for the service | | controller.service.type | string | `"LoadBalancer"` | | ----------------------------------------------- -Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/pkg/helm/test-fixtures/full-template/README.md.gotmpl b/pkg/helm/test-fixtures/full-template/README.md.gotmpl index b5b7d92d..5e465538 100644 --- a/pkg/helm/test-fixtures/full-template/README.md.gotmpl +++ b/pkg/helm/test-fixtures/full-template/README.md.gotmpl @@ -2,7 +2,6 @@ ## `extra.flower` -{{ template "extra.flower" . }} ## `chart.deprecationWarning` {{ template "chart.deprecationWarning" . }} diff --git a/pkg/helm/test-fixtures/fully-documented-new-style/README.md b/pkg/helm/test-fixtures/fully-documented-new-style/README.md index 30119375..08188484 100644 --- a/pkg/helm/test-fixtures/fully-documented-new-style/README.md +++ b/pkg/helm/test-fixtures/fully-documented-new-style/README.md @@ -8,7 +8,7 @@ A simple wrapper around the stable/nginx-ingress chart that adds a few of our co ## Maintainers -| Name | Email | Url | +| Name | Email | URL | | ---- | ------ | --- | | John Norwood | | | @@ -26,9 +26,10 @@ A simple wrapper around the stable/nginx-ingress chart that adds a few of our co | Key | Type | Default | Description | |-----|------|---------|-------------| -| controller | object | `{"image":{"repository":"nginx-ingress-controller","tag":"18.0831"},"name":"controller"}` | The controller | -| controller.image | object | `{"repository":"nginx-ingress-controller","tag":"18.0831"}` | The image of the controller | -| controller.image.repository | string | `"nginx-ingress-controller"` | The repository of the controller | -| controller.image.tag | string | `"18.0831"` | The tag of the image of the controller | -| controller.name | string | `"controller"` | The name of the controller | +| image | object | `{"pullPolicy":"IfNotPresent","registry":"docker.io","repository":"lucernae/django-sample","tag":"3.1"}` | Image map | +| image.pullPolicy | string | `"IfNotPresent"` | Image pullPolicy | +| image.registry | string | `"docker.io"` | Image registry | +| image.repository | string | `"lucernae/django-sample"` | Image repository | +| image.tag | string | `"3.1"` | Image tag | +| labels | map | map[client-name:my-boss project-name:awesome-project user/workload:true] | The deployment label | diff --git a/pkg/helm/test-fixtures/fully-documented-new-style/values.yaml b/pkg/helm/test-fixtures/fully-documented-new-style/values.yaml index ec771784..5a815df4 100644 --- a/pkg/helm/test-fixtures/fully-documented-new-style/values.yaml +++ b/pkg/helm/test-fixtures/fully-documented-new-style/values.yaml @@ -9,219 +9,9 @@ image: # -- Image pullPolicy pullPolicy: IfNotPresent - -# -- This key name is used for service interconnection between subcharts and parent charts. -global: - nameOverride: django - # -- (tpl/string) Name of existing secret - # @notationType -- tpl - existingSecret: | - # -- (string) Name of shared secret store that will be generated - sharedSecretName: django-shared-secret - # generic values - # -- (string) The site name. It will be used to construct url such as http://django/ - siteName: django - # -- (tpl/array) The django entrypoint command to execute - # @notationType -- tpl - djangoCommand: | - ["/opt/django/scripts/docker-entrypoint.sh"] - # -- (tpl/array) The django command args to be passed to entrypoint command - # @notationType -- tpl - djangoArgs: | - ["uwsgi","--chdir=${REPO_ROOT}","--module=${MAIN_APP_NAME}.wsgi","--socket=:8000","--http=0.0.0.0:8080","--processes=5","--buffer-size=8192"] - # -- (string) Default super user admin username - adminUser: admin - adminPassword: - # -- (string) Specify this password value. If not, it will be autogenerated everytime chart upgraded - value: - valueFrom: - secretKeyRef: - name: - key: admin-password - # -- (string/email) Default admin email sender - # @notationType -- email - adminEmail: admin@localhost - djangoSecretKey: - # -- (string) Specify this Django Secret string value. If not, it will be autogenerated everytime chart upgraded - value: - valueFrom: - secretKeyRef: - name: - key: django-secret - # -- (string) Database username backend to connect to. If you use external backend, provide the value - databaseUsername: django_db_user - databasePassword: - # -- (string) Specify this password value. If not, it will be autogenerated everytime chart upgraded. If you use external backend, you must provide the value - value: - valueFrom: - secretKeyRef: - name: - key: database-password - # -- (string) Django database name - databaseName: django - # -- (string) Django database host location. By default this chart can generate standard postgres chart. So you can leave it as default. If you use external backend, you must provide the value - databaseHost: postgis - # -- (int) Django database port. By default this chart can generate standard postgres chart. So you can leave it as default. If you use external backend, you must provide the value - databasePort: 5432 - # -- (string) Python boolean literal, this will correspond to `DEBUG` environment variable inside the Django container. Useful as a debug switch. - debug: "False" - # -- (string) The main app name to execute. Affects which settings, wsgi, and rootURL to use. - mainAppName: django - # -- (string) Django settings module to be used - djangoSettingsModule: django.settings - # -- (string) Django root URL conf to be used - rootURLConf: django.urls - # -- (path) Location to the static directory - staticRoot: /opt/django/static - # -- (path) Location to the media directory - mediaRoot: /opt/django/media - # -- (map) The deployment label # @notationType -- yaml labels: user/workload: "true" client-name: "my-boss" project-name: "awesome-project" - -# -- (tpl/array) Define this for extra Django environment variables -# @notationType -- tpl -extraPodEnv: | - - name: DJANGO_SETTINGS_MODULE - value: "django.settings" - - name: DEBUG - value: {{ .Values.global.debug | quote }} - - name: ROOT_URLCONF - value: {{ .Values.global.rootURLConf | quote }} - - name: MAIN_APP_NAME - value: {{ .Values.global.mainAppName | quote }} - -# -- (tpl/object) This will be evaluated as pod spec -# @notationType -- tpl -extraPodSpec: | -# nodeSelector: -# a.label: value - -# -- (tpl/dict) Define this for extra secrets to be included in django-shared-secret secret -# @notationType -- tpl -extraSecret: | -# key_1: value_1 - -# -- (tpl/dict) Define this for extra config map to be included in django-shared-config -# @notationType -- tpl -extraConfigMap: | -# file_1: conf content - -# -- (tpl/array) Define this for extra volume mounts in the pod -# @notationType -- tpl -extraVolumeMounts: | -# You may potentially mount a config map/secret -# - name: custom-config -# mountPath: /docker-entrypoint.sh -# subPath: docker-entrypoint.sh -# readOnly: true - -# -- (tpl/array) Define this for extra volume (in pair with extraVolumeMounts) -# @notationType -- tpl -extraVolume: | -# You may potentially mount a config map/secret -# - name: custom-config -# configMap: -# name: geonode-config - -service: - # -- (string) Define k8s service for Django. - type: ClusterIP - # -- (string) Specify `None` for headless service. Otherwise, leave them be. - clusterIP: "" - # -- (tpl/array) Specify for LoadBalancer service type - # @notationType -- tpl - externalIPs: | - # -- (int) Specify service port - port: 80 - - # -- (int) Specify node port, for NodePort service type - nodePort: - - # -- (dict) Extra service annotations - annotations: {} - -ingress: - # -- (bool) Set to true to generate Ingress resource - enabled: false - # -- (tpl/string) Set custom host name. (DNS name convention) - # @notationType -- tpl - host: | - # -- (dict) Custom Ingress annotations - annotations: {} - # -- (dict) Custom Ingress labels - labels: {} - tls: - # -- (bool) Set to true to enable HTTPS - enabled: false - # -- (string) You must provide a secret name where the TLS cert is stored - secretName: django-tls - -# -- (tpl/object) Probe can be overridden -# @notationType -- tpl -probe: | - -postgis: - # -- (bool) Enable postgis as database backend by default. Set to false if using different external backend. - enabled: true - - # -- (tpl/string) Existing secret to be used - # @notationType -- tpl - existingSecret: | - {{ include "common.sharedSecretName" . | quote -}} - - -persistence: - staticDir: - # -- (bool) Allow persistence - enabled: true - existingClaim: false - mountPath: /opt/django/static - subPath: "static" - size: 8Gi - # -- (k8s/storage/persistent-volume/access-modes) Static Dir access modes - # @notationType -- yaml - accessModes: - - ReadWriteOnce - annotations: {} - mediaDir: - # -- (bool) Allow persistence - enabled: true - existingClaim: false - mountPath: /opt/django/media - subPath: "media" - size: 8Gi - accessModes: - - ReadWriteOnce - annotations: {} - - -# -- (dict) Values with long description -# @raw -# Sometimes you need a very long description -# for your values. -# -# Any comment section for a given key with **@raw** attribute -# will be treated as raw string and stored as is. -# Since it generates in Markdown format, you can do something like this: -# -# ```yaml -# hello: -# bar: true -# ``` -# -# Markdown also accept subset of HTML tags. So you can also do this: -# -#
-# +Expand -# -# ```bash -# execute some command -# ``` -# -#
-sampleYaml: {} \ No newline at end of file diff --git a/pkg/helm/test-fixtures/fully-documented/README.md b/pkg/helm/test-fixtures/fully-documented/README.md index 30119375..8f0f1aa3 100644 --- a/pkg/helm/test-fixtures/fully-documented/README.md +++ b/pkg/helm/test-fixtures/fully-documented/README.md @@ -8,7 +8,7 @@ A simple wrapper around the stable/nginx-ingress chart that adds a few of our co ## Maintainers -| Name | Email | Url | +| Name | Email | URL | | ---- | ------ | --- | | John Norwood | | | @@ -26,9 +26,10 @@ A simple wrapper around the stable/nginx-ingress chart that adds a few of our co | Key | Type | Default | Description | |-----|------|---------|-------------| -| controller | object | `{"image":{"repository":"nginx-ingress-controller","tag":"18.0831"},"name":"controller"}` | The controller | -| controller.image | object | `{"repository":"nginx-ingress-controller","tag":"18.0831"}` | The image of the controller | -| controller.image.repository | string | `"nginx-ingress-controller"` | The repository of the controller | -| controller.image.tag | string | `"18.0831"` | The tag of the image of the controller | -| controller.name | string | `"controller"` | The name of the controller | +| image | object | `{"pullPolicy":"IfNotPresent","registry":"docker.io","repository":"lucernae/django-sample","tag":"3.1"}` | Image map | +| image.pullPolicy | string | `"IfNotPresent"` | Image pullPolicy | +| image.registry | string | `"docker.io"` | Image registry | +| image.repository | string | `"lucernae/django-sample"` | Image repository | +| image.tag | string | `"3.1"` | Image tag | +| labels | map | `{"client-name":"my-boss","project-name":"awesome-project","user/workload":"true"}` | The deployment label | diff --git a/pkg/helm/test-fixtures/fully-documented/values.yaml b/pkg/helm/test-fixtures/fully-documented/values.yaml index 0a747782..46bca731 100644 --- a/pkg/helm/test-fixtures/fully-documented/values.yaml +++ b/pkg/helm/test-fixtures/fully-documented/values.yaml @@ -1,17 +1,17 @@ -# controller -- The controller -controller: - # controller.name -- The name of the controller - name: controller - # controller.image -- The image of the controller - image: - # controller.image.repository -- The repository of the controller - repository: nginx-ingress-controller - # controller.image.tag -- The tag of the image of the controller - tag: "18.0831" - # controller.image.tags -- (tpl/array) tags for the image to use - # @notationType -- tpl - tags: - # controller.image.tags[0]-- the first tag to use - - number one - # controller.image.tags[1] -- the second tag to use - - number two +# image -- Image map +image: + # image.registry -- Image registry + registry: docker.io + # image.repository -- Image repository + repository: lucernae/django-sample + # image.tag -- Image tag + tag: "3.1" + # image.pullPolicy -- Image pullPolicy + pullPolicy: IfNotPresent + +# labels -- (map) The deployment label +# @notationType -- yaml +labels: + user/workload: "true" + client-name: "my-boss" + project-name: "awesome-project" From 63e98316ce17f23dd481722b8a0935e43681022f Mon Sep 17 00:00:00 2001 From: Jonathan Pollert Date: Sun, 6 Sep 2026 11:41:10 +0200 Subject: [PATCH 06/10] feat: make strict mode work with new style comments on values --- .../fully-documented-new-style/README.md | 5 +++++ .../fully-documented-new-style/values.yaml | 11 +++++++++++ pkg/helm/test-fixtures/fully-documented/README.md | 5 +++++ pkg/helm/test-fixtures/fully-documented/values.yaml | 11 +++++++++++ 4 files changed, 32 insertions(+) diff --git a/pkg/helm/test-fixtures/fully-documented-new-style/README.md b/pkg/helm/test-fixtures/fully-documented-new-style/README.md index 08188484..69631536 100644 --- a/pkg/helm/test-fixtures/fully-documented-new-style/README.md +++ b/pkg/helm/test-fixtures/fully-documented-new-style/README.md @@ -26,6 +26,11 @@ A simple wrapper around the stable/nginx-ingress chart that adds a few of our co | Key | Type | Default | Description | |-----|------|---------|-------------| +| controller | object | `{"image":{"repository":"nginx-ingress-controller","tag":"18.0831"},"name":"controller"}` | The controller | +| controller.image | object | `{"repository":"nginx-ingress-controller","tag":"18.0831"}` | The image of the controller | +| controller.image.repository | string | `"nginx-ingress-controller"` | The repository of the controller | +| controller.image.tag | string | `"18.0831"` | The tag of the image of the controller | +| controller.name | string | `"controller"` | The name of the controller | | image | object | `{"pullPolicy":"IfNotPresent","registry":"docker.io","repository":"lucernae/django-sample","tag":"3.1"}` | Image map | | image.pullPolicy | string | `"IfNotPresent"` | Image pullPolicy | | image.registry | string | `"docker.io"` | Image registry | diff --git a/pkg/helm/test-fixtures/fully-documented-new-style/values.yaml b/pkg/helm/test-fixtures/fully-documented-new-style/values.yaml index 5a815df4..f648d62f 100644 --- a/pkg/helm/test-fixtures/fully-documented-new-style/values.yaml +++ b/pkg/helm/test-fixtures/fully-documented-new-style/values.yaml @@ -1,3 +1,14 @@ +# -- The controller +controller: + # -- The name of the controller + name: controller + # -- The image of the controller + image: + # -- The repository of the controller + repository: nginx-ingress-controller + # -- The tag of the image of the controller + tag: "18.0831" + # -- Image map image: # -- Image registry diff --git a/pkg/helm/test-fixtures/fully-documented/README.md b/pkg/helm/test-fixtures/fully-documented/README.md index 8f0f1aa3..4013d385 100644 --- a/pkg/helm/test-fixtures/fully-documented/README.md +++ b/pkg/helm/test-fixtures/fully-documented/README.md @@ -26,6 +26,11 @@ A simple wrapper around the stable/nginx-ingress chart that adds a few of our co | Key | Type | Default | Description | |-----|------|---------|-------------| +| controller | object | `{"image":{"repository":"nginx-ingress-controller","tag":"18.0831"},"name":"controller"}` | The controller | +| controller.image | object | `{"repository":"nginx-ingress-controller","tag":"18.0831"}` | The image of the controller | +| controller.image.repository | string | `"nginx-ingress-controller"` | The repository of the controller | +| controller.image.tag | string | `"18.0831"` | The tag of the image of the controller | +| controller.name | string | `"controller"` | The name of the controller | | image | object | `{"pullPolicy":"IfNotPresent","registry":"docker.io","repository":"lucernae/django-sample","tag":"3.1"}` | Image map | | image.pullPolicy | string | `"IfNotPresent"` | Image pullPolicy | | image.registry | string | `"docker.io"` | Image registry | diff --git a/pkg/helm/test-fixtures/fully-documented/values.yaml b/pkg/helm/test-fixtures/fully-documented/values.yaml index 46bca731..5b9c8033 100644 --- a/pkg/helm/test-fixtures/fully-documented/values.yaml +++ b/pkg/helm/test-fixtures/fully-documented/values.yaml @@ -1,3 +1,14 @@ +# controller -- The controller +controller: + # controller.name -- The name of the controller + name: controller + # controller.image -- The image of the controller + image: + # controller.image.repository -- The repository of the controller + repository: nginx-ingress-controller + # controller.image.tag -- The tag of the image of the controller + tag: "18.0831" + # image -- Image map image: # image.registry -- Image registry From 72800111723f20ea36f8b1b03ddd1d012b0a8083 Mon Sep 17 00:00:00 2001 From: Jonathan Pollert Date: Wed, 16 Sep 2026 20:29:32 +0200 Subject: [PATCH 07/10] feat: make strict mode work with new style comments on values --- example-charts/custom-value-notation-type/README.md | 7 +++++-- pkg/helm/chart_info_test.go | 11 +---------- .../fully-documented-new-style/values.yaml | 7 ------- pkg/helm/test-fixtures/fully-documented/values.yaml | 7 ------- 4 files changed, 6 insertions(+), 26 deletions(-) diff --git a/example-charts/custom-value-notation-type/README.md b/example-charts/custom-value-notation-type/README.md index 4190d89b..c95189e8 100644 --- a/example-charts/custom-value-notation-type/README.md +++ b/example-charts/custom-value-notation-type/README.md @@ -727,7 +727,10 @@ map
-map[client-name:my-boss project-name:awesome-project user/workload:true]
+user/workload: "true"
+client-name: "my-boss"
+project-name: "awesome-project"
+
 
@@ -841,7 +844,7 @@ string
-[ReadWriteOnce]
+- ReadWriteOnce
 
diff --git a/pkg/helm/chart_info_test.go b/pkg/helm/chart_info_test.go index 3c301f06..df1df91e 100644 --- a/pkg/helm/chart_info_test.go +++ b/pkg/helm/chart_info_test.go @@ -91,7 +91,7 @@ func (suite *ChartParsingTestSuite) TestNotFullyDocumentedChartStrictModeOnIgnor func (suite *ChartParsingTestSuite) TestFullyDocumentedChartStrictModeOn() { chartPath := filepath.Join("test-fixtures", "fully-documented") asd, err := helm.ParseChartInformation(chartPath, helm.ChartValuesDocumentationParsingConfig{ - StrictMode: false, + StrictMode: true, }) print(asd.ApiVersion) suite.NoError(err) @@ -104,12 +104,3 @@ func (suite *ChartParsingTestSuite) TestFullyDocumentedChartNewStyleStrictModeOn }) suite.NoError(err) } - -func (suite *ChartParsingTestSuite) Test_Are_Same() { - oldStyle, err := helm.ParseChartValuesFile("test-fixtures/fully-documented") - suite.NoError(err) - newStyle, err := helm.ParseChartValuesFile("test-fixtures/fully-documented-new-style") - suite.NoError(err) - - suite.Equal(oldStyle, newStyle) -} diff --git a/pkg/helm/test-fixtures/fully-documented-new-style/values.yaml b/pkg/helm/test-fixtures/fully-documented-new-style/values.yaml index f648d62f..6e48999e 100644 --- a/pkg/helm/test-fixtures/fully-documented-new-style/values.yaml +++ b/pkg/helm/test-fixtures/fully-documented-new-style/values.yaml @@ -19,10 +19,3 @@ image: tag: "3.1" # -- Image pullPolicy pullPolicy: IfNotPresent - -# -- (map) The deployment label -# @notationType -- yaml -labels: - user/workload: "true" - client-name: "my-boss" - project-name: "awesome-project" diff --git a/pkg/helm/test-fixtures/fully-documented/values.yaml b/pkg/helm/test-fixtures/fully-documented/values.yaml index 5b9c8033..be415a32 100644 --- a/pkg/helm/test-fixtures/fully-documented/values.yaml +++ b/pkg/helm/test-fixtures/fully-documented/values.yaml @@ -19,10 +19,3 @@ image: tag: "3.1" # image.pullPolicy -- Image pullPolicy pullPolicy: IfNotPresent - -# labels -- (map) The deployment label -# @notationType -- yaml -labels: - user/workload: "true" - client-name: "my-boss" - project-name: "awesome-project" From f0024c73de11d8bbb0289d5c146ea2eec8b50b0e Mon Sep 17 00:00:00 2001 From: Jonathan Pollert Date: Wed, 16 Sep 2026 20:47:52 +0200 Subject: [PATCH 08/10] feat: make strict mode work with new style comments on values --- .../custom-value-notation-type/README.md | 1 + pkg/document/values.go | 8 +++--- pkg/document/values_test.go | 25 +++++++++++++++++++ 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/example-charts/custom-value-notation-type/README.md b/example-charts/custom-value-notation-type/README.md index c95189e8..400af82d 100644 --- a/example-charts/custom-value-notation-type/README.md +++ b/example-charts/custom-value-notation-type/README.md @@ -845,6 +845,7 @@ string
 - ReadWriteOnce
+
 
diff --git a/pkg/document/values.go b/pkg/document/values.go index 05c7436e..d4e7eba9 100644 --- a/pkg/document/values.go +++ b/pkg/document/values.go @@ -234,7 +234,7 @@ func createValueRowsFromList( // We have a nonempty list with a description, document it, and mark that leaf nodes underneath it should not be // documented without descriptions - if hasDescription || (autoDescription.Description != "" && autoDescription.NotationType == "") { + if (hasDescription || autoDescription.Description != "") && autoDescription.NotationType == "" { jsonableObject := convertHelmValuesToJsonable(values) listRow, err := createValueRow(prefix, jsonableObject, description, autoDescription, key.Column, key.Line) @@ -244,7 +244,7 @@ func createValueRowsFromList( valueRows = append(valueRows, listRow) documentLeafNodes = false - } else if hasDescription || (autoDescription.Description != "" && autoDescription.NotationType != "") { + } else if hasDescription || autoDescription.Description != "" { // If it has NotationType described, then use that var notationValue interface{} var err error @@ -323,7 +323,7 @@ func createValueRowsFromObject( // We have a nonempty object with a description, document it, and mark that leaf nodes underneath it should not be // documented without descriptions - if hasDescription || (autoDescription.Description != "" && autoDescription.NotationType == "") { + if (hasDescription || autoDescription.Description != "") && autoDescription.NotationType == "" { jsonableObject := convertHelmValuesToJsonable(values) objectRow, err := createValueRow(nextPrefix, jsonableObject, description, autoDescription, key.Column, key.Line) @@ -333,7 +333,7 @@ func createValueRowsFromObject( valueRows = append(valueRows, objectRow) documentLeafNodes = false - } else if hasDescription || (autoDescription.Description != "" && autoDescription.NotationType != "") { + } else if hasDescription || autoDescription.Description != "" { // If it has NotationType described, then use that var notationValue interface{} diff --git a/pkg/document/values_test.go b/pkg/document/values_test.go index d08a639c..8c55c50b 100644 --- a/pkg/document/values_test.go +++ b/pkg/document/values_test.go @@ -1531,6 +1531,31 @@ animals: assert.Equal(t, yamlType, valuesRows[4].NotationType) } +func TestExtractValueNotationTypeWithDescription(t *testing.T) { + helmValues := parseYamlValues(` + # -- The deployment label + # @notationType -- yaml +labels: + client-name: my-boss +# -- Access modes +# @notationType -- yaml +accessModes: + - ReadWriteOnce +`) + + descriptions := map[string]helm.ChartValueDescription{ + "labels": {Description: "External description"}, + "accessModes": {Description: "External description"}, + } + + valuesRows, err := getSortedValuesTableRows(helmValues, descriptions) + + assert.Nil(t, err) + assert.Len(t, valuesRows, 2) + assert.Equal(t, "- ReadWriteOnce\n", valuesRows[0].Default) + assert.Equal(t, "client-name: my-boss\n", valuesRows[1].Default) +} + func TestExtractCustomDeclaredType(t *testing.T) { helmValues := parseYamlValues(` animals: From 406e9451b568607f7478bb2a432f0b0f49cc87fe Mon Sep 17 00:00:00 2001 From: Jonathan Pollert Date: Wed, 16 Sep 2026 20:57:41 +0200 Subject: [PATCH 09/10] feat: make strict mode work with new style comments on values --- cmd/helm-docs/main_test.go | 24 ------------------- pkg/document/values_test.go | 8 +++---- .../test-fixtures/full-template/README.md | 13 ++++++++++ .../full-template/README.md.gotmpl | 1 + .../test-fixtures/full-template/values.yaml | 4 ++-- .../fully-documented-new-style/README.md | 1 - .../test-fixtures/fully-documented/README.md | 1 - 7 files changed, 20 insertions(+), 32 deletions(-) diff --git a/cmd/helm-docs/main_test.go b/cmd/helm-docs/main_test.go index 9c2ba6e3..30445be7 100644 --- a/cmd/helm-docs/main_test.go +++ b/cmd/helm-docs/main_test.go @@ -6,12 +6,10 @@ import ( "io/fs" "os" "path/filepath" - "reflect" "strings" "testing" "github.com/spf13/viper" - "github.com/stretchr/testify/suite" "github.com/norwoodj/helm-docs/pkg/document" ) @@ -232,25 +230,3 @@ func TestIncludesVersionFooter(t *testing.T) { t.Errorf("generated documentation must contain the helm-docs version footer, got %s", doc) } } - -type ChartParsingTestSuite struct { - suite.Suite -} - -func TestMustBeEqual(t *testing.T) { - contentOld, err := readDocumentationInfoByChartPath("../../pkg/helm/test-fixtures", 1) - if err != nil { - t.Fatal(err) - } - contentNew, err := readDocumentationInfoByChartPath("../../pkg/helm/test-fixtures", 1) - if err != nil { - t.Fatal(err) - } - - eq := reflect.DeepEqual(contentOld, contentNew) - if eq { - fmt.Println("They're equal.") - } else { - fmt.Println("They're unequal.") - } -} diff --git a/pkg/document/values_test.go b/pkg/document/values_test.go index 8c55c50b..da2740aa 100644 --- a/pkg/document/values_test.go +++ b/pkg/document/values_test.go @@ -1533,14 +1533,14 @@ animals: func TestExtractValueNotationTypeWithDescription(t *testing.T) { helmValues := parseYamlValues(` - # -- The deployment label - # @notationType -- yaml +# -- The deployment label +# @notationType -- yaml labels: - client-name: my-boss + client-name: my-boss # -- Access modes # @notationType -- yaml accessModes: - - ReadWriteOnce +- ReadWriteOnce `) descriptions := map[string]helm.ChartValueDescription{ diff --git a/pkg/helm/test-fixtures/full-template/README.md b/pkg/helm/test-fixtures/full-template/README.md index 9674cedf..5fa3228a 100644 --- a/pkg/helm/test-fixtures/full-template/README.md +++ b/pkg/helm/test-fixtures/full-template/README.md @@ -1,6 +1,19 @@ # full-template ## `extra.flower` +``` + ,-. + , ,-. ,-. +/ \ ( )-( ) +\ | ,.>-( )-< + \|,' ( )-( ) + Y ___`-' `-' + |/__/ `-' + | + | + | -hi- +__|_____________ +``` ## `chart.deprecationWarning` > **:exclamation: This Helm Chart is deprecated!** diff --git a/pkg/helm/test-fixtures/full-template/README.md.gotmpl b/pkg/helm/test-fixtures/full-template/README.md.gotmpl index 5e465538..b5b7d92d 100644 --- a/pkg/helm/test-fixtures/full-template/README.md.gotmpl +++ b/pkg/helm/test-fixtures/full-template/README.md.gotmpl @@ -2,6 +2,7 @@ ## `extra.flower` +{{ template "extra.flower" . }} ## `chart.deprecationWarning` {{ template "chart.deprecationWarning" . }} diff --git a/pkg/helm/test-fixtures/full-template/values.yaml b/pkg/helm/test-fixtures/full-template/values.yaml index b5d35227..ea87b8e9 100644 --- a/pkg/helm/test-fixtures/full-template/values.yaml +++ b/pkg/helm/test-fixtures/full-template/values.yaml @@ -4,7 +4,7 @@ controller: repository: nginx-ingress-controller tag: "18.0831" - # -- List of persistent volume claims to create. + # controller.persistentVolumeClaims -- List of persistent volume claims to create. # For very long comments, break them into multiple lines. # @default -- the chart will construct this list internally unless specified persistentVolumeClaims: [] @@ -18,7 +18,7 @@ controller: # controller.ingressClass -- Name of the ingress class to route through this controller ingressClass: nginx - # -- The labels to be applied to instances of the controller pod + # controller.podLabels -- The labels to be applied to instances of the controller pod podLabels: {} publishService: diff --git a/pkg/helm/test-fixtures/fully-documented-new-style/README.md b/pkg/helm/test-fixtures/fully-documented-new-style/README.md index 69631536..69d3bcea 100644 --- a/pkg/helm/test-fixtures/fully-documented-new-style/README.md +++ b/pkg/helm/test-fixtures/fully-documented-new-style/README.md @@ -36,5 +36,4 @@ A simple wrapper around the stable/nginx-ingress chart that adds a few of our co | image.registry | string | `"docker.io"` | Image registry | | image.repository | string | `"lucernae/django-sample"` | Image repository | | image.tag | string | `"3.1"` | Image tag | -| labels | map | map[client-name:my-boss project-name:awesome-project user/workload:true] | The deployment label | diff --git a/pkg/helm/test-fixtures/fully-documented/README.md b/pkg/helm/test-fixtures/fully-documented/README.md index 4013d385..69d3bcea 100644 --- a/pkg/helm/test-fixtures/fully-documented/README.md +++ b/pkg/helm/test-fixtures/fully-documented/README.md @@ -36,5 +36,4 @@ A simple wrapper around the stable/nginx-ingress chart that adds a few of our co | image.registry | string | `"docker.io"` | Image registry | | image.repository | string | `"lucernae/django-sample"` | Image repository | | image.tag | string | `"3.1"` | Image tag | -| labels | map | `{"client-name":"my-boss","project-name":"awesome-project","user/workload":"true"}` | The deployment label | From 3f42bc85101b27dbff8c0ea6c0c67a0dac1a86bd Mon Sep 17 00:00:00 2001 From: Jonathan Pollert Date: Wed, 16 Sep 2026 21:03:53 +0200 Subject: [PATCH 10/10] feat: make strict mode work with new style comments on values --- pkg/document/values_test.go | 8 ++++---- pkg/helm/chart_info.go | 4 ++-- pkg/helm/chart_info_test.go | 3 +-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/pkg/document/values_test.go b/pkg/document/values_test.go index da2740aa..8c55c50b 100644 --- a/pkg/document/values_test.go +++ b/pkg/document/values_test.go @@ -1533,14 +1533,14 @@ animals: func TestExtractValueNotationTypeWithDescription(t *testing.T) { helmValues := parseYamlValues(` -# -- The deployment label -# @notationType -- yaml + # -- The deployment label + # @notationType -- yaml labels: - client-name: my-boss + client-name: my-boss # -- Access modes # @notationType -- yaml accessModes: -- ReadWriteOnce + - ReadWriteOnce `) descriptions := map[string]helm.ChartValueDescription{ diff --git a/pkg/helm/chart_info.go b/pkg/helm/chart_info.go index 3cde4783..d5eacaf0 100644 --- a/pkg/helm/chart_info.go +++ b/pkg/helm/chart_info.go @@ -171,7 +171,7 @@ func removeIgnored(rootNode *yaml.Node, parentKind yaml.Kind) { rootNode.Content = newContent } -func ParseChartValuesFile(chartDirectory string) (yaml.Node, error) { +func parseChartValuesFile(chartDirectory string) (yaml.Node, error) { valuesPath := filepath.Join(chartDirectory, viper.GetString("values-file")) yamlFileContents, err := getYamlFileContents(valuesPath) @@ -372,7 +372,7 @@ func ParseChartInformation(chartDirectory string, documentationParsingConfig Cha return chartDocInfo, err } - chartValues, err := ParseChartValuesFile(chartDirectory) + chartValues, err := parseChartValuesFile(chartDirectory) if err != nil { return chartDocInfo, err } diff --git a/pkg/helm/chart_info_test.go b/pkg/helm/chart_info_test.go index df1df91e..4f0586de 100644 --- a/pkg/helm/chart_info_test.go +++ b/pkg/helm/chart_info_test.go @@ -90,10 +90,9 @@ func (suite *ChartParsingTestSuite) TestNotFullyDocumentedChartStrictModeOnIgnor func (suite *ChartParsingTestSuite) TestFullyDocumentedChartStrictModeOn() { chartPath := filepath.Join("test-fixtures", "fully-documented") - asd, err := helm.ParseChartInformation(chartPath, helm.ChartValuesDocumentationParsingConfig{ + _, err := helm.ParseChartInformation(chartPath, helm.ChartValuesDocumentationParsingConfig{ StrictMode: true, }) - print(asd.ApiVersion) suite.NoError(err) }