Lint and Render Helm Charts Before Every Release
Catch schema errors, missing values, and broken templates by linting and rendering every chart in CI before it reaches a cluster.
Task
Block chart changes that fail linting or render invalid Kubernetes objects, instead of discovering the breakage during a deploy.
When to use this
A values key is renamed in a chart and lint passes locally, but the render silently drops an environment variable, so production pods start with the default database host.
Prerequisites
- Helm 3.14 or newer
- kubeconform 0.6 or newer installed in CI
- A chart directory with a values file per environment
Steps
1. Run lint with the production values file and treat warnings as failures.
helm lint charts/payments-api --strict -f values/production.yamlExpected output: helm prints 1 chart(s) linted, 0 chart(s) failed and exits with code 0.
2. Render the chart and validate every object against the target Kubernetes schema.
helm template payments charts/payments-api -f values/production.yaml | kubeconform -strict -summary -kubernetes-version 1.30.0Expected output: kubeconform reports 0 errors and 0 invalid resources for the rendered manifests.
3. Render each environment values file so a typo in staging fails CI instead of the deploy.
for f in values/*.yaml; do helm template payments charts/payments-api -f "$f" > /dev/null || exit 1; doneExpected output: The loop exits 0 only when every environment values file renders successfully.
4. Confirm the chart version was bumped for the release.
helm show chart charts/payments-api | grep '^version:'Expected output: The printed version is greater than the last published chart version and matches the release tag.
Troubleshooting
Problem
helm lint reports that the chart metadata is missing
Solution
Point the command at the chart directory that contains Chart.yaml, not at the values file or the repository root.
Problem
kubeconform rejects a manifest the cluster accepts
Solution
Pin -kubernetes-version to the cluster minor and add schema locations for custom resources instead of disabling validation.
Limitations
- Linting does not type-check values; add values.schema.json when wrong types must be rejected.
- Rendered output can still differ from the cluster after admission controllers mutate it.
Lint catches chart mistakes, rendering catches API mistakes
helm lint validates chart structure, template syntax, and values when a values.schema.json exists. It never talks to a Kubernetes API, so a chart can lint cleanly and still render an object the cluster rejects. Run both checks in CI against the same values file that production uses, and make warnings fatal so a deprecated field cannot slip through.
- name: Lint chart
run: helm lint charts/payments-api --strict -f values/production.yaml
- name: Render and validate
run: |
helm template payments charts/payments-api -f values/production.yaml \
| kubeconform -strict -summary -kubernetes-version 1.30.0
Render every environment
A chart that renders in production can still fail in staging when a values file references a removed key. Loop over every values file and render each one; the step takes seconds and catches the entire class of “it worked in the other environment” failures. Keep the loop in the same job as lint so a single required status check covers both.
Version and promote
The chart version is part of the release contract. If version does not increase, a chart repository will either reject the push or overwrite the previous package, and rollbacks become ambiguous. Compare the rendered image tag with the chart version in the pipeline, so a release cannot ship a chart that points at an older image. Keep the rendered manifests as a build artifact, because that exact output is what should be applied and what a reviewer should diff.