gitops-replacer 0.1.1__tar.gz

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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Simon Lauger
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,5 @@
1
+ include README.md
2
+ include LICENSE
3
+ include CHANGELOG.md
4
+ include pyproject.toml
5
+ include example.json
@@ -0,0 +1,345 @@
1
+ Metadata-Version: 2.4
2
+ Name: gitops-replacer
3
+ Version: 0.1.1
4
+ Summary: Automated YAML/JSON value updates for GitOps repositories via GitHub API
5
+ Author-email: Simon Lauger <simon@lauger.de>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/slauger/gitops-replacer
8
+ Project-URL: Documentation, https://github.com/slauger/gitops-replacer#readme
9
+ Project-URL: Repository, https://github.com/slauger/gitops-replacer
10
+ Project-URL: Issues, https://github.com/slauger/gitops-replacer/issues
11
+ Project-URL: Changelog, https://github.com/slauger/gitops-replacer/blob/main/CHANGELOG.md
12
+ Keywords: gitops,yaml,json,kubernetes,helm,automation,github,ci-cd,deployment
13
+ Classifier: Development Status :: 5 - Production/Stable
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: System Administrators
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: License :: OSI Approved :: MIT License
22
+ Classifier: Operating System :: OS Independent
23
+ Classifier: Topic :: Software Development :: Build Tools
24
+ Classifier: Topic :: System :: Systems Administration
25
+ Classifier: Topic :: Utilities
26
+ Requires-Python: >=3.10
27
+ Description-Content-Type: text/markdown
28
+ License-File: LICENSE
29
+ Requires-Dist: requests>=2.25.0
30
+ Requires-Dist: PyYAML>=5.4.0
31
+ Dynamic: license-file
32
+
33
+ # gitops-replacer
34
+
35
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
36
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
37
+ [![PyPI version](https://img.shields.io/pypi/v/gitops-replacer.svg)](https://pypi.org/project/gitops-replacer/)
38
+ [![PyPI downloads](https://img.shields.io/pypi/dm/gitops-replacer.svg)](https://pypi.org/project/gitops-replacer/)
39
+
40
+ A lightweight CLI tool that automates value updates in GitOps repositories using marker comments. Replace values across multiple GitHub repositories with a single command, enabling automated deployment workflows.
41
+
42
+ ## Features
43
+
44
+ - **Marker-based Approach**: Uses `# gitops-replacer: <name>` comments to locate values
45
+ - **Format Preservation**: No YAML parsing - comments, quotes, and formatting are preserved
46
+ - **Multiple Dependencies**: Update different values in the same file via unique markers
47
+ - **Flexible Modes**: Dry-run for validation, apply mode for commits
48
+ - **CI/CD Integration**: Built-in CI mode with `GITHUB_REF` pattern matching
49
+ - **Multiple Repositories**: Update values across any number of repos and files
50
+ - **Configuration Formats**: JSON (default) and YAML support
51
+ - **Performance Optimized**: Response caching eliminates duplicate API calls
52
+ - **Robust HTTP**: Automatic retries, timeouts, and error handling
53
+
54
+ ## Requirements
55
+
56
+ - Python 3.10+
57
+ - A GitHub/GitHub Enterprise token with content read/write access
58
+
59
+ ## Installation
60
+
61
+ ### Via pip (recommended)
62
+
63
+ ```bash
64
+ # Install from PyPI
65
+ pip install gitops-replacer
66
+
67
+ # Verify installation
68
+ gitops-replacer --help
69
+ ```
70
+
71
+ ### From source
72
+
73
+ ```bash
74
+ # Clone repository
75
+ git clone https://github.com/slauger/gitops-replacer.git
76
+ cd gitops-replacer
77
+
78
+ # Install in development mode
79
+ pip install -e .
80
+
81
+ # Or run directly
82
+ python -m gitops_replacer --help
83
+ ```
84
+
85
+ ## Quick Start
86
+
87
+ 1. Add marker comments to your target files (see [Marker Format](#marker-format))
88
+ 2. Create a configuration file (default: `gitops-replacer.json`)
89
+ 3. Run a dry-run:
90
+ ```bash
91
+ gitops-replacer "1.2.3"
92
+ ```
93
+ 4. Apply changes (commit to target repos):
94
+ ```bash
95
+ gitops-replacer --apply "1.2.3"
96
+ ```
97
+
98
+ ## Marker Format
99
+
100
+ Add a comment **above** the line you want to update:
101
+
102
+ ```yaml
103
+ dependencies:
104
+ # gitops-replacer: my-app
105
+ - name: my-app
106
+ version: "0.0.0-e0f72bb"
107
+ repository: oci://registry.example.com/charts
108
+
109
+ # gitops-replacer: another-chart
110
+ - name: another-chart
111
+ version: "1.0.0"
112
+ repository: oci://registry.example.com/charts
113
+ ```
114
+
115
+ The tool will:
116
+ 1. Find the line with `# gitops-replacer: <depName>`
117
+ 2. Replace the value on the **next line** (preserving key, quotes, and formatting)
118
+
119
+ ### Examples
120
+
121
+ **Chart.yaml (Helm dependency version):**
122
+ ```yaml
123
+ dependencies:
124
+ # gitops-replacer: my-app
125
+ - name: my-app
126
+ version: "0.0.0-e0f72bb"
127
+ repository: oci://registry.example.com/charts
128
+ ```
129
+
130
+ **values.yaml (image tag):**
131
+ ```yaml
132
+ # gitops-replacer: my-app-image
133
+ image: registry.example.com/myorg/my-app:1.2.3
134
+ ```
135
+
136
+ **Note:** Only YAML files are supported (JSON has no comments). GitOps manifests are typically YAML.
137
+
138
+ ## CLI
139
+
140
+ ```text
141
+ usage: gitops-replacer [-h] [--config <file>] [--apply] [--ci]
142
+ [--name <string>] [--email <string>]
143
+ [--message <string>] [--api <string>]
144
+ [--verbose]
145
+ <string>
146
+ ```
147
+
148
+ - `--config` Path to the configuration file (default: `gitops-replacer.json`). JSON recommended.
149
+ - `--apply` Apply changes (commit). Without this flag the tool runs in dry-run.
150
+ - `--ci` CI mode: validates `GITHUB_REF` against `when`/`except` regex patterns from config.
151
+ - `--name` Commit author name (default: env `GIT_COMMIT_NAME` or `Replacer Bot`).
152
+ - `--email` Commit author email (default: env `GIT_COMMIT_EMAIL` or `replacer-bot@localhost.localdomain`).
153
+ - `--message` Commit message template (default: `fix: update {} to {}`). First `{}` is depName, second is value.
154
+ - `--api` GitHub API URL (default: env `GITHUB_API_URL` or `https://api.github.com`).
155
+ - `--verbose` Print file contents and desired state (use with care in CI logs).
156
+ - Positional: `value` - the new value to set at the marked location.
157
+
158
+ ### Environment
159
+
160
+ - `GITHUB_TOKEN` **(required)** – token with access to read/write repository contents.
161
+ - `GITHUB_REF` *(required when `--ci`)* – the current ref string, e.g., `refs/heads/main`. Falls back to `GIT_REF` for backwards compatibility.
162
+
163
+ Recommended token scopes:
164
+ - Public repos only: `public_repo`
165
+ - Private repos: `repo`
166
+ - GitHub Enterprise: equivalent content permissions
167
+
168
+ ## Configuration
169
+
170
+ Default format is **JSON**. YAML (`.yaml`/`.yml`) is supported as well.
171
+
172
+ ### JSON schema (per entry)
173
+
174
+ ```json
175
+ {
176
+ "gitops-replacer": [
177
+ {
178
+ "repository": "acme/gitops",
179
+ "branch": "main",
180
+ "file": "apps/my-app/Chart.yaml",
181
+ "depName": "my-app",
182
+ "when": "^refs/heads/main$"
183
+ }
184
+ ]
185
+ }
186
+ ```
187
+
188
+ **Fields**
189
+
190
+ | Field | Description |
191
+ |-------|-------------|
192
+ | `repository` | Target repo on GitHub (`ORG/REPO` format) |
193
+ | `branch` | Target branch |
194
+ | `file` | Target file path relative to repo root |
195
+ | `depName` | Dependency name (must match marker in file) |
196
+ | `when` | Regex that must match `GITHUB_REF` when `--ci` is enabled (optional) |
197
+ | `except` | Regex that must **not** match `GITHUB_REF` when `--ci` is enabled (optional) |
198
+
199
+ > The tool uses `re.match` (anchored at the string start). Use `^...$` in your patterns if you require a full match.
200
+
201
+ ### Examples
202
+
203
+ **JSON (default)**
204
+
205
+ ```json
206
+ {
207
+ "gitops-replacer": [
208
+ {
209
+ "repository": "acme/gitops",
210
+ "branch": "main",
211
+ "file": "apps/my-app/Chart.yaml",
212
+ "depName": "my-app",
213
+ "when": "^refs/heads/(main|release/.*)$"
214
+ },
215
+ {
216
+ "repository": "acme/gitops",
217
+ "branch": "develop",
218
+ "file": "apps/my-app-dev/Chart.yaml",
219
+ "depName": "my-app",
220
+ "except": "^refs/heads/legacy/"
221
+ }
222
+ ]
223
+ }
224
+ ```
225
+
226
+ **YAML (alternative)**
227
+
228
+ ```yaml
229
+ gitops-replacer:
230
+ - repository: acme/gitops
231
+ branch: main
232
+ file: apps/my-app/Chart.yaml
233
+ depName: my-app
234
+ when: '^refs/heads/(main|release/.*)$'
235
+ - repository: acme/gitops
236
+ branch: develop
237
+ file: apps/my-app-dev/Chart.yaml
238
+ depName: my-app
239
+ except: '^refs/heads/legacy/'
240
+ ```
241
+
242
+ ## How it works
243
+
244
+ 1. **Validation**: Checks CLI arguments, environment variables, and configuration file
245
+ 2. **Precheck Phase**: Validates access to all target repositories/files (caches responses)
246
+ 3. **Replace Phase**: Downloads files (reuses cached data), finds marker comments, replaces values
247
+ 4. **Commit Phase**: If `--apply` is set and changes detected, commits via GitHub Contents API
248
+ 5. **Exit Codes**: Returns `0` on success, non-zero on failures
249
+
250
+ ### Why Marker-based?
251
+
252
+ Traditional approaches parse YAML, modify the data structure, and serialize back. This often breaks:
253
+ - Comments are lost
254
+ - Quote styles change (`"1.0"` becomes `'1.0'` or `1.0`)
255
+ - Key ordering may change
256
+ - Multi-line strings get reformatted
257
+
258
+ The marker-based approach works on raw text:
259
+ - **Explicit**: Only marked lines are modified
260
+ - **Safe**: No risk of unintended changes
261
+ - **Preserving**: Comments, quotes, and formatting stay intact
262
+
263
+ ## Exit Codes
264
+
265
+ - `0` success (no changes or committed changes)
266
+ - `1` validation or API error
267
+
268
+ ## Use Cases
269
+
270
+ ### Automated Deployment Pipeline
271
+
272
+ Update chart version when a new release is built:
273
+
274
+ ```bash
275
+ # In your CI/CD pipeline after publishing a chart
276
+ gitops-replacer --ci --apply "0.1.0-abc123"
277
+ ```
278
+
279
+ ### Multi-Environment Updates
280
+
281
+ Use CI mode to update different environments based on branch:
282
+
283
+ ```json
284
+ {
285
+ "gitops-replacer": [
286
+ {
287
+ "repository": "myorg/gitops",
288
+ "branch": "main",
289
+ "file": "apps/production/Chart.yaml",
290
+ "depName": "myapp",
291
+ "when": "^refs/heads/main$"
292
+ },
293
+ {
294
+ "repository": "myorg/gitops",
295
+ "branch": "main",
296
+ "file": "apps/staging/Chart.yaml",
297
+ "depName": "myapp",
298
+ "when": "^refs/heads/(main|develop)$"
299
+ }
300
+ ]
301
+ }
302
+ ```
303
+
304
+ ## Troubleshooting
305
+
306
+ ### Common Issues
307
+
308
+ **401 Unauthorized**
309
+ - Verify `GITHUB_TOKEN` is set correctly
310
+ - Check token has `repo` or `public_repo` scope
311
+ - For GitHub Enterprise, confirm token has access to the organization
312
+
313
+ **404 Not Found**
314
+ - Verify `repository`, `branch`, and `file` paths in config
315
+ - Check branch name spelling (case-sensitive)
316
+ - Ensure file exists at the specified path
317
+
318
+ **No marker found**
319
+ - Confirm the marker comment exists in the target file
320
+ - Check `depName` in config matches the marker exactly
321
+ - Marker format: `# gitops-replacer: <depName>`
322
+
323
+ **No changes detected**
324
+ - The current value already matches the new value
325
+ - Use `--verbose` to see file contents
326
+
327
+ ### Debug Mode
328
+
329
+ Run with `--verbose` to see:
330
+ - Full API URLs being called
331
+ - Complete file contents before replacement
332
+ - Desired file contents after replacement
333
+
334
+ **Warning**: Verbose mode may expose sensitive data in logs.
335
+
336
+ ## Contributing
337
+
338
+ Contributions are welcome! Please ensure:
339
+ - Code follows existing style and patterns
340
+ - Changes are tested with both dry-run and apply modes
341
+ - Documentation is updated for new features
342
+
343
+ ## License
344
+
345
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,313 @@
1
+ # gitops-replacer
2
+
3
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
5
+ [![PyPI version](https://img.shields.io/pypi/v/gitops-replacer.svg)](https://pypi.org/project/gitops-replacer/)
6
+ [![PyPI downloads](https://img.shields.io/pypi/dm/gitops-replacer.svg)](https://pypi.org/project/gitops-replacer/)
7
+
8
+ A lightweight CLI tool that automates value updates in GitOps repositories using marker comments. Replace values across multiple GitHub repositories with a single command, enabling automated deployment workflows.
9
+
10
+ ## Features
11
+
12
+ - **Marker-based Approach**: Uses `# gitops-replacer: <name>` comments to locate values
13
+ - **Format Preservation**: No YAML parsing - comments, quotes, and formatting are preserved
14
+ - **Multiple Dependencies**: Update different values in the same file via unique markers
15
+ - **Flexible Modes**: Dry-run for validation, apply mode for commits
16
+ - **CI/CD Integration**: Built-in CI mode with `GITHUB_REF` pattern matching
17
+ - **Multiple Repositories**: Update values across any number of repos and files
18
+ - **Configuration Formats**: JSON (default) and YAML support
19
+ - **Performance Optimized**: Response caching eliminates duplicate API calls
20
+ - **Robust HTTP**: Automatic retries, timeouts, and error handling
21
+
22
+ ## Requirements
23
+
24
+ - Python 3.10+
25
+ - A GitHub/GitHub Enterprise token with content read/write access
26
+
27
+ ## Installation
28
+
29
+ ### Via pip (recommended)
30
+
31
+ ```bash
32
+ # Install from PyPI
33
+ pip install gitops-replacer
34
+
35
+ # Verify installation
36
+ gitops-replacer --help
37
+ ```
38
+
39
+ ### From source
40
+
41
+ ```bash
42
+ # Clone repository
43
+ git clone https://github.com/slauger/gitops-replacer.git
44
+ cd gitops-replacer
45
+
46
+ # Install in development mode
47
+ pip install -e .
48
+
49
+ # Or run directly
50
+ python -m gitops_replacer --help
51
+ ```
52
+
53
+ ## Quick Start
54
+
55
+ 1. Add marker comments to your target files (see [Marker Format](#marker-format))
56
+ 2. Create a configuration file (default: `gitops-replacer.json`)
57
+ 3. Run a dry-run:
58
+ ```bash
59
+ gitops-replacer "1.2.3"
60
+ ```
61
+ 4. Apply changes (commit to target repos):
62
+ ```bash
63
+ gitops-replacer --apply "1.2.3"
64
+ ```
65
+
66
+ ## Marker Format
67
+
68
+ Add a comment **above** the line you want to update:
69
+
70
+ ```yaml
71
+ dependencies:
72
+ # gitops-replacer: my-app
73
+ - name: my-app
74
+ version: "0.0.0-e0f72bb"
75
+ repository: oci://registry.example.com/charts
76
+
77
+ # gitops-replacer: another-chart
78
+ - name: another-chart
79
+ version: "1.0.0"
80
+ repository: oci://registry.example.com/charts
81
+ ```
82
+
83
+ The tool will:
84
+ 1. Find the line with `# gitops-replacer: <depName>`
85
+ 2. Replace the value on the **next line** (preserving key, quotes, and formatting)
86
+
87
+ ### Examples
88
+
89
+ **Chart.yaml (Helm dependency version):**
90
+ ```yaml
91
+ dependencies:
92
+ # gitops-replacer: my-app
93
+ - name: my-app
94
+ version: "0.0.0-e0f72bb"
95
+ repository: oci://registry.example.com/charts
96
+ ```
97
+
98
+ **values.yaml (image tag):**
99
+ ```yaml
100
+ # gitops-replacer: my-app-image
101
+ image: registry.example.com/myorg/my-app:1.2.3
102
+ ```
103
+
104
+ **Note:** Only YAML files are supported (JSON has no comments). GitOps manifests are typically YAML.
105
+
106
+ ## CLI
107
+
108
+ ```text
109
+ usage: gitops-replacer [-h] [--config <file>] [--apply] [--ci]
110
+ [--name <string>] [--email <string>]
111
+ [--message <string>] [--api <string>]
112
+ [--verbose]
113
+ <string>
114
+ ```
115
+
116
+ - `--config` Path to the configuration file (default: `gitops-replacer.json`). JSON recommended.
117
+ - `--apply` Apply changes (commit). Without this flag the tool runs in dry-run.
118
+ - `--ci` CI mode: validates `GITHUB_REF` against `when`/`except` regex patterns from config.
119
+ - `--name` Commit author name (default: env `GIT_COMMIT_NAME` or `Replacer Bot`).
120
+ - `--email` Commit author email (default: env `GIT_COMMIT_EMAIL` or `replacer-bot@localhost.localdomain`).
121
+ - `--message` Commit message template (default: `fix: update {} to {}`). First `{}` is depName, second is value.
122
+ - `--api` GitHub API URL (default: env `GITHUB_API_URL` or `https://api.github.com`).
123
+ - `--verbose` Print file contents and desired state (use with care in CI logs).
124
+ - Positional: `value` - the new value to set at the marked location.
125
+
126
+ ### Environment
127
+
128
+ - `GITHUB_TOKEN` **(required)** – token with access to read/write repository contents.
129
+ - `GITHUB_REF` *(required when `--ci`)* – the current ref string, e.g., `refs/heads/main`. Falls back to `GIT_REF` for backwards compatibility.
130
+
131
+ Recommended token scopes:
132
+ - Public repos only: `public_repo`
133
+ - Private repos: `repo`
134
+ - GitHub Enterprise: equivalent content permissions
135
+
136
+ ## Configuration
137
+
138
+ Default format is **JSON**. YAML (`.yaml`/`.yml`) is supported as well.
139
+
140
+ ### JSON schema (per entry)
141
+
142
+ ```json
143
+ {
144
+ "gitops-replacer": [
145
+ {
146
+ "repository": "acme/gitops",
147
+ "branch": "main",
148
+ "file": "apps/my-app/Chart.yaml",
149
+ "depName": "my-app",
150
+ "when": "^refs/heads/main$"
151
+ }
152
+ ]
153
+ }
154
+ ```
155
+
156
+ **Fields**
157
+
158
+ | Field | Description |
159
+ |-------|-------------|
160
+ | `repository` | Target repo on GitHub (`ORG/REPO` format) |
161
+ | `branch` | Target branch |
162
+ | `file` | Target file path relative to repo root |
163
+ | `depName` | Dependency name (must match marker in file) |
164
+ | `when` | Regex that must match `GITHUB_REF` when `--ci` is enabled (optional) |
165
+ | `except` | Regex that must **not** match `GITHUB_REF` when `--ci` is enabled (optional) |
166
+
167
+ > The tool uses `re.match` (anchored at the string start). Use `^...$` in your patterns if you require a full match.
168
+
169
+ ### Examples
170
+
171
+ **JSON (default)**
172
+
173
+ ```json
174
+ {
175
+ "gitops-replacer": [
176
+ {
177
+ "repository": "acme/gitops",
178
+ "branch": "main",
179
+ "file": "apps/my-app/Chart.yaml",
180
+ "depName": "my-app",
181
+ "when": "^refs/heads/(main|release/.*)$"
182
+ },
183
+ {
184
+ "repository": "acme/gitops",
185
+ "branch": "develop",
186
+ "file": "apps/my-app-dev/Chart.yaml",
187
+ "depName": "my-app",
188
+ "except": "^refs/heads/legacy/"
189
+ }
190
+ ]
191
+ }
192
+ ```
193
+
194
+ **YAML (alternative)**
195
+
196
+ ```yaml
197
+ gitops-replacer:
198
+ - repository: acme/gitops
199
+ branch: main
200
+ file: apps/my-app/Chart.yaml
201
+ depName: my-app
202
+ when: '^refs/heads/(main|release/.*)$'
203
+ - repository: acme/gitops
204
+ branch: develop
205
+ file: apps/my-app-dev/Chart.yaml
206
+ depName: my-app
207
+ except: '^refs/heads/legacy/'
208
+ ```
209
+
210
+ ## How it works
211
+
212
+ 1. **Validation**: Checks CLI arguments, environment variables, and configuration file
213
+ 2. **Precheck Phase**: Validates access to all target repositories/files (caches responses)
214
+ 3. **Replace Phase**: Downloads files (reuses cached data), finds marker comments, replaces values
215
+ 4. **Commit Phase**: If `--apply` is set and changes detected, commits via GitHub Contents API
216
+ 5. **Exit Codes**: Returns `0` on success, non-zero on failures
217
+
218
+ ### Why Marker-based?
219
+
220
+ Traditional approaches parse YAML, modify the data structure, and serialize back. This often breaks:
221
+ - Comments are lost
222
+ - Quote styles change (`"1.0"` becomes `'1.0'` or `1.0`)
223
+ - Key ordering may change
224
+ - Multi-line strings get reformatted
225
+
226
+ The marker-based approach works on raw text:
227
+ - **Explicit**: Only marked lines are modified
228
+ - **Safe**: No risk of unintended changes
229
+ - **Preserving**: Comments, quotes, and formatting stay intact
230
+
231
+ ## Exit Codes
232
+
233
+ - `0` success (no changes or committed changes)
234
+ - `1` validation or API error
235
+
236
+ ## Use Cases
237
+
238
+ ### Automated Deployment Pipeline
239
+
240
+ Update chart version when a new release is built:
241
+
242
+ ```bash
243
+ # In your CI/CD pipeline after publishing a chart
244
+ gitops-replacer --ci --apply "0.1.0-abc123"
245
+ ```
246
+
247
+ ### Multi-Environment Updates
248
+
249
+ Use CI mode to update different environments based on branch:
250
+
251
+ ```json
252
+ {
253
+ "gitops-replacer": [
254
+ {
255
+ "repository": "myorg/gitops",
256
+ "branch": "main",
257
+ "file": "apps/production/Chart.yaml",
258
+ "depName": "myapp",
259
+ "when": "^refs/heads/main$"
260
+ },
261
+ {
262
+ "repository": "myorg/gitops",
263
+ "branch": "main",
264
+ "file": "apps/staging/Chart.yaml",
265
+ "depName": "myapp",
266
+ "when": "^refs/heads/(main|develop)$"
267
+ }
268
+ ]
269
+ }
270
+ ```
271
+
272
+ ## Troubleshooting
273
+
274
+ ### Common Issues
275
+
276
+ **401 Unauthorized**
277
+ - Verify `GITHUB_TOKEN` is set correctly
278
+ - Check token has `repo` or `public_repo` scope
279
+ - For GitHub Enterprise, confirm token has access to the organization
280
+
281
+ **404 Not Found**
282
+ - Verify `repository`, `branch`, and `file` paths in config
283
+ - Check branch name spelling (case-sensitive)
284
+ - Ensure file exists at the specified path
285
+
286
+ **No marker found**
287
+ - Confirm the marker comment exists in the target file
288
+ - Check `depName` in config matches the marker exactly
289
+ - Marker format: `# gitops-replacer: <depName>`
290
+
291
+ **No changes detected**
292
+ - The current value already matches the new value
293
+ - Use `--verbose` to see file contents
294
+
295
+ ### Debug Mode
296
+
297
+ Run with `--verbose` to see:
298
+ - Full API URLs being called
299
+ - Complete file contents before replacement
300
+ - Desired file contents after replacement
301
+
302
+ **Warning**: Verbose mode may expose sensitive data in logs.
303
+
304
+ ## Contributing
305
+
306
+ Contributions are welcome! Please ensure:
307
+ - Code follows existing style and patterns
308
+ - Changes are tested with both dry-run and apply modes
309
+ - Documentation is updated for new features
310
+
311
+ ## License
312
+
313
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,11 @@
1
+ {
2
+ "gitops-replacer": [
3
+ {
4
+ "repository": "slauger/gitops",
5
+ "branch": "main",
6
+ "file": "apps/eibtalerhof-mcp-server/Chart.yaml",
7
+ "depName": "eibtalerhof-mcp-server",
8
+ "when": "^refs/heads/main$"
9
+ }
10
+ ]
11
+ }