helm-env-delta
v1.7.1
Published
HelmEnvDelta – environment-aware YAML delta and sync for GitOps
Maintainers
Readme
🚀 HelmEnvDelta
Sync YAML configs across environments in seconds, not hours.
Stop copying files manually. Stop worrying about accidental overwrites. Stop production incidents from configuration drift.
HelmEnvDelta (hed) automates environment synchronization for GitOps workflows while protecting your production-specific settings and preventing dangerous changes.
💡 Why Teams Love HelmEnvDelta
Before:
- ⏰ 30+ minutes manually copying files between UAT → Prod
- 😰 Accidentally overwrite production namespaces and replica counts
- 🐛 Major version upgrades slip through to production
- 📝 Inconsistent YAML formatting across environments
- 🔍 Noisy git diffs make code review painful
After:
- ⚡ 1 minute automated sync with safety guarantees
- 🛡️ Production-specific values automatically preserved
- 🚦 Stop rules block dangerous changes before deployment
- ✨ Consistent formatting across all environments
- 📊 Clean, structural diffs that show what actually changed
✨ Key Features
🔍 Smart YAML Diff - Compares structure, not text. Ignores formatting, comments, and array reordering to show only meaningful changes.
🎯 Path Filtering - Preserve environment-specific values (namespaces, replicas, secrets) that should never sync.
🔄 Powerful Transforms - Regex find/replace for both file content and paths. Load transforms from external YAML files for reusability. Change uat-db.internal → prod-db.internal automatically.
🛡️ Safety Rules - Block major version upgrades, scaling violations, and forbidden patterns. Load validation rules from external files. Scan globally or target specific fields.
🎨 Format Enforcement - Standardize YAML across all environments: key ordering, indentation, quoting, array sorting.
📦 Config Inheritance - Reuse base configurations with environment-specific overrides.
📊 Multiple Reports - Console, HTML (visual), and JSON (CI/CD) output formats.
🔍 Discovery Tools - Preview files (--list-files), inspect config (--show-config), validate with comprehensive warnings including unused pattern detection.
💡 Smart Suggestions - Heuristic analysis (--suggest) detects patterns and recommends transforms and stop rules automatically. Control sensitivity with --suggest-threshold.
🛡️ Safety First - Pre-execution summary, first-run tips, improved error messages with helpful examples.
⚡ High Performance - 45-60% faster than alternatives with intelligent caching and parallel processing.
🔔 Auto Updates - Notifies when newer versions are available (skips in CI/CD).
📥 Installation
npm install -g helm-env-deltaRequirements: Node.js ≥ 22, npm ≥ 9
🎯 Quick Start
1️⃣ Create Config
# config.yaml
source: './uat'
destination: './prod'
skipPath:
'**/*.yaml':
- 'metadata.namespace' # Never overwrite prod namespace
- 'spec.replicas' # Keep prod scaling
transforms:
'**/*.yaml':
content:
- find: "-uat\\b"
replace: '-prod'2️⃣ Preview Changes
helm-env-delta --config config.yaml --dry-run --diff3️⃣ Execute Sync
helm-env-delta --config config.yaml4️⃣ Review in Browser
helm-env-delta --config config.yaml --diff-html5️⃣ Get Smart Suggestions (Optional)
helm-env-delta --config config.yaml --suggest
# Control suggestion sensitivity (0-1, default: 0.3)
helm-env-delta --config config.yaml --suggest --suggest-threshold 0.7Analyzes differences and suggests transforms and stop rules automatically with configurable confidence filtering.
Done! All files synced, production values preserved, changes validated.
🎬 Real-World Use Cases
🏢 Multi-Service GitOps
Challenge: 20+ microservices across Dev → UAT → Prod. Each has environment-specific namespaces, resource limits, and URLs.
Solution:
source: './helm/uat'
destination: './helm/prod'
skipPath:
'**/*.yaml':
- 'metadata.namespace'
- 'resources.limits'
- 'spec.replicas'
transforms:
'**/*.yaml':
content:
- find: '-uat\\b'
replace: '-prod'Result: Sync 50+ files in 5 seconds with zero risk of overwriting production settings.
🚨 Prevent Production Incidents
Challenge: Production incidents from accidental major version upgrades or scaling beyond cluster capacity.
Solution:
stopRules:
'services/**/values.yaml':
- type: 'semverMajorUpgrade' # Block v1.x → v2.x
path: 'image.tag'
- type: 'numeric' # Enforce limits
path: 'replicaCount'
min: 2
max: 10Result: Dangerous changes blocked automatically. Use --force only when you intend it.
📐 Standardize Formatting
Challenge: Different editors, different formatting. Git diffs full of noise.
Solution:
outputFormat:
indent: 2
keySeparator: true
keyOrders:
'**/*.yaml':
- 'apiVersion'
- 'kind'
- 'metadata'
- 'spec'
arraySort:
'**/*.yaml':
- path: 'env'
sortBy: 'name'
order: 'asc'Result: Every file formatted consistently. Clean diffs. Easier reviews.
🎓 Live Examples
The repository includes ready-to-run examples:
📁 Example 1: Config Inheritance
Shows how to reuse base configuration across multiple environment pairs.
helm-env-delta --config example/1-config-inheritance/config.uat-to-prod.yaml --dry-run --diff🚦 Example 2: Stop Rules
Demonstrates all 5 stop rule types and how violations block execution.
helm-env-delta --config example/2-stop-rules/config.yaml --dry-run --diff⛓️ Example 3: Multi-Environment Chain
Progressive promotion through Dev → UAT → Prod with cumulative transforms.
cd example/3-multi-env-chain
./sync-all.sh🗑️ Example 4: Prune Mode
File deletion behavior with prune: true vs prune: false.
helm-env-delta --config example/4-prune-mode/config.with-prune.yaml --dry-run --diff📦 Example 5: External Files
Load transforms and stop rules from external YAML files for better organization and reusability.
helm-env-delta --config example/5-external-files/config.yaml --dry-run --diffFeatures shown:
- Transform files (
contentFile,filenameFile) - Pattern files (
regexFile,regexFileKey) - Global vs targeted regex validation
💡 Smart Configuration Suggestions (Heuristic)
The --suggest flag uses heuristic analysis to examine differences between environments and automatically recommend configuration updates. This intelligent pattern detection helps bootstrap your config by discovering repeated changes and potential safety rules.
How It Works
helm-env-delta --config config.yaml --suggest
# Control suggestion sensitivity (higher threshold = fewer, higher-confidence suggestions)
helm-env-delta --config config.yaml --suggest --suggest-threshold 0.7How heuristic analysis works:
- 🔍 Intelligently detects repeated value changes across files
- 🎯 Suggests transform patterns (regex find/replace) based on semantic patterns
- 🛡️ Recommends stop rules for safety validation using pattern recognition
- 📊 Provides confidence scores and occurrence counts for each suggestion
- 🎛️ NEW: Configurable threshold filters suggestions by confidence level (0-1)
- 📝 Outputs copy-paste ready YAML configuration
- ✨ Enhanced noise filtering:
- Ignores UUIDs, timestamps, single-character changes
- Filters antonym pairs (enable/disable, true/false, on/off)
- Filters regex special characters (unless semantic keywords present)
- Filters version-number-only changes (service-v1 → service-v2)
- Allows semantic patterns even with special chars (db.uat.com → db.prod.com)
Example Output
# Suggested Transforms
transforms:
'**/*.yaml':
content:
- find: 'uat-cluster'
replace: 'prod-cluster'
# Confidence: 95% (42 occurrences across 12 files)
# Suggested Stop Rules
stopRules:
'**/*.yaml':
- type: 'semverMajorUpgrade'
path: 'image.tag'
# Detected version changes: v1.2.3 → v2.0.0When to Use
- 🚀 First-time setup: Let heuristics discover patterns automatically instead of manual analysis
- 🔄 Config refinement: Find missing transforms or stop rules through smart detection
- 📚 Learning tool: Understand what's changing between environments
- ⚡ Quick start: Bootstrap configuration from existing files using intelligent pattern matching
- 🧠 Pattern discovery: Leverage heuristic algorithms to identify semantic transformations (uat→prod, staging→production)
- 🎯 Confidence tuning: Adjust threshold to balance between finding all patterns vs. high-confidence only
Confidence threshold control:
# More suggestions (lower threshold = less strict)
helm-env-delta --config config.yaml --suggest --suggest-threshold 0.2
# Default balance (standard heuristics, threshold: 0.3)
helm-env-delta --config config.yaml --suggest
# Only high-confidence (higher threshold = more strict)
helm-env-delta --config config.yaml --suggest --suggest-threshold 0.8Workflow:
# 1. Get suggestions (optionally with custom threshold)
helm-env-delta --config config.yaml --suggest --suggest-threshold 0.5 > suggestions.yaml
# 2. Review and copy relevant sections to config.yaml
# 3. Test with dry-run
helm-env-delta --config config.yaml --dry-run --diff
# 4. Execute
helm-env-delta --config config.yaml⚙️ Configuration Reference
🎯 Core Settings
source: './uat' # Required: Source folder
destination: './prod' # Required: Destination folder
include: # Optional: File patterns (default: all)
- '**/*.yaml'
exclude: # Optional: Exclude patterns
- '**/test*.yaml'
prune: false # Optional: Delete dest files not in source🔒 Path Filtering (skipPath)
Preserve environment-specific fields during sync.
skipPath:
'apps/*.yaml':
- 'metadata.namespace' # Top-level field
- 'spec.destination.namespace' # Nested field
- 'spec.ignoreDifferences[*].jsonPointers' # Array wildcard
'services/**/values.yaml':
- 'microservice.env[*].value' # All array items
- 'resources.limits'Filter Expressions (Skip by Name)
Skip specific array items by property value using filter syntax:
skipPath:
'**/*.yaml':
- 'env[name=SECRET_KEY]' # Skip item where name=SECRET_KEY
- 'env[name=INTERNAL_TOKEN].value' # Skip nested field in matching item
- 'containers[name=sidecar]' # Skip entire sidecar container
- 'spec.containers[name=app].env[name=DEBUG]' # Nested filtersSyntax:
array[prop=value]- Match items where property equals valuearray[prop="value with spaces"]- Quoted values for special characters- Combine with wildcards:
containers[name=app].env[*].value
Use cases: Namespaces, replicas, resource limits, secrets, URLs, environment-specific array items.
🔄 Transformations
Regex find/replace for content and file paths. Load transforms from external files or define inline.
Inline Transforms (Regex)
transforms:
'services/**/values.yaml':
content: # Transform YAML values (not keys)
- find: "uat-db\\.(.+)\\.internal"
replace: 'prod-db.$1.internal' # Capture group $1
'config/**/*.yaml':
filename: # Transform file paths
- find: 'envs/uat/'
replace: 'envs/prod/'
- find: '-uat\.'
replace: '-prod.'File-Based Transforms (Literal)
Load transforms from external YAML files for better organization and reusability:
transforms:
'**/*.yaml':
# Load content transforms from files (literal string replacement)
contentFile:
- './transforms/common.yaml' # Single file
- './transforms/services.yaml' # Or array of files
# Load filename transforms from file
filenameFile: './transforms/paths.yaml'
# Can combine with inline transforms (file-based run first)
content:
- find: 'v(\d+)-uat'
replace: 'v$1-prod'Transform file format (key:value pairs):
# transforms/common.yaml - literal string replacements
staging: production
stg: prod
staging-db.internal: production-db.internalExecution order:
- File-based transforms (literal, case-sensitive)
- Inline regex transforms (patterns)
Content scope: All string values in matched files Filename scope: Full relative path (folders + filename) Processing: Sequential (rule 1 output → rule 2 input)
🛡️ Stop Rules
Block dangerous changes before deployment.
| Icon | Rule Type | Purpose | Example |
| ---- | -------------------- | -------------------------- | ------------------------------------------ |
| 🚫 | semverMajorUpgrade | Block major version bumps | Prevent v1.2.3 → v2.0.0 |
| ⬇️ | semverDowngrade | Block any downgrades | Prevent v1.3.0 → v1.2.0 |
| 📏 | versionFormat | Enforce strict format | Reject 1.2, v1.2.3-rc, require 1.2.3 |
| 🔢 | numeric | Validate ranges | Keep replicas between 2-10 |
| 🔤 | regex | Block patterns (inline) | Reject v0.x pre-release versions |
| 📄 | regexFile | Block patterns (from file) | Load forbidden patterns from YAML array |
| 🔑 | regexFileKey | Block transform file keys | Use transform keys as forbidden patterns |
Inline Stop Rules
stopRules:
'services/**/values.yaml':
- type: 'semverMajorUpgrade'
path: 'image.tag'
- type: 'numeric'
path: 'replicaCount'
min: 2
max: 10
- type: 'versionFormat'
path: 'image.tag'
vPrefix: 'required' # or 'forbidden', 'allowed'
# Regex with path (targeted)
- type: 'regex'
path: 'image.tag'
regex: '^v0\.'
# NEW: Regex without path (global - scans all values)
- type: 'regex'
regex: '^127\.' # Block localhost IPs anywhereFile-Based Stop Rules
Load validation patterns from external files:
stopRules:
'**/*.yaml':
# Load patterns from array file (with path - targeted)
- type: 'regexFile'
path: 'image.tag'
file: './patterns/forbidden-versions.yaml'
# Load patterns from array file (without path - global scan)
- type: 'regexFile'
file: './patterns/forbidden-global.yaml'
# Use transform file keys as patterns (targeted)
- type: 'regexFileKey'
path: 'service.name'
file: './transforms/common.yaml'Pattern file format (array):
# patterns/forbidden-versions.yaml
- ^0\..* # Block 0.x.x versions
- .*-alpha.* # Block alpha releases
- .*-beta.* # Block beta releasesPath modes:
- With
path: Check specific field only (targeted) - Without
path: Scan all values recursively (global)
Override: Use --force to bypass stop rules when needed.
🎨 Output Formatting
Standardize YAML across all environments.
outputFormat:
indent: 2 # Indentation size
keySeparator: true # Blank line between top-level keys
keyOrders: # Custom key ordering
'apps/*.yaml':
- 'apiVersion'
- 'kind'
- 'metadata'
- 'spec'
arraySort: # Sort arrays
'services/**/values.yaml':
- path: 'env'
sortBy: 'name'
order: 'asc'
quoteValues: # Force quoting
'services/**/values.yaml':
- 'env[*].value'Benefits: Consistent formatting, cleaner diffs, better readability.
🔗 Config Inheritance
Reuse base configurations across environment pairs.
Base config (base.yaml):
include: ['**/*.yaml']
prune: true
skipPath:
'apps/*.yaml':
- 'spec.destination.namespace'
outputFormat:
indent: 2
keySeparator: trueEnvironment config (prod.yaml):
extends: './base.yaml' # Inherit base settings
source: './uat'
destination: './prod'
transforms: # Add environment-specific transforms
'**/*.yaml':
content:
- find: '-uat\\b'
replace: '-prod'
stopRules: # Add production safety rules
'services/**/values.yaml':
- type: 'semverMajorUpgrade'
path: 'image.tag'Merging:
- Arrays: Concatenated (child adds to parent)
- Objects: Deep merged (child overrides parent)
- Max depth: 5 levels
🖥️ CLI Reference
Commands
helm-env-delta --config <file> [options]
hed --config <file> [options] # Short aliasOptions
| Flag | Description |
| --------------------------- | -------------------------------------------------- |
| --config <path> | Required - Configuration file |
| --validate | Validate config and pattern usage (shows warnings) |
| --suggest | Analyze differences and suggest config updates |
| --suggest-threshold <0-1> | Minimum confidence for suggestions (default: 0.3) |
| --dry-run | Preview changes without writing files |
| --force | Override stop rules |
| --diff | Show console diff |
| --diff-html | Generate HTML report (opens in browser) |
| --diff-json | Output JSON to stdout (pipe to jq) |
| --list-files | List source/destination files without processing |
| --show-config | Display resolved config after inheritance |
| --skip-format | Skip YAML formatting |
| --no-color | Disable colored output (CI/accessibility) |
| --verbose | Show detailed debug info |
| --quiet | Suppress output except errors |
Examples
# Validate configuration (shows warnings)
hed --config config.yaml --validate
# Get smart configuration suggestions
hed --config config.yaml --suggest
# Get only high-confidence suggestions
hed --config config.yaml --suggest --suggest-threshold 0.7
# Preview files that will be synced
hed --config config.yaml --list-files
# Display resolved config (after inheritance)
hed --config config.yaml --show-config
# Preview with diff
hed --config config.yaml --dry-run --diff
# Visual HTML report
hed --config config.yaml --diff-html
# CI/CD integration (no colors)
hed --config config.yaml --diff-json --no-color | jq '.summary'
# Execute sync
hed --config config.yaml
# Force override stop rules
hed --config config.yaml --force🔄 Typical Workflow
flowchart LR
A[💾 UAT Files] --> B[⚙️ Config]
B --> C[🔍 Preview]
C --> D{✅ Approve?}
D -->|Yes| E[🚀 Execute]
D -->|No| F[📝 Adjust]
F --> C
E --> G[📁 Prod Updated]
G --> H[🔄 Git Commit]
H --> I[🚢 Deploy]Step-by-step:
# 1. Preview changes
hed --config config.yaml --dry-run --diff
# 2. Review in browser
hed --config config.yaml --diff-html
# 3. Execute sync
hed --config config.yaml
# 4. Git workflow
git add prod/
git commit -m "Sync UAT to Prod"
git push origin main🏆 Why Choose HelmEnvDelta?
🆚 Compared to Alternatives
HelmEnvDelta is purpose-built for environment synchronization, not template generation or deployment.
| What You Get | vs Helmfile | vs Kustomize | vs Bash Scripts | | ------------------------- | ------------- | ------------ | --------------- | | 🔍 Structural YAML diff | ✅ Yes | ❌ No | ❌ No | | 🎯 Environment-aware sync | ✅ Yes | ⚠️ Manual | ⚠️ Custom | | 🛡️ Safety validation | ✅ Built-in | ❌ None | ⚠️ DIY | | 🔄 Smart merge | ✅ Deep merge | ⚠️ Limited | ⚠️ DIY | | 🎨 Format enforcement | ✅ Yes | ❌ No | ❌ No | | 📚 Learning curve | 🟢 Low | 🟡 Medium | 🔴 High |
Complementary: Use HelmEnvDelta alongside Helm, Helmfile, Kustomize, ArgoCD, or Flux.
💪 Benefits
✅ Safety - Stop rules prevent dangerous changes. Dry-run previews everything.
✅ Speed - 30 minutes → 1 minute sync time. Parallel processing.
✅ Consistency - Uniform YAML formatting. No more diff noise.
✅ Auditability - Field-level change tracking with JSONPath. Clean structural diffs.
✅ Flexibility - Per-file patterns. Config inheritance. Regex transforms.
✅ Reliability - 917 tests, 84% coverage. Battle-tested.
📊 JSON Output for CI/CD
hed --config config.yaml --diff-json > report.jsonSchema:
{
"metadata": {
"timestamp": "2025-12-27T10:30:00Z",
"source": "./uat",
"destination": "./prod",
"dryRun": true
},
"summary": {
"added": 2,
"changed": 3,
"deleted": 1,
"unchanged": 15
},
"files": {
"changed": [
{
"path": "prod/app.yaml",
"changes": [
{
"path": "$.image.tag",
"oldValue": "v1.2.3",
"updatedValue": "v1.3.0"
}
]
}
]
},
"stopRuleViolations": [
{
"file": "prod/app.yaml",
"rule": { "type": "semverMajorUpgrade" },
"message": "Major upgrade: v1.2.3 → v2.0.0"
}
]
}Use with jq:
# Summary
jq '.summary' report.json
# Violations
jq '.stopRuleViolations' report.json
# Changed files
jq '.files.changed[].path' report.json🔧 Advanced Features
🧠 Structural Comparison
Git diffs are noisy when arrays are reordered. HelmEnvDelta compares YAML structure and recognizes identical content regardless of order.
Example:
# Source
env:
- name: DB_URL
value: uat-db
- name: LOG_LEVEL
value: debug
# Destination
env:
- name: LOG_LEVEL
value: info
- name: DB_URL
value: prod-dbGit diff: Shows all lines changed (noisy)
HelmEnvDelta: Only LOG_LEVEL: debug → info (clean)
🔍 Pattern Usage Validation
HelmEnvDelta validates that your configuration patterns actually match files and exist in your YAML structure. This helps catch typos, outdated patterns, and misconfigured rules early.
Run validation:
helm-env-delta --config config.yaml --validateWhat gets validated:
- exclude patterns - Warns if pattern matches no files
- skipPath patterns - Two-level validation:
- Glob pattern must match at least one file
- JSONPath must exist in at least one matched file
- Filter expressions
[prop=value]validated against actual array items
- stopRules patterns - Two-level validation:
- Glob pattern must match at least one file
- JSONPath (if specified) must exist in at least one matched file
Example output:
✓ Configuration is valid
⚠️ Pattern Usage Warnings (non-fatal):
• Exclude pattern 'test/**/*.yaml' matches no files
• skipPath pattern 'legacy/*.yaml' matches no files
• skipPath JSONPath 'microservice.replicaCountX' not found in any matched files (Pattern: svc/**/values.yaml, matches 50 file(s))
• stopRules glob pattern 'helm-charts/**/*.yaml' matches no files (3 rule(s) defined)
• stopRules JSONPath 'spec.replicas' not found in any matched files (Rule type: numeric, matches 5 file(s))Validation phases:
- Phase 1 (Static): Validates config syntax, checks for inefficient patterns, duplicates, conflicts
- Phase 2 (File-Based): Loads files and validates all patterns actually match and paths exist
When to use:
- After updating configuration
- When patterns stop working as expected
- To verify config file patterns after file reorganization
- As part of CI/CD pre-flight checks
Important: Warnings are non-fatal and don't block execution. They help you catch potential issues but won't stop your workflow.
🔀 Deep Merge
Preserves destination values for skipped paths.
# Source (UAT)
metadata:
namespace: uat
spec:
replicas: 3
# Config
skipPath:
"*.yaml":
- "metadata.namespace"
- "spec.replicas"
# Destination (Prod) - preserved after sync!
metadata:
namespace: prod # ← Kept
spec:
replicas: 5 # ← Kept🆘 Common Issues
❓ Stop rule violations blocking sync
Error: 🛑 Stop Rule Violation (semverMajorUpgrade)
Fix: Review change carefully. Use --force if intentional.
❓ Transforms not applying
Check:
- File pattern:
**/*.yamlvs*.yaml - Regex escaping:
\\.for literal dots - Word boundaries:
\\b
❓ JSONPath syntax errors
# ❌ Wrong
- '$.spec.replicas' # Don't use $. prefix
- 'env.*.name' # Use [*] not .*
# ✅ Correct
- 'spec.replicas' # No prefix
- 'env[*].name' # Array wildcard
- 'env[name=DEBUG]' # Filter by property value
- 'containers[name=app].env[name=SECRET]' # Nested filters❓ Glob patterns not matching
| Pattern | Matches |
| ---------------- | ----------------------- |
| *.yaml | Current directory only |
| **/*.yaml | Recursive (all subdirs) |
| apps/*.yaml | One level deep |
| apps/**/*.yaml | Recursive under apps/ |
📚 Resources
📦 npm: helm-env-delta
🐙 GitHub: BCsabaEngine/helm-env-delta
🐛 Issues: GitHub Issues
📄 License: ISC
🎉 Success Stories
Typical adoption timeline:
- Week 1: Install, create basic config, dry-run on one service
- Week 2: Expand to 5 services, add skipPath rules
- Week 3: Add stop rules (catch first bug!)
- Week 4: Standardize YAML formatting
- Month 2: Full adoption for all services
Results:
- ⏱️ Sync time: 2 hours/week → 10 minutes/week
- 🐛 Production incidents from sync errors: Zero
- 😊 Team satisfaction: High
Built for DevOps and Platform teams managing multi-environment Kubernetes and Helm deployments.
Made with ❤️ by BCsabaEngine
