helm-env-delta 1.3.2 → 1.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,128 +1,130 @@
1
- # HelmEnvDelta
1
+ # 🚀 HelmEnvDelta
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/helm-env-delta.svg)](https://www.npmjs.com/package/helm-env-delta)
4
4
  [![License: ISC](https://img.shields.io/badge/License-ISC-blue.svg)](https://opensource.org/licenses/ISC)
5
5
  [![Node.js Version](https://img.shields.io/badge/node-%3E%3D22-brightgreen.svg)](https://nodejs.org/)
6
- ![Tests](https://img.shields.io/badge/tests-763%20passing-brightgreen.svg)
7
- ![Coverage](https://img.shields.io/badge/coverage-84%25-brightgreen.svg)
8
6
 
9
- **Environment-aware YAML delta and sync for GitOps workflows**
7
+ **Sync YAML configs across environments in seconds, not hours.**
10
8
 
11
- HelmEnvDelta (`helm-env-delta` or `hed`) is a CLI tool that safely synchronizes YAML configuration files across different environments (UAT Production, Dev → Staging, etc.) while respecting environment-specific differences and enforcing validation rules.
9
+ Stop copying files manually. Stop worrying about accidental overwrites. Stop production incidents from configuration drift.
10
+
11
+ HelmEnvDelta (`hed`) automates environment synchronization for GitOps workflows while protecting your production-specific settings and preventing dangerous changes.
12
12
 
13
13
  ---
14
14
 
15
- ## Table of Contents
16
-
17
- - [Why HelmEnvDelta?](#why-helmenvdelta)
18
- - [Comparison with Alternatives](#comparison-with-alternatives)
19
- - [When to Use HelmEnvDelta](#when-to-use-helmenvdelta)
20
- - [Adopting HelmEnvDelta in Existing GitOps Workflows](#adopting-helmenvdelta-in-existing-gitops-workflows)
21
- - [Key Features](#key-features)
22
- - [Installation](#installation)
23
- - [Examples](#examples)
24
- - [Quick Start](#quick-start)
25
- - [Use Cases](#use-cases)
26
- - [Configuration Guide](#configuration-guide)
27
- - [Core Settings](#core-settings)
28
- - [Path Filtering (skipPath)](#path-filtering-skippath)
29
- - [Transformations (transforms)](#transformations-transforms)
30
- - [Stop Rules (stopRules)](#stop-rules-stoprules)
31
- - [Output Formatting (outputFormat)](#output-formatting-outputformat)
32
- - [Config Inheritance (extends)](#config-inheritance-extends)
33
- - [CLI Usage](#cli-usage)
34
- - [Complete Workflow Example](#complete-workflow-example)
35
- - [Advanced Features](#advanced-features)
36
- - [Advantages & Benefits](#advantages--benefits)
37
- - [Real-World Configuration Examples](#real-world-configuration-examples)
38
- - [JSON Output Schema](#json-output-schema)
39
- - [Migration Guide](#migration-guide)
40
- - [Troubleshooting](#troubleshooting)
41
- - [License & Links](#license--links)
15
+ ## 💡 Why Teams Love HelmEnvDelta
16
+
17
+ **Before:**
18
+
19
+ - 30+ minutes manually copying files between UAT → Prod
20
+ - 😰 Accidentally overwrite production namespaces and replica counts
21
+ - 🐛 Major version upgrades slip through to production
22
+ - 📝 Inconsistent YAML formatting across environments
23
+ - 🔍 Noisy git diffs make code review painful
24
+
25
+ **After:**
26
+
27
+ - 1 minute automated sync with safety guarantees
28
+ - 🛡️ Production-specific values automatically preserved
29
+ - 🚦 Stop rules block dangerous changes before deployment
30
+ - Consistent formatting across all environments
31
+ - 📊 Clean, structural diffs that show what actually changed
42
32
 
43
33
  ---
44
34
 
45
- ## Why HelmEnvDelta?
35
+ ## Key Features
36
+
37
+ 🔍 **Smart YAML Diff** - Compares structure, not text. Ignores formatting, comments, and array reordering to show only meaningful changes.
38
+
39
+ 🎯 **Path Filtering** - Preserve environment-specific values (namespaces, replicas, secrets) that should never sync.
40
+
41
+ 🔄 **Powerful Transforms** - Regex find/replace for both file content and paths. Change `uat-db.internal` → `prod-db.internal` automatically.
46
42
 
47
- Managing multiple Kubernetes/Helm environments in GitOps workflows presents several challenges:
43
+ 🛡️ **Safety Rules** - Block major version upgrades, scaling violations, and forbidden patterns before they reach production.
48
44
 
49
- **Problems:**
45
+ 🎨 **Format Enforcement** - Standardize YAML across all environments: key ordering, indentation, quoting, array sorting.
50
46
 
51
- - **Manual Syncing is Error-Prone**: Copying changes between environments manually leads to mistakes, missed files, and inconsistencies
52
- - **Environment-Specific Config Gets Lost**: Accidentally overwriting production-specific values (namespaces, secrets, scaling) causes deployment failures
53
- - **Dangerous Changes Slip Through**: Major version upgrades, resource scaling beyond limits, or forbidden configurations can be deployed without review
54
- - **YAML Formatting Becomes Inconsistent**: Different team members format YAML differently, making diffs noisy and reviews difficult
55
- - **No Audit Trail**: Manual changes lack clear visibility into what changed and why
47
+ 📦 **Config Inheritance** - Reuse base configurations with environment-specific overrides.
56
48
 
57
- **HelmEnvDelta solves these problems by:**
49
+ 📊 **Multiple Reports** - Console, HTML (visual), and JSON (CI/CD) output formats.
58
50
 
59
- - Automating synchronization while respecting environment differences
60
- - Filtering out environment-specific paths that should never be synced
61
- - Validating changes against safety rules before applying them
62
- - Enforcing consistent YAML formatting across all environments
63
- - Providing clear diff reports for audit and review
51
+ ⚡ **High Performance** - 45-60% faster than alternatives with intelligent caching and parallel processing.
52
+
53
+ 🔔 **Auto Updates** - Notifies when newer versions are available (skips in CI/CD).
64
54
 
65
55
  ---
66
56
 
67
- ## Comparison with Alternatives
57
+ ## 📥 Installation
58
+
59
+ ```bash
60
+ npm install -g helm-env-delta
61
+ ```
62
+
63
+ **Requirements:** Node.js ≥ 22, npm ≥ 9
64
+
65
+ ---
68
66
 
69
- HelmEnvDelta focuses on a specific problem that existing tools don't fully address: safe, environment-aware YAML synchronization with deep structural comparison.
67
+ ## 🎯 Quick Start
70
68
 
71
- | Feature | HelmEnvDelta | Helmfile | Kustomize | Bespoke Scripts |
72
- | ----------------------------- | ------------------------------------------------------------------------------- | ------------------------------------------- | -------------------------------------- | -------------------------- |
73
- | **Deep YAML structural diff** | ✅ Parses and compares YAML structure, ignoring formatting and array reordering | ❌ No diff capability | ❌ No diff capability | ❌ Text-based diff only |
74
- | **Environment-aware sync** | ✅ Skip specific JSON paths per environment with `skipPath` | ⚠️ Environment values but no selective sync | ⚠️ Overlays but manual management | ⚠️ Custom logic required |
75
- | **Safety validation rules** | ✅ Semver, numeric, regex stop rules prevent dangerous changes | ❌ No validation | ❌ No validation | ⚠️ Must implement manually |
76
- | **Intelligent merge** | ✅ Deep merge preserves destination values for skipped paths | ❌ N/A | ⚠️ Strategic merge but limited control | ⚠️ Custom logic required |
77
- | **Content transformations** | ✅ Regex find/replace with capture groups | ⚠️ Values templating only | ❌ No transformation capability | ⚠️ sed/awk scripts |
78
- | **Filename transformations** | ✅ Transform file paths and folder structures | ❌ No capability | ❌ No capability | ⚠️ Complex mv/cp logic |
79
- | **Purpose** | Sync existing configs between environments | Deploy Helm charts declaratively | Generate variants from base manifests | Custom workflows |
80
- | **Learning curve** | Low (YAML config) | Medium (DSL + Helm) | Medium (overlays + patches) | High (bash scripting) |
81
- | **Output consistency** | ✅ Enforced YAML formatting | ❌ Depends on Helm | ❌ Depends on base files | ❌ Inconsistent |
69
+ ### 1️⃣ Create Config
82
70
 
83
- **What HelmEnvDelta uniquely provides:**
71
+ ```yaml
72
+ # config.yaml
73
+ source: './uat'
74
+ destination: './prod'
84
75
 
85
- 1. **Structural YAML comparison**: Unlike git diffs that show line-by-line changes, HelmEnvDelta parses YAML and compares structure, making diffs cleaner and more meaningful
86
- 2. **Environment-specific field preservation**: `skipPath` ensures production namespaces, replica counts, and secrets never get overwritten during sync
87
- 3. **Pre-deployment safety nets**: Stop rules catch dangerous changes (major version upgrades, scaling violations) before they reach production
88
- 4. **Bi-directional awareness**: Understands both source and destination environments, intelligently merging changes while preserving environment-specific values
76
+ skipPath:
77
+ '**/*.yaml':
78
+ - 'metadata.namespace' # Never overwrite prod namespace
79
+ - 'spec.replicas' # Keep prod scaling
89
80
 
90
- **Complementary, not competitive:**
81
+ transforms:
82
+ '**/*.yaml':
83
+ content:
84
+ - find: "-uat\\b"
85
+ replace: '-prod'
86
+ ```
91
87
 
92
- HelmEnvDelta works alongside your existing tools:
88
+ ### 2️⃣ Preview Changes
93
89
 
94
- - **Use with Helm**: HelmEnvDelta syncs Helm values files across environments
95
- - **Use with Helmfile**: Sync Helmfile environment declarations (UAT → Prod)
96
- - **Use with Kustomize**: Sync base manifests or overlays between environments
97
- - **Use with ArgoCD/Flux**: HelmEnvDelta updates files, your GitOps tool deploys them
90
+ ```bash
91
+ helm-env-delta --config config.yaml --dry-run --diff
92
+ ```
98
93
 
99
- ---
94
+ ### 3️⃣ Execute Sync
100
95
 
101
- ## When to Use HelmEnvDelta
96
+ ```bash
97
+ helm-env-delta --config config.yaml
98
+ ```
99
+
100
+ ### 4️⃣ Review in Browser
101
+
102
+ ```bash
103
+ helm-env-delta --config config.yaml --diff-html
104
+ ```
102
105
 
103
- ### Ideal Scenarios
106
+ **Done!** All files synced, production values preserved, changes validated.
104
107
 
105
- **1. Multi-Service, Multi-Environment GitOps with Shared Base Configurations**
108
+ ---
106
109
 
107
- You have 20+ microservices deployed across Dev → UAT → Production, each with a Helm chart. Services share a common base configuration but have environment-specific overrides (namespaces, resource limits, external URLs).
110
+ ## 🎬 Real-World Use Cases
108
111
 
109
- **Without HelmEnvDelta:**
112
+ ### 🏢 Multi-Service GitOps
110
113
 
111
- - Manually copy files between environment folders
112
- - Find/replace environment-specific values in IDE
113
- - Risk accidentally overwriting production namespaces or replica counts
114
- - Spend 30+ minutes per promotion, prone to human error
114
+ **Challenge:** 20+ microservices across Dev → UAT → Prod. Each has environment-specific namespaces, resource limits, and URLs.
115
115
 
116
- **With HelmEnvDelta:**
116
+ **Solution:**
117
117
 
118
118
  ```yaml
119
119
  source: './helm/uat'
120
120
  destination: './helm/prod'
121
+
121
122
  skipPath:
122
123
  '**/*.yaml':
123
124
  - 'metadata.namespace'
124
- - 'spec.replicas'
125
125
  - 'resources.limits'
126
+ - 'spec.replicas'
127
+
126
128
  transforms:
127
129
  '**/*.yaml':
128
130
  content:
@@ -130,59 +132,36 @@ transforms:
130
132
  replace: '-prod'
131
133
  ```
132
134
 
133
- Run `helm-env-delta --config config.yaml` and sync 50+ files in seconds, with guarantees that production-specific values are preserved.
135
+ **Result:** Sync 50+ files in 5 seconds with zero risk of overwriting production settings.
134
136
 
135
137
  ---
136
138
 
137
- **2. Preventing Production Incidents from Configuration Drift**
138
-
139
- Your team has experienced production incidents caused by:
140
-
141
- - Accidentally promoting a major version upgrade without review
142
- - Scaling replica counts beyond cluster capacity
143
- - Deploying pre-release (v0.x) versions to production
144
-
145
- **Without HelmEnvDelta:**
139
+ ### 🚨 Prevent Production Incidents
146
140
 
147
- - Manual code review is the only safety net
148
- - Easy to miss version changes buried in 100-line diffs
149
- - No automated validation before deployment
141
+ **Challenge:** Production incidents from accidental major version upgrades or scaling beyond cluster capacity.
150
142
 
151
- **With HelmEnvDelta:**
143
+ **Solution:**
152
144
 
153
145
  ```yaml
154
146
  stopRules:
155
147
  'services/**/values.yaml':
156
- - type: 'semverMajorUpgrade'
148
+ - type: 'semverMajorUpgrade' # Block v1.x → v2.x
157
149
  path: 'image.tag'
158
- - type: 'numeric'
150
+ - type: 'numeric' # Enforce limits
159
151
  path: 'replicaCount'
160
152
  min: 2
161
153
  max: 10
162
- - type: 'regex'
163
- path: 'image.tag'
164
- regex: '^v0\.'
165
154
  ```
166
155
 
167
- HelmEnvDelta validates every change and blocks dangerous promotions automatically. Use `--force` only when you explicitly intend to make a risky change.
156
+ **Result:** Dangerous changes blocked automatically. Use `--force` only when you intend it.
168
157
 
169
158
  ---
170
159
 
171
- **3. Standardizing YAML Formatting Across Teams and Environments**
172
-
173
- Your GitOps repository has inconsistent YAML formatting because:
174
-
175
- - Different team members use different editors (VS Code, IntelliJ, vim)
176
- - UAT files have one key ordering, Production has another
177
- - Git diffs are noisy with formatting changes unrelated to actual config changes
178
-
179
- **Without HelmEnvDelta:**
160
+ ### 📐 Standardize Formatting
180
161
 
181
- - Enforce formatting rules through documentation (often ignored)
182
- - Pre-commit hooks can format but don't standardize key ordering
183
- - Difficult to see meaningful changes in noisy diffs
162
+ **Challenge:** Different editors, different formatting. Git diffs full of noise.
184
163
 
185
- **With HelmEnvDelta:**
164
+ **Solution:**
186
165
 
187
166
  ```yaml
188
167
  outputFormat:
@@ -201,1571 +180,535 @@ outputFormat:
201
180
  order: 'asc'
202
181
  ```
203
182
 
204
- Every file gets consistently formatted on every sync, reducing diff noise and making code reviews easier.
183
+ **Result:** Every file formatted consistently. Clean diffs. Easier reviews.
205
184
 
206
185
  ---
207
186
 
208
- ### When NOT to Use HelmEnvDelta
187
+ ## 🎓 Live Examples
209
188
 
210
- **Single environment**: If you only have production, there's nothing to sync
189
+ The repository includes ready-to-run examples:
211
190
 
212
- **Completely different environments**: If Dev and Prod are architecturally different (different services, different structures), HelmEnvDelta isn't designed for that
191
+ ### 📁 Example 1: Config Inheritance
213
192
 
214
- **Template generation**: Use Helm/Helmfile for generating manifests from templates. HelmEnvDelta syncs existing files.
193
+ Shows how to reuse base configuration across multiple environment pairs.
215
194
 
216
- **Real-time deployments**: HelmEnvDelta updates files in git. Use ArgoCD/Flux for actual Kubernetes deployments.
195
+ ```bash
196
+ helm-env-delta --config example/1-config-inheritance/config.uat-to-prod.yaml --dry-run --diff
197
+ ```
217
198
 
218
- ---
199
+ ### 🚦 Example 2: Stop Rules
219
200
 
220
- ## Adopting HelmEnvDelta in Existing GitOps Workflows
201
+ Demonstrates all 5 stop rule types and how violations block execution.
202
+
203
+ ```bash
204
+ helm-env-delta --config example/2-stop-rules/config.yaml --dry-run --diff
205
+ ```
221
206
 
222
- If you're currently managing multiple environments manually in a GitOps workflow, HelmEnvDelta can be seamlessly integrated into your existing processes without disrupting your current setup.
207
+ ### ⛓️ Example 3: Multi-Environment Chain
223
208
 
224
- ### Before HelmEnvDelta: Manual Environment Sync
209
+ Progressive promotion through Dev UAT → Prod with cumulative transforms.
225
210
 
226
- Many teams start with manual synchronization between environments:
211
+ ```bash
212
+ cd example/3-multi-env-chain
213
+ ./sync-all.sh
214
+ ```
227
215
 
228
- 1. **Manual File Copying**: Copy YAML files from UAT to Production manually
229
- 2. **Find & Replace in IDE**: Use editor search/replace to update environment-specific values
230
- 3. **Visual Diff Review**: Compare files side-by-side to ensure correctness
231
- 4. **Manual Git Commits**: Stage, commit, and push changes individually
232
- 5. **Hope for the Best**: Cross fingers that no environment-specific values were accidentally overwritten
216
+ ### 🗑️ Example 4: Prune Mode
233
217
 
234
- This process works but is:
218
+ File deletion behavior with `prune: true` vs `prune: false`.
235
219
 
236
- - **Time-consuming**: 15-30 minutes per sync depending on complexity
237
- - **Error-prone**: Easy to miss files or make incorrect replacements
238
- - **Inconsistent**: Different team members may format YAML differently
239
- - **Unvalidated**: No automated checks for dangerous changes
240
- - **Difficult to audit**: Hard to track what changed and why
220
+ ```bash
221
+ helm-env-delta --config example/4-prune-mode/config.with-prune.yaml --dry-run --diff
222
+ ```
241
223
 
242
- ### After HelmEnvDelta: Automated Sync
224
+ ---
243
225
 
244
- With HelmEnvDelta, the same workflow becomes:
226
+ ## ⚙️ Configuration Reference
245
227
 
246
- ```bash
247
- # 1. Preview changes (5 seconds)
248
- helm-env-delta --config config.yaml --dry-run --diff
228
+ ### 🎯 Core Settings
249
229
 
250
- # 2. Review in browser (visual confirmation)
251
- helm-env-delta --config config.yaml --diff-html
230
+ ```yaml
231
+ source: './uat' # Required: Source folder
232
+ destination: './prod' # Required: Destination folder
252
233
 
253
- # 3. Execute sync (2 seconds)
254
- helm-env-delta --config config.yaml
234
+ include: # Optional: File patterns (default: all)
235
+ - '**/*.yaml'
236
+ exclude: # Optional: Exclude patterns
237
+ - '**/test*.yaml'
255
238
 
256
- # 4. Commit (standard git workflow)
257
- git add . && git commit -m "Sync UAT to Prod" && git push
239
+ prune: false # Optional: Delete dest files not in source
258
240
  ```
259
241
 
260
- **Benefits:**
242
+ ---
243
+
244
+ ### 🔒 Path Filtering (skipPath)
245
+
246
+ Preserve environment-specific fields during sync.
247
+
248
+ ```yaml
249
+ skipPath:
250
+ 'apps/*.yaml':
251
+ - 'metadata.namespace' # Top-level field
252
+ - 'spec.destination.namespace' # Nested field
253
+ - 'spec.ignoreDifferences[*].jsonPointers' # Array wildcard
254
+
255
+ 'services/**/values.yaml':
256
+ - 'microservice.env[*].value' # All array items
257
+ - 'resources.limits'
258
+ ```
261
259
 
262
- - **Faster**: Reduces sync time from 15-30 minutes to under 1 minute
263
- - **Safer**: Stop rules prevent dangerous changes (version downgrades, scaling violations)
264
- - **Consistent**: Enforces uniform YAML formatting across all files
265
- - **Auditable**: Clear diff reports show exactly what changed
266
- - **Repeatable**: Same configuration produces same results every time
260
+ **Use cases:** Namespaces, replicas, resource limits, secrets, URLs.
267
261
 
268
- ### Migration Path: Start Small
262
+ ---
269
263
 
270
- You don't need to configure everything at once. Start with a minimal configuration and expand gradually:
264
+ ### 🔄 Transformations
271
265
 
272
- **Phase 1: Basic Sync (Day 1)**
266
+ Regex find/replace for content and file paths.
273
267
 
274
268
  ```yaml
275
- source: './uat'
276
- destination: './prod'
277
269
  transforms:
278
- '**/*.yaml':
279
- content:
280
- - find: "-uat\\b"
281
- replace: '-prod'
270
+ 'services/**/values.yaml':
271
+ content: # Transform YAML values (not keys)
272
+ - find: "uat-db\\.(.+)\\.internal"
273
+ replace: 'prod-db.$1.internal' # Capture group $1
274
+
275
+ 'config/**/*.yaml':
276
+ filename: # Transform file paths
277
+ - find: 'envs/uat/'
278
+ replace: 'envs/prod/'
279
+ - find: '-uat\.'
280
+ replace: '-prod.'
282
281
  ```
283
282
 
284
- Run `--dry-run --diff` to see what would change. This gives you confidence without modifying any files.
283
+ **Content scope:** All string values in matched files
284
+ **Filename scope:** Full relative path (folders + filename)
285
+ **Processing:** Sequential (rule 1 output → rule 2 input)
285
286
 
286
- **Phase 2: Add Path Filtering (Week 1)**
287
+ ---
287
288
 
288
- ```yaml
289
- skipPath:
290
- '**/*.yaml':
291
- - 'metadata.namespace'
292
- - 'spec.replicas'
293
- ```
289
+ ### 🛡️ Stop Rules
294
290
 
295
- Identify fields that should never sync (namespaces, replica counts, resource limits) based on your environment differences.
291
+ Block dangerous changes before deployment.
296
292
 
297
- **Phase 3: Add Safety Rules (Week 2)**
293
+ | Icon | Rule Type | Purpose | Example |
294
+ | ---- | -------------------- | ------------------------- | ------------------------------------------ |
295
+ | 🚫 | `semverMajorUpgrade` | Block major version bumps | Prevent `v1.2.3` → `v2.0.0` |
296
+ | ⬇️ | `semverDowngrade` | Block any downgrades | Prevent `v1.3.0` → `v1.2.0` |
297
+ | 📏 | `versionFormat` | Enforce strict format | Reject `1.2`, `v1.2.3-rc`, require `1.2.3` |
298
+ | 🔢 | `numeric` | Validate ranges | Keep `replicas` between 2-10 |
299
+ | 🔤 | `regex` | Block patterns | Reject `v0.x` pre-release versions |
298
300
 
299
301
  ```yaml
300
302
  stopRules:
301
- '**/*.yaml':
303
+ 'services/**/values.yaml':
302
304
  - type: 'semverMajorUpgrade'
303
305
  path: 'image.tag'
306
+
304
307
  - type: 'numeric'
305
308
  path: 'replicaCount'
306
309
  min: 2
307
310
  max: 10
311
+
312
+ - type: 'versionFormat'
313
+ path: 'image.tag'
314
+ vPrefix: 'required' # or 'forbidden', 'allowed'
315
+
316
+ - type: 'regex'
317
+ path: 'image.tag'
318
+ regex: '^v0\.'
308
319
  ```
309
320
 
310
- Add validation rules to catch dangerous changes before they reach production.
321
+ **Override:** Use `--force` to bypass stop rules when needed.
322
+
323
+ ---
324
+
325
+ ### 🎨 Output Formatting
311
326
 
312
- **Phase 4: Enforce Formatting (Week 3)**
327
+ Standardize YAML across all environments.
313
328
 
314
329
  ```yaml
315
330
  outputFormat:
316
- indent: 2
317
- keySeparator: true
318
- keyOrders:
331
+ indent: 2 # Indentation size
332
+ keySeparator: true # Blank line between top-level keys
333
+
334
+ keyOrders: # Custom key ordering
319
335
  'apps/*.yaml':
320
336
  - 'apiVersion'
321
337
  - 'kind'
322
338
  - 'metadata'
323
339
  - 'spec'
324
- ```
325
340
 
326
- Standardize YAML formatting to reduce diff noise in git.
341
+ arraySort: # Sort arrays
342
+ 'services/**/values.yaml':
343
+ - path: 'env'
344
+ sortBy: 'name'
345
+ order: 'asc'
346
+
347
+ quoteValues: # Force quoting
348
+ 'services/**/values.yaml':
349
+ - 'env[*].value'
350
+ ```
327
351
 
328
- ### Gradual Adoption Strategy
352
+ **Benefits:** Consistent formatting, cleaner diffs, better readability.
329
353
 
330
- 1. **Start Read-Only**: Use `--dry-run` exclusively for the first week to build confidence
331
- 2. **Single Environment First**: Test with a non-critical environment pair (Dev → QA)
332
- 3. **Expand Configuration**: Add skipPath rules as you discover environment-specific fields
333
- 4. **Add Safety Nets**: Configure stop rules based on incidents you want to prevent
334
- 5. **Full Adoption**: Roll out to all environment pairs once validated
354
+ ---
335
355
 
336
- ### Validating Your Configuration
356
+ ### 🔗 Config Inheritance
337
357
 
338
- Before fully adopting HelmEnvDelta, validate your configuration captures all environment differences:
358
+ Reuse base configurations across environment pairs.
339
359
 
340
- ```bash
341
- # 1. Run dry-run with diff
342
- helm-env-delta --config config.yaml --dry-run --diff
360
+ **Base config (`base.yaml`):**
343
361
 
344
- # 2. Review changes carefully
345
- # Look for fields that should be skipped but aren't
362
+ ```yaml
363
+ include: ['**/*.yaml']
364
+ prune: true
346
365
 
347
- # 3. Generate JSON report for detailed analysis
348
- helm-env-delta --config config.yaml --dry-run --diff-json > report.json
366
+ skipPath:
367
+ 'apps/*.yaml':
368
+ - 'spec.destination.namespace'
349
369
 
350
- # 4. Check specific fields
351
- cat report.json | jq '.files.changed[].changes[] | select(.path | contains("namespace"))'
370
+ outputFormat:
371
+ indent: 2
372
+ keySeparator: true
352
373
  ```
353
374
 
354
- If you see fields changing that shouldn't (like production namespaces or replica counts), add them to `skipPath`.
375
+ **Environment config (`prod.yaml`):**
355
376
 
356
- ### Coexistence with Manual Processes
377
+ ```yaml
378
+ extends: './base.yaml' # Inherit base settings
357
379
 
358
- HelmEnvDelta doesn't replace your entire workflow. It complements it:
380
+ source: './uat'
381
+ destination: './prod'
359
382
 
360
- - **Still use git**: HelmEnvDelta syncs files, you commit them
361
- - **Still review PRs**: Generate HTML diffs for team review
362
- - **Still use ArgoCD/Flux**: HelmEnvDelta updates files, your GitOps tool deploys them
363
- - **Still have manual override**: Use `--force` when you need to bypass safety rules
383
+ transforms: # Add environment-specific transforms
384
+ '**/*.yaml':
385
+ content:
386
+ - find: '-uat\\b'
387
+ replace: '-prod'
364
388
 
365
- ### Real-World Adoption Example
389
+ stopRules: # Add production safety rules
390
+ 'services/**/values.yaml':
391
+ - type: 'semverMajorUpgrade'
392
+ path: 'image.tag'
393
+ ```
366
394
 
367
- A typical adoption timeline for a team managing 20+ microservices across 3 environments:
395
+ **Merging:**
368
396
 
369
- - **Week 1**: Install tool, create basic config, run dry-run on one service
370
- - **Week 2**: Expand to 5 services, add skipPath rules, first real sync
371
- - **Week 3**: Add stop rules after catching a version downgrade bug
372
- - **Week 4**: Standardize YAML formatting across all environments
373
- - **Month 2**: Full adoption for all services, integrated into CI/CD
374
- - **Result**: Sync time reduced from 2 hours/week to 10 minutes/week, zero production incidents from sync errors
397
+ - Arrays: Concatenated (child adds to parent)
398
+ - Objects: Deep merged (child overrides parent)
399
+ - Max depth: 5 levels
375
400
 
376
401
  ---
377
402
 
378
- ## Key Features
403
+ ## 🖥️ CLI Reference
379
404
 
380
- ```mermaid
381
- flowchart LR
382
- A[Source Files] --> B[Load & Parse]
383
- B --> C[Apply Transforms]
384
- C --> D[Apply skipPath]
385
- D --> E[Normalize YAML]
386
- E --> F[Deep Comparison]
387
- F --> G[Validate Stop Rules]
388
- G --> H{Violations?}
389
- H -->|Yes| I[Fail or Force]
390
- H -->|No| J[Deep Merge]
391
- J --> K[Apply Output Format]
392
- K --> L[Write Destination]
405
+ ### Commands
406
+
407
+ ```bash
408
+ helm-env-delta --config <file> [options]
409
+ hed --config <file> [options] # Short alias
393
410
  ```
394
411
 
395
- - **Intelligent YAML Diff & Sync**: Deep comparison of YAML content, ignoring formatting differences
396
- - Parses YAML structure instead of comparing text lines
397
- - Normal git diffs show changes when array items are reordered, but HelmEnvDelta's deep analysis recognizes that content is identical
398
- - Detects only meaningful changes (values, keys, structure) while ignoring whitespace, comments, and quote style differences
399
- - Results in cleaner, more accurate diffs that focus on what actually changed
400
- - **Path Filtering (`skipPath`)**: Exclude environment-specific JSON paths from synchronization
401
- - **Transformations (`transforms`)**: Regex-based find/replace for environment-specific values (DB URLs, service names)
402
- - **Stop Rules (`stopRules`)**: Prevent dangerous changes (major version upgrades, scaling violations, forbidden patterns)
403
- - **YAML Output Formatting**: Enforce consistent formatting (key ordering, indentation, value quoting, array sorting)
404
- - **Config Inheritance (`extends`)**: Hierarchical configuration with base + environment-specific overrides
405
- - **Multiple Reporting Formats**: Console diff, HTML report (visual side-by-side), JSON output (CI/CD integration)
406
- - **Prune Mode**: Remove destination files not present in source
407
- - **Dry-Run Preview**: Review all changes before applying them
408
- - **Automatic Update Notifications**: Notifies when newer versions are available on npm (skips in CI/CD environments)
412
+ ### Options
409
413
 
410
- ---
414
+ | Flag | Description |
415
+ | ----------------- | --------------------------------------------- |
416
+ | `--config <path>` | **Required** - Configuration file |
417
+ | `--validate` | Validate config and exit (no file operations) |
418
+ | `--dry-run` | Preview changes without writing files |
419
+ | `--force` | Override stop rules |
420
+ | `--diff` | Show console diff |
421
+ | `--diff-html` | Generate HTML report (opens in browser) |
422
+ | `--diff-json` | Output JSON to stdout (pipe to jq) |
423
+ | `--skip-format` | Skip YAML formatting |
424
+ | `--verbose` | Show detailed debug info |
425
+ | `--quiet` | Suppress output except errors |
411
426
 
412
- ## Installation
427
+ ### Examples
413
428
 
414
429
  ```bash
415
- # Global installation
416
- npm install -g helm-env-delta
417
- ```
430
+ # Validate configuration
431
+ hed --config config.yaml --validate
418
432
 
419
- **Prerequisites:**
433
+ # Preview with diff
434
+ hed --config config.yaml --dry-run --diff
420
435
 
421
- - Node.js >= 22
422
- - npm >= 9
436
+ # Visual HTML report
437
+ hed --config config.yaml --diff-html
423
438
 
424
- **Note:** The tool automatically checks for updates on every run and displays a notification if a newer version is available. This check is skipped in CI/CD environments and fails silently if the npm registry is unreachable.
425
-
426
- ---
439
+ # CI/CD integration
440
+ hed --config config.yaml --diff-json | jq '.summary'
427
441
 
428
- ## Examples
442
+ # Execute sync
443
+ hed --config config.yaml
429
444
 
430
- The repository includes several ready-to-run examples demonstrating common use cases. Each example is self-contained with its own README explaining what it demonstrates and how to run it.
445
+ # Force override stop rules
446
+ hed --config config.yaml --force
447
+ ```
431
448
 
432
- ### Example 1: Config Inheritance
449
+ ---
433
450
 
434
- **Location**: `example/1-config-inheritance/`
451
+ ## 🔄 Typical Workflow
435
452
 
436
- Demonstrates the `extends` pattern for reusing base configuration across multiple environment pairs.
453
+ ```mermaid
454
+ flowchart LR
455
+ A[💾 UAT Files] --> B[⚙️ Config]
456
+ B --> C[🔍 Preview]
457
+ C --> D{✅ Approve?}
458
+ D -->|Yes| E[🚀 Execute]
459
+ D -->|No| F[📝 Adjust]
460
+ F --> C
461
+ E --> G[📁 Prod Updated]
462
+ G --> H[🔄 Git Commit]
463
+ H --> I[🚢 Deploy]
464
+ ```
437
465
 
438
- **What it shows**:
466
+ **Step-by-step:**
439
467
 
440
- - Base configuration with shared settings
441
- - Child configs that extend and override the base
442
- - How arrays (skipPath) are concatenated and objects (outputFormat) are deep merged
443
- - Environment-specific transforms and stop rules
468
+ ```bash
469
+ # 1. Preview changes
470
+ hed --config config.yaml --dry-run --diff
444
471
 
445
- **Quick start**:
472
+ # 2. Review in browser
473
+ hed --config config.yaml --diff-html
446
474
 
447
- ```bash
448
- # Dev → UAT sync
449
- helm-env-delta --config example/1-config-inheritance/config.dev-to-uat.yaml --dry-run --diff
475
+ # 3. Execute sync
476
+ hed --config config.yaml
450
477
 
451
- # UAT Prod sync (with stop rules)
452
- helm-env-delta --config example/1-config-inheritance/config.uat-to-prod.yaml --dry-run --diff
478
+ # 4. Git workflow
479
+ git add prod/
480
+ git commit -m "Sync UAT to Prod"
481
+ git push origin main
453
482
  ```
454
483
 
455
484
  ---
456
485
 
457
- ### Example 2: Stop Rules
458
-
459
- **Location**: `example/2-stop-rules/`
486
+ ## 🏆 Why Choose HelmEnvDelta?
460
487
 
461
- Demonstrates stop rule validation for dangerous changes, how violations are detected, and how to override with --force.
488
+ ### 🆚 Compared to Alternatives
462
489
 
463
- **What it shows**:
490
+ **HelmEnvDelta** is purpose-built for environment synchronization, not template generation or deployment.
464
491
 
465
- - All 5 stop rule types: `semverMajorUpgrade`, `semverDowngrade`, `versionFormat`, `numeric`, `regex`
466
- - How violations block execution by default
467
- - Using `--force` to override violations
468
- - JSON output for CI/CD integration
492
+ | What You Get | vs Helmfile | vs Kustomize | vs Bash Scripts |
493
+ | ------------------------- | ------------- | ------------ | --------------- |
494
+ | 🔍 Structural YAML diff | ✅ Yes | ❌ No | ❌ No |
495
+ | 🎯 Environment-aware sync | Yes | ⚠️ Manual | ⚠️ Custom |
496
+ | 🛡️ Safety validation | ✅ Built-in | ❌ None | ⚠️ DIY |
497
+ | 🔄 Smart merge | ✅ Deep merge | ⚠️ Limited | ⚠️ DIY |
498
+ | 🎨 Format enforcement | ✅ Yes | ❌ No | ❌ No |
499
+ | 📚 Learning curve | 🟢 Low | 🟡 Medium | 🔴 High |
469
500
 
470
- **Quick start**:
501
+ **Complementary:** Use HelmEnvDelta alongside Helm, Helmfile, Kustomize, ArgoCD, or Flux.
471
502
 
472
- ```bash
473
- # See violations in action
474
- helm-env-delta --config example/2-stop-rules/config.yaml --dry-run --diff
503
+ ---
475
504
 
476
- # Try syncing (will fail due to violations)
477
- helm-env-delta --config example/2-stop-rules/config.yaml
505
+ ### 💪 Benefits
478
506
 
479
- # Override with force
480
- helm-env-delta --config example/2-stop-rules/config.yaml --force
481
- ```
507
+ **Safety** - Stop rules prevent dangerous changes. Dry-run previews everything.
482
508
 
483
- ---
509
+ ✅ **Speed** - 30 minutes → 1 minute sync time. Parallel processing.
484
510
 
485
- ### Example 3: Multi-Environment Chain
511
+ **Consistency** - Uniform YAML formatting. No more diff noise.
486
512
 
487
- **Location**: `example/3-multi-env-chain/`
513
+ **Auditability** - Field-level change tracking with JSONPath. Clean structural diffs.
488
514
 
489
- Demonstrates progressive promotion through Dev UAT Prod with cumulative transforms at each stage.
515
+ **Flexibility** - Per-file patterns. Config inheritance. Regex transforms.
490
516
 
491
- **What it shows**:
517
+ **Reliability** - 763 tests, 84% coverage. Battle-tested.
492
518
 
493
- - Multi-stage promotion workflow
494
- - Cumulative transforms across environments
495
- - Environment-specific resources preserved via skipPath
496
- - Stricter validation rules for production
497
- - Shell script automation with interactive prompts
519
+ ---
498
520
 
499
- **Quick start**:
521
+ ## 📊 JSON Output for CI/CD
500
522
 
501
523
  ```bash
502
- # Manual two-stage sync
503
- helm-env-delta --config example/3-multi-env-chain/config.dev-to-uat.yaml --dry-run --diff
504
- helm-env-delta --config example/3-multi-env-chain/config.uat-to-prod.yaml --dry-run --diff
524
+ hed --config config.yaml --diff-json > report.json
525
+ ```
505
526
 
506
- # Or use the automated script
507
- cd example/3-multi-env-chain
508
- chmod +x sync-all.sh
509
- ./sync-all.sh
527
+ **Schema:**
528
+
529
+ ```json
530
+ {
531
+ "metadata": {
532
+ "timestamp": "2025-12-27T10:30:00Z",
533
+ "source": "./uat",
534
+ "destination": "./prod",
535
+ "dryRun": true
536
+ },
537
+ "summary": {
538
+ "added": 2,
539
+ "changed": 3,
540
+ "deleted": 1,
541
+ "unchanged": 15
542
+ },
543
+ "files": {
544
+ "changed": [
545
+ {
546
+ "path": "prod/app.yaml",
547
+ "changes": [
548
+ {
549
+ "path": "$.image.tag",
550
+ "oldValue": "v1.2.3",
551
+ "updatedValue": "v1.3.0"
552
+ }
553
+ ]
554
+ }
555
+ ]
556
+ },
557
+ "stopRuleViolations": [
558
+ {
559
+ "file": "prod/app.yaml",
560
+ "rule": { "type": "semverMajorUpgrade" },
561
+ "message": "Major upgrade: v1.2.3 → v2.0.0"
562
+ }
563
+ ]
564
+ }
510
565
  ```
511
566
 
512
- ---
567
+ **Use with jq:**
568
+
569
+ ```bash
570
+ # Summary
571
+ jq '.summary' report.json
513
572
 
514
- ### Example 4: Prune Mode
573
+ # Violations
574
+ jq '.stopRuleViolations' report.json
515
575
 
516
- **Location**: `example/4-prune-mode/`
576
+ # Changed files
577
+ jq '.files.changed[].path' report.json
578
+ ```
517
579
 
518
- Demonstrates file deletion behavior with `prune: true` vs `prune: false`.
580
+ ---
519
581
 
520
- **What it shows**:
582
+ ## 🔧 Advanced Features
521
583
 
522
- - How `prune: false` (default) keeps extra files in destination
523
- - How `prune: true` deletes files not present in source
524
- - Dry-run safety for previewing deletions
525
- - JSON output to see deleted files
584
+ ### 🧠 Structural Comparison
526
585
 
527
- **Quick start**:
586
+ Git diffs are noisy when arrays are reordered. HelmEnvDelta compares YAML structure and recognizes identical content regardless of order.
528
587
 
529
- ```bash
530
- # Without prune (keeps extra files)
531
- helm-env-delta --config example/4-prune-mode/config.without-prune.yaml --dry-run --diff
588
+ **Example:**
532
589
 
533
- # With prune (deletes extra files)
534
- helm-env-delta --config example/4-prune-mode/config.with-prune.yaml --dry-run --diff
590
+ ```yaml
591
+ # Source
592
+ env:
593
+ - name: DB_URL
594
+ value: uat-db
595
+ - name: LOG_LEVEL
596
+ value: debug
597
+
598
+ # Destination
599
+ env:
600
+ - name: LOG_LEVEL
601
+ value: info
602
+ - name: DB_URL
603
+ value: prod-db
535
604
  ```
536
605
 
606
+ **Git diff:** Shows all lines changed (noisy)
607
+ **HelmEnvDelta:** Only `LOG_LEVEL: debug → info` (clean)
608
+
537
609
  ---
538
610
 
539
- ### Other Examples
611
+ ### 🔀 Deep Merge
540
612
 
541
- **Location**: `example/` (root level files)
613
+ Preserves destination values for skipped paths.
542
614
 
543
- The example directory also contains a simple UAT → Prod sync scenario at the root level demonstrating basic features with minimal configuration.
615
+ ```yaml
616
+ # Source (UAT)
617
+ metadata:
618
+ namespace: uat
619
+ spec:
620
+ replicas: 3
544
621
 
545
- **What it shows**:
622
+ # Config
623
+ skipPath:
624
+ "*.yaml":
625
+ - "metadata.namespace"
626
+ - "spec.replicas"
546
627
 
547
- - Basic Helm values synchronization
548
- - Simple content transforms
549
- - Path filtering with skipPath
550
- - Array sorting in output format
628
+ # Destination (Prod) - preserved after sync!
629
+ metadata:
630
+ namespace: prod # Kept
631
+ spec:
632
+ replicas: 5 # ← Kept
633
+ ```
551
634
 
552
635
  ---
553
636
 
554
- ## Quick Start
637
+ ## 🆘 Common Issues
555
638
 
556
- **1. Create a configuration file (`config.yaml`):**
639
+ ### Stop rule violations blocking sync
557
640
 
558
- ```yaml
559
- source: './uat'
560
- destination: './prod'
641
+ **Error:** `🛑 Stop Rule Violation (semverMajorUpgrade)`
561
642
 
562
- # Skip environment-specific fields
563
- skipPath:
564
- '**/*.yaml':
565
- - 'metadata.namespace'
566
- - 'spec.destination.namespace'
567
-
568
- # Transform environment names
569
- transforms:
570
- '**/*.yaml':
571
- content:
572
- - find: "-uat\\b"
573
- replace: '-prod'
574
- ```
575
-
576
- **2. Run dry-run to preview changes:**
577
-
578
- ```bash
579
- helm-env-delta --config config.yaml --dry-run --diff
580
- ```
581
-
582
- **3. Execute the sync:**
583
-
584
- ```bash
585
- helm-env-delta --config config.yaml
586
- ```
587
-
588
- ---
589
-
590
- ## Use Cases
591
-
592
- ### 1. Multi-Environment Promotion (UAT → Production)
593
-
594
- ```mermaid
595
- flowchart TD
596
- A[UAT Environment] --> B[helm-env-delta --dry-run]
597
- B --> C{Review Changes}
598
- C -->|Approve| D[helm-env-delta sync]
599
- C -->|Reject| E[Adjust Config]
600
- E --> B
601
- D --> F[Production Files Updated]
602
- F --> G[Git Commit & Push]
603
- G --> H[ArgoCD Auto-Sync]
604
- H --> I[Production Deployed]
605
- ```
606
-
607
- Safely promote tested configurations from UAT to Production while preserving production-specific settings.
608
-
609
- ### 2. Helm Values Management
610
-
611
- Synchronize Helm values files across environments while maintaining environment-specific overrides:
612
-
613
- - Database connection strings
614
- - Replica counts
615
- - Resource limits
616
- - Feature flags
617
-
618
- ### 3. Kubernetes Configuration
619
-
620
- - **ArgoCD Applications**: Sync application manifests while preserving destination namespaces
621
- - **Service Mesh Configs**: Istio, Linkerd configurations with environment-specific routing
622
- - **Custom Resources**: CRDs with environment-specific parameters
623
-
624
- ### 4. Configuration Standardization
625
-
626
- - Enforce consistent YAML formatting across all environments
627
- - Apply naming convention transformations
628
- - Standardize key ordering for better readability
629
-
630
- ### 5. CI/CD Integration
631
-
632
- ```bash
633
- # Pipeline validation step
634
- helm-env-delta --config config.yaml --dry-run --diff-json | jq '.summary'
635
-
636
- # Check for violations
637
- helm-env-delta --config config.yaml --diff-json | jq '.stopRuleViolations | length'
638
- ```
639
-
640
- Integrate with CI/CD pipelines for pre-deployment validation and automated reporting.
641
-
642
- ---
643
-
644
- ## Configuration Guide
645
-
646
- ### Core Settings
647
-
648
- ```yaml
649
- # Required for final config
650
- source: './uat' # Source folder path
651
- destination: './prod' # Destination folder path
652
-
653
- # File selection (optional)
654
- include: # Patterns to include (default: all files)
655
- - '**/*.yaml'
656
- - '**/README.md'
657
- exclude: # Patterns to exclude (default: none)
658
- - '**/skip*.yaml'
659
-
660
- # Pruning (optional)
661
- prune: false # Remove dest files not in source (default: false)
662
- ```
663
-
664
- **Notes:**
665
-
666
- - `source` and `destination` are mandatory in the final config (can be omitted in base configs)
667
- - `include`/`exclude` use glob patterns (`**` = recursive, `*` = wildcard)
668
- - `prune: true` will delete files in destination that don't exist in source
669
-
670
- ---
671
-
672
- ### Path Filtering (skipPath)
673
-
674
- Skip specific JSON paths during synchronization to preserve environment-specific values.
675
-
676
- ```yaml
677
- skipPath:
678
- # Pattern: file glob
679
- 'apps/*.yaml':
680
- - 'apiVersion' # Top-level field
681
- - 'spec.destination.namespace' # Nested field
682
- - 'spec.ignoreDifferences[*].jsonPointers' # Array wildcards
683
-
684
- 'svc/**/Chart.yaml':
685
- - 'annotations.createdAt'
686
- - 'annotations.lastModified'
687
-
688
- 'svc/**/values.yaml':
689
- - 'microservice.env[*].value' # All array items
690
- ```
691
-
692
- **JSON Path Syntax:**
693
-
694
- - Use dot notation: `spec.destination.namespace`
695
- - Array wildcards: `env[*].name` matches all items
696
- - Nested arrays: `spec.items[*].subitems[*].value`
697
-
698
- **When to use `skipPath`:**
699
-
700
- - Environment-specific namespaces
701
- - Timestamps and auto-generated metadata
702
- - Environment-specific secrets references
703
- - Scaling parameters that differ per environment
704
-
705
- ---
706
-
707
- ### Transformations (transforms)
708
-
709
- Regex-based find/replace for both YAML content and file paths.
710
-
711
- ```yaml
712
- transforms:
713
- 'svc/**/values.yaml':
714
- content: # Transforms YAML values (not keys)
715
- - find: "uat-db\\.(.+)\\.internal" # Regex with escaped dots
716
- replace: 'prod-db.$1.internal' # Capture group $1
717
- - find: 'uat-redis'
718
- replace: 'prod-redis'
719
-
720
- 'apps/*.yaml':
721
- content: # Transforms YAML values
722
- - find: "-uat\\b" # Word boundary suffix
723
- replace: '-prod'
724
- - find: "\\buat/" # Prefix with slash
725
- replace: 'prod/'
726
-
727
- '**/*.yaml':
728
- filename: # Transforms file paths (full relative path)
729
- - find: 'envs/uat/'
730
- replace: 'envs/prod/'
731
- - find: '-uat\.'
732
- replace: '-prod.'
733
- ```
734
-
735
- **Configuration Structure:**
736
-
737
- Each file pattern can have:
738
-
739
- - `content`: Transforms YAML values (preserves keys)
740
- - `filename`: Transforms file paths (folders + filename)
741
- - At least one of `content` or `filename` must be specified
742
-
743
- **Features:**
744
-
745
- - **Regex Support**: Full regex patterns with escaping
746
- - **Capture Groups**: Use `$1`, `$2`, etc. for captured values
747
- - **Sequential Application**: Rules apply in order (first rule's output becomes input for second)
748
- - **Content Scope**: Transforms ALL string values in matched files, not just specific paths
749
- - **Filename Scope**: Transforms full relative path (e.g., `envs/uat/app.yaml` → `envs/prod/app.yaml`)
750
-
751
- **Common Use Cases:**
752
-
753
- - **Content transforms:**
754
- - Database URLs: `uat-db.example.internal` → `prod-db.example.internal`
755
- - Service names: `my-service-uat` → `my-service-prod`
756
- - Domain names: `uat.example.com` → `prod.example.com`
757
- - Environment prefixes/suffixes in any string field
758
-
759
- - **Filename transforms:**
760
- - Environment folders: `envs/uat/app.yaml` → `envs/prod/app.yaml`
761
- - Environment suffixes: `app-uat.yaml` → `app-prod.yaml`
762
- - Combined: `config/uat/service-uat.yaml` → `config/prod/service-prod.yaml`
763
-
764
- ---
765
-
766
- ### Stop Rules (stopRules)
767
-
768
- Validation rules that prevent dangerous changes from being applied.
769
-
770
- #### Rule Types
771
-
772
- | Rule Type | Purpose | Example Use Case |
773
- | -------------------- | ----------------------------- | ----------------------------------------- |
774
- | `semverMajorUpgrade` | Block major version increases | Prevent `v1.x.x` → `v2.0.0` |
775
- | `semverDowngrade` | Block any version downgrades | Prevent `v1.3.2` → `v1.2.4` |
776
- | `versionFormat` | Enforce strict version format | Reject `1.2`, `1.2.3-rc`, require `1.2.3` |
777
- | `numeric` | Validate numeric ranges | Ensure `replicaCount` between 2-10 |
778
- | `regex` | Block pattern matches | Reject production URLs in staging |
779
-
780
- #### Configuration Examples
781
-
782
- ```yaml
783
- stopRules:
784
- 'apps/*.yaml':
785
- - type: 'semverMajorUpgrade'
786
- path: 'spec.source.targetRevision'
787
- # Blocks: v1.2.3 → v2.0.0
788
-
789
- 'svc/**/Chart.yaml':
790
- - type: 'semverDowngrade'
791
- path: 'version'
792
- # Blocks: v2.0.0 → v1.0.0 (major), v1.3.2 → v1.2.4 (minor), v1.2.5 → v1.2.3 (patch)
793
-
794
- - type: 'versionFormat'
795
- path: 'version'
796
- vPrefix: 'forbidden'
797
- # Blocks: 1.2 (incomplete), 1.2.3-rc (pre-release), v1.2.3 (has v-prefix)
798
- # Accepts: 1.2.3 (strict major.minor.patch format)
799
-
800
- 'svc/**/values.yaml':
801
- - type: 'numeric'
802
- path: 'replicaCount'
803
- min: 2
804
- max: 10
805
- # Blocks: values < 2 or > 10
806
-
807
- - type: 'regex'
808
- path: 'image.tag'
809
- regex: "^v0\\."
810
- # Blocks: any tag starting with "v0."
811
-
812
- - type: 'versionFormat'
813
- path: 'image.tag'
814
- vPrefix: 'required'
815
- # Blocks: 1.2.3 (missing v-prefix), 1.2 (incomplete), v1.2.3-alpha (pre-release)
816
- # Accepts: v1.2.3 (requires v-prefix)
817
- ```
818
-
819
- **Overriding Stop Rules:**
820
-
821
- Use `--force` flag to override stop rules when intentional dangerous changes are needed:
822
-
823
- ```bash
824
- helm-env-delta --config config.yaml --force
825
- ```
826
-
827
- ---
828
-
829
- ### Output Formatting (outputFormat)
830
-
831
- Enforce consistent YAML formatting across all output files.
832
-
833
- ```yaml
834
- outputFormat:
835
- # Indentation
836
- indent: 2 # YAML indent size (default: 2)
837
-
838
- # Key separator
839
- keySeparator: true # Blank line between top-level keys (default: false)
840
-
841
- # Value quoting
842
- quoteValues:
843
- 'svc/**/values.yaml':
844
- - 'microservice.env[*].value' # Quote environment variable values
845
-
846
- # Custom key ordering (hierarchical JSONPath)
847
- keyOrders:
848
- 'apps/*.yaml':
849
- - 'apiVersion'
850
- - 'kind'
851
- - 'metadata.namespace'
852
- - 'metadata.name'
853
- - 'spec.project'
854
- - 'spec.source'
855
- - 'spec.destination'
856
-
857
- 'svc/**/Chart.yaml':
858
- - 'apiVersion'
859
- - 'name'
860
- - 'description'
861
- - 'version'
862
- - 'dependencies'
863
-
864
- # Array sorting
865
- arraySort:
866
- 'svc/**/values.yaml':
867
- - path: 'microservice.env'
868
- sortBy: 'name'
869
- order: 'asc' # or "desc"
870
- ```
871
-
872
- **Benefits:**
873
-
874
- - **Consistent Formatting**: Same YAML structure across all environments
875
- - **Better Diffs**: Format changes don't show up as content changes
876
- - **Readability**: Logical key ordering makes files easier to understand
877
- - **Safety**: Value quoting protects special characters
878
- - **VSCode Compatible**: Output includes trailing newlines and preserves multi-line strings to match VSCode formatting, preventing unnecessary git diffs
879
-
880
- ---
881
-
882
- ### Config Inheritance (extends)
883
-
884
- Hierarchical configuration with base + environment-specific overrides.
885
-
886
- ```mermaid
887
- flowchart TD
888
- A[base.yaml] --> B[uat.yaml extends base]
889
- A --> C[prod.yaml extends base]
890
- B --> D[Arrays Concatenated]
891
- B --> E[Objects Deep Merged]
892
- C --> D
893
- C --> E
894
- ```
895
-
896
- #### Base Configuration (`config.base.yaml`)
897
-
898
- ```yaml
899
- # Partial config (source/dest optional in base)
900
- include:
901
- - '**/*.yaml'
902
- exclude:
903
- - '**/skip*.yaml'
904
- prune: true
905
-
906
- skipPath:
907
- 'apps/*.yaml':
908
- - 'spec.destination.namespace'
909
-
910
- outputFormat:
911
- indent: 2
912
- keySeparator: true
913
- ```
914
-
915
- #### Environment-Specific Config (`config.prod.yaml`)
916
-
917
- ```yaml
918
- extends: './config.base.yaml'
919
-
920
- # Required in final config
921
- source: './uat'
922
- destination: './prod'
923
-
924
- # Additional includes (concatenated with base)
925
- include:
926
- - 'config/*'
927
-
928
- # Additional skipPath rules (merged with base)
929
- skipPath:
930
- 'apps/*.yaml': # Adds to base rule
931
- - 'metadata.annotations'
932
- 'svc/*.yaml': # New pattern
933
- - 'spec.env[*].value'
934
-
935
- # Environment-specific transforms
936
- transforms:
937
- '**/*.yaml':
938
- content:
939
- - find: "-uat\\b"
940
- replace: '-prod'
941
- ```
942
-
943
- **Merging Rules:**
944
-
945
- - **Arrays**: Concatenated (child adds to parent)
946
- - **Objects**: Deep merged (child overrides parent)
947
- - **Per-file rules**: Merged (child adds/overrides parent patterns)
948
- - **Max depth**: 5 levels of nesting
949
- - **Circular dependencies**: Detected and rejected
950
-
951
- ---
952
-
953
- ## CLI Usage
954
-
955
- ### Command Syntax
956
-
957
- ```bash
958
- helm-env-delta --config <file> [options]
959
-
960
- # Short alias
961
- hed --config <file> [options]
962
- ```
963
-
964
- ### Options
965
-
966
- | Option | Short | Description | Default |
967
- | ----------------- | ----- | ---------------------------------------------------------- | ------------ |
968
- | `--config <path>` | `-c` | Path to YAML configuration file | **required** |
969
- | `--validate` | | Validate configuration file and exit | `false` |
970
- | `--dry-run` | | Preview changes without writing files | `false` |
971
- | `--force` | | Override stop rules and proceed | `false` |
972
- | `--diff` | | Display console diff for changed files | `false` |
973
- | `--diff-html` | | Generate HTML report and open in browser | `false` |
974
- | `--diff-json` | | Output diff as JSON to stdout | `false` |
975
- | `--skip-format` | | Skip YAML formatting (outputFormat section) | `false` |
976
- | `--verbose` | | Show detailed debug information (config, transforms, etc.) | `false` |
977
- | `--quiet` | | Suppress all output except critical errors | `false` |
978
- | `--help` | `-h` | Display help | |
979
-
980
- **Note:** `--verbose` and `--quiet` are mutually exclusive. Machine-readable output (`--diff-json`) always outputs regardless of verbosity.
981
-
982
- ### Examples
983
-
984
- ```bash
985
- # Validate configuration file
986
- helm-env-delta --config config.yaml --validate
987
-
988
- # Basic sync
989
- helm-env-delta --config config.yaml
990
-
991
- # Dry-run with console diff
992
- helm-env-delta --config config.yaml --dry-run --diff
993
-
994
- # Generate HTML report
995
- helm-env-delta --config config.yaml --diff-html
996
-
997
- # JSON output for CI/CD
998
- helm-env-delta --config config.yaml --diff-json | jq '.summary'
999
-
1000
- # Combine multiple diff formats
1001
- helm-env-delta --config config.yaml --diff --diff-html --diff-json
1002
-
1003
- # Override stop rules (use with caution)
1004
- helm-env-delta --config config.yaml --force
1005
-
1006
- # Pipe JSON to jq for filtering
1007
- helm-env-delta --config config.yaml --diff-json | jq '.files.changed[0].changes'
1008
- ```
1009
-
1010
- ---
1011
-
1012
- ## Complete Workflow Example
1013
-
1014
- ### Step 1: Create Configuration
1015
-
1016
- ```yaml
1017
- # config.yaml
1018
- source: './helm/uat'
1019
- destination: './helm/prod'
1020
-
1021
- include:
1022
- - 'apps/**/*.yaml'
1023
- - 'services/**/*.yaml'
1024
-
1025
- skipPath:
1026
- 'apps/*.yaml':
1027
- - 'spec.destination.namespace'
1028
- - 'metadata.annotations[kubernetes.io/last-applied-at]'
1029
-
1030
- transforms:
1031
- 'services/**/values.yaml':
1032
- content:
1033
- - find: "uat-database\\.(.+)\\.internal"
1034
- replace: 'prod-database.$1.internal'
1035
- - find: "\\.uat\\."
1036
- replace: '.prod.'
1037
-
1038
- stopRules:
1039
- 'services/**/values.yaml':
1040
- - type: 'semverMajorUpgrade'
1041
- path: 'image.tag'
1042
- - type: 'numeric'
1043
- path: 'replicaCount'
1044
- min: 3
1045
- max: 20
1046
-
1047
- outputFormat:
1048
- indent: 2
1049
- keySeparator: true
1050
- keyOrders:
1051
- 'apps/*.yaml':
1052
- - 'apiVersion'
1053
- - 'kind'
1054
- - 'metadata'
1055
- - 'spec'
1056
- ```
1057
-
1058
- ### Step 2: Dry-Run with Diff
1059
-
1060
- ```bash
1061
- helm-env-delta --config config.yaml --dry-run --diff
1062
- ```
1063
-
1064
- **Output:**
1065
-
1066
- ```
1067
- Configuration loaded: ./helm/uat -> ./helm/prod
1068
-
1069
- ⏳ Loading files...
1070
- ✓ Loaded 15 source file(s)
1071
- ✓ Loaded 15 destination file(s)
1072
-
1073
- ℹ Computing differences...
1074
- New files: 2
1075
- Deleted files: 0
1076
- Changed files: 5
1077
- Unchanged files: 8
1078
-
1079
- --- apps/my-app.yaml
1080
- +++ apps/my-app.yaml
1081
- @@ -12,7 +12,7 @@
1082
- - targetRevision: v1.5.0
1083
- + targetRevision: v1.6.0
1084
- ```
1085
-
1086
- ### Step 3: Review HTML Report
1087
-
1088
- ```bash
1089
- helm-env-delta --config config.yaml --diff-html
1090
- ```
1091
-
1092
- Opens browser with visual side-by-side diff report.
1093
-
1094
- ### Step 4: Execute Sync
1095
-
1096
- ```bash
1097
- helm-env-delta --config config.yaml
1098
- ```
1099
-
1100
- **Output:**
1101
-
1102
- ```
1103
- ✓ Files updated successfully:
1104
- 2 files added
1105
- 5 files updated
1106
- 0 files formatted
1107
- 0 files deleted
1108
- ```
1109
-
1110
- ### Step 5: Commit and Deploy
1111
-
1112
- ```bash
1113
- git add helm/prod
1114
- git commit -m "Sync UAT changes to prod"
1115
- git push origin main
1116
- ```
1117
-
1118
- ---
1119
-
1120
- ## Advanced Features
1121
-
1122
- ### Structural YAML Comparison
1123
-
1124
- HelmEnvDelta compares YAML by parsing and analyzing structure, not by comparing text lines. This provides much cleaner diffs than traditional git comparison.
1125
-
1126
- **Example: Array Reordering**
1127
-
1128
- Git diff would show many changes when array items are reordered, but HelmEnvDelta recognizes the content is identical:
1129
-
1130
- ```yaml
1131
- # Source (UAT)
1132
- env:
1133
- - name: DATABASE_URL
1134
- value: uat-db.internal
1135
- - name: CACHE_URL
1136
- value: uat-redis.internal
1137
- - name: LOG_LEVEL
1138
- value: debug
1139
-
1140
- # Destination (Prod)
1141
- env:
1142
- - name: LOG_LEVEL
1143
- value: info
1144
- - name: DATABASE_URL
1145
- value: prod-db.internal
1146
- - name: CACHE_URL
1147
- value: prod-redis.internal
1148
- ```
1149
-
1150
- **Git diff output (noisy):**
1151
-
1152
- - Shows all lines as changed due to reordering
1153
- - Difficult to identify actual value differences
1154
-
1155
- **HelmEnvDelta output (clean):**
1156
-
1157
- - Recognizes array items are the same (after transforms)
1158
- - Only shows actual value changes: `LOG_LEVEL: debug → info`
1159
- - Ignores reordering, focusing on meaningful differences
1160
-
1161
- This structural comparison is especially valuable for:
1162
-
1163
- - YAML files with arrays that may be sorted differently
1164
- - Files reformatted by different tools
1165
- - Configurations where order doesn't matter semantically
1166
-
1167
- ### Deep YAML Merge
1168
-
1169
- HelmEnvDelta uses intelligent deep merging to preserve destination values:
1170
-
1171
- 1. Source content is processed (transforms + skipPath applied)
1172
- 2. Destination is read in full (including skipped paths)
1173
- 3. Processed source is deep-merged into destination
1174
- 4. Result: Destination keeps values for skipped paths
1175
-
1176
- **Example:**
1177
-
1178
- ```yaml
1179
- # Source (UAT)
1180
- metadata:
1181
- namespace: uat
1182
- spec:
1183
- replicas: 3
1184
-
1185
- # Destination (Prod) before sync
1186
- metadata:
1187
- namespace: prod
1188
- spec:
1189
- replicas: 5
1190
-
1191
- # Config
1192
- skipPath:
1193
- "*.yaml":
1194
- - "metadata.namespace"
1195
- - "spec.replicas"
1196
-
1197
- # Destination after sync (preserved!)
1198
- metadata:
1199
- namespace: prod # ← Preserved
1200
- spec:
1201
- replicas: 5 # ← Preserved
1202
- ```
1203
-
1204
- ### Multiple Diff Formats
1205
-
1206
- Combine diff formats for comprehensive review:
1207
-
1208
- ```bash
1209
- # Console + JSON
1210
- helm-env-delta --config config.yaml --diff --diff-json > report.json
1211
-
1212
- # All three formats
1213
- helm-env-delta --config config.yaml --diff --diff-html --diff-json
1214
- ```
1215
-
1216
- **Piping JSON to jq:**
1217
-
1218
- ```bash
1219
- # Summary only
1220
- helm-env-delta --config config.yaml --diff-json | jq '.summary'
1221
-
1222
- # Stop rule violations
1223
- helm-env-delta --config config.yaml --diff-json | jq '.stopRuleViolations'
1224
-
1225
- # Changed files only
1226
- helm-env-delta --config config.yaml --diff-json | jq '.files.changed[].path'
1227
-
1228
- # Field-level changes
1229
- helm-env-delta --config config.yaml --diff-json | jq '.files.changed[0].changes'
1230
- ```
1231
-
1232
- ### Prune Mode
1233
-
1234
- Remove files in destination that don't exist in source:
1235
-
1236
- ```yaml
1237
- prune: true
1238
- ```
1239
-
1240
- **Safety Considerations:**
1241
-
1242
- - Use with caution in production environments
1243
- - Always run `--dry-run` first to review deletions
1244
- - Consider using version control for rollback capability
1245
-
1246
- ```bash
1247
- # Preview what will be deleted
1248
- helm-env-delta --config config.yaml --dry-run --diff
1249
-
1250
- # Check deleted files
1251
- helm-env-delta --config config.yaml --diff-json | jq '.files.deleted'
1252
- ```
1253
-
1254
- ---
1255
-
1256
- ## Advantages & Benefits
1257
-
1258
- ### Safety
1259
-
1260
- - **Stop Rules**: Prevent dangerous changes (version upgrades, scaling violations) before deployment
1261
- - **Dry-Run Mode**: Preview all changes before applying them
1262
- - **Validation**: Type-safe configuration with helpful error messages
1263
-
1264
- ### Consistency
1265
-
1266
- - **YAML Formatting**: Enforce uniform formatting across all environments
1267
- - **Key Ordering**: Logical structure for better readability
1268
- - **Value Quoting**: Protect special characters automatically
1269
-
1270
- ### Efficiency
1271
-
1272
- - **Automated Sync**: Save hours of manual file copying and editing
1273
- - **Parallel Processing**: Fast file loading and comparison
1274
- - **Batch Operations**: Sync multiple files at once
1275
-
1276
- ### Auditability
1277
-
1278
- - **Clear Diff Reports**: See exactly what changed and why
1279
- - **Structural Comparison**: Unlike git diffs that show line changes, HelmEnvDelta compares YAML structure, ignoring reordered arrays and formatting noise
1280
- - **Multiple Formats**: Console, HTML, JSON for different review needs
1281
- - **Field-Level Detection**: Track changes at individual field level with JSONPath notation
1282
-
1283
- ### Flexibility
1284
-
1285
- - **Highly Configurable**: Per-file patterns for skipPath, transforms, stopRules
1286
- - **Config Inheritance**: Reuse base configs across environments
1287
- - **Regex Transforms**: Powerful pattern-based replacements
1288
-
1289
- ### Integration
1290
-
1291
- - **JSON Output**: Seamless CI/CD pipeline integration
1292
- - **Exit Codes**: Non-zero exit on stop rule violations
1293
- - **Pipeable**: Works with jq, grep, and other CLI tools
1294
-
1295
- ### Reliability
1296
-
1297
- - **84%+ Test Coverage**: 763 comprehensive tests across 28 test files ensure stability
1298
- - **Error Handling**: Clear, actionable error messages
1299
- - **Binary File Detection**: Safely handle non-text files
1300
-
1301
- ### Performance
1302
-
1303
- - **Parallel I/O**: Fast file loading with concurrent operations
1304
- - **Efficient Glob**: Optimized pattern matching with tinyglobby
1305
- - **Memory Efficient**: Streams large files when possible
1306
-
1307
- ### Developer Experience
1308
-
1309
- - **Type-Safe Config**: Zod schema validation with inference
1310
- - **Helpful Errors**: Contextual error messages with hints
1311
- - **Short Alias**: Use `hed` for faster typing
1312
-
1313
- ---
1314
-
1315
- ## Real-World Configuration Examples
1316
-
1317
- ### Basic: Simple UAT → Prod Sync
1318
-
1319
- ```yaml
1320
- # config.yaml
1321
- source: './uat'
1322
- destination: './prod'
1323
-
1324
- skipPath:
1325
- '**/*.yaml':
1326
- - 'metadata.namespace'
1327
-
1328
- transforms:
1329
- '**/*.yaml':
1330
- content:
1331
- - find: "-uat\\b"
1332
- replace: '-prod'
1333
- ```
1334
-
1335
- ### Intermediate: With Stop Rules
1336
-
1337
- ```yaml
1338
- # config.yaml
1339
- source: './helm/uat'
1340
- destination: './helm/prod'
1341
-
1342
- include:
1343
- - 'apps/**/*.yaml'
1344
- - 'svc/**/*.yaml'
1345
-
1346
- skipPath:
1347
- 'apps/*.yaml':
1348
- - 'spec.destination.namespace'
1349
- - 'spec.ignoreDifferences[*].jsonPointers'
1350
-
1351
- 'svc/**/values.yaml':
1352
- - 'microservice.env[*].value'
1353
-
1354
- transforms:
1355
- 'svc/**/values.yaml':
1356
- content:
1357
- - find: "uat-db\\.(.+)\\.internal"
1358
- replace: 'prod-db.$1.internal'
1359
-
1360
- stopRules:
1361
- 'svc/**/values.yaml':
1362
- - type: 'semverMajorUpgrade'
1363
- path: 'image.tag'
1364
- - type: 'numeric'
1365
- path: 'replicaCount'
1366
- min: 2
1367
- max: 10
1368
-
1369
- outputFormat:
1370
- indent: 2
1371
- keySeparator: true
1372
- ```
1373
-
1374
- ### Advanced: Config Inheritance
1375
-
1376
- **Base Config (`config.base.yaml`):**
1377
-
1378
- ```yaml
1379
- include:
1380
- - 'apps/**/*.yaml'
1381
- - 'svc/**/*.yaml'
1382
- exclude:
1383
- - '**/test*.yaml'
1384
- prune: true
1385
-
1386
- skipPath:
1387
- 'apps/*.yaml':
1388
- - 'spec.destination.namespace'
1389
-
1390
- outputFormat:
1391
- indent: 2
1392
- keySeparator: true
1393
- keyOrders:
1394
- 'apps/*.yaml':
1395
- - 'apiVersion'
1396
- - 'kind'
1397
- - 'metadata'
1398
- - 'spec'
1399
- ```
1400
-
1401
- **Production Config (`config.prod.yaml`):**
1402
-
1403
- ```yaml
1404
- extends: './config.base.yaml'
1405
-
1406
- source: './helm/uat'
1407
- destination: './helm/prod'
1408
-
1409
- transforms:
1410
- '**/*.yaml':
1411
- content:
1412
- - find: "-uat\\b"
1413
- replace: '-prod'
1414
- - find: "\\.uat\\."
1415
- replace: '.prod.'
1416
-
1417
- stopRules:
1418
- 'svc/**/values.yaml':
1419
- - type: 'semverMajorUpgrade'
1420
- path: 'image.tag'
1421
- - type: 'numeric'
1422
- path: 'replicaCount'
1423
- min: 3
1424
- max: 20
1425
- ```
1426
-
1427
- ### CI/CD Integration
1428
-
1429
- **GitHub Actions Workflow:**
1430
-
1431
- ```yaml
1432
- name: Sync UAT to Prod
1433
-
1434
- on:
1435
- workflow_dispatch:
1436
- push:
1437
- branches: [main]
1438
-
1439
- jobs:
1440
- sync:
1441
- runs-on: ubuntu-latest
1442
- steps:
1443
- - uses: actions/checkout@v3
1444
-
1445
- - uses: actions/setup-node@v3
1446
- with:
1447
- node-version: '22'
1448
-
1449
- - name: Install helm-env-delta
1450
- run: npm install -g helm-env-delta
1451
-
1452
- - name: Dry-run sync
1453
- run: |
1454
- helm-env-delta --config config.yaml --dry-run --diff-json > report.json
1455
- cat report.json | jq '.summary'
1456
-
1457
- - name: Check stop rule violations
1458
- run: |
1459
- VIOLATIONS=$(cat report.json | jq '.stopRuleViolations | length')
1460
- if [ "$VIOLATIONS" -gt 0 ]; then
1461
- echo "Stop rule violations detected!"
1462
- cat report.json | jq '.stopRuleViolations'
1463
- exit 1
1464
- fi
1465
-
1466
- - name: Execute sync
1467
- run: helm-env-delta --config config.yaml
1468
-
1469
- - name: Commit changes
1470
- run: |
1471
- git config user.name "GitHub Actions"
1472
- git config user.email "actions@github.com"
1473
- git add helm/prod
1474
- git commit -m "Sync UAT to Prod" || echo "No changes"
1475
- git push
1476
- ```
643
+ **Fix:** Review change carefully. Use `--force` if intentional.
1477
644
 
1478
645
  ---
1479
646
 
1480
- ## JSON Output Schema
1481
-
1482
- When using `--diff-json`, the tool outputs structured JSON to stdout:
1483
-
1484
- ```json
1485
- {
1486
- "metadata": {
1487
- "timestamp": "2025-12-18T10:30:00.000Z",
1488
- "source": "./uat",
1489
- "destination": "./prod",
1490
- "dryRun": true,
1491
- "version": "0.0.1"
1492
- },
1493
- "summary": {
1494
- "added": 2,
1495
- "deleted": 1,
1496
- "changed": 3,
1497
- "formatted": 5,
1498
- "unchanged": 15
1499
- },
1500
- "files": {
1501
- "added": ["prod/new-service.yaml"],
1502
- "deleted": ["prod/old-service.yaml"],
1503
- "changed": [
1504
- {
1505
- "path": "prod/app-values.yaml",
1506
- "diff": "unified diff string...",
1507
- "changes": [
1508
- {
1509
- "path": "$.image.tag",
1510
- "oldValue": "v1.2.3",
1511
- "updatedValue": "v1.3.0"
1512
- },
1513
- {
1514
- "path": "$.replicaCount",
1515
- "oldValue": 2,
1516
- "updatedValue": 3
1517
- }
1518
- ]
1519
- }
1520
- ],
1521
- "formatted": ["prod/config.yaml"],
1522
- "unchanged": ["prod/service.yaml"]
1523
- },
1524
- "stopRuleViolations": [
1525
- {
1526
- "file": "prod/app-values.yaml",
1527
- "rule": {
1528
- "type": "semverMajorUpgrade",
1529
- "path": "image.tag"
1530
- },
1531
- "path": "image.tag",
1532
- "oldValue": "v1.2.3",
1533
- "updatedValue": "v2.0.0",
1534
- "message": "Major version upgrade detected: v1.2.3 → v2.0.0"
1535
- }
1536
- ]
1537
- }
1538
- ```
647
+ ### Transforms not applying
1539
648
 
1540
- **Field Descriptions:**
649
+ **Check:**
1541
650
 
1542
- - `metadata`: Execution context (timestamp, paths, dry-run status, version)
1543
- - `summary`: Counts for each file category
1544
- - `files.changed[].changes`: Field-level changes with JSONPath notation
1545
- - `stopRuleViolations`: All validation failures with context
651
+ - File pattern: `**/*.yaml` vs `*.yaml`
652
+ - Regex escaping: `\\.` for literal dots
653
+ - Word boundaries: `\\b`
1546
654
 
1547
655
  ---
1548
656
 
1549
- ## Migration Guide
1550
-
1551
- ### Transform Configuration Format
1552
-
1553
- The `transforms` configuration structure supports both content and filename transformations.
1554
-
1555
- **Transform Structure:**
1556
-
1557
- ```yaml
1558
- transforms:
1559
- '**/*.yaml':
1560
- content: # Transforms YAML values
1561
- - find: '-uat'
1562
- replace: '-prod'
1563
- - find: 'uat-db'
1564
- replace: 'prod-db'
1565
- ```
1566
-
1567
- **Features:**
1568
-
1569
- The transform format enables:
1570
-
1571
- 1. **Content transformations**: Transform YAML values while preserving keys
1572
- 2. **Filename transformations**: Transform file paths including folder structures
1573
- 3. **Clear separation**: Explicit distinction between content and filename transforms
1574
-
1575
- **Configuration Examples:**
1576
-
1577
- Basic content transform:
1578
-
1579
- ```yaml
1580
- transforms:
1581
- 'pattern':
1582
- content:
1583
- - find: '...'
1584
- replace: '...'
1585
- ```
1586
-
1587
- Filename transform:
1588
-
1589
- ```yaml
1590
- transforms:
1591
- '**/*.yaml':
1592
- filename: # Transform file paths
1593
- - find: 'envs/uat/'
1594
- replace: 'envs/prod/'
1595
- ```
1596
-
1597
- Combining both:
657
+ ### JSONPath syntax errors
1598
658
 
1599
659
  ```yaml
1600
- transforms:
1601
- '**/*.yaml':
1602
- content:
1603
- - find: 'uat-'
1604
- replace: 'prod-'
1605
- filename:
1606
- - find: 'envs/uat/'
1607
- replace: 'envs/prod/'
1608
- ```
1609
-
1610
- **Advanced Features:**
1611
-
1612
- - **Transform file paths**: Change folder structures and filenames
1613
-
1614
- ```yaml
1615
- transforms:
1616
- '**/*.yaml':
1617
- filename:
1618
- - find: '/staging/'
1619
- replace: '/production/'
1620
- - find: '-stg\.'
1621
- replace: '-prod.'
1622
- ```
1623
-
1624
- - **Use capture groups in paths**:
1625
- ```yaml
1626
- transforms:
1627
- '**/*.yaml':
1628
- filename:
1629
- - find: 'config/(uat)/(.+)\.yaml'
1630
- replace: 'config/prod/$2.yaml'
1631
- ```
1632
-
1633
- **Collision Detection:**
1634
-
1635
- The tool automatically detects when multiple source files would transform to the same destination filename, preventing accidental overwrites.
1636
-
1637
- **Testing:**
1638
-
1639
- Always test your transform configuration with dry-run:
1640
-
1641
- ```bash
1642
- helm-env-delta --config config.yaml --dry-run --diff
1643
- ```
1644
-
1645
- ---
1646
-
1647
- ## Troubleshooting
1648
-
1649
- ### Config Validation Errors
1650
-
1651
- **Error: "source is required"**
1652
-
1653
- ```
1654
- Config Validation Error: source is required
1655
- File: config.yaml
1656
- ```
1657
-
1658
- **Solution:** Add `source` field to your config (or use `extends` from a base config).
1659
-
1660
- ---
1661
-
1662
- **Error: "Invalid JSON path syntax"**
660
+ # ❌ Wrong
661
+ - '$.spec.replicas' # Don't use $. prefix
662
+ - 'env.*.name' # Use [*] not .*
1663
663
 
664
+ # ✅ Correct
665
+ - 'spec.replicas' # No prefix
666
+ - 'env[*].name' # Array wildcard
1664
667
  ```
1665
- Config Validation Error: skipPath pattern 'apps/*.yaml' contains invalid path
1666
- ```
1667
-
1668
- **Solution:** Check JSON path syntax:
1669
-
1670
- - Use dot notation: `spec.replicas` not `spec/replicas`
1671
- - Array wildcards: `env[*].name` not `env.*.name`
1672
668
 
1673
669
  ---
1674
670
 
1675
- ### Stop Rule Violations
671
+ ### Glob patterns not matching
1676
672
 
1677
- **Error: "Major version upgrade detected"**
1678
-
1679
- ```
1680
- 🛑 Stop Rule Violation (semverMajorUpgrade)
1681
- File: svc/my-service/values.yaml
1682
- Path: image.tag
1683
- Change: v1.2.3 → v2.0.0
1684
- ```
1685
-
1686
- **Solutions:**
1687
-
1688
- - Review the change carefully
1689
- - If intentional, use `--force` to override
1690
- - Update the stop rule configuration if needed
673
+ | Pattern | Matches |
674
+ | ---------------- | ----------------------- |
675
+ | `*.yaml` | Current directory only |
676
+ | `**/*.yaml` | Recursive (all subdirs) |
677
+ | `apps/*.yaml` | One level deep |
678
+ | `apps/**/*.yaml` | Recursive under apps/ |
1691
679
 
1692
680
  ---
1693
681
 
1694
- ### Transform Pattern Issues
1695
-
1696
- **Problem:** Transform not applying
1697
-
1698
- **Check:**
1699
-
1700
- 1. File pattern matches: `svc/**/values.yaml` vs `svc/*/values.yaml`
1701
- 2. Regex escaping: Use `\\.` for literal dots
1702
- 3. Word boundaries: Use `\\b` for word boundaries
1703
- 4. Order matters: Rules apply sequentially
1704
-
1705
- **Example:**
1706
-
1707
- ```yaml
1708
- # Wrong: . matches any character
1709
- - find: 'uat.internal'
1710
-
1711
- # Correct: escaped dot
1712
- - find: "uat\\.internal"
1713
- ```
1714
-
1715
- ---
682
+ ## 📚 Resources
1716
683
 
1717
- ### JSONPath Syntax Problems
684
+ 📦 **npm:** [helm-env-delta](https://www.npmjs.com/package/helm-env-delta)
1718
685
 
1719
- **Common Mistakes:**
686
+ 🐙 **GitHub:** [BCsabaEngine/helm-env-delta](https://github.com/BCsabaEngine/helm-env-delta)
1720
687
 
1721
- ```yaml
1722
- # ❌ Wrong
1723
- skipPath:
1724
- "*.yaml":
1725
- - "$.spec.replicas" # Don't use $. prefix
1726
- - "env.*.name" # Use [*] not .*
688
+ 🐛 **Issues:** [GitHub Issues](https://github.com/BCsabaEngine/helm-env-delta/issues)
1727
689
 
1728
- # Correct
1729
- skipPath:
1730
- "*.yaml":
1731
- - "spec.replicas" # No $. prefix
1732
- - "env[*].name" # Array wildcard
1733
- ```
690
+ 📄 **License:** [ISC](https://opensource.org/licenses/ISC)
1734
691
 
1735
692
  ---
1736
693
 
1737
- ### File Glob Patterns Not Matching
694
+ ## 🎉 Success Stories
1738
695
 
1739
- **Glob Pattern Reference:**
696
+ **Typical adoption timeline:**
1740
697
 
1741
- | Pattern | Matches |
1742
- | ---------------- | -------------------------------------------------------- |
1743
- | `*.yaml` | `app.yaml` (current directory only) |
1744
- | `**/*.yaml` | `apps/app.yaml`, `svc/my-svc/values.yaml` (recursive) |
1745
- | `apps/*.yaml` | `apps/app.yaml` (one level deep) |
1746
- | `apps/**/*.yaml` | `apps/foo/app.yaml`, `apps/foo/bar/app.yaml` (recursive) |
698
+ - **Week 1:** Install, create basic config, dry-run on one service
699
+ - **Week 2:** Expand to 5 services, add skipPath rules
700
+ - **Week 3:** Add stop rules (catch first bug!)
701
+ - **Week 4:** Standardize YAML formatting
702
+ - **Month 2:** Full adoption for all services
1747
703
 
1748
- **Debugging:**
704
+ **Results:**
1749
705
 
1750
- ```bash
1751
- # Check which files match your pattern
1752
- find . -name "*.yaml"
1753
- ```
706
+ - ⏱️ Sync time: **2 hours/week → 10 minutes/week**
707
+ - 🐛 Production incidents from sync errors: **Zero**
708
+ - 😊 Team satisfaction: **High**
1754
709
 
1755
710
  ---
1756
711
 
1757
- ## License & Links
1758
-
1759
- **License:** [ISC](https://opensource.org/licenses/ISC)
1760
-
1761
- **Links:**
1762
-
1763
- - **npm Package**: [helm-env-delta](https://www.npmjs.com/package/helm-env-delta)
1764
- - **GitHub Repository**: [BCsabaEngine/helm-env-delta](https://github.com/BCsabaEngine/helm-env-delta)
1765
- - **Issue Tracker**: [GitHub Issues](https://github.com/BCsabaEngine/helm-env-delta/issues)
1766
-
1767
- **Author:** BCsabaEngine
1768
-
1769
- ---
712
+ **Built for DevOps and Platform teams managing multi-environment Kubernetes and Helm deployments.**
1770
713
 
1771
- **Made for DevOps and Platform teams managing multi-environment Kubernetes and Helm deployments in GitOps workflows.**
714
+ **Made with ❤️ by BCsabaEngine**