pipecraft 0.0.0-releaseit → 0.26.0

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 (183) hide show
  1. package/README.md +126 -108
  2. package/dist/cli/index.d.ts +69 -0
  3. package/dist/cli/index.d.ts.map +1 -1
  4. package/dist/cli/index.js +94 -22
  5. package/dist/cli/index.js.map +1 -1
  6. package/dist/generators/init.tpl.d.ts +70 -0
  7. package/dist/generators/init.tpl.d.ts.map +1 -1
  8. package/dist/generators/init.tpl.js +100 -8
  9. package/dist/generators/init.tpl.js.map +1 -1
  10. package/dist/generators/workflows.tpl.d.ts +86 -0
  11. package/dist/generators/workflows.tpl.d.ts.map +1 -1
  12. package/dist/generators/workflows.tpl.js +101 -9
  13. package/dist/generators/workflows.tpl.js.map +1 -1
  14. package/dist/templates/actions/calculate-version.yml.tpl.d.ts +47 -0
  15. package/dist/templates/actions/calculate-version.yml.tpl.d.ts.map +1 -1
  16. package/dist/templates/actions/calculate-version.yml.tpl.js +72 -3
  17. package/dist/templates/actions/calculate-version.yml.tpl.js.map +1 -1
  18. package/dist/templates/actions/create-pr.yml.tpl.d.ts +14 -0
  19. package/dist/templates/actions/create-pr.yml.tpl.d.ts.map +1 -1
  20. package/dist/templates/actions/create-pr.yml.tpl.js +22 -2
  21. package/dist/templates/actions/create-pr.yml.tpl.js.map +1 -1
  22. package/dist/templates/actions/create-release.yml.tpl.d.ts +18 -0
  23. package/dist/templates/actions/create-release.yml.tpl.d.ts.map +1 -0
  24. package/dist/templates/actions/create-release.yml.tpl.js +141 -0
  25. package/dist/templates/actions/create-release.yml.tpl.js.map +1 -0
  26. package/dist/templates/actions/create-tag.yml.tpl.d.ts +14 -0
  27. package/dist/templates/actions/create-tag.yml.tpl.d.ts.map +1 -1
  28. package/dist/templates/actions/create-tag.yml.tpl.js +22 -2
  29. package/dist/templates/actions/create-tag.yml.tpl.js.map +1 -1
  30. package/dist/templates/actions/detect-changes.yml.tpl.d.ts +70 -0
  31. package/dist/templates/actions/detect-changes.yml.tpl.d.ts.map +1 -1
  32. package/dist/templates/actions/detect-changes.yml.tpl.js +98 -2
  33. package/dist/templates/actions/detect-changes.yml.tpl.js.map +1 -1
  34. package/dist/templates/actions/manage-branch.yml.tpl.d.ts +14 -0
  35. package/dist/templates/actions/manage-branch.yml.tpl.d.ts.map +1 -1
  36. package/dist/templates/actions/manage-branch.yml.tpl.js +22 -2
  37. package/dist/templates/actions/manage-branch.yml.tpl.js.map +1 -1
  38. package/dist/templates/actions/promote-branch.yml.tpl.d.ts +14 -0
  39. package/dist/templates/actions/promote-branch.yml.tpl.d.ts.map +1 -1
  40. package/dist/templates/actions/promote-branch.yml.tpl.js +50 -7
  41. package/dist/templates/actions/promote-branch.yml.tpl.js.map +1 -1
  42. package/dist/templates/workflows/pipeline-path-based.yml.tpl.d.ts +114 -1
  43. package/dist/templates/workflows/pipeline-path-based.yml.tpl.d.ts.map +1 -1
  44. package/dist/templates/workflows/pipeline-path-based.yml.tpl.js +479 -74
  45. package/dist/templates/workflows/pipeline-path-based.yml.tpl.js.map +1 -1
  46. package/dist/types/index.d.ts +231 -8
  47. package/dist/types/index.d.ts.map +1 -1
  48. package/dist/types/index.js +9 -0
  49. package/dist/types/index.js.map +1 -1
  50. package/dist/utils/ast-path-operations.d.ts.map +1 -1
  51. package/dist/utils/ast-path-operations.js +24 -11
  52. package/dist/utils/ast-path-operations.js.map +1 -1
  53. package/dist/utils/config.d.ts +63 -0
  54. package/dist/utils/config.d.ts.map +1 -1
  55. package/dist/utils/config.js +71 -0
  56. package/dist/utils/config.js.map +1 -1
  57. package/dist/utils/github-setup.d.ts +323 -2
  58. package/dist/utils/github-setup.d.ts.map +1 -1
  59. package/dist/utils/github-setup.js +551 -23
  60. package/dist/utils/github-setup.js.map +1 -1
  61. package/dist/utils/idempotency.d.ts +147 -7
  62. package/dist/utils/idempotency.d.ts.map +1 -1
  63. package/dist/utils/idempotency.js +143 -15
  64. package/dist/utils/idempotency.js.map +1 -1
  65. package/dist/utils/logger.d.ts +134 -0
  66. package/dist/utils/logger.d.ts.map +1 -0
  67. package/dist/utils/logger.js +153 -0
  68. package/dist/utils/logger.js.map +1 -0
  69. package/dist/utils/preflight.d.ts +223 -12
  70. package/dist/utils/preflight.d.ts.map +1 -1
  71. package/dist/utils/preflight.js +216 -16
  72. package/dist/utils/preflight.js.map +1 -1
  73. package/dist/utils/versioning.d.ts +160 -8
  74. package/dist/utils/versioning.d.ts.map +1 -1
  75. package/dist/utils/versioning.js +179 -15
  76. package/dist/utils/versioning.js.map +1 -1
  77. package/package.json +26 -5
  78. package/.claude/settings.local.json +0 -35
  79. package/.github/actions/calculate-version/action.yml +0 -106
  80. package/.github/actions/create-pr/action.yml +0 -122
  81. package/.github/actions/create-release/action.yml +0 -74
  82. package/.github/actions/create-tag/action.yml +0 -94
  83. package/.github/actions/detect-changes/action.yml +0 -62
  84. package/.github/actions/manage-branch/action.yml +0 -113
  85. package/.github/actions/promote-branch/action.yml +0 -352
  86. package/.github/example/workflows/job.analyze.code.yml +0 -26
  87. package/.github/example/workflows/job.analyze.docker.yml +0 -32
  88. package/.github/example/workflows/job.app.api.deploy.yml +0 -127
  89. package/.github/example/workflows/job.app.api.test.yml +0 -102
  90. package/.github/example/workflows/job.app.docs.deploy.yml +0 -40
  91. package/.github/example/workflows/job.app.docs.test.yml +0 -50
  92. package/.github/example/workflows/job.app.web.deploy.yml +0 -96
  93. package/.github/example/workflows/job.app.web.test.yml +0 -49
  94. package/.github/example/workflows/job.changes.yml +0 -82
  95. package/.github/example/workflows/job.create-pr.yml +0 -96
  96. package/.github/example/workflows/job.env-check.yml +0 -43
  97. package/.github/example/workflows/job.fast-forward.yml +0 -103
  98. package/.github/example/workflows/job.lint.yml +0 -64
  99. package/.github/example/workflows/job.pr-name.yml +0 -70
  100. package/.github/example/workflows/job.pr-squash-name.yml +0 -27
  101. package/.github/example/workflows/job.tag.yml +0 -38
  102. package/.github/example/workflows/job.version.yml +0 -99
  103. package/.github/example/workflows/lib.plugin-base.publish.yml +0 -59
  104. package/.github/example/workflows/pipe.yml +0 -178
  105. package/.github/example/workflows/scripts/fastforward.sh +0 -51
  106. package/.github/example/workflows/scripts/pipe-cleaner.sh +0 -70
  107. package/.github/scripts/fastforward.sh +0 -51
  108. package/.github/scripts/pipe-cleaner.sh +0 -70
  109. package/.github/workflows/pipeline.yml +0 -220
  110. package/.github/workflows/pr-title-check.yml +0 -70
  111. package/.github/workflows/publish.yml +0 -39
  112. package/.pipecraftrc.json +0 -78
  113. package/.release-it.cjs +0 -71
  114. package/PIPELINE_TESTING_PLAN.md +0 -499
  115. package/TRUNK_FLOW_PLAN.md +0 -401
  116. package/assets/logo_banner.png +0 -0
  117. package/assets/logo_banner.webp +0 -0
  118. package/docs/USER_JOURNEY_ERRORS.md +0 -352
  119. package/eslint.config.js +0 -77
  120. package/examples/basic-config.json +0 -41
  121. package/examples/monorepo-config.json +0 -49
  122. package/examples/usage.md +0 -289
  123. package/scripts/debug-workflows.sh +0 -339
  124. package/scripts/parse-pipeline.js +0 -29
  125. package/scripts/test-job-order.cjs +0 -140
  126. package/scripts/validate-pipeline.cjs +0 -379
  127. package/scripts/verify-job-order.sh +0 -30
  128. package/src/cli/index.ts +0 -414
  129. package/src/generators/init.tpl.ts +0 -126
  130. package/src/generators/workflows.tpl.ts +0 -80
  131. package/src/templates/actions/calculate-version.yml.tpl.ts +0 -124
  132. package/src/templates/actions/create-pr.yml.tpl.ts +0 -147
  133. package/src/templates/actions/create-tag.yml.tpl.ts +0 -112
  134. package/src/templates/actions/detect-changes.yml.tpl.ts +0 -87
  135. package/src/templates/actions/manage-branch.yml.tpl.ts +0 -132
  136. package/src/templates/actions/promote-branch.yml.tpl.ts +0 -364
  137. package/src/templates/workflows/pipeline-path-based.yml.tpl.ts +0 -706
  138. package/src/types/index.ts +0 -64
  139. package/src/utils/README-ast-path-operations.md +0 -390
  140. package/src/utils/ast-path-operations.ts +0 -581
  141. package/src/utils/config.ts +0 -64
  142. package/src/utils/github-setup.ts +0 -558
  143. package/src/utils/idempotency.ts +0 -215
  144. package/src/utils/preflight.ts +0 -306
  145. package/src/utils/versioning.ts +0 -244
  146. package/tests/README.md +0 -229
  147. package/tests/TEST_STRUCTURE.md +0 -256
  148. package/tests/act/run-act-tests.sh +0 -345
  149. package/tests/debugging/debug-utils.ts +0 -538
  150. package/tests/debugging/debug-workflow.test.ts +0 -339
  151. package/tests/debugging/debug-workflows.sh +0 -339
  152. package/tests/debugging/iterative-debug.ts +0 -652
  153. package/tests/debugging/run-debug-tests.sh +0 -431
  154. package/tests/fixtures/basic-config.json +0 -51
  155. package/tests/fixtures/invalid-config.json +0 -9
  156. package/tests/fixtures/pipeline-generated.yml +0 -235
  157. package/tests/fixtures/pipeline-preserve-comments.yml +0 -245
  158. package/tests/fixtures/pipeline-user-modified.yml +0 -245
  159. package/tests/fixtures/test-config.json +0 -58
  160. package/tests/github-live/README.md +0 -250
  161. package/tests/github-local/JOB_WORKFLOW_TESTS.md +0 -296
  162. package/tests/github-local/README.md +0 -240
  163. package/tests/github-local/run-all-tests.sh +0 -422
  164. package/tests/github-local/test-job-workflows.sh +0 -631
  165. package/tests/github-local/test-pipeline-workflow.sh +0 -440
  166. package/tests/integration/generators.test.ts +0 -578
  167. package/tests/integration/path-based-template.test.ts +0 -510
  168. package/tests/integration/simple-path-based.test.ts +0 -415
  169. package/tests/setup.ts +0 -56
  170. package/tests/unit/ast-path-operations-extended.test.ts +0 -302
  171. package/tests/unit/cli.test.ts +0 -541
  172. package/tests/unit/config-extended.test.ts +0 -412
  173. package/tests/unit/config.test.ts +0 -152
  174. package/tests/unit/github-setup.test.ts +0 -189
  175. package/tests/unit/idempotency-isolated.test.ts +0 -297
  176. package/tests/unit/job-order.test.ts +0 -157
  177. package/tests/unit/pipeline-path-based.test.ts +0 -511
  178. package/tests/unit/validate-pipeline.test.ts +0 -384
  179. package/tests/unit/versioning-extended.test.ts +0 -279
  180. package/tests/unit/versioning.test.ts +0 -241
  181. package/tsconfig.debug.json +0 -17
  182. package/tsconfig.json +0 -28
  183. package/vitest.config.ts +0 -51
@@ -1,541 +0,0 @@
1
- /**
2
- * CLI Unit Tests
3
- *
4
- * These tests directly test the CLI logic without spawning processes,
5
- * avoiding the race conditions that plagued the previous integration tests.
6
- *
7
- * Strategy:
8
- * - Mock external dependencies (fs, runModule, etc.)
9
- * - Test command logic directly
10
- * - Use isolated temp directories
11
- * - Verify correct function calls and outputs
12
- */
13
-
14
- import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
15
- import { writeFileSync, existsSync, rmSync, mkdirSync } from 'fs'
16
- import { join } from 'path'
17
- import { tmpdir } from 'os'
18
-
19
- // We'll test by mocking and importing the functions that would be called
20
- // Note: The CLI uses commander which makes it hard to test directly
21
- // So we'll test the underlying logic functions instead
22
-
23
- import { loadConfig, validateConfig } from '../../src/utils/config'
24
- import { IdempotencyManager } from '../../src/utils/idempotency'
25
- import { VersionManager } from '../../src/utils/versioning'
26
- import { PipecraftConfig } from '../../src/types'
27
-
28
- describe('CLI Logic Tests', () => {
29
- let testDir: string
30
- let originalCwd: string
31
-
32
- beforeEach(() => {
33
- // Create unique temp directory for this test
34
- testDir = join(tmpdir(), `pipecraft-cli-test-${Date.now()}-${Math.random().toString(36).slice(2)}`)
35
- mkdirSync(testDir, { recursive: true })
36
- originalCwd = process.cwd()
37
- process.chdir(testDir)
38
- })
39
-
40
- afterEach(() => {
41
- // Restore original directory and cleanup
42
- try {
43
- // Only chdir if the original directory still exists
44
- if (existsSync(originalCwd)) {
45
- process.chdir(originalCwd)
46
- } else {
47
- // Fallback to a safe directory if original doesn't exist
48
- process.chdir(__dirname)
49
- }
50
- } catch (error) {
51
- // If chdir fails, try to go to the test directory parent
52
- process.chdir(__dirname)
53
- }
54
-
55
- if (existsSync(testDir)) {
56
- rmSync(testDir, { recursive: true, force: true })
57
- }
58
- })
59
-
60
- describe('Config Loading and Validation', () => {
61
- it('should load valid config file', () => {
62
- const config: PipecraftConfig = {
63
- ciProvider: 'github',
64
- mergeStrategy: 'fast-forward',
65
- requireConventionalCommits: true,
66
- initialBranch: 'develop',
67
- finalBranch: 'main',
68
- branchFlow: ['develop', 'staging', 'main'],
69
- semver: {
70
- bumpRules: {
71
- feat: 'minor',
72
- fix: 'patch',
73
- breaking: 'major'
74
- }
75
- },
76
- actions: {
77
- onDevelopMerge: ['runTests', 'fastForwardToStaging'],
78
- onStagingMerge: ['runTests', 'calculateVersion', 'createOrFastForwardToMain']
79
- },
80
- domains: {
81
- api: {
82
- paths: ['apps/api/**'],
83
- description: 'API application'
84
- }
85
- }
86
- }
87
-
88
- const configPath = join(testDir, '.pipecraftrc.json')
89
- writeFileSync(configPath, JSON.stringify(config, null, 2))
90
-
91
- const loadedConfig = loadConfig(configPath)
92
- expect(loadedConfig).toBeDefined()
93
- expect(loadedConfig.ciProvider).toBe('github')
94
- expect(loadedConfig.domains).toHaveProperty('api')
95
- })
96
-
97
- it('should throw error when config file not found', () => {
98
- expect(() => loadConfig(join(testDir, 'nonexistent.json'))).toThrow()
99
- })
100
-
101
- it('should validate correct config', () => {
102
- const config: PipecraftConfig = {
103
- ciProvider: 'github',
104
- mergeStrategy: 'fast-forward',
105
- requireConventionalCommits: true,
106
- initialBranch: 'develop',
107
- finalBranch: 'main',
108
- branchFlow: ['develop', 'main'],
109
- semver: {
110
- bumpRules: {
111
- feat: 'minor',
112
- fix: 'patch',
113
- breaking: 'major'
114
- }
115
- },
116
- actions: {
117
- onDevelopMerge: ['runTests']
118
- },
119
- domains: {
120
- api: {
121
- paths: ['apps/api/**'],
122
- description: 'API'
123
- }
124
- }
125
- }
126
-
127
- expect(() => validateConfig(config)).not.toThrow()
128
- })
129
-
130
- it('should fail validation for invalid config', () => {
131
- const invalidConfig = {
132
- ciProvider: 'invalid-provider', // Invalid
133
- mergeStrategy: 'fast-forward',
134
- requireConventionalCommits: true,
135
- initialBranch: 'develop',
136
- finalBranch: 'main'
137
- } as any
138
-
139
- expect(() => validateConfig(invalidConfig)).toThrow()
140
- })
141
-
142
- it('should fail validation for missing required fields', () => {
143
- const incompleteConfig = {
144
- ciProvider: 'github'
145
- // Missing other required fields
146
- } as any
147
-
148
- expect(() => validateConfig(incompleteConfig)).toThrow()
149
- })
150
- })
151
-
152
- describe('Generate Command Logic', () => {
153
- let config: PipecraftConfig
154
-
155
- beforeEach(() => {
156
- config = {
157
- ciProvider: 'github',
158
- mergeStrategy: 'fast-forward',
159
- requireConventionalCommits: true,
160
- initialBranch: 'develop',
161
- finalBranch: 'main',
162
- branchFlow: ['develop', 'main'],
163
- semver: {
164
- bumpRules: {
165
- feat: 'minor',
166
- fix: 'patch',
167
- breaking: 'major'
168
- }
169
- },
170
- actions: {
171
- onDevelopMerge: ['runTests']
172
- },
173
- domains: {
174
- api: {
175
- paths: ['apps/api/**'],
176
- description: 'API'
177
- }
178
- },
179
- rebuild: {
180
- enabled: true,
181
- skipIfUnchanged: true,
182
- forceRegenerate: false,
183
- watchMode: false,
184
- hashAlgorithm: 'sha256',
185
- cacheFile: join(testDir, '.pipecraft-cache.json'),
186
- ignorePatterns: []
187
- }
188
- }
189
-
190
- const configPath = join(testDir, '.pipecraftrc.json')
191
- writeFileSync(configPath, JSON.stringify(config, null, 2))
192
- })
193
-
194
- it('should detect when regeneration is needed (no cache)', async () => {
195
- const idempotencyManager = new IdempotencyManager(config)
196
- const hasChanges = await idempotencyManager.hasChanges()
197
-
198
- expect(hasChanges).toBe(true)
199
- })
200
-
201
- it('should detect no changes when cache exists and unchanged', async () => {
202
- const idempotencyManager = new IdempotencyManager(config)
203
-
204
- // Create initial cache
205
- await idempotencyManager.updateCache()
206
-
207
- // Check again - should be no changes
208
- const hasChanges = await idempotencyManager.hasChanges()
209
-
210
- expect(hasChanges).toBe(false)
211
- })
212
-
213
- it('should force regeneration when force flag is true', async () => {
214
- const configWithForce = {
215
- ...config,
216
- rebuild: {
217
- ...config.rebuild!,
218
- forceRegenerate: true
219
- }
220
- }
221
-
222
- const idempotencyManager = new IdempotencyManager(configWithForce)
223
-
224
- // Even with cache, should return true due to force
225
- await idempotencyManager.updateCache()
226
- const hasChanges = await idempotencyManager.hasChanges()
227
-
228
- expect(hasChanges).toBe(true)
229
- })
230
-
231
- it('should skip regeneration when rebuild is disabled', async () => {
232
- const configWithoutRebuild = {
233
- ...config,
234
- rebuild: {
235
- ...config.rebuild!,
236
- enabled: false
237
- }
238
- }
239
-
240
- const idempotencyManager = new IdempotencyManager(configWithoutRebuild)
241
- const hasChanges = await idempotencyManager.hasChanges()
242
-
243
- // Should always return true when rebuild is disabled
244
- expect(hasChanges).toBe(true)
245
- })
246
-
247
- it('should update cache after generation', async () => {
248
- const idempotencyManager = new IdempotencyManager(config)
249
- const cacheFile = join(testDir, '.pipecraft-cache.json')
250
-
251
- // Cache shouldn't exist initially
252
- expect(existsSync(cacheFile)).toBe(false)
253
-
254
- // Update cache
255
- await idempotencyManager.updateCache()
256
-
257
- // Cache should now exist
258
- expect(existsSync(cacheFile)).toBe(true)
259
-
260
- // Cache should contain valid data
261
- const cache = idempotencyManager.loadCache()
262
- expect(cache).toBeDefined()
263
- expect(cache?.configHash).toBeDefined()
264
- expect(cache?.lastGenerated).toBeDefined()
265
- })
266
- })
267
-
268
- describe('Version Command Logic', () => {
269
- let config: PipecraftConfig
270
-
271
- beforeEach(() => {
272
- config = {
273
- ciProvider: 'github',
274
- mergeStrategy: 'fast-forward',
275
- requireConventionalCommits: true,
276
- initialBranch: 'develop',
277
- finalBranch: 'main',
278
- branchFlow: ['develop', 'main'],
279
- semver: {
280
- bumpRules: {
281
- feat: 'minor',
282
- fix: 'patch',
283
- breaking: 'major'
284
- }
285
- },
286
- actions: {
287
- onDevelopMerge: ['runTests']
288
- },
289
- domains: {
290
- api: {
291
- paths: ['apps/api/**'],
292
- description: 'API'
293
- }
294
- },
295
- versioning: {
296
- enabled: true,
297
- releaseItConfig: '.release-it.cjs',
298
- conventionalCommits: true,
299
- autoTag: true,
300
- autoPush: true,
301
- changelog: true,
302
- bumpRules: {
303
- feat: 'minor',
304
- fix: 'patch',
305
- breaking: 'major'
306
- }
307
- }
308
- }
309
-
310
- // Create package.json for version reading
311
- writeFileSync(join(testDir, 'package.json'), JSON.stringify({
312
- name: 'test-project',
313
- version: '1.0.0'
314
- }, null, 2))
315
- })
316
-
317
- it('should create version manager with config', () => {
318
- const versionManager = new VersionManager(config)
319
- expect(versionManager).toBeDefined()
320
- })
321
-
322
- it('should calculate next version based on commits', () => {
323
- const versionManager = new VersionManager(config)
324
- const nextVersion = versionManager.calculateNextVersion()
325
-
326
- expect(nextVersion).toBeDefined()
327
- expect(nextVersion.version).toBeDefined()
328
- expect(nextVersion.type).toBeDefined()
329
- })
330
-
331
- it('should validate conventional commits', () => {
332
- const versionManager = new VersionManager(config)
333
- const isValid = versionManager.validateConventionalCommits()
334
-
335
- // Should return boolean
336
- expect(typeof isValid).toBe('boolean')
337
- })
338
- })
339
-
340
- describe('Verify Command Logic', () => {
341
- it('should detect when config file exists', () => {
342
- const config = {
343
- ciProvider: 'github',
344
- mergeStrategy: 'fast-forward',
345
- requireConventionalCommits: true,
346
- initialBranch: 'develop',
347
- finalBranch: 'main',
348
- branchFlow: ['develop', 'main'],
349
- domains: {
350
- api: { paths: ['apps/api/**'], description: 'API' }
351
- }
352
- } as PipecraftConfig
353
-
354
- writeFileSync(join(testDir, '.pipecraftrc.json'), JSON.stringify(config, null, 2))
355
-
356
- expect(existsSync(join(testDir, '.pipecraftrc.json'))).toBe(true)
357
- })
358
-
359
- it('should detect when workflow files exist', () => {
360
- const workflowDir = join(testDir, '.github', 'workflows')
361
- mkdirSync(workflowDir, { recursive: true })
362
-
363
- const pipelineFile = join(workflowDir, 'pipeline.yml')
364
- writeFileSync(pipelineFile, 'name: Pipeline\n')
365
-
366
- expect(existsSync(pipelineFile)).toBe(true)
367
- })
368
-
369
- it('should handle missing workflow directory', () => {
370
- const workflowDir = join(testDir, '.github', 'workflows')
371
-
372
- expect(existsSync(workflowDir)).toBe(false)
373
- })
374
- })
375
-
376
- describe('Error Handling', () => {
377
- it('should handle malformed config file', () => {
378
- const configPath = join(testDir, '.pipecraftrc.json')
379
- writeFileSync(configPath, '{ invalid json }')
380
-
381
- expect(() => loadConfig(configPath)).toThrow()
382
- })
383
-
384
- it('should handle config with missing domains', () => {
385
- const config = {
386
- ciProvider: 'github',
387
- mergeStrategy: 'fast-forward',
388
- requireConventionalCommits: true,
389
- initialBranch: 'develop',
390
- finalBranch: 'main',
391
- branchFlow: ['develop', 'main']
392
- // Missing domains
393
- } as any
394
-
395
- expect(() => validateConfig(config)).toThrow()
396
- })
397
-
398
- it('should handle empty branch flow', () => {
399
- const config = {
400
- ciProvider: 'github',
401
- mergeStrategy: 'fast-forward',
402
- requireConventionalCommits: true,
403
- initialBranch: 'develop',
404
- finalBranch: 'main',
405
- branchFlow: [], // Empty
406
- domains: {
407
- api: { paths: ['apps/api/**'], description: 'API' }
408
- }
409
- } as any
410
-
411
- expect(() => validateConfig(config)).toThrow()
412
- })
413
- })
414
-
415
- describe('Configuration Edge Cases', () => {
416
- it('should handle custom branch names', () => {
417
- const config: PipecraftConfig = {
418
- ciProvider: 'github',
419
- mergeStrategy: 'fast-forward',
420
- requireConventionalCommits: true,
421
- initialBranch: 'alpha',
422
- finalBranch: 'production',
423
- branchFlow: ['alpha', 'beta', 'gamma', 'production'],
424
- semver: {
425
- bumpRules: {
426
- feat: 'minor',
427
- fix: 'patch',
428
- breaking: 'major'
429
- }
430
- },
431
- actions: {
432
- onDevelopMerge: ['runTests']
433
- },
434
- domains: {
435
- backend: {
436
- paths: ['services/backend/**'],
437
- description: 'Backend services'
438
- }
439
- }
440
- }
441
-
442
- writeFileSync(join(testDir, '.pipecraftrc.json'), JSON.stringify(config, null, 2))
443
-
444
- const loadedConfig = loadConfig(join(testDir, '.pipecraftrc.json'))
445
- expect(loadedConfig.initialBranch).toBe('alpha')
446
- expect(loadedConfig.finalBranch).toBe('production')
447
- expect(loadedConfig.branchFlow).toHaveLength(4)
448
- })
449
-
450
- it('should handle many domains', () => {
451
- const config: PipecraftConfig = {
452
- ciProvider: 'github',
453
- mergeStrategy: 'fast-forward',
454
- requireConventionalCommits: true,
455
- initialBranch: 'develop',
456
- finalBranch: 'main',
457
- branchFlow: ['develop', 'main'],
458
- semver: {
459
- bumpRules: {
460
- feat: 'minor',
461
- fix: 'patch',
462
- breaking: 'major'
463
- }
464
- },
465
- actions: {
466
- onDevelopMerge: ['runTests']
467
- },
468
- domains: {
469
- 'api': { paths: ['apps/api/**'], description: 'API' },
470
- 'web': { paths: ['apps/web/**'], description: 'Web' },
471
- 'mobile': { paths: ['apps/mobile/**'], description: 'Mobile' },
472
- 'admin': { paths: ['apps/admin/**'], description: 'Admin' },
473
- 'analytics': { paths: ['apps/analytics/**'], description: 'Analytics' }
474
- }
475
- }
476
-
477
- writeFileSync(join(testDir, '.pipecraftrc.json'), JSON.stringify(config, null, 2))
478
-
479
- const loadedConfig = loadConfig(join(testDir, '.pipecraftrc.json'))
480
- expect(Object.keys(loadedConfig.domains)).toHaveLength(5)
481
- })
482
-
483
- it('should handle gitlab CI provider', () => {
484
- const config: PipecraftConfig = {
485
- ciProvider: 'gitlab',
486
- mergeStrategy: 'fast-forward',
487
- requireConventionalCommits: true,
488
- initialBranch: 'develop',
489
- finalBranch: 'main',
490
- branchFlow: ['develop', 'main'],
491
- semver: {
492
- bumpRules: {
493
- feat: 'minor',
494
- fix: 'patch',
495
- breaking: 'major'
496
- }
497
- },
498
- actions: {
499
- onDevelopMerge: ['runTests']
500
- },
501
- domains: {
502
- api: { paths: ['apps/api/**'], description: 'API' }
503
- }
504
- }
505
-
506
- writeFileSync(join(testDir, '.pipecraftrc.json'), JSON.stringify(config, null, 2))
507
-
508
- const loadedConfig = loadConfig(join(testDir, '.pipecraftrc.json'))
509
- expect(loadedConfig.ciProvider).toBe('gitlab')
510
- })
511
-
512
- it('should handle merge strategy', () => {
513
- const config: PipecraftConfig = {
514
- ciProvider: 'github',
515
- mergeStrategy: 'merge',
516
- requireConventionalCommits: true,
517
- initialBranch: 'develop',
518
- finalBranch: 'main',
519
- branchFlow: ['develop', 'main'],
520
- semver: {
521
- bumpRules: {
522
- feat: 'minor',
523
- fix: 'patch',
524
- breaking: 'major'
525
- }
526
- },
527
- actions: {
528
- onDevelopMerge: ['runTests']
529
- },
530
- domains: {
531
- api: { paths: ['apps/api/**'], description: 'API' }
532
- }
533
- }
534
-
535
- writeFileSync(join(testDir, '.pipecraftrc.json'), JSON.stringify(config, null, 2))
536
-
537
- const loadedConfig = loadConfig(join(testDir, '.pipecraftrc.json'))
538
- expect(loadedConfig.mergeStrategy).toBe('merge')
539
- })
540
- })
541
- })