helm-snoop keeps your config and docs in your values.yaml
and (in the future) schema.json
in sync with the code in your helm template files.
It parses the values.yaml and template files of helm charts
and finds undefined and unused values.
Beta Status: Expect some false positives and breaking changes as the project matures.
docker run --rm -v $(pwd):/chart ghcr.io/y0-l0/helm-snoop:latest /chartHomebrew (macOS/Linux):
brew install y0-l0/tap/helm-snoopAPT (Debian/Ubuntu):
echo "deb [trusted=yes] https://apt.fury.io/stadimeter/ /" \
| sudo tee /etc/apt/sources.list.d/fury.list
sudo apt update && sudo apt install helm-snoopBinary (Linux amd64):
VERSION=0.7.0
curl -fsSL "https://github.com/y0-l0/helm-snoop/releases/download/v${VERSION}/helm-snoop_${VERSION}_linux_amd64.tar.gz" | tar -xz
sudo mv helm-snoop /usr/local/bin/# Analyze a chart directory or archive
helm-snoop ./my-chart/
helm-snoop ./my-chart-0.1.0.tgz
# Include additional values files
helm-snoop --values ./env-values.yaml --values ./secrets-values.yaml ./my-chart/
# Suppress specific findings
helm-snoop --ignore .image.tag --ignore .config.* ./my-chart/
# JSON output
helm-snoop --json ./my-chartAnalyzes Helm charts and reports:
- Unused: Keys defined in values files but never referenced in templates
- Undefined: Paths referenced in templates but not defined in any values file
See docs/CLI.md for the complete cli flag documentation.
- Variable tracking: Variables are tracked across references (e.g.,
{{ $var := .Values.foo }}{{ $var.bar }}) - Context-aware path resolution: Correctly resolves relative paths within
withandrangecontexts (e.g.,.Values.configβwithβ.timeoutresolves to.Values.config.timeout) - Dict/list operations: Tracks values through
dict,list,merge,concatoperations - Nested template definitions: Follows
defineblocks across multiple files - Include/Template functions: Template includes are followed and analyzed
- Wildcard ignore patterns: Advanced pattern matching for suppressing specific warnings
- Control flow: All branches of
if/elseblocks are analyzed
- Limited
tplfunction support: Dynamic template strings have partial support - No schema.json validation: Only compares templates against values.yaml, not against schema definitions
- Limited dynamic evaluation: Complex patterns like
{{ index .Values.a .Values.b }}may not be fully resolved - No subchart analysis: Does not analyze subcharts (only collects template functions via
define) - No global values from subcharts: May report false positives for undefined global paths from subcharts
Add to your .pre-commit-config.yaml:
repos:
- repo: https://github.com/y0-l0/helm-snoop
rev: v0.7.0
hooks:
- id: helm-snoop # requires helm-snoop on PATH
# - id: helm-snoop-docker # uses Docker insteadTwo hooks are available: helm-snoop (requires the binary on $PATH) and
helm-snoop-docker (runs via ghcr.io/y0-l0/helm-snoop). Changed files are
resolved to their parent chart directories automatically.
In monorepos with multiple charts, consider adding the hook once per chart with
a scoped files regex. This keeps flags like -i within the chart boundaries.
Golang doesn't compile with undefined or unused variables. Helm has no such checks.
In my day job, my team maintains 50_000 lines of helm chart code.
The majority of bugs in these helm charts are:
- Typos in either template files or values.yaml files
- Mismatches between defaults/documentation in values.yaml and actual template implementation
It is also close to impossible to keep the documentation in values.yaml in sync with the actual template implementation. New config options are implemented but never documented. Old config options are never removed from the documentation.
All of these could be detected by a Helm Chart linter using static analysis:
- No undefined values -
.Values.*paths require defaults and documentation in values.yaml - No unused values - No outdated or misspelled keys in values.yaml
helm-snoop is (trying to become) that linter.
helm-unused-values Similar PoC implementation, appears unfinished and inactive since some time.
Regex-based tools Limited by their approach; can't handle complex template logic.
JSON Schema for values.yaml Validates user input, which is valuable. However, it suffers from the same sync problem: if your schema.json is out of sync with your template implementation, users can't configure those out-of-sync properties.
For detailed comparison, see docs/RESEARCH.md
Contributions would be wonderful:
- Architecture input, especially from Helm codebase experts
- Testing and user feedback
- Code quality and idiomatic Go (inexperienced gopher here!)