pipecraft 0.0.0-releaseit

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.
Files changed (176) hide show
  1. package/.claude/settings.local.json +35 -0
  2. package/.github/actions/calculate-version/action.yml +106 -0
  3. package/.github/actions/create-pr/action.yml +122 -0
  4. package/.github/actions/create-release/action.yml +74 -0
  5. package/.github/actions/create-tag/action.yml +94 -0
  6. package/.github/actions/detect-changes/action.yml +62 -0
  7. package/.github/actions/manage-branch/action.yml +113 -0
  8. package/.github/actions/promote-branch/action.yml +352 -0
  9. package/.github/example/workflows/job.analyze.code.yml +26 -0
  10. package/.github/example/workflows/job.analyze.docker.yml +32 -0
  11. package/.github/example/workflows/job.app.api.deploy.yml +127 -0
  12. package/.github/example/workflows/job.app.api.test.yml +102 -0
  13. package/.github/example/workflows/job.app.docs.deploy.yml +40 -0
  14. package/.github/example/workflows/job.app.docs.test.yml +50 -0
  15. package/.github/example/workflows/job.app.web.deploy.yml +96 -0
  16. package/.github/example/workflows/job.app.web.test.yml +49 -0
  17. package/.github/example/workflows/job.changes.yml +82 -0
  18. package/.github/example/workflows/job.create-pr.yml +96 -0
  19. package/.github/example/workflows/job.env-check.yml +43 -0
  20. package/.github/example/workflows/job.fast-forward.yml +103 -0
  21. package/.github/example/workflows/job.lint.yml +64 -0
  22. package/.github/example/workflows/job.pr-name.yml +70 -0
  23. package/.github/example/workflows/job.pr-squash-name.yml +27 -0
  24. package/.github/example/workflows/job.tag.yml +38 -0
  25. package/.github/example/workflows/job.version.yml +99 -0
  26. package/.github/example/workflows/lib.plugin-base.publish.yml +59 -0
  27. package/.github/example/workflows/pipe.yml +178 -0
  28. package/.github/example/workflows/scripts/fastforward.sh +51 -0
  29. package/.github/example/workflows/scripts/pipe-cleaner.sh +70 -0
  30. package/.github/scripts/fastforward.sh +51 -0
  31. package/.github/scripts/pipe-cleaner.sh +70 -0
  32. package/.github/workflows/pipeline.yml +220 -0
  33. package/.github/workflows/pr-title-check.yml +70 -0
  34. package/.github/workflows/publish.yml +39 -0
  35. package/.pipecraftrc.json +78 -0
  36. package/.release-it.cjs +71 -0
  37. package/PIPELINE_TESTING_PLAN.md +499 -0
  38. package/README.md +1101 -0
  39. package/TRUNK_FLOW_PLAN.md +401 -0
  40. package/assets/logo_banner.png +0 -0
  41. package/assets/logo_banner.webp +0 -0
  42. package/dist/cli/index.d.ts +3 -0
  43. package/dist/cli/index.d.ts.map +1 -0
  44. package/dist/cli/index.js +364 -0
  45. package/dist/cli/index.js.map +1 -0
  46. package/dist/generators/init.tpl.d.ts +3 -0
  47. package/dist/generators/init.tpl.d.ts.map +1 -0
  48. package/dist/generators/init.tpl.js +117 -0
  49. package/dist/generators/init.tpl.js.map +1 -0
  50. package/dist/generators/workflows.tpl.d.ts +7 -0
  51. package/dist/generators/workflows.tpl.d.ts.map +1 -0
  52. package/dist/generators/workflows.tpl.js +73 -0
  53. package/dist/generators/workflows.tpl.js.map +1 -0
  54. package/dist/templates/actions/calculate-version.yml.tpl.d.ts +3 -0
  55. package/dist/templates/actions/calculate-version.yml.tpl.d.ts.map +1 -0
  56. package/dist/templates/actions/calculate-version.yml.tpl.js +122 -0
  57. package/dist/templates/actions/calculate-version.yml.tpl.js.map +1 -0
  58. package/dist/templates/actions/create-pr.yml.tpl.d.ts +3 -0
  59. package/dist/templates/actions/create-pr.yml.tpl.d.ts.map +1 -0
  60. package/dist/templates/actions/create-pr.yml.tpl.js +145 -0
  61. package/dist/templates/actions/create-pr.yml.tpl.js.map +1 -0
  62. package/dist/templates/actions/create-tag.yml.tpl.d.ts +3 -0
  63. package/dist/templates/actions/create-tag.yml.tpl.d.ts.map +1 -0
  64. package/dist/templates/actions/create-tag.yml.tpl.js +111 -0
  65. package/dist/templates/actions/create-tag.yml.tpl.js.map +1 -0
  66. package/dist/templates/actions/detect-changes.yml.tpl.d.ts +3 -0
  67. package/dist/templates/actions/detect-changes.yml.tpl.d.ts.map +1 -0
  68. package/dist/templates/actions/detect-changes.yml.tpl.js +79 -0
  69. package/dist/templates/actions/detect-changes.yml.tpl.js.map +1 -0
  70. package/dist/templates/actions/manage-branch.yml.tpl.d.ts +3 -0
  71. package/dist/templates/actions/manage-branch.yml.tpl.d.ts.map +1 -0
  72. package/dist/templates/actions/manage-branch.yml.tpl.js +130 -0
  73. package/dist/templates/actions/manage-branch.yml.tpl.js.map +1 -0
  74. package/dist/templates/actions/promote-branch.yml.tpl.d.ts +3 -0
  75. package/dist/templates/actions/promote-branch.yml.tpl.d.ts.map +1 -0
  76. package/dist/templates/actions/promote-branch.yml.tpl.js +362 -0
  77. package/dist/templates/actions/promote-branch.yml.tpl.js.map +1 -0
  78. package/dist/templates/workflows/pipeline-path-based.yml.tpl.d.ts +16 -0
  79. package/dist/templates/workflows/pipeline-path-based.yml.tpl.d.ts.map +1 -0
  80. package/dist/templates/workflows/pipeline-path-based.yml.tpl.js +652 -0
  81. package/dist/templates/workflows/pipeline-path-based.yml.tpl.js.map +1 -0
  82. package/dist/types/index.d.ts +63 -0
  83. package/dist/types/index.d.ts.map +1 -0
  84. package/dist/types/index.js +2 -0
  85. package/dist/types/index.js.map +1 -0
  86. package/dist/utils/ast-path-operations.d.ts +287 -0
  87. package/dist/utils/ast-path-operations.d.ts.map +1 -0
  88. package/dist/utils/ast-path-operations.js +419 -0
  89. package/dist/utils/ast-path-operations.js.map +1 -0
  90. package/dist/utils/config.d.ts +3 -0
  91. package/dist/utils/config.d.ts.map +1 -0
  92. package/dist/utils/config.js +49 -0
  93. package/dist/utils/config.js.map +1 -0
  94. package/dist/utils/github-setup.d.ts +74 -0
  95. package/dist/utils/github-setup.d.ts.map +1 -0
  96. package/dist/utils/github-setup.js +418 -0
  97. package/dist/utils/github-setup.js.map +1 -0
  98. package/dist/utils/idempotency.d.ts +47 -0
  99. package/dist/utils/idempotency.d.ts.map +1 -0
  100. package/dist/utils/idempotency.js +176 -0
  101. package/dist/utils/idempotency.js.map +1 -0
  102. package/dist/utils/preflight.d.ts +55 -0
  103. package/dist/utils/preflight.d.ts.map +1 -0
  104. package/dist/utils/preflight.js +261 -0
  105. package/dist/utils/preflight.js.map +1 -0
  106. package/dist/utils/versioning.d.ts +41 -0
  107. package/dist/utils/versioning.d.ts.map +1 -0
  108. package/dist/utils/versioning.js +219 -0
  109. package/dist/utils/versioning.js.map +1 -0
  110. package/docs/USER_JOURNEY_ERRORS.md +352 -0
  111. package/eslint.config.js +77 -0
  112. package/examples/basic-config.json +41 -0
  113. package/examples/monorepo-config.json +49 -0
  114. package/examples/usage.md +289 -0
  115. package/package.json +58 -0
  116. package/scripts/debug-workflows.sh +339 -0
  117. package/scripts/parse-pipeline.js +29 -0
  118. package/scripts/test-job-order.cjs +140 -0
  119. package/scripts/validate-pipeline.cjs +379 -0
  120. package/scripts/verify-job-order.sh +30 -0
  121. package/src/cli/index.ts +414 -0
  122. package/src/generators/init.tpl.ts +126 -0
  123. package/src/generators/workflows.tpl.ts +80 -0
  124. package/src/templates/actions/calculate-version.yml.tpl.ts +124 -0
  125. package/src/templates/actions/create-pr.yml.tpl.ts +147 -0
  126. package/src/templates/actions/create-tag.yml.tpl.ts +112 -0
  127. package/src/templates/actions/detect-changes.yml.tpl.ts +87 -0
  128. package/src/templates/actions/manage-branch.yml.tpl.ts +132 -0
  129. package/src/templates/actions/promote-branch.yml.tpl.ts +364 -0
  130. package/src/templates/workflows/pipeline-path-based.yml.tpl.ts +706 -0
  131. package/src/types/index.ts +64 -0
  132. package/src/utils/README-ast-path-operations.md +390 -0
  133. package/src/utils/ast-path-operations.ts +581 -0
  134. package/src/utils/config.ts +64 -0
  135. package/src/utils/github-setup.ts +558 -0
  136. package/src/utils/idempotency.ts +215 -0
  137. package/src/utils/preflight.ts +306 -0
  138. package/src/utils/versioning.ts +244 -0
  139. package/tests/README.md +229 -0
  140. package/tests/TEST_STRUCTURE.md +256 -0
  141. package/tests/act/run-act-tests.sh +345 -0
  142. package/tests/debugging/debug-utils.ts +538 -0
  143. package/tests/debugging/debug-workflow.test.ts +339 -0
  144. package/tests/debugging/debug-workflows.sh +339 -0
  145. package/tests/debugging/iterative-debug.ts +652 -0
  146. package/tests/debugging/run-debug-tests.sh +431 -0
  147. package/tests/fixtures/basic-config.json +51 -0
  148. package/tests/fixtures/invalid-config.json +9 -0
  149. package/tests/fixtures/pipeline-generated.yml +235 -0
  150. package/tests/fixtures/pipeline-preserve-comments.yml +245 -0
  151. package/tests/fixtures/pipeline-user-modified.yml +245 -0
  152. package/tests/fixtures/test-config.json +58 -0
  153. package/tests/github-live/README.md +250 -0
  154. package/tests/github-local/JOB_WORKFLOW_TESTS.md +296 -0
  155. package/tests/github-local/README.md +240 -0
  156. package/tests/github-local/run-all-tests.sh +422 -0
  157. package/tests/github-local/test-job-workflows.sh +631 -0
  158. package/tests/github-local/test-pipeline-workflow.sh +440 -0
  159. package/tests/integration/generators.test.ts +578 -0
  160. package/tests/integration/path-based-template.test.ts +510 -0
  161. package/tests/integration/simple-path-based.test.ts +415 -0
  162. package/tests/setup.ts +56 -0
  163. package/tests/unit/ast-path-operations-extended.test.ts +302 -0
  164. package/tests/unit/cli.test.ts +541 -0
  165. package/tests/unit/config-extended.test.ts +412 -0
  166. package/tests/unit/config.test.ts +152 -0
  167. package/tests/unit/github-setup.test.ts +189 -0
  168. package/tests/unit/idempotency-isolated.test.ts +297 -0
  169. package/tests/unit/job-order.test.ts +157 -0
  170. package/tests/unit/pipeline-path-based.test.ts +511 -0
  171. package/tests/unit/validate-pipeline.test.ts +384 -0
  172. package/tests/unit/versioning-extended.test.ts +279 -0
  173. package/tests/unit/versioning.test.ts +241 -0
  174. package/tsconfig.debug.json +17 -0
  175. package/tsconfig.json +28 -0
  176. package/vitest.config.ts +51 -0
@@ -0,0 +1,64 @@
1
+ export interface DomainConfig {
2
+ paths: string[]
3
+ description: string
4
+ testable?: boolean
5
+ deployable?: boolean
6
+ }
7
+
8
+
9
+ export interface PipecraftConfig {
10
+ ciProvider: 'github' | 'gitlab'
11
+ mergeStrategy: 'fast-forward' | 'merge'
12
+ requireConventionalCommits: boolean
13
+ initialBranch: string
14
+ finalBranch: string
15
+ branchFlow: string[]
16
+ autoMerge?: boolean | Record<string, boolean> // Auto-merge per target branch (default: false)
17
+ mergeMethod?: 'auto' | 'merge' | 'squash' | 'rebase' | Record<string, 'auto' | 'merge' | 'squash' | 'rebase'> // Merge method per target branch (default: 'auto' which uses fast-forward for autoMerge=true)
18
+ semver: {
19
+ bumpRules: Record<string, string>
20
+ }
21
+ actions: {
22
+ onDevelopMerge: string[]
23
+ onStagingMerge: string[]
24
+ }
25
+ domains: Record<string, DomainConfig>
26
+ // Idempotency and rebuild configuration
27
+ rebuild?: {
28
+ enabled: boolean
29
+ skipIfUnchanged: boolean
30
+ forceRegenerate: boolean
31
+ watchMode: boolean
32
+ hashAlgorithm: 'md5' | 'sha1' | 'sha256'
33
+ cacheFile: string
34
+ ignorePatterns: string[]
35
+ }
36
+ // Version management with release-it
37
+ versioning?: {
38
+ enabled: boolean
39
+ releaseItConfig: string
40
+ conventionalCommits: boolean
41
+ autoTag: boolean
42
+ autoPush: boolean
43
+ changelog: boolean
44
+ bumpRules: Record<string, string>
45
+ }
46
+ }
47
+
48
+ export interface PipecraftContext {
49
+ projectName: string
50
+ ciProvider: 'github' | 'gitlab'
51
+ mergeStrategy: 'fast-forward' | 'merge'
52
+ requireConventionalCommits: boolean
53
+ initialBranch: string
54
+ finalBranch: string
55
+ branchFlow: string[]
56
+ domains: Record<string, { paths: string[], description: string }>
57
+ semver: {
58
+ bumpRules: Record<string, string>
59
+ }
60
+ actions: {
61
+ onDevelopMerge: string[]
62
+ onStagingMerge: string[]
63
+ }
64
+ }
@@ -0,0 +1,390 @@
1
+ # AST Path Operations for YAML Manipulation
2
+
3
+ A powerful and precise library for manipulating YAML documents using path-based operations. This library allows you to target specific locations in YAML structures and apply different types of operations with full TypeScript support.
4
+
5
+ ## 🚀 Quick Start
6
+
7
+ ```typescript
8
+ import { applyPathOperations, createValueFromString } from './ast-path-operations'
9
+ import { parseDocument } from 'yaml'
10
+
11
+ // Create a YAML document
12
+ const doc = parseDocument(`
13
+ name: "Pipeline"
14
+ on:
15
+ pull_request:
16
+ branches: [main]
17
+ `)
18
+
19
+ // Define operations
20
+ const operations = [
21
+ {
22
+ path: 'on.workflow_call.inputs.version',
23
+ operation: 'set',
24
+ value: {
25
+ description: 'The version to deploy',
26
+ required: false,
27
+ type: 'string'
28
+ }
29
+ }
30
+ ]
31
+
32
+ // Apply operations
33
+ applyPathOperations(doc.contents, operations)
34
+ ```
35
+
36
+ ## 📋 Table of Contents
37
+
38
+ - [Features](#features)
39
+ - [Operation Types](#operation-types)
40
+ - [Value Types](#value-types)
41
+ - [API Reference](#api-reference)
42
+ - [Examples](#examples)
43
+ - [Best Practices](#best-practices)
44
+
45
+ ## ✨ Features
46
+
47
+ - **🎯 Path-based targeting**: Use dot notation to target specific YAML paths
48
+ - **🔧 Multiple operation types**: Set, merge, overwrite, or preserve values
49
+ - **📦 Flexible value types**: Support objects, arrays, strings, YAML nodes, and parsed documents
50
+ - **🛡️ Type safety**: Full TypeScript support with proper Node types
51
+ - **⚡ Context injection**: Dynamic values can be injected at build time
52
+ - **🔄 Intelligent merging**: Smart merge logic for objects and arrays
53
+
54
+ ## 🔧 Operation Types
55
+
56
+ ### `set`
57
+ Set a value at the specified path (creates if doesn't exist)
58
+
59
+ ```typescript
60
+ {
61
+ path: 'jobs.changes.runs-on',
62
+ operation: 'set',
63
+ value: 'ubuntu-latest'
64
+ }
65
+ ```
66
+
67
+ ### `merge`
68
+ Merge with existing value (for objects/arrays)
69
+
70
+ ```typescript
71
+ {
72
+ path: 'on.pull_request.branches',
73
+ operation: 'merge',
74
+ value: ['develop', 'staging', 'main']
75
+ }
76
+ ```
77
+
78
+ ### `overwrite`
79
+ Replace existing value completely
80
+
81
+ ```typescript
82
+ {
83
+ path: 'jobs.changes',
84
+ operation: 'overwrite',
85
+ value: createValueFromString(`
86
+ runs-on: ubuntu-latest
87
+ steps:
88
+ - uses: ./.github/actions/detect-changes
89
+ `)
90
+ }
91
+ ```
92
+
93
+ ### `preserve`
94
+ Keep existing value, ignore template value
95
+
96
+ ```typescript
97
+ {
98
+ path: 'jobs.user-custom-job',
99
+ operation: 'preserve',
100
+ value: null // This will be ignored
101
+ }
102
+ ```
103
+
104
+ ## 📦 Value Types
105
+
106
+ ### Objects
107
+ Simple key-value pairs for configuration
108
+
109
+ ```typescript
110
+ {
111
+ path: 'on.workflow_call.inputs.version',
112
+ operation: 'set',
113
+ value: {
114
+ description: 'The version to deploy',
115
+ required: false,
116
+ type: 'string'
117
+ }
118
+ }
119
+ ```
120
+
121
+ ### Arrays
122
+ Simple arrays for lists
123
+
124
+ ```typescript
125
+ {
126
+ path: 'on.pull_request.branches',
127
+ operation: 'merge',
128
+ value: ['develop', 'staging', 'main']
129
+ }
130
+ ```
131
+
132
+ ### YAML Strings
133
+ Multi-line YAML with proper formatting
134
+
135
+ ```typescript
136
+ {
137
+ path: 'jobs.changes',
138
+ operation: 'overwrite',
139
+ value: createValueFromString(`
140
+ runs-on: ubuntu-latest
141
+ steps:
142
+ - uses: ./.github/actions/detect-changes
143
+ with:
144
+ baseRef: \${{ inputs.baseRef || 'main' }}
145
+ `)
146
+ }
147
+ ```
148
+
149
+ ### Parsed Documents
150
+ Pre-parsed YAML nodes
151
+
152
+ ```typescript
153
+ const parsedJob = parseDocument(`
154
+ runs-on: ubuntu-latest
155
+ steps:
156
+ - name: Example step
157
+ run: echo "Hello"
158
+ `)
159
+
160
+ {
161
+ path: 'jobs.example',
162
+ operation: 'set',
163
+ value: parsedJob.contents
164
+ }
165
+ ```
166
+
167
+ ## 📚 API Reference
168
+
169
+ ### Core Functions
170
+
171
+ #### `applyPathOperations(doc, operations)`
172
+ Apply multiple path operations to a document
173
+
174
+ **Parameters:**
175
+ - `doc: YAMLMap` - The YAML document to modify
176
+ - `operations: PathOperationConfig[]` - Array of operations to apply
177
+
178
+ #### `setPathValue(doc, path, value)`
179
+ Set a value at a specific path in the YAML AST
180
+
181
+ **Parameters:**
182
+ - `doc: YAMLMap` - The YAML document to modify
183
+ - `path: string` - Dot-notation path (e.g., 'jobs.changes.steps')
184
+ - `value: PathValue` - Value to set at the path
185
+
186
+ #### `getPathValue(doc, path)`
187
+ Get a value at a specific path in the YAML AST
188
+
189
+ **Parameters:**
190
+ - `doc: YAMLMap` - The YAML document to read from
191
+ - `path: string` - Dot-notation path (e.g., 'jobs.changes.steps')
192
+ - **Returns:** `Node | null` - The node at the path, or null if not found
193
+
194
+ ### Helper Functions
195
+
196
+ #### `createValueFromString(yamlString)`
197
+ Create a YAML node from a YAML string
198
+
199
+ #### `createValueFromObject(obj)`
200
+ Create a YAML node from a JavaScript object
201
+
202
+ #### `createValueFromArray(arr)`
203
+ Create a YAML node from a JavaScript array
204
+
205
+ ## 💡 Examples
206
+
207
+ ### Basic Workflow Configuration
208
+
209
+ ```typescript
210
+ import { applyPathOperations, createValueFromString } from './ast-path-operations'
211
+ import { parseDocument } from 'yaml'
212
+
213
+ const doc = parseDocument('name: "Pipeline"')
214
+
215
+ const operations = [
216
+ // Set workflow inputs
217
+ {
218
+ path: 'on.workflow_call.inputs.version',
219
+ operation: 'set',
220
+ value: {
221
+ description: 'The version to deploy',
222
+ required: false,
223
+ type: 'string'
224
+ }
225
+ },
226
+
227
+ // Merge branch list
228
+ {
229
+ path: 'on.pull_request.branches',
230
+ operation: 'merge',
231
+ value: ['develop', 'staging', 'main']
232
+ },
233
+
234
+ // Overwrite job definition
235
+ {
236
+ path: 'jobs.changes',
237
+ operation: 'overwrite',
238
+ value: createValueFromString(`
239
+ runs-on: ubuntu-latest
240
+ steps:
241
+ - uses: ./.github/actions/detect-changes
242
+ with:
243
+ baseRef: \${{ inputs.baseRef || 'main' }}
244
+ `)
245
+ }
246
+ ]
247
+
248
+ applyPathOperations(doc.contents, operations)
249
+ ```
250
+
251
+ ### Complex Job Definitions
252
+
253
+ ```typescript
254
+ const jobOperations = [
255
+ {
256
+ path: 'jobs.test',
257
+ operation: 'overwrite',
258
+ value: createValueFromString(`
259
+ runs-on: ubuntu-latest
260
+ needs: changes
261
+ steps:
262
+ - name: Checkout code
263
+ uses: actions/checkout@v3
264
+ - name: Setup Node.js
265
+ uses: actions/setup-node@v3
266
+ with:
267
+ node-version: '18'
268
+ - name: Install dependencies
269
+ run: npm ci
270
+ - name: Run tests
271
+ run: npm test
272
+ `)
273
+ }
274
+ ]
275
+ ```
276
+
277
+ ### Preserving User Customizations
278
+
279
+ ```typescript
280
+ const operations = [
281
+ // Template-managed (always updated)
282
+ {
283
+ path: 'jobs.changes',
284
+ operation: 'overwrite',
285
+ value: createValueFromString(`...`) // Latest template
286
+ },
287
+
288
+ // User-managed (preserved)
289
+ {
290
+ path: 'jobs.user-tests',
291
+ operation: 'preserve',
292
+ value: null // User's customizations kept
293
+ }
294
+ ]
295
+ ```
296
+
297
+ ## 🎯 Best Practices
298
+
299
+ ### 1. Use Appropriate Value Types
300
+
301
+ **✅ Good:**
302
+ ```typescript
303
+ // Simple objects for configuration
304
+ { path: 'on.workflow_call.inputs.version', value: { description: '...', type: 'string' } }
305
+
306
+ // YAML strings for complex structures
307
+ { path: 'jobs.changes', value: createValueFromString(`runs-on: ubuntu-latest\nsteps: ...`) }
308
+ ```
309
+
310
+ **❌ Avoid:**
311
+ ```typescript
312
+ // Don't use YAML strings for simple values
313
+ { path: 'jobs.changes.runs-on', value: createValueFromString('ubuntu-latest') }
314
+ ```
315
+
316
+ ### 2. Choose the Right Operation
317
+
318
+ - **`set`**: For required configuration that must exist
319
+ - **`merge`**: For arrays/lists where you want to add items
320
+ - **`overwrite`**: For template-managed sections that should get updates
321
+ - **`preserve`**: For user-managed sections that should keep customizations
322
+
323
+ ### 3. Organize Operations by Purpose
324
+
325
+ ```typescript
326
+ const operations = [
327
+ // 1. Ensure required inputs exist
328
+ { path: 'on.workflow_call.inputs.version', operation: 'set', value: {...} },
329
+
330
+ // 2. Merge configuration
331
+ { path: 'on.pull_request.branches', operation: 'merge', value: [...] },
332
+
333
+ // 3. Overwrite template-managed jobs
334
+ { path: 'jobs.changes', operation: 'overwrite', value: createValueFromString(...) },
335
+
336
+ // 4. Preserve user sections
337
+ { path: 'jobs.user-tests', operation: 'preserve', value: null }
338
+ ]
339
+ ```
340
+
341
+ ### 4. Use Context Injection
342
+
343
+ ```typescript
344
+ const operations = [
345
+ {
346
+ path: 'jobs.version',
347
+ operation: 'overwrite',
348
+ value: createValueFromString(`
349
+ if: github.ref_name == '${ctx.initialBranch || 'develop'}'
350
+ needs: changes
351
+ runs-on: ubuntu-latest
352
+ `)
353
+ }
354
+ ]
355
+ ```
356
+
357
+ ## 🔍 Troubleshooting
358
+
359
+ ### Common Issues
360
+
361
+ **Path not found errors:**
362
+ - Ensure the path exists or use `required: false`
363
+ - Check for typos in dot notation paths
364
+
365
+ **Type errors:**
366
+ - Use proper TypeScript types for Node values
367
+ - Cast parsed documents correctly
368
+
369
+ **Merge conflicts:**
370
+ - Use `overwrite` for template-managed sections
371
+ - Use `preserve` for user-managed sections
372
+
373
+ ### Debug Tips
374
+
375
+ ```typescript
376
+ // Check if path exists before applying
377
+ const existingValue = getPathValue(doc, 'jobs.changes')
378
+ if (existingValue) {
379
+ console.log('Path exists:', stringify(existingValue))
380
+ }
381
+
382
+ // Use console.log to debug operations
383
+ console.log('Applying operation:', operation)
384
+ applyPathOperations(doc, [operation])
385
+ console.log('Result:', stringify(doc))
386
+ ```
387
+
388
+ ## 📄 License
389
+
390
+ This library is part of the Pipecraft project and follows the same licensing terms.