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 +451 -1508
- package/dist/arrayDiffer.js +12 -4
- package/dist/fileDiff.js +16 -8
- package/dist/fileLoader.js +6 -4
- package/dist/stopRulesValidator.js +2 -2
- package/dist/utils/deepEqual.js +16 -4
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +4 -1
- package/dist/utils/jsonPath.d.ts +1 -0
- package/dist/utils/jsonPath.js +12 -2
- package/dist/utils/patternMatcher.d.ts +7 -0
- package/dist/utils/patternMatcher.js +24 -0
- package/dist/utils/serialization.js +5 -5
- package/dist/utils/transformer.js +9 -6
- package/dist/yamlFormatter.js +39 -21
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -1,128 +1,130 @@
|
|
|
1
|
-
# HelmEnvDelta
|
|
1
|
+
# 🚀 HelmEnvDelta
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/helm-env-delta)
|
|
4
4
|
[](https://opensource.org/licenses/ISC)
|
|
5
5
|
[](https://nodejs.org/)
|
|
6
|
-

|
|
7
|
-

|
|
8
6
|
|
|
9
|
-
**
|
|
7
|
+
**Sync YAML configs across environments in seconds, not hours.**
|
|
10
8
|
|
|
11
|
-
|
|
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
|
-
##
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
-
##
|
|
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
|
-
|
|
43
|
+
🛡️ **Safety Rules** - Block major version upgrades, scaling violations, and forbidden patterns before they reach production.
|
|
48
44
|
|
|
49
|
-
**
|
|
45
|
+
🎨 **Format Enforcement** - Standardize YAML across all environments: key ordering, indentation, quoting, array sorting.
|
|
50
46
|
|
|
51
|
-
|
|
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
|
-
**
|
|
49
|
+
📊 **Multiple Reports** - Console, HTML (visual), and JSON (CI/CD) output formats.
|
|
58
50
|
|
|
59
|
-
-
|
|
60
|
-
|
|
61
|
-
-
|
|
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
|
-
##
|
|
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
|
-
|
|
67
|
+
## 🎯 Quick Start
|
|
70
68
|
|
|
71
|
-
|
|
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
|
-
|
|
71
|
+
```yaml
|
|
72
|
+
# config.yaml
|
|
73
|
+
source: './uat'
|
|
74
|
+
destination: './prod'
|
|
84
75
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
76
|
+
skipPath:
|
|
77
|
+
'**/*.yaml':
|
|
78
|
+
- 'metadata.namespace' # Never overwrite prod namespace
|
|
79
|
+
- 'spec.replicas' # Keep prod scaling
|
|
89
80
|
|
|
90
|
-
|
|
81
|
+
transforms:
|
|
82
|
+
'**/*.yaml':
|
|
83
|
+
content:
|
|
84
|
+
- find: "-uat\\b"
|
|
85
|
+
replace: '-prod'
|
|
86
|
+
```
|
|
91
87
|
|
|
92
|
-
|
|
88
|
+
### 2️⃣ Preview Changes
|
|
93
89
|
|
|
94
|
-
|
|
95
|
-
-
|
|
96
|
-
|
|
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
|
-
|
|
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
|
-
|
|
106
|
+
**Done!** All files synced, production values preserved, changes validated.
|
|
104
107
|
|
|
105
|
-
|
|
108
|
+
---
|
|
106
109
|
|
|
107
|
-
|
|
110
|
+
## 🎬 Real-World Use Cases
|
|
108
111
|
|
|
109
|
-
|
|
112
|
+
### 🏢 Multi-Service GitOps
|
|
110
113
|
|
|
111
|
-
|
|
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
|
-
**
|
|
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
|
-
|
|
135
|
+
**Result:** Sync 50+ files in 5 seconds with zero risk of overwriting production settings.
|
|
134
136
|
|
|
135
137
|
---
|
|
136
138
|
|
|
137
|
-
|
|
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
|
-
|
|
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
|
-
**
|
|
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
|
-
|
|
156
|
+
**Result:** Dangerous changes blocked automatically. Use `--force` only when you intend it.
|
|
168
157
|
|
|
169
158
|
---
|
|
170
159
|
|
|
171
|
-
|
|
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
|
-
|
|
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
|
-
**
|
|
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
|
|
183
|
+
**Result:** Every file formatted consistently. Clean diffs. Easier reviews.
|
|
205
184
|
|
|
206
185
|
---
|
|
207
186
|
|
|
208
|
-
|
|
187
|
+
## 🎓 Live Examples
|
|
209
188
|
|
|
210
|
-
|
|
189
|
+
The repository includes ready-to-run examples:
|
|
211
190
|
|
|
212
|
-
|
|
191
|
+
### 📁 Example 1: Config Inheritance
|
|
213
192
|
|
|
214
|
-
|
|
193
|
+
Shows how to reuse base configuration across multiple environment pairs.
|
|
215
194
|
|
|
216
|
-
|
|
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
|
-
|
|
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
|
-
|
|
207
|
+
### ⛓️ Example 3: Multi-Environment Chain
|
|
223
208
|
|
|
224
|
-
|
|
209
|
+
Progressive promotion through Dev → UAT → Prod with cumulative transforms.
|
|
225
210
|
|
|
226
|
-
|
|
211
|
+
```bash
|
|
212
|
+
cd example/3-multi-env-chain
|
|
213
|
+
./sync-all.sh
|
|
214
|
+
```
|
|
227
215
|
|
|
228
|
-
|
|
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
|
-
|
|
218
|
+
File deletion behavior with `prune: true` vs `prune: false`.
|
|
235
219
|
|
|
236
|
-
|
|
237
|
-
-
|
|
238
|
-
|
|
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
|
-
|
|
224
|
+
---
|
|
243
225
|
|
|
244
|
-
|
|
226
|
+
## ⚙️ Configuration Reference
|
|
245
227
|
|
|
246
|
-
|
|
247
|
-
# 1. Preview changes (5 seconds)
|
|
248
|
-
helm-env-delta --config config.yaml --dry-run --diff
|
|
228
|
+
### 🎯 Core Settings
|
|
249
229
|
|
|
250
|
-
|
|
251
|
-
|
|
230
|
+
```yaml
|
|
231
|
+
source: './uat' # Required: Source folder
|
|
232
|
+
destination: './prod' # Required: Destination folder
|
|
252
233
|
|
|
253
|
-
#
|
|
254
|
-
|
|
234
|
+
include: # Optional: File patterns (default: all)
|
|
235
|
+
- '**/*.yaml'
|
|
236
|
+
exclude: # Optional: Exclude patterns
|
|
237
|
+
- '**/test*.yaml'
|
|
255
238
|
|
|
256
|
-
#
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
262
|
+
---
|
|
269
263
|
|
|
270
|
-
|
|
264
|
+
### 🔄 Transformations
|
|
271
265
|
|
|
272
|
-
|
|
266
|
+
Regex find/replace for content and file paths.
|
|
273
267
|
|
|
274
268
|
```yaml
|
|
275
|
-
source: './uat'
|
|
276
|
-
destination: './prod'
|
|
277
269
|
transforms:
|
|
278
|
-
'
|
|
279
|
-
content:
|
|
280
|
-
- find: "-
|
|
281
|
-
replace: '-
|
|
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
|
-
|
|
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
|
-
|
|
287
|
+
---
|
|
287
288
|
|
|
288
|
-
|
|
289
|
-
skipPath:
|
|
290
|
-
'**/*.yaml':
|
|
291
|
-
- 'metadata.namespace'
|
|
292
|
-
- 'spec.replicas'
|
|
293
|
-
```
|
|
289
|
+
### 🛡️ Stop Rules
|
|
294
290
|
|
|
295
|
-
|
|
291
|
+
Block dangerous changes before deployment.
|
|
296
292
|
|
|
297
|
-
|
|
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
|
-
'
|
|
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
|
-
|
|
321
|
+
**Override:** Use `--force` to bypass stop rules when needed.
|
|
322
|
+
|
|
323
|
+
---
|
|
324
|
+
|
|
325
|
+
### 🎨 Output Formatting
|
|
311
326
|
|
|
312
|
-
|
|
327
|
+
Standardize YAML across all environments.
|
|
313
328
|
|
|
314
329
|
```yaml
|
|
315
330
|
outputFormat:
|
|
316
|
-
indent: 2
|
|
317
|
-
keySeparator: true
|
|
318
|
-
|
|
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
|
-
|
|
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
|
-
|
|
352
|
+
**Benefits:** Consistent formatting, cleaner diffs, better readability.
|
|
329
353
|
|
|
330
|
-
|
|
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
|
-
###
|
|
356
|
+
### 🔗 Config Inheritance
|
|
337
357
|
|
|
338
|
-
|
|
358
|
+
Reuse base configurations across environment pairs.
|
|
339
359
|
|
|
340
|
-
|
|
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
|
-
|
|
345
|
-
|
|
362
|
+
```yaml
|
|
363
|
+
include: ['**/*.yaml']
|
|
364
|
+
prune: true
|
|
346
365
|
|
|
347
|
-
|
|
348
|
-
|
|
366
|
+
skipPath:
|
|
367
|
+
'apps/*.yaml':
|
|
368
|
+
- 'spec.destination.namespace'
|
|
349
369
|
|
|
350
|
-
|
|
351
|
-
|
|
370
|
+
outputFormat:
|
|
371
|
+
indent: 2
|
|
372
|
+
keySeparator: true
|
|
352
373
|
```
|
|
353
374
|
|
|
354
|
-
|
|
375
|
+
**Environment config (`prod.yaml`):**
|
|
355
376
|
|
|
356
|
-
|
|
377
|
+
```yaml
|
|
378
|
+
extends: './base.yaml' # Inherit base settings
|
|
357
379
|
|
|
358
|
-
|
|
380
|
+
source: './uat'
|
|
381
|
+
destination: './prod'
|
|
359
382
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
-
|
|
383
|
+
transforms: # Add environment-specific transforms
|
|
384
|
+
'**/*.yaml':
|
|
385
|
+
content:
|
|
386
|
+
- find: '-uat\\b'
|
|
387
|
+
replace: '-prod'
|
|
364
388
|
|
|
365
|
-
|
|
389
|
+
stopRules: # Add production safety rules
|
|
390
|
+
'services/**/values.yaml':
|
|
391
|
+
- type: 'semverMajorUpgrade'
|
|
392
|
+
path: 'image.tag'
|
|
393
|
+
```
|
|
366
394
|
|
|
367
|
-
|
|
395
|
+
**Merging:**
|
|
368
396
|
|
|
369
|
-
-
|
|
370
|
-
-
|
|
371
|
-
-
|
|
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
|
-
##
|
|
403
|
+
## 🖥️ CLI Reference
|
|
379
404
|
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
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
|
-
|
|
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
|
-
|
|
427
|
+
### Examples
|
|
413
428
|
|
|
414
429
|
```bash
|
|
415
|
-
#
|
|
416
|
-
|
|
417
|
-
```
|
|
430
|
+
# Validate configuration
|
|
431
|
+
hed --config config.yaml --validate
|
|
418
432
|
|
|
419
|
-
|
|
433
|
+
# Preview with diff
|
|
434
|
+
hed --config config.yaml --dry-run --diff
|
|
420
435
|
|
|
421
|
-
|
|
422
|
-
|
|
436
|
+
# Visual HTML report
|
|
437
|
+
hed --config config.yaml --diff-html
|
|
423
438
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
---
|
|
439
|
+
# CI/CD integration
|
|
440
|
+
hed --config config.yaml --diff-json | jq '.summary'
|
|
427
441
|
|
|
428
|
-
|
|
442
|
+
# Execute sync
|
|
443
|
+
hed --config config.yaml
|
|
429
444
|
|
|
430
|
-
|
|
445
|
+
# Force override stop rules
|
|
446
|
+
hed --config config.yaml --force
|
|
447
|
+
```
|
|
431
448
|
|
|
432
|
-
|
|
449
|
+
---
|
|
433
450
|
|
|
434
|
-
|
|
451
|
+
## 🔄 Typical Workflow
|
|
435
452
|
|
|
436
|
-
|
|
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
|
-
**
|
|
466
|
+
**Step-by-step:**
|
|
439
467
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
- Environment-specific transforms and stop rules
|
|
468
|
+
```bash
|
|
469
|
+
# 1. Preview changes
|
|
470
|
+
hed --config config.yaml --dry-run --diff
|
|
444
471
|
|
|
445
|
-
|
|
472
|
+
# 2. Review in browser
|
|
473
|
+
hed --config config.yaml --diff-html
|
|
446
474
|
|
|
447
|
-
|
|
448
|
-
|
|
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
|
-
#
|
|
452
|
-
|
|
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
|
-
|
|
458
|
-
|
|
459
|
-
**Location**: `example/2-stop-rules/`
|
|
486
|
+
## 🏆 Why Choose HelmEnvDelta?
|
|
460
487
|
|
|
461
|
-
|
|
488
|
+
### 🆚 Compared to Alternatives
|
|
462
489
|
|
|
463
|
-
**
|
|
490
|
+
**HelmEnvDelta** is purpose-built for environment synchronization, not template generation or deployment.
|
|
464
491
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
-
|
|
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
|
-
**
|
|
501
|
+
**Complementary:** Use HelmEnvDelta alongside Helm, Helmfile, Kustomize, ArgoCD, or Flux.
|
|
471
502
|
|
|
472
|
-
|
|
473
|
-
# See violations in action
|
|
474
|
-
helm-env-delta --config example/2-stop-rules/config.yaml --dry-run --diff
|
|
503
|
+
---
|
|
475
504
|
|
|
476
|
-
|
|
477
|
-
helm-env-delta --config example/2-stop-rules/config.yaml
|
|
505
|
+
### 💪 Benefits
|
|
478
506
|
|
|
479
|
-
|
|
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
|
-
|
|
511
|
+
✅ **Consistency** - Uniform YAML formatting. No more diff noise.
|
|
486
512
|
|
|
487
|
-
**
|
|
513
|
+
✅ **Auditability** - Field-level change tracking with JSONPath. Clean structural diffs.
|
|
488
514
|
|
|
489
|
-
|
|
515
|
+
✅ **Flexibility** - Per-file patterns. Config inheritance. Regex transforms.
|
|
490
516
|
|
|
491
|
-
**
|
|
517
|
+
✅ **Reliability** - 763 tests, 84% coverage. Battle-tested.
|
|
492
518
|
|
|
493
|
-
|
|
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
|
-
|
|
521
|
+
## 📊 JSON Output for CI/CD
|
|
500
522
|
|
|
501
523
|
```bash
|
|
502
|
-
|
|
503
|
-
|
|
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
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
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
|
-
|
|
573
|
+
# Violations
|
|
574
|
+
jq '.stopRuleViolations' report.json
|
|
515
575
|
|
|
516
|
-
|
|
576
|
+
# Changed files
|
|
577
|
+
jq '.files.changed[].path' report.json
|
|
578
|
+
```
|
|
517
579
|
|
|
518
|
-
|
|
580
|
+
---
|
|
519
581
|
|
|
520
|
-
|
|
582
|
+
## 🔧 Advanced Features
|
|
521
583
|
|
|
522
|
-
|
|
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
|
-
|
|
586
|
+
Git diffs are noisy when arrays are reordered. HelmEnvDelta compares YAML structure and recognizes identical content regardless of order.
|
|
528
587
|
|
|
529
|
-
|
|
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
|
-
|
|
534
|
-
|
|
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
|
-
###
|
|
611
|
+
### 🔀 Deep Merge
|
|
540
612
|
|
|
541
|
-
|
|
613
|
+
Preserves destination values for skipped paths.
|
|
542
614
|
|
|
543
|
-
|
|
615
|
+
```yaml
|
|
616
|
+
# Source (UAT)
|
|
617
|
+
metadata:
|
|
618
|
+
namespace: uat
|
|
619
|
+
spec:
|
|
620
|
+
replicas: 3
|
|
544
621
|
|
|
545
|
-
|
|
622
|
+
# Config
|
|
623
|
+
skipPath:
|
|
624
|
+
"*.yaml":
|
|
625
|
+
- "metadata.namespace"
|
|
626
|
+
- "spec.replicas"
|
|
546
627
|
|
|
547
|
-
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
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
|
-
##
|
|
637
|
+
## 🆘 Common Issues
|
|
555
638
|
|
|
556
|
-
|
|
639
|
+
### ❓ Stop rule violations blocking sync
|
|
557
640
|
|
|
558
|
-
|
|
559
|
-
source: './uat'
|
|
560
|
-
destination: './prod'
|
|
641
|
+
**Error:** `🛑 Stop Rule Violation (semverMajorUpgrade)`
|
|
561
642
|
|
|
562
|
-
|
|
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
|
-
|
|
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
|
-
**
|
|
649
|
+
**Check:**
|
|
1541
650
|
|
|
1542
|
-
-
|
|
1543
|
-
-
|
|
1544
|
-
-
|
|
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
|
-
|
|
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
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
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
|
-
###
|
|
671
|
+
### ❓ Glob patterns not matching
|
|
1676
672
|
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
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
|
-
|
|
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
|
-
|
|
684
|
+
📦 **npm:** [helm-env-delta](https://www.npmjs.com/package/helm-env-delta)
|
|
1718
685
|
|
|
1719
|
-
**
|
|
686
|
+
🐙 **GitHub:** [BCsabaEngine/helm-env-delta](https://github.com/BCsabaEngine/helm-env-delta)
|
|
1720
687
|
|
|
1721
|
-
|
|
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
|
-
|
|
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
|
-
|
|
694
|
+
## 🎉 Success Stories
|
|
1738
695
|
|
|
1739
|
-
**
|
|
696
|
+
**Typical adoption timeline:**
|
|
1740
697
|
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
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
|
-
**
|
|
704
|
+
**Results:**
|
|
1749
705
|
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
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
|
-
|
|
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
|
|
714
|
+
**Made with ❤️ by BCsabaEngine**
|