Template errors otherwise surface in production deploys; charts deserve tests like code.
Layers of checking, cheapest first:
helm lint ./shop -f prod.yamlchecks structure, renders templates, and flags common mistakes. Run it with each environment's values.- values.schema.json: a JSON Schema for values. Helm validates against it on install, upgrade, lint and template, rejecting typos and wrong types with a clear message. Mark required keys, set
additionalProperties: falsewhere you can, and use enums. requiredin templates:{{ required "image.tag is required" .Values.image.tag }}fails rendering with your message.helm template ... | kubeconform -strictvalidates rendered manifests against Kubernetes schemas offline; policy tools (conftest, Kyverno CLI) check rules such as "every container has limits".- helm-unittest (a plugin) asserts on rendered output: given these values, the Deployment has 3 replicas and no hostPath. Fast and needs no cluster.
- chart-testing (
ct lint,ct install) lints changed charts and installs them into a kind cluster in CI, checking version bumps too.
A sensible CI pipeline for a chart repo: lint, schema, unit tests, kubeconform on each values file, then install into a throwaway kind cluster and run helm test.
Example
{
"$schema": "https://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["image"],
"properties": {
"replicaCount": {"type": "integer", "minimum": 1},
"image": {
"type": "object",
"required": ["repository", "tag"],
"properties": {
"repository": {"type": "string"},
"tag": {"type": "string", "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"},
"pullPolicy": {"enum": ["Always", "IfNotPresent", "Never"]}
},
"additionalProperties": false
}
}
}Remember
- helm lint and helm template per environment's values
- values.schema.json rejects bad values before anything is applied
- helm-unittest for fast assertions; chart-testing + kind for real installs
Watch out for
- Writing a schema but leaving additionalProperties open, so typos like replicaCont still pass.