A Terraform-style summary tool for helm diff.
helm-diff-summary converts noisy Helm diff output into a concise, human-readable table showing:
- What Kubernetes resources are changing
- Whether resources are being created, updated, or deleted
- Approximate logical change counts
- A summarized deployment plan
Inspired by:
Raw helm diff output becomes difficult to review for:
- large charts
- GitOps workflows
- CI/CD pipelines
- Pull requests
- platform engineering teams
Example:
- replicas: 2
+ replicas: 3
- image: app:v1
+ image: app:v2After a few hundred lines, identifying the actual impact becomes painful.
helm-diff-summary provides a higher-level overview similar to Terraform plans.
- Summarizes Helm diff output in a table
- Detects:
- CREATE
- UPDATE
- DELETE
- Counts logical resource changes
- Works with:
helm diff upgrade--allow-unreleased
- CI/CD friendly
- Lightweight single binary
- No Kubernetes cluster access required
helm diff upgrade sample ./chart \
--allow-unreleased \
-n crossplane-system \
--output diff | ./helm-diff-summary+------------+-------------------+-------------------+---------+---------+
| KIND | NAME | NAMESPACE | ACTION | CHANGES |
+------------+-------------------+-------------------+---------+---------+
| Deployment | sample | crossplane-system | CREATE | 12 |
| Service | sample | crossplane-system | CREATE | 4 |
| ConfigMap | sample-config | crossplane-system | CREATE | 7 |
+------------+-------------------+-------------------+---------+---------+
Plan: 3 to create, 0 to update, 0 to delete.
Updated documentation on all available commands and flags can be found here.
- Recommend installing released versions. Release binaries are available on the releases page.
Install:
- Helm
- helm-diff plugin
- Go 1.22+
Install helm-diff:
helm plugin install https://github.com/databus23/helm-diffInstall helm-diff-summary on macOS
brew tap nikshilsbhat/stable git@github.com:nikhilsbhat/homebrew-stable.git
# for latest version
brew install nikhilsbhat/stable/helm-diff-summary
# for specific version
brew install nikhilsbhat/stable/helm-diff-summary@0.2.5Check repo for all available versions of the formula.
Latest version of docker images are published to ghcr.io, all available images can be found there.
docker pull ghcr.io/nikhilsbhat/helm-diff-summary:latest
docker pull ghcr.io/nikhilsbhat/helm-diff-summary:<github-release-tag>- Clone the repository:
git clone https://github.com/nikhilsbhat/helm-diff-summary.git cd helm-diff-summary - Build the project:
make local.build
helm diff upgrade my-release ./chart \
--output diff | ./helm-diff-summaryhelm diff upgrade my-release ./chart \
--allow-unreleased \
--output diff | ./helm-diff-summaryhelm diff upgrade my-release ./chart \
-n production \
--output diff | ./helm-diff-summaryhelm-diff-summary parses the structured resource headers emitted by helm diff.
Example:
crossplane-system, sample, Deployment (apps) has been added:
From this it extracts:
- namespace
- resource name
- resource kind
- action type
It then counts meaningful diff lines inside the resource block.
Raw unified diffs tend to overcount changes.
Example:
- image: app:v1
+ image: app:v2Technically this is:
- 1 deletion
- 1 addition
But semantically it is a single field update.
To make output more human-friendly:
- CREATE β counts additions
- DELETE β counts deletions
- UPDATE β counts additions only
This produces Terraform-style summaries instead of raw diff math.
# Sample output on fresh installation
+----------------+------------------------------+-----------+--------+---------+
| KIND | NAME | NAMESPACE | ACTION | CHANGES |
+----------------+------------------------------+-----------+--------+---------+
| DaemonSet | fluentd-elasticsearch | default | CREATE | 53 |
| ReplicaSet | frontend | default | CREATE | 20 |
| Function | function-patch-and-transform | default | CREATE | 7 |
| CronJob | hello | default | CREATE | 19 |
| Configuration | my-configuration | default | CREATE | 7 |
| Pod | nginx | default | CREATE | 14 |
| Pod | nginx-2 | default | CREATE | 10 |
| Job | pi | default | CREATE | 13 |
| Provider | provider-aws | default | CREATE | 7 |
| Deployment | sample | default | CREATE | 45 |
| Service | sample | default | CREATE | 20 |
| ServiceAccount | sample | default | CREATE | 10 |
| ConfigMap | sample-config-map | default | CREATE | 10 |
| ConfigMap | sample-config-map-json | default | CREATE | 16 |
| ConfigMap | sample-config-map-test | default | CREATE | 17 |
| ConfigMap | sample-config-map-test-2 | default | CREATE | 13 |
| ConfigMap | sample-config-map-yaml | default | CREATE | 15 |
| ConfigMap | test-cm | default | CREATE | 7 |
| StatefulSet | web | default | CREATE | 35 |
+----------------+------------------------------+-----------+--------+---------+# Sample output for following diff
# default, sample-config-map-test-2, ConfigMap (v1) has changed:
# # Source: sample/templates/configmap.yaml
# apiVersion: v1
# kind: ConfigMap
# metadata:
# name: sample-config-map-test-2
# namespace: default
# data:
# config: |
# - name: test
# image: ghcr.io/virtu/test:v2.2.0
# - name: virtu
#- type: foo
#+ type: foor
# - name: foolist
# type: bar
+-----------+--------------------------+-----------+--------+---------+
| KIND | NAME | NAMESPACE | ACTION | CHANGES |
+-----------+--------------------------+-----------+--------+---------+
| ConfigMap | sample-config-map-test-2 | default | UPDATE | 1 |
+-----------+--------------------------+-----------+--------+---------+This tool currently uses unified diff parsing.
It does not yet perform:
- semantic YAML diffing
- Kubernetes-aware field comparison
- exact field-level mutation analysis
Therefore:
- counts are approximate
- formatting changes may still appear as updates
Useful for:
- GitHub Actions
- GitLab CI
- ArgoCD
- FluxCD
- Atlantis-style workflows
- PR review automation
Example:
helm diff upgrade app ./chart \
--output diff | ./helm-diff-summaryCustom policies can be configured using a helm-diff-summary.yaml file.
The tool automatically loads policies from:
./helm-diff-summary.yamlpolicies:
# ------------------------------------------------------------
# Block all deletions
# ------------------------------------------------------------
- name: resource-deletion
action: DELETE
severity: CRITICAL
message: resource deletion detected
# ------------------------------------------------------------
# Networking updates
# ------------------------------------------------------------
- name: networking-update
category: NETWORKING
action: UPDATE
severity: HIGH
message: networking resource updated
# ------------------------------------------------------------
# Sensitive namespaces
# ------------------------------------------------------------
- name: production-namespace
namespace: production
severity: HIGH
message: change detected in production namespace
# ------------------------------------------------------------
# Critical platform resources
# ------------------------------------------------------------
- name: crd-update
kind: CustomResourceDefinition
severity: CRITICAL
message: CRD modification detected
# ------------------------------------------------------------
# Large changes
# ------------------------------------------------------------
- name: large-change
min_changes: 100
severity: MEDIUM
message: large resource change detected| Field | Description |
|---|---|
name |
Unique policy name |
kind |
Match Kubernetes resource kind |
category |
Match resource category |
action |
Match action (CREATE, UPDATE, DELETE) |
namespace |
Match namespace |
severity |
Violation severity |
message |
Violation message |
min_changes |
Minimum changed lines threshold |
LOWMEDIUMHIGHCRITICAL
CREATEUPDATEDELETE
helm diff upgrade app ./chart \
--output diff | ./helm-diff-summaryIf helm-diff-summary.yaml exists in the current directory, custom policies are automatically loaded and merged with the built-in default policies.
helm-diff-summary supports sending deployment summaries and policy violations to external notification systems.
Currently supported:
- Slack
- Microsoft Teams
- Google Chat
- Generic webhooks
Notifications reuse the same table output shown in the CLI.
export SLACK_WEBHOOK_URL=https://hooks.slack.com/services/xxx
helm diff upgrade app ./chart \
--output diff | ./helm-diff-summary \
--notify slackexport TEAMS_WEBHOOK_URL=https://example.webhook.office.com/xxx
helm diff upgrade app ./chart \
--output diff | ./helm-diff-summary \
--notify teamsexport GCHAT_WEBHOOK_URL=https://chat.googleapis.com/xxx
helm diff upgrade app ./chart \
--output diff | ./helm-diff-summary \
--notify gchatexport WEBHOOK_URL=https://example.com/webhook
helm diff upgrade app ./chart \
--output diff | ./helm-diff-summary \
--notify webhookMultiple notifiers can be specified together.
export SLACK_WEBHOOK_URL=https://hooks.slack.com/services/xxx
export TEAMS_WEBHOOK_URL=https://example.webhook.office.com/xxx
helm diff upgrade app ./chart \
--output diff | ./helm-diff-summary \
--notify slack,teamsπ Helm Deployment Summary
+------------+-------------------+-------------+--------+----------+-----------+---------+
| KIND | NAME | NAMESPACE | ACTION | SEVERITY | CATEGORY | CHANGES |
+------------+-------------------+-------------+--------+----------+-----------+---------+
| Deployment | sample-api | production | UPDATE | HIGH | WORKLOAD | 12 |
| ConfigMap | sample-config | production | UPDATE | MEDIUM | CONFIG | 3 |
| Service | sample | production | CREATE | LOW | NETWORK | 4 |
+------------+-------------------+-------------+--------+----------+-----------+---------+
Plan: 1 to create, 2 to update, 0 to delete.
π¨ Critical Violations
[CRITICAL] sensitive-namespace-production:
[HIGH] change detected in sensitive namespace (sample-api)
Webhook credentials are loaded through environment variables instead of CLI flags to avoid leaking secrets into:
- shell history
- CI logs
- process lists
go run . < diff.txthelm diff upgrade sample ./chart \
--allow-unreleased \
--output diff > diff.txt
cat diff.txt | go run .MIT