I'd recommend using named templates for validation, which you can execute in your installation notes instead of regular template files. Furthermore, by using failsafe validation functions (unlike require) for individual values, you can validate multiple values before failing execution of your helm command.
Bitnami charts use this strategy.
Setup
In a partials file, e.g. templates/_helpers.tpl, define named templates for validating the supplied values:
{{/* Compile all validation warnings into a single message and call fail. */}}
{{- define "mychart.validateValues" -}}
{{- $messages := list -}}
{{- $messages = append $messages (include "mychart.validateValues.foo" .) -}}
{{- $messages = append $messages (include "mychart.validateValues.bar" .) -}}
{{- $messages = without $messages "" -}}
{{- $message := join "\n" $messages -}}
{{- if $message -}}
{{- printf "\nVALUES VALIDATION:\n%s" $message | fail -}}
{{- end -}}
{{- end -}}
{{/* Validate value of foo */}}
{{- define "mychart.validateValues.foo" -}}
{{- if not (and .Values.foo (kindIs "string" .Values.foo)) -}}
mychart: foo
`foo` is required and should be a non-empty string
{{- end -}}
{{- end -}}
{{/* Validate the value of bar */}}
{{- define "mychart.validateValues.bar" -}}
{{- if not (and .Values.bar (kindIs "string" .Values.bar)) -}}
mychart: bar
`bar` is required and should be a non-empty string
{{- end -}}
{{- end -}}
In this case, the named template mychart.validateValues will run multiple validations (i.e. mychart.validateValues.foo, mychart.validateValues.bar). If one or more validations produce a validation warning, it will call fail with a summary of the warnings.
In templates/NOTES.txt, evaluate the named template for validation:
{{- include "mychart.validateValues" . }}
Test
With the following values.yaml file:
bar: 24
Templating, installing, or upgrading the chart will fail with the following message:
Error: execution error at (test/templates/NOTES.txt:1:4):
VALUES VALIDATION:
mychart: foo
`foo` is required and should be a non-empty string
mychart: bar
`bar` is required and should be a non-empty string