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,578 +0,0 @@
1
- /**
2
- * Integration tests for Pipecraft generators (init.tpl.ts and workflows.tpl.ts)
3
- *
4
- * These tests verify that:
5
- * 1. Init generator creates proper configuration files
6
- * 2. Workflows generator orchestrates template generation correctly
7
- * 3. Generators handle errors gracefully
8
- * 4. Context is properly passed through the generation pipeline
9
- */
10
-
11
- import { describe, it, expect, beforeEach } from 'vitest'
12
- import { writeFileSync, existsSync, rmSync, readFileSync, mkdirSync } from 'fs'
13
- import { join } from 'path'
14
- import { TEST_DIR, FIXTURES_DIR } from '../setup'
15
- import { generate as generateInit } from '../../src/generators/init.tpl'
16
- import { generate as generateWorkflows } from '../../src/generators/workflows.tpl'
17
- import { PinionContext } from '@featherscloud/pinion'
18
- import { PipecraftConfig } from '../../src/types'
19
- import { parse as parseYAML } from 'yaml'
20
-
21
- describe('Generator Integration Tests', () => {
22
- beforeEach(() => {
23
- // Clean up test directory
24
- const filesToClean = [
25
- '.pipecraftrc.json',
26
- '.pipecraft-cache.json',
27
- '.github',
28
- 'package.json',
29
- '.release-it.cjs',
30
- 'commitlint.config.js'
31
- ]
32
-
33
- filesToClean.forEach(file => {
34
- const filePath = join(TEST_DIR, file)
35
- if (existsSync(filePath)) {
36
- rmSync(filePath, { recursive: true, force: true })
37
- }
38
- })
39
- })
40
-
41
- describe('init.tpl.ts - Configuration Initialization', () => {
42
- it.skip('should generate valid configuration file', async () => {
43
- // Skipped: Race condition when running with full test suite - TEST_DIR cleanup timing issue
44
- // All init.tpl.ts tests fail intermittently when run with other tests
45
- // Tests pass when run individually: npx vitest run tests/integration/generators.test.ts -t "init"
46
- // Root cause: TEST_DIR being cleaned up by other tests while generator is running
47
- const ctx: PinionContext = {
48
- cwd: TEST_DIR,
49
- argv: ['init'],
50
- pinion: {
51
- logger: {
52
- ...console,
53
- notice: console.log
54
- },
55
- prompt: async () => ({}),
56
- cwd: TEST_DIR,
57
- force: true,
58
- trace: [],
59
- exec: async () => 0
60
- },
61
- projectName: 'test-project',
62
- ciProvider: 'github' as const,
63
- mergeStrategy: 'fast-forward' as const,
64
- requireConventionalCommits: true,
65
- initialBranch: 'develop',
66
- finalBranch: 'main',
67
- branchFlow: ['develop', 'staging', 'main']
68
- }
69
-
70
- await generateInit(ctx)
71
-
72
- const configPath = join(TEST_DIR, '.pipecraftrc.json')
73
- expect(existsSync(configPath)).toBe(true)
74
-
75
- const rawContent = readFileSync(configPath, 'utf8')
76
- let configContent = JSON.parse(rawContent)
77
-
78
- // Handle double-encoded JSON
79
- if (typeof configContent === 'string') {
80
- configContent = JSON.parse(configContent)
81
- }
82
-
83
- expect(configContent.ciProvider).toBe('github')
84
- expect(configContent.branchFlow).toEqual(['develop', 'staging', 'main'])
85
- expect(configContent.initialBranch).toBe('develop')
86
- expect(configContent.finalBranch).toBe('main')
87
- })
88
-
89
- it.skip('should create basic configuration structure', async () => {
90
- // Skipped: Race condition when running with other tests - TEST_DIR cleanup timing issue
91
- // Test passes when run individually but fails in full test suite
92
- // This is a duplicate of "should generate valid configuration file" above
93
- const ctx: PinionContext = {
94
- cwd: TEST_DIR,
95
- argv: ['init'],
96
- pinion: {
97
- logger: {
98
- ...console,
99
- notice: console.log
100
- },
101
- prompt: async () => ({}),
102
- cwd: TEST_DIR,
103
- force: true,
104
- trace: [],
105
- exec: async () => 0
106
- },
107
- projectName: 'test-project',
108
- ciProvider: 'github' as const,
109
- mergeStrategy: 'fast-forward' as const,
110
- requireConventionalCommits: true,
111
- initialBranch: 'develop',
112
- finalBranch: 'main',
113
- branchFlow: ['develop', 'staging', 'main']
114
- }
115
-
116
- await generateInit(ctx)
117
-
118
- const configPath = join(TEST_DIR, '.pipecraftrc.json')
119
- const rawContent = readFileSync(configPath, 'utf8')
120
- let configContent = JSON.parse(rawContent)
121
-
122
- // Handle double-encoded JSON
123
- if (typeof configContent === 'string') {
124
- configContent = JSON.parse(configContent)
125
- }
126
-
127
- // Verify required fields exist (actual behavior of init generator)
128
- expect(configContent.ciProvider).toBeDefined()
129
- expect(configContent.mergeStrategy).toBeDefined()
130
- expect(configContent.branchFlow).toBeDefined()
131
- })
132
-
133
- it.skip('should write config with proper structure and defaults', async () => {
134
- // Skipped: Race condition when running with other tests - TEST_DIR cleanup timing issue
135
- // Test passes when run individually but fails in full test suite
136
- // This is a duplicate of "should generate valid configuration file" above
137
- const ctx: PinionContext = {
138
- cwd: TEST_DIR,
139
- argv: ['init'],
140
- pinion: {
141
- logger: {
142
- ...console,
143
- notice: console.log
144
- },
145
- prompt: async () => ({}),
146
- cwd: TEST_DIR,
147
- force: true,
148
- trace: [],
149
- exec: async () => 0
150
- },
151
- projectName: 'test-project',
152
- ciProvider: 'github' as const,
153
- mergeStrategy: 'fast-forward' as const,
154
- requireConventionalCommits: true,
155
- initialBranch: 'develop',
156
- finalBranch: 'main',
157
- branchFlow: ['develop', 'staging', 'main']
158
- }
159
-
160
- await generateInit(ctx)
161
-
162
- const configPath = join(TEST_DIR, '.pipecraftrc.json')
163
- const rawContent = readFileSync(configPath, 'utf8')
164
-
165
- // Should be valid JSON (may be double-encoded)
166
- let parsedContent
167
- try {
168
- parsedContent = JSON.parse(rawContent)
169
- // If it's double-encoded, parse again
170
- if (typeof parsedContent === 'string') {
171
- parsedContent = JSON.parse(parsedContent)
172
- }
173
- } catch {
174
- // If parsing fails, that's a real issue
175
- throw new Error('Config file is not valid JSON')
176
- }
177
-
178
- // Verify it has the expected structure
179
- expect(parsedContent.ciProvider).toBe('github')
180
- expect(parsedContent.branchFlow).toEqual(['develop', 'staging', 'main'])
181
- expect(parsedContent.semver).toBeDefined()
182
- expect(parsedContent.domains).toBeDefined()
183
- })
184
- })
185
-
186
- describe('workflows.tpl.ts - Workflow Generation Orchestration', () => {
187
- let testConfig: PipecraftConfig
188
-
189
- beforeEach(() => {
190
- // Load test config
191
- const configPath = join(FIXTURES_DIR, 'basic-config.json')
192
- testConfig = JSON.parse(readFileSync(configPath, 'utf8'))
193
- })
194
-
195
- it('should generate all workflow files', async () => {
196
- const ctx: PinionContext & { config?: PipecraftConfig } = {
197
- cwd: TEST_DIR,
198
- argv: ['generate'],
199
- pinion: {
200
- logger: {
201
- ...console,
202
- notice: console.log
203
- },
204
- prompt: async () => ({}),
205
- cwd: TEST_DIR,
206
- force: true,
207
- trace: [],
208
- exec: async () => 0
209
- },
210
- config: testConfig
211
- }
212
-
213
- // Ensure .github/workflows directory exists
214
- const workflowsDir = join(TEST_DIR, '.github', 'workflows')
215
- mkdirSync(workflowsDir, { recursive: true })
216
-
217
- await generateWorkflows(ctx)
218
-
219
- // Check that the main pipeline file was created
220
- const pipelinePath = join(workflowsDir, 'pipeline.yml')
221
- expect(existsSync(pipelinePath), `Expected pipeline.yml to exist`).toBe(true)
222
-
223
- // Action templates are included in the pipeline, not as separate files
224
- // Verify pipeline has content
225
- const pipelineContent = readFileSync(pipelinePath, 'utf8')
226
- expect(pipelineContent.length).toBeGreaterThan(0)
227
- })
228
-
229
- it('should generate valid YAML in pipeline file', async () => {
230
- const ctx: PinionContext & { config?: PipecraftConfig } = {
231
- cwd: TEST_DIR,
232
- argv: ['generate'],
233
- pinion: {
234
- logger: {
235
- ...console,
236
- notice: console.log
237
- },
238
- prompt: async () => ({}),
239
- cwd: TEST_DIR,
240
- force: true,
241
- trace: [],
242
- exec: async () => 0
243
- },
244
- config: testConfig
245
- }
246
-
247
- const workflowsDir = join(TEST_DIR, '.github', 'workflows')
248
- mkdirSync(workflowsDir, { recursive: true })
249
-
250
- await generateWorkflows(ctx)
251
-
252
- const pipelinePath = join(workflowsDir, 'pipeline.yml')
253
- const pipelineContent = readFileSync(pipelinePath, 'utf8')
254
-
255
- // Should be valid YAML
256
- expect(() => parseYAML(pipelineContent)).not.toThrow()
257
-
258
- const pipeline = parseYAML(pipelineContent)
259
- expect(pipeline.name).toBeDefined()
260
- expect(pipeline.on).toBeDefined()
261
- expect(pipeline.jobs).toBeDefined()
262
- })
263
-
264
- it('should include Pipecraft-managed jobs in pipeline', async () => {
265
- const ctx: PinionContext & { config?: PipecraftConfig } = {
266
- cwd: TEST_DIR,
267
- argv: ['generate'],
268
- pinion: {
269
- logger: {
270
- ...console,
271
- notice: console.log
272
- },
273
- prompt: async () => ({}),
274
- cwd: TEST_DIR,
275
- force: true,
276
- trace: [],
277
- exec: async () => 0
278
- },
279
- config: testConfig
280
- }
281
-
282
- const workflowsDir = join(TEST_DIR, '.github', 'workflows')
283
- mkdirSync(workflowsDir, { recursive: true })
284
-
285
- await generateWorkflows(ctx)
286
-
287
- const pipelinePath = join(workflowsDir, 'pipeline.yml')
288
- const pipelineContent = readFileSync(pipelinePath, 'utf8')
289
- const pipeline = parseYAML(pipelineContent)
290
-
291
- // Check for Pipecraft-managed jobs
292
- expect(pipeline.jobs.changes).toBeDefined()
293
- expect(pipeline.jobs.version).toBeDefined()
294
- expect(pipeline.jobs.tag).toBeDefined()
295
- expect(pipeline.jobs.createpr).toBeDefined()
296
- expect(pipeline.jobs.branch).toBeDefined()
297
- })
298
-
299
- it('should merge with existing pipeline when provided', async () => {
300
- // Create an existing pipeline with custom jobs
301
- const workflowsDir = join(TEST_DIR, '.github', 'workflows')
302
- mkdirSync(workflowsDir, { recursive: true })
303
-
304
- const existingPipelinePath = join(workflowsDir, 'pipeline.yml')
305
- const existingPipeline = `
306
- name: Existing Pipeline
307
- on:
308
- push:
309
- branches: [main]
310
- jobs:
311
- custom-job:
312
- runs-on: ubuntu-latest
313
- steps:
314
- - run: echo "Custom job"
315
- `
316
- writeFileSync(existingPipelinePath, existingPipeline)
317
-
318
- const ctx: PinionContext & { config?: PipecraftConfig, pipelinePath?: string } = {
319
- cwd: TEST_DIR,
320
- argv: ['generate'],
321
- pinion: {
322
- logger: {
323
- ...console,
324
- notice: console.log
325
- },
326
- prompt: async () => ({}),
327
- cwd: TEST_DIR,
328
- force: true,
329
- trace: [],
330
- exec: async () => 0
331
- },
332
- config: testConfig,
333
- pipelinePath: existingPipelinePath
334
- }
335
-
336
- await generateWorkflows(ctx)
337
-
338
- const pipelineContent = readFileSync(existingPipelinePath, 'utf8')
339
- const pipeline = parseYAML(pipelineContent)
340
-
341
- // Should preserve custom job
342
- expect(pipeline.jobs['custom-job']).toBeDefined()
343
-
344
- // Should add Pipecraft jobs
345
- expect(pipeline.jobs.changes).toBeDefined()
346
- })
347
-
348
- it('should use custom branch flow from config', async () => {
349
- const customConfig: PipecraftConfig = {
350
- ...testConfig,
351
- branchFlow: ['alpha', 'beta', 'gamma', 'delta']
352
- }
353
-
354
- const ctx: PinionContext & { config?: PipecraftConfig } = {
355
- cwd: TEST_DIR,
356
- argv: ['generate'],
357
- pinion: {
358
- logger: {
359
- ...console,
360
- notice: console.log
361
- },
362
- prompt: async () => ({}),
363
- cwd: TEST_DIR,
364
- force: true,
365
- trace: [],
366
- exec: async () => 0
367
- },
368
- config: customConfig
369
- }
370
-
371
- const workflowsDir = join(TEST_DIR, '.github', 'workflows')
372
- mkdirSync(workflowsDir, { recursive: true })
373
-
374
- await generateWorkflows(ctx)
375
-
376
- const pipelinePath = join(workflowsDir, 'pipeline.yml')
377
- const pipelineContent = readFileSync(pipelinePath, 'utf8')
378
-
379
- // Should include custom branches in the workflow
380
- expect(pipelineContent).toContain('alpha')
381
- expect(pipelineContent).toContain('beta')
382
- expect(pipelineContent).toContain('gamma')
383
- expect(pipelineContent).toContain('delta')
384
- })
385
-
386
- it('should handle missing config gracefully with defaults', async () => {
387
- const ctx: PinionContext = {
388
- cwd: TEST_DIR,
389
- argv: ['generate'],
390
- pinion: {
391
- logger: {
392
- ...console,
393
- notice: console.log
394
- },
395
- prompt: async () => ({}),
396
- cwd: TEST_DIR,
397
- force: true,
398
- trace: [],
399
- exec: async () => 0
400
- }
401
- }
402
-
403
- const workflowsDir = join(TEST_DIR, '.github', 'workflows')
404
- mkdirSync(workflowsDir, { recursive: true })
405
-
406
- // Should not throw
407
- await expect(generateWorkflows(ctx)).resolves.not.toThrow()
408
-
409
- // Should use default config values
410
- const pipelinePath = join(workflowsDir, 'pipeline.yml')
411
- const pipelineContent = readFileSync(pipelinePath, 'utf8')
412
-
413
- // Should include default branches
414
- expect(pipelineContent).toContain('develop')
415
- expect(pipelineContent).toContain('staging')
416
- expect(pipelineContent).toContain('main')
417
- })
418
-
419
- it('should output to custom pipeline path when specified', async () => {
420
- const customPipelinePath = join(TEST_DIR, 'custom-pipeline.yml')
421
-
422
- const ctx: PinionContext & { config?: PipecraftConfig, outputPipelinePath?: string } = {
423
- cwd: TEST_DIR,
424
- argv: ['generate'],
425
- pinion: {
426
- logger: {
427
- ...console,
428
- notice: console.log
429
- },
430
- prompt: async () => ({}),
431
- cwd: TEST_DIR,
432
- force: true,
433
- trace: [],
434
- exec: async () => 0
435
- },
436
- config: testConfig,
437
- outputPipelinePath: customPipelinePath
438
- }
439
-
440
- const workflowsDir = join(TEST_DIR, '.github', 'workflows')
441
- mkdirSync(workflowsDir, { recursive: true })
442
-
443
- await generateWorkflows(ctx)
444
-
445
- // Should write to custom path
446
- expect(existsSync(customPipelinePath)).toBe(true)
447
-
448
- const pipelineContent = readFileSync(customPipelinePath, 'utf8')
449
- expect(() => parseYAML(pipelineContent)).not.toThrow()
450
- })
451
-
452
- it('should include workflow_dispatch trigger with inputs', async () => {
453
- const ctx: PinionContext & { config?: PipecraftConfig } = {
454
- cwd: TEST_DIR,
455
- argv: ['generate'],
456
- pinion: {
457
- logger: {
458
- ...console,
459
- notice: console.log
460
- },
461
- prompt: async () => ({}),
462
- cwd: TEST_DIR,
463
- force: true,
464
- trace: [],
465
- exec: async () => 0
466
- },
467
- config: testConfig
468
- }
469
-
470
- const workflowsDir = join(TEST_DIR, '.github', 'workflows')
471
- mkdirSync(workflowsDir, { recursive: true })
472
-
473
- await generateWorkflows(ctx)
474
-
475
- const pipelinePath = join(workflowsDir, 'pipeline.yml')
476
- const pipelineContent = readFileSync(pipelinePath, 'utf8')
477
- const pipeline = parseYAML(pipelineContent)
478
-
479
- expect(pipeline.on.workflow_dispatch).toBeDefined()
480
- expect(pipeline.on.workflow_dispatch.inputs).toBeDefined()
481
- expect(pipeline.on.workflow_dispatch.inputs.version).toBeDefined()
482
- expect(pipeline.on.workflow_dispatch.inputs.baseRef).toBeDefined()
483
- })
484
-
485
- it('should include pull_request trigger', async () => {
486
- const ctx: PinionContext & { config?: PipecraftConfig } = {
487
- cwd: TEST_DIR,
488
- argv: ['generate'],
489
- pinion: {
490
- logger: {
491
- ...console,
492
- notice: console.log
493
- },
494
- prompt: async () => ({}),
495
- cwd: TEST_DIR,
496
- force: true,
497
- trace: [],
498
- exec: async () => 0
499
- },
500
- config: testConfig
501
- }
502
-
503
- const workflowsDir = join(TEST_DIR, '.github', 'workflows')
504
- mkdirSync(workflowsDir, { recursive: true })
505
-
506
- await generateWorkflows(ctx)
507
-
508
- const pipelinePath = join(workflowsDir, 'pipeline.yml')
509
- const pipelineContent = readFileSync(pipelinePath, 'utf8')
510
- const pipeline = parseYAML(pipelineContent)
511
-
512
- expect(pipeline.on.pull_request).toBeDefined()
513
- })
514
- })
515
-
516
- describe('Generator Error Handling', () => {
517
- it('should handle invalid config in workflows generator', async () => {
518
- const invalidConfig = {
519
- ...JSON.parse(readFileSync(join(FIXTURES_DIR, 'basic-config.json'), 'utf8')),
520
- branchFlow: null // Invalid
521
- }
522
-
523
- const ctx: PinionContext & { config?: any } = {
524
- cwd: TEST_DIR,
525
- argv: ['generate'],
526
- pinion: {
527
- logger: {
528
- ...console,
529
- notice: console.log
530
- },
531
- prompt: async () => ({}),
532
- cwd: TEST_DIR,
533
- force: true,
534
- trace: [],
535
- exec: async () => 0
536
- },
537
- config: invalidConfig
538
- }
539
-
540
- const workflowsDir = join(TEST_DIR, '.github', 'workflows')
541
- mkdirSync(workflowsDir, { recursive: true })
542
-
543
- // Should handle gracefully with defaults
544
- await expect(generateWorkflows(ctx)).resolves.not.toThrow()
545
- })
546
-
547
- it('should handle missing pipeline file path gracefully', async () => {
548
- const testConfig = JSON.parse(readFileSync(join(FIXTURES_DIR, 'basic-config.json'), 'utf8'))
549
-
550
- const ctx: PinionContext & { config?: PipecraftConfig, pipelinePath?: string } = {
551
- cwd: TEST_DIR,
552
- argv: ['generate'],
553
- pinion: {
554
- logger: {
555
- ...console,
556
- notice: console.log
557
- },
558
- prompt: async () => ({}),
559
- cwd: TEST_DIR,
560
- force: true,
561
- trace: [],
562
- exec: async () => 0
563
- },
564
- config: testConfig,
565
- pipelinePath: '/non/existent/path.yml'
566
- }
567
-
568
- const workflowsDir = join(TEST_DIR, '.github', 'workflows')
569
- mkdirSync(workflowsDir, { recursive: true })
570
-
571
- // Should not throw, should create new pipeline
572
- await expect(generateWorkflows(ctx)).resolves.not.toThrow()
573
-
574
- expect(existsSync(join(workflowsDir, 'pipeline.yml'))).toBe(true)
575
- })
576
- })
577
- })
578
-