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.
- package/.claude/settings.local.json +35 -0
- package/.github/actions/calculate-version/action.yml +106 -0
- package/.github/actions/create-pr/action.yml +122 -0
- package/.github/actions/create-release/action.yml +74 -0
- package/.github/actions/create-tag/action.yml +94 -0
- package/.github/actions/detect-changes/action.yml +62 -0
- package/.github/actions/manage-branch/action.yml +113 -0
- package/.github/actions/promote-branch/action.yml +352 -0
- package/.github/example/workflows/job.analyze.code.yml +26 -0
- package/.github/example/workflows/job.analyze.docker.yml +32 -0
- package/.github/example/workflows/job.app.api.deploy.yml +127 -0
- package/.github/example/workflows/job.app.api.test.yml +102 -0
- package/.github/example/workflows/job.app.docs.deploy.yml +40 -0
- package/.github/example/workflows/job.app.docs.test.yml +50 -0
- package/.github/example/workflows/job.app.web.deploy.yml +96 -0
- package/.github/example/workflows/job.app.web.test.yml +49 -0
- package/.github/example/workflows/job.changes.yml +82 -0
- package/.github/example/workflows/job.create-pr.yml +96 -0
- package/.github/example/workflows/job.env-check.yml +43 -0
- package/.github/example/workflows/job.fast-forward.yml +103 -0
- package/.github/example/workflows/job.lint.yml +64 -0
- package/.github/example/workflows/job.pr-name.yml +70 -0
- package/.github/example/workflows/job.pr-squash-name.yml +27 -0
- package/.github/example/workflows/job.tag.yml +38 -0
- package/.github/example/workflows/job.version.yml +99 -0
- package/.github/example/workflows/lib.plugin-base.publish.yml +59 -0
- package/.github/example/workflows/pipe.yml +178 -0
- package/.github/example/workflows/scripts/fastforward.sh +51 -0
- package/.github/example/workflows/scripts/pipe-cleaner.sh +70 -0
- package/.github/scripts/fastforward.sh +51 -0
- package/.github/scripts/pipe-cleaner.sh +70 -0
- package/.github/workflows/pipeline.yml +220 -0
- package/.github/workflows/pr-title-check.yml +70 -0
- package/.github/workflows/publish.yml +39 -0
- package/.pipecraftrc.json +78 -0
- package/.release-it.cjs +71 -0
- package/PIPELINE_TESTING_PLAN.md +499 -0
- package/README.md +1101 -0
- package/TRUNK_FLOW_PLAN.md +401 -0
- package/assets/logo_banner.png +0 -0
- package/assets/logo_banner.webp +0 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +364 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/generators/init.tpl.d.ts +3 -0
- package/dist/generators/init.tpl.d.ts.map +1 -0
- package/dist/generators/init.tpl.js +117 -0
- package/dist/generators/init.tpl.js.map +1 -0
- package/dist/generators/workflows.tpl.d.ts +7 -0
- package/dist/generators/workflows.tpl.d.ts.map +1 -0
- package/dist/generators/workflows.tpl.js +73 -0
- package/dist/generators/workflows.tpl.js.map +1 -0
- package/dist/templates/actions/calculate-version.yml.tpl.d.ts +3 -0
- package/dist/templates/actions/calculate-version.yml.tpl.d.ts.map +1 -0
- package/dist/templates/actions/calculate-version.yml.tpl.js +122 -0
- package/dist/templates/actions/calculate-version.yml.tpl.js.map +1 -0
- package/dist/templates/actions/create-pr.yml.tpl.d.ts +3 -0
- package/dist/templates/actions/create-pr.yml.tpl.d.ts.map +1 -0
- package/dist/templates/actions/create-pr.yml.tpl.js +145 -0
- package/dist/templates/actions/create-pr.yml.tpl.js.map +1 -0
- package/dist/templates/actions/create-tag.yml.tpl.d.ts +3 -0
- package/dist/templates/actions/create-tag.yml.tpl.d.ts.map +1 -0
- package/dist/templates/actions/create-tag.yml.tpl.js +111 -0
- package/dist/templates/actions/create-tag.yml.tpl.js.map +1 -0
- package/dist/templates/actions/detect-changes.yml.tpl.d.ts +3 -0
- package/dist/templates/actions/detect-changes.yml.tpl.d.ts.map +1 -0
- package/dist/templates/actions/detect-changes.yml.tpl.js +79 -0
- package/dist/templates/actions/detect-changes.yml.tpl.js.map +1 -0
- package/dist/templates/actions/manage-branch.yml.tpl.d.ts +3 -0
- package/dist/templates/actions/manage-branch.yml.tpl.d.ts.map +1 -0
- package/dist/templates/actions/manage-branch.yml.tpl.js +130 -0
- package/dist/templates/actions/manage-branch.yml.tpl.js.map +1 -0
- package/dist/templates/actions/promote-branch.yml.tpl.d.ts +3 -0
- package/dist/templates/actions/promote-branch.yml.tpl.d.ts.map +1 -0
- package/dist/templates/actions/promote-branch.yml.tpl.js +362 -0
- package/dist/templates/actions/promote-branch.yml.tpl.js.map +1 -0
- package/dist/templates/workflows/pipeline-path-based.yml.tpl.d.ts +16 -0
- package/dist/templates/workflows/pipeline-path-based.yml.tpl.d.ts.map +1 -0
- package/dist/templates/workflows/pipeline-path-based.yml.tpl.js +652 -0
- package/dist/templates/workflows/pipeline-path-based.yml.tpl.js.map +1 -0
- package/dist/types/index.d.ts +63 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/ast-path-operations.d.ts +287 -0
- package/dist/utils/ast-path-operations.d.ts.map +1 -0
- package/dist/utils/ast-path-operations.js +419 -0
- package/dist/utils/ast-path-operations.js.map +1 -0
- package/dist/utils/config.d.ts +3 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +49 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/github-setup.d.ts +74 -0
- package/dist/utils/github-setup.d.ts.map +1 -0
- package/dist/utils/github-setup.js +418 -0
- package/dist/utils/github-setup.js.map +1 -0
- package/dist/utils/idempotency.d.ts +47 -0
- package/dist/utils/idempotency.d.ts.map +1 -0
- package/dist/utils/idempotency.js +176 -0
- package/dist/utils/idempotency.js.map +1 -0
- package/dist/utils/preflight.d.ts +55 -0
- package/dist/utils/preflight.d.ts.map +1 -0
- package/dist/utils/preflight.js +261 -0
- package/dist/utils/preflight.js.map +1 -0
- package/dist/utils/versioning.d.ts +41 -0
- package/dist/utils/versioning.d.ts.map +1 -0
- package/dist/utils/versioning.js +219 -0
- package/dist/utils/versioning.js.map +1 -0
- package/docs/USER_JOURNEY_ERRORS.md +352 -0
- package/eslint.config.js +77 -0
- package/examples/basic-config.json +41 -0
- package/examples/monorepo-config.json +49 -0
- package/examples/usage.md +289 -0
- package/package.json +58 -0
- package/scripts/debug-workflows.sh +339 -0
- package/scripts/parse-pipeline.js +29 -0
- package/scripts/test-job-order.cjs +140 -0
- package/scripts/validate-pipeline.cjs +379 -0
- package/scripts/verify-job-order.sh +30 -0
- package/src/cli/index.ts +414 -0
- package/src/generators/init.tpl.ts +126 -0
- package/src/generators/workflows.tpl.ts +80 -0
- package/src/templates/actions/calculate-version.yml.tpl.ts +124 -0
- package/src/templates/actions/create-pr.yml.tpl.ts +147 -0
- package/src/templates/actions/create-tag.yml.tpl.ts +112 -0
- package/src/templates/actions/detect-changes.yml.tpl.ts +87 -0
- package/src/templates/actions/manage-branch.yml.tpl.ts +132 -0
- package/src/templates/actions/promote-branch.yml.tpl.ts +364 -0
- package/src/templates/workflows/pipeline-path-based.yml.tpl.ts +706 -0
- package/src/types/index.ts +64 -0
- package/src/utils/README-ast-path-operations.md +390 -0
- package/src/utils/ast-path-operations.ts +581 -0
- package/src/utils/config.ts +64 -0
- package/src/utils/github-setup.ts +558 -0
- package/src/utils/idempotency.ts +215 -0
- package/src/utils/preflight.ts +306 -0
- package/src/utils/versioning.ts +244 -0
- package/tests/README.md +229 -0
- package/tests/TEST_STRUCTURE.md +256 -0
- package/tests/act/run-act-tests.sh +345 -0
- package/tests/debugging/debug-utils.ts +538 -0
- package/tests/debugging/debug-workflow.test.ts +339 -0
- package/tests/debugging/debug-workflows.sh +339 -0
- package/tests/debugging/iterative-debug.ts +652 -0
- package/tests/debugging/run-debug-tests.sh +431 -0
- package/tests/fixtures/basic-config.json +51 -0
- package/tests/fixtures/invalid-config.json +9 -0
- package/tests/fixtures/pipeline-generated.yml +235 -0
- package/tests/fixtures/pipeline-preserve-comments.yml +245 -0
- package/tests/fixtures/pipeline-user-modified.yml +245 -0
- package/tests/fixtures/test-config.json +58 -0
- package/tests/github-live/README.md +250 -0
- package/tests/github-local/JOB_WORKFLOW_TESTS.md +296 -0
- package/tests/github-local/README.md +240 -0
- package/tests/github-local/run-all-tests.sh +422 -0
- package/tests/github-local/test-job-workflows.sh +631 -0
- package/tests/github-local/test-pipeline-workflow.sh +440 -0
- package/tests/integration/generators.test.ts +578 -0
- package/tests/integration/path-based-template.test.ts +510 -0
- package/tests/integration/simple-path-based.test.ts +415 -0
- package/tests/setup.ts +56 -0
- package/tests/unit/ast-path-operations-extended.test.ts +302 -0
- package/tests/unit/cli.test.ts +541 -0
- package/tests/unit/config-extended.test.ts +412 -0
- package/tests/unit/config.test.ts +152 -0
- package/tests/unit/github-setup.test.ts +189 -0
- package/tests/unit/idempotency-isolated.test.ts +297 -0
- package/tests/unit/job-order.test.ts +157 -0
- package/tests/unit/pipeline-path-based.test.ts +511 -0
- package/tests/unit/validate-pipeline.test.ts +384 -0
- package/tests/unit/versioning-extended.test.ts +279 -0
- package/tests/unit/versioning.test.ts +241 -0
- package/tsconfig.debug.json +17 -0
- package/tsconfig.json +28 -0
- package/vitest.config.ts +51 -0
|
@@ -0,0 +1,510 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest'
|
|
2
|
+
import { writeFileSync, existsSync, rmSync, readFileSync, mkdirSync } from 'fs'
|
|
3
|
+
import { join } from 'path'
|
|
4
|
+
import { TEST_DIR, FIXTURES_DIR } from '../setup'
|
|
5
|
+
import { parse } from 'yaml'
|
|
6
|
+
|
|
7
|
+
// Import the internal function directly for testing
|
|
8
|
+
import { createPathBasedPipeline } from '../../src/templates/workflows/pipeline-path-based.yml.tpl'
|
|
9
|
+
|
|
10
|
+
describe('Path-Based Template Generation Tests', () => {
|
|
11
|
+
const testConfigPath = join(TEST_DIR, 'custom-pipecraftrc.json')
|
|
12
|
+
const testPipelinePath = join(TEST_DIR, 'custom-pipeline.yml')
|
|
13
|
+
const outputPath = join(TEST_DIR, '.github/workflows/pipeline.yml')
|
|
14
|
+
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
// Clean up test files
|
|
17
|
+
const filesToClean = [testConfigPath, testPipelinePath, outputPath, '.pipecraft-cache.json']
|
|
18
|
+
filesToClean.forEach(file => {
|
|
19
|
+
const fullPath = join(TEST_DIR, file)
|
|
20
|
+
if (existsSync(fullPath)) {
|
|
21
|
+
rmSync(fullPath, { recursive: true, force: true })
|
|
22
|
+
}
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
// Create .github/workflows directory
|
|
26
|
+
mkdirSync(join(TEST_DIR, '.github/workflows'), { recursive: true })
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
afterEach(() => {
|
|
30
|
+
// Clean up after each test
|
|
31
|
+
const filesToClean = [testConfigPath, testPipelinePath, outputPath, '.pipecraft-cache.json']
|
|
32
|
+
filesToClean.forEach(file => {
|
|
33
|
+
const fullPath = join(TEST_DIR, file)
|
|
34
|
+
if (existsSync(fullPath)) {
|
|
35
|
+
rmSync(fullPath, { recursive: true, force: true })
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
describe('Custom Config and Pipeline Files', () => {
|
|
41
|
+
it('should generate pipeline with custom config file containing unexpected variables', async () => {
|
|
42
|
+
// Create custom config with unexpected variables (alpha, beta, gamma, delta, epsilon)
|
|
43
|
+
const customConfig = {
|
|
44
|
+
ciProvider: 'github',
|
|
45
|
+
mergeStrategy: 'fast-forward',
|
|
46
|
+
requireConventionalCommits: true,
|
|
47
|
+
initialBranch: 'alpha',
|
|
48
|
+
finalBranch: 'epsilon',
|
|
49
|
+
branchFlow: ['alpha', 'beta', 'gamma', 'delta', 'epsilon'],
|
|
50
|
+
semver: {
|
|
51
|
+
bumpRules: {
|
|
52
|
+
feat: 'minor',
|
|
53
|
+
fix: 'patch',
|
|
54
|
+
breaking: 'major'
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
actions: {
|
|
58
|
+
onDevelopMerge: ['runTests', 'fastForwardToStaging'],
|
|
59
|
+
onStagingMerge: ['runTests', 'calculateVersion', 'createOrFastForwardToMain']
|
|
60
|
+
},
|
|
61
|
+
domains: {
|
|
62
|
+
'fake-domain1': {
|
|
63
|
+
paths: ['apps/fake-domain1/**'],
|
|
64
|
+
description: 'fake-domain1 application changes'
|
|
65
|
+
},
|
|
66
|
+
'fake-domain2': {
|
|
67
|
+
paths: ['apps/fake-domain2/**'],
|
|
68
|
+
description: 'fake-domain2 application changes'
|
|
69
|
+
},
|
|
70
|
+
'fake-domain3': {
|
|
71
|
+
paths: ['libs/fake-domain3/**'],
|
|
72
|
+
description: 'fake-domain3 application changes'
|
|
73
|
+
},
|
|
74
|
+
'fake-domain4': {
|
|
75
|
+
paths: ['.github/workflows/fake-domain4/**'],
|
|
76
|
+
description: 'fake-domain4 application changes'
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
writeFileSync(testConfigPath, JSON.stringify(customConfig, null, 2))
|
|
82
|
+
|
|
83
|
+
// Create context with custom config
|
|
84
|
+
const ctx = {
|
|
85
|
+
...customConfig,
|
|
86
|
+
cwd: TEST_DIR,
|
|
87
|
+
force: true
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Generate pipeline
|
|
91
|
+
const result = createPathBasedPipeline(ctx)
|
|
92
|
+
|
|
93
|
+
expect(result.yamlContent).toBeDefined()
|
|
94
|
+
expect(result.mergeStatus).toBe('overwritten')
|
|
95
|
+
|
|
96
|
+
// Parse generated YAML to verify structure
|
|
97
|
+
const parsedYaml = parse(result.yamlContent)
|
|
98
|
+
expect(parsedYaml).toBeDefined()
|
|
99
|
+
expect(parsedYaml.name).toBe('Pipeline')
|
|
100
|
+
expect(parsedYaml.on).toBeDefined()
|
|
101
|
+
expect(parsedYaml.jobs).toBeDefined()
|
|
102
|
+
|
|
103
|
+
// Verify workflow inputs are set correctly
|
|
104
|
+
expect(parsedYaml.on.workflow_call?.inputs?.version).toBeDefined()
|
|
105
|
+
expect(parsedYaml.on.workflow_call?.inputs?.baseRef).toBeDefined()
|
|
106
|
+
|
|
107
|
+
// Verify branch configuration uses custom branch flow
|
|
108
|
+
expect(parsedYaml.on.pull_request?.branches).toContain('alpha')
|
|
109
|
+
expect(parsedYaml.on.pull_request?.branches).toContain('beta')
|
|
110
|
+
expect(parsedYaml.on.pull_request?.branches).toContain('gamma')
|
|
111
|
+
expect(parsedYaml.on.pull_request?.branches).toContain('delta')
|
|
112
|
+
expect(parsedYaml.on.pull_request?.branches).toContain('epsilon')
|
|
113
|
+
|
|
114
|
+
// Verify core jobs exist
|
|
115
|
+
expect(parsedYaml.jobs.changes).toBeDefined()
|
|
116
|
+
expect(parsedYaml.jobs.version).toBeDefined()
|
|
117
|
+
expect(parsedYaml.jobs.tag).toBeDefined()
|
|
118
|
+
expect(parsedYaml.jobs.createpr).toBeDefined()
|
|
119
|
+
expect(parsedYaml.jobs.branch).toBeDefined()
|
|
120
|
+
|
|
121
|
+
// Verify version job uses custom initial branch
|
|
122
|
+
expect(parsedYaml.jobs.version.if).toContain('alpha')
|
|
123
|
+
expect(parsedYaml.jobs.tag.if).toContain('alpha')
|
|
124
|
+
|
|
125
|
+
// Verify createpr job excludes custom final branch
|
|
126
|
+
expect(parsedYaml.jobs.createpr.if).toContain('epsilon')
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
it('should merge with existing pipeline file containing user customizations', async () => {
|
|
130
|
+
// Create custom config
|
|
131
|
+
const customConfig = {
|
|
132
|
+
ciProvider: 'github',
|
|
133
|
+
mergeStrategy: 'fast-forward',
|
|
134
|
+
requireConventionalCommits: true,
|
|
135
|
+
initialBranch: 'alpha',
|
|
136
|
+
finalBranch: 'epsilon',
|
|
137
|
+
branchFlow: ['alpha', 'beta', 'gamma', 'delta', 'epsilon'],
|
|
138
|
+
semver: {
|
|
139
|
+
bumpRules: {
|
|
140
|
+
feat: 'minor',
|
|
141
|
+
fix: 'patch',
|
|
142
|
+
breaking: 'major'
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
actions: {
|
|
146
|
+
onDevelopMerge: ['runTests', 'fastForwardToStaging'],
|
|
147
|
+
onStagingMerge: ['runTests', 'calculateVersion', 'createOrFastForwardToMain']
|
|
148
|
+
},
|
|
149
|
+
domains: {
|
|
150
|
+
'fake-domain1': {
|
|
151
|
+
paths: ['apps/fake-domain1/**'],
|
|
152
|
+
description: 'fake-domain1 application changes'
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Create existing pipeline with user customizations (similar to pipeline-user-modified.yml)
|
|
158
|
+
const existingPipeline = {
|
|
159
|
+
name: "USER NAME",
|
|
160
|
+
on: {
|
|
161
|
+
pull_request: {
|
|
162
|
+
paths: ['**/*.yml', '**/*.yaml', '**/*.json', '**/*.ts', '**/*.js', '**/*.tsx'],
|
|
163
|
+
branches: ['develop', 'feature']
|
|
164
|
+
},
|
|
165
|
+
workflow_call: {
|
|
166
|
+
inputs: {
|
|
167
|
+
fakevar1: {
|
|
168
|
+
description: 'The fake version to deploy',
|
|
169
|
+
required: false,
|
|
170
|
+
type: 'string'
|
|
171
|
+
},
|
|
172
|
+
version: {
|
|
173
|
+
description: 'The version to deploy',
|
|
174
|
+
required: false,
|
|
175
|
+
type: 'string'
|
|
176
|
+
},
|
|
177
|
+
fakevar2: {
|
|
178
|
+
description: 'The fake version to deploy',
|
|
179
|
+
required: false,
|
|
180
|
+
type: 'string'
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
outputs: {
|
|
184
|
+
fakevar3: {
|
|
185
|
+
value: 'fakevalue3'
|
|
186
|
+
},
|
|
187
|
+
fakevar4: {
|
|
188
|
+
value: 'fakevalue4'
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
jobs: {
|
|
194
|
+
'fake-job-1': {
|
|
195
|
+
runs_on: 'ubuntu-latest',
|
|
196
|
+
steps: [
|
|
197
|
+
{
|
|
198
|
+
name: 'Fake Job',
|
|
199
|
+
run: 'echo "Running fake job"'
|
|
200
|
+
}
|
|
201
|
+
]
|
|
202
|
+
},
|
|
203
|
+
changes: {
|
|
204
|
+
runs_on: 'ubuntu-latest',
|
|
205
|
+
steps: [
|
|
206
|
+
{
|
|
207
|
+
uses: './.github/actions/detect-changes',
|
|
208
|
+
with: {
|
|
209
|
+
baseRef: '${{ inputs.baseRef || \'main\' }}'
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
]
|
|
213
|
+
},
|
|
214
|
+
'fake-job-2': {
|
|
215
|
+
runs_on: 'ubuntu-latest',
|
|
216
|
+
steps: [
|
|
217
|
+
{
|
|
218
|
+
name: 'Fake Job',
|
|
219
|
+
run: 'echo "Running fake job"'
|
|
220
|
+
}
|
|
221
|
+
]
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Create context with existing pipeline
|
|
227
|
+
const ctx = {
|
|
228
|
+
...customConfig,
|
|
229
|
+
existingPipeline,
|
|
230
|
+
cwd: TEST_DIR,
|
|
231
|
+
force: true
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Generate pipeline
|
|
235
|
+
const result = createPathBasedPipeline(ctx)
|
|
236
|
+
|
|
237
|
+
expect(result.yamlContent).toBeDefined()
|
|
238
|
+
expect(result.mergeStatus).toBe('merged')
|
|
239
|
+
|
|
240
|
+
// Parse generated YAML to verify merging
|
|
241
|
+
const parsedYaml = parse(result.yamlContent)
|
|
242
|
+
expect(parsedYaml).toBeDefined()
|
|
243
|
+
|
|
244
|
+
// Verify user customizations are preserved
|
|
245
|
+
expect(parsedYaml.name).toBe('USER NAME')
|
|
246
|
+
expect(parsedYaml.on.pull_request.paths).toContain('**/*.yml')
|
|
247
|
+
expect(parsedYaml.on.pull_request.branches).toContain('develop')
|
|
248
|
+
expect(parsedYaml.on.pull_request.branches).toContain('feature')
|
|
249
|
+
|
|
250
|
+
// Verify user inputs are preserved and required inputs are added
|
|
251
|
+
expect(parsedYaml.on.workflow_call.inputs.fakevar1).toBeDefined()
|
|
252
|
+
expect(parsedYaml.on.workflow_call.inputs.version).toBeDefined()
|
|
253
|
+
expect(parsedYaml.on.workflow_call.inputs.fakevar2).toBeDefined()
|
|
254
|
+
expect(parsedYaml.on.workflow_call.inputs.baseRef).toBeDefined()
|
|
255
|
+
|
|
256
|
+
// Verify user outputs are preserved
|
|
257
|
+
expect(parsedYaml.on.workflow_call.outputs.fakevar3).toBeDefined()
|
|
258
|
+
expect(parsedYaml.on.workflow_call.outputs.fakevar4).toBeDefined()
|
|
259
|
+
|
|
260
|
+
// Verify user jobs are preserved
|
|
261
|
+
expect(parsedYaml.jobs['fake-job-1']).toBeDefined()
|
|
262
|
+
expect(parsedYaml.jobs['fake-job-2']).toBeDefined()
|
|
263
|
+
|
|
264
|
+
// Verify core Pipecraft jobs are updated/overwritten
|
|
265
|
+
expect(parsedYaml.jobs.changes).toBeDefined()
|
|
266
|
+
expect(parsedYaml.jobs.version).toBeDefined()
|
|
267
|
+
expect(parsedYaml.jobs.tag).toBeDefined()
|
|
268
|
+
expect(parsedYaml.jobs.createpr).toBeDefined()
|
|
269
|
+
expect(parsedYaml.jobs.branch).toBeDefined()
|
|
270
|
+
|
|
271
|
+
// Verify branch configuration is merged (user branches + template branches)
|
|
272
|
+
expect(parsedYaml.on.pull_request.branches).toContain('develop')
|
|
273
|
+
expect(parsedYaml.on.pull_request.branches).toContain('feature')
|
|
274
|
+
expect(parsedYaml.on.pull_request.branches).toContain('alpha')
|
|
275
|
+
expect(parsedYaml.on.pull_request.branches).toContain('beta')
|
|
276
|
+
expect(parsedYaml.on.pull_request.branches).toContain('gamma')
|
|
277
|
+
expect(parsedYaml.on.pull_request.branches).toContain('delta')
|
|
278
|
+
expect(parsedYaml.on.pull_request.branches).toContain('epsilon')
|
|
279
|
+
})
|
|
280
|
+
|
|
281
|
+
it('should handle missing existing pipeline gracefully', async () => {
|
|
282
|
+
const customConfig = {
|
|
283
|
+
ciProvider: 'github',
|
|
284
|
+
mergeStrategy: 'fast-forward',
|
|
285
|
+
requireConventionalCommits: true,
|
|
286
|
+
initialBranch: 'alpha',
|
|
287
|
+
finalBranch: 'epsilon',
|
|
288
|
+
branchFlow: ['alpha', 'beta', 'gamma', 'delta', 'epsilon'],
|
|
289
|
+
semver: {
|
|
290
|
+
bumpRules: {
|
|
291
|
+
feat: 'minor',
|
|
292
|
+
fix: 'patch',
|
|
293
|
+
breaking: 'major'
|
|
294
|
+
}
|
|
295
|
+
},
|
|
296
|
+
actions: {
|
|
297
|
+
onDevelopMerge: ['runTests', 'fastForwardToStaging'],
|
|
298
|
+
onStagingMerge: ['runTests', 'calculateVersion', 'createOrFastForwardToMain']
|
|
299
|
+
},
|
|
300
|
+
domains: {
|
|
301
|
+
'fake-domain1': {
|
|
302
|
+
paths: ['apps/fake-domain1/**'],
|
|
303
|
+
description: 'fake-domain1 application changes'
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Create context without existing pipeline
|
|
309
|
+
const ctx = {
|
|
310
|
+
...customConfig,
|
|
311
|
+
cwd: TEST_DIR,
|
|
312
|
+
force: true
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// Generate pipeline
|
|
316
|
+
const result = createPathBasedPipeline(ctx)
|
|
317
|
+
|
|
318
|
+
expect(result.yamlContent).toBeDefined()
|
|
319
|
+
expect(result.mergeStatus).toBe('overwritten')
|
|
320
|
+
|
|
321
|
+
// Parse generated YAML to verify structure
|
|
322
|
+
const parsedYaml = parse(result.yamlContent)
|
|
323
|
+
expect(parsedYaml).toBeDefined()
|
|
324
|
+
expect(parsedYaml.name).toBe('Pipeline')
|
|
325
|
+
expect(parsedYaml.jobs).toBeDefined()
|
|
326
|
+
})
|
|
327
|
+
})
|
|
328
|
+
|
|
329
|
+
describe('Path Operations Validation', () => {
|
|
330
|
+
it('should correctly apply set operations for workflow inputs', async () => {
|
|
331
|
+
const ctx = {
|
|
332
|
+
ciProvider: 'github',
|
|
333
|
+
mergeStrategy: 'fast-forward',
|
|
334
|
+
requireConventionalCommits: true,
|
|
335
|
+
initialBranch: 'alpha',
|
|
336
|
+
finalBranch: 'epsilon',
|
|
337
|
+
branchFlow: ['alpha', 'beta', 'gamma', 'delta', 'epsilon'],
|
|
338
|
+
semver: { bumpRules: { feat: 'minor', fix: 'patch', breaking: 'major' } },
|
|
339
|
+
actions: { onDevelopMerge: ['runTests'], onStagingMerge: ['runTests'] },
|
|
340
|
+
domains: { 'fake-domain1': { paths: ['apps/fake-domain1/**'], description: 'fake-domain1' } },
|
|
341
|
+
cwd: TEST_DIR,
|
|
342
|
+
force: true
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
const result = createPathBasedPipeline(ctx)
|
|
346
|
+
const parsedYaml = parse(result.yamlContent)
|
|
347
|
+
|
|
348
|
+
// Verify workflow_call inputs are set
|
|
349
|
+
expect(parsedYaml.on.workflow_call?.inputs?.version).toEqual({
|
|
350
|
+
description: 'The version to deploy',
|
|
351
|
+
required: false,
|
|
352
|
+
type: 'string'
|
|
353
|
+
})
|
|
354
|
+
expect(parsedYaml.on.workflow_call?.inputs?.baseRef).toEqual({
|
|
355
|
+
description: 'The base reference for comparison',
|
|
356
|
+
required: false,
|
|
357
|
+
type: 'string'
|
|
358
|
+
})
|
|
359
|
+
})
|
|
360
|
+
|
|
361
|
+
it('should correctly apply merge operations for branch configuration', async () => {
|
|
362
|
+
const existingPipeline = {
|
|
363
|
+
name: "Test Pipeline",
|
|
364
|
+
on: {
|
|
365
|
+
pull_request: {
|
|
366
|
+
branches: ['develop', 'feature', 'custom-branch']
|
|
367
|
+
}
|
|
368
|
+
},
|
|
369
|
+
jobs: {}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
const ctx = {
|
|
373
|
+
ciProvider: 'github',
|
|
374
|
+
mergeStrategy: 'fast-forward',
|
|
375
|
+
requireConventionalCommits: true,
|
|
376
|
+
initialBranch: 'alpha',
|
|
377
|
+
finalBranch: 'epsilon',
|
|
378
|
+
branchFlow: ['alpha', 'beta', 'gamma', 'delta', 'epsilon'],
|
|
379
|
+
semver: { bumpRules: { feat: 'minor', fix: 'patch', breaking: 'major' } },
|
|
380
|
+
actions: { onDevelopMerge: ['runTests'], onStagingMerge: ['runTests'] },
|
|
381
|
+
domains: { 'fake-domain1': { paths: ['apps/fake-domain1/**'], description: 'fake-domain1' } },
|
|
382
|
+
existingPipeline,
|
|
383
|
+
cwd: TEST_DIR,
|
|
384
|
+
force: true
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
const result = createPathBasedPipeline(ctx)
|
|
388
|
+
const parsedYaml = parse(result.yamlContent)
|
|
389
|
+
|
|
390
|
+
// Verify branches are merged (user + template)
|
|
391
|
+
const branches = parsedYaml.on.pull_request.branches
|
|
392
|
+
expect(branches).toContain('develop')
|
|
393
|
+
expect(branches).toContain('feature')
|
|
394
|
+
expect(branches).toContain('custom-branch')
|
|
395
|
+
expect(branches).toContain('alpha')
|
|
396
|
+
expect(branches).toContain('beta')
|
|
397
|
+
expect(branches).toContain('gamma')
|
|
398
|
+
expect(branches).toContain('delta')
|
|
399
|
+
expect(branches).toContain('epsilon')
|
|
400
|
+
})
|
|
401
|
+
|
|
402
|
+
it('should correctly apply overwrite operations for core Pipecraft jobs', async () => {
|
|
403
|
+
const existingPipeline = {
|
|
404
|
+
name: "Test Pipeline",
|
|
405
|
+
on: { pull_request: { branches: ['develop'] } },
|
|
406
|
+
jobs: {
|
|
407
|
+
changes: {
|
|
408
|
+
runs_on: 'ubuntu-latest',
|
|
409
|
+
steps: [
|
|
410
|
+
{
|
|
411
|
+
name: 'Old Changes Job',
|
|
412
|
+
run: 'echo "This should be overwritten"'
|
|
413
|
+
}
|
|
414
|
+
]
|
|
415
|
+
},
|
|
416
|
+
version: {
|
|
417
|
+
runs_on: 'ubuntu-latest',
|
|
418
|
+
steps: [
|
|
419
|
+
{
|
|
420
|
+
name: 'Old Version Job',
|
|
421
|
+
run: 'echo "This should be overwritten"'
|
|
422
|
+
}
|
|
423
|
+
]
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
const ctx = {
|
|
429
|
+
ciProvider: 'github',
|
|
430
|
+
mergeStrategy: 'fast-forward',
|
|
431
|
+
requireConventionalCommits: true,
|
|
432
|
+
initialBranch: 'alpha',
|
|
433
|
+
finalBranch: 'epsilon',
|
|
434
|
+
branchFlow: ['alpha', 'beta', 'gamma', 'delta', 'epsilon'],
|
|
435
|
+
semver: { bumpRules: { feat: 'minor', fix: 'patch', breaking: 'major' } },
|
|
436
|
+
actions: { onDevelopMerge: ['runTests'], onStagingMerge: ['runTests'] },
|
|
437
|
+
domains: { 'fake-domain1': { paths: ['apps/fake-domain1/**'], description: 'fake-domain1' } },
|
|
438
|
+
existingPipeline,
|
|
439
|
+
cwd: TEST_DIR,
|
|
440
|
+
force: true
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
const result = createPathBasedPipeline(ctx)
|
|
444
|
+
const parsedYaml = parse(result.yamlContent)
|
|
445
|
+
|
|
446
|
+
// Verify core jobs are overwritten with template versions
|
|
447
|
+
expect(parsedYaml.jobs.changes.steps[0].uses).toBe('./.github/actions/detect-changes')
|
|
448
|
+
expect(parsedYaml.jobs.version.steps[0].uses).toBe('./.github/actions/calculate-version')
|
|
449
|
+
expect(parsedYaml.jobs.changes.steps[0].name).toBeUndefined() // No custom name
|
|
450
|
+
expect(parsedYaml.jobs.version.steps[0].name).toBeUndefined() // No custom name
|
|
451
|
+
})
|
|
452
|
+
|
|
453
|
+
it('should correctly apply preserve operations for user-managed sections', async () => {
|
|
454
|
+
const existingPipeline = {
|
|
455
|
+
name: "Test Pipeline",
|
|
456
|
+
on: { pull_request: { branches: ['develop'] } },
|
|
457
|
+
jobs: {
|
|
458
|
+
'testing-section': {
|
|
459
|
+
'test-api': {
|
|
460
|
+
needs: 'changes',
|
|
461
|
+
runs_on: 'ubuntu-latest',
|
|
462
|
+
steps: [
|
|
463
|
+
{
|
|
464
|
+
name: 'Test API',
|
|
465
|
+
run: 'echo "Running API tests"'
|
|
466
|
+
}
|
|
467
|
+
]
|
|
468
|
+
}
|
|
469
|
+
},
|
|
470
|
+
'deployment-section': {
|
|
471
|
+
'deploy-api': {
|
|
472
|
+
needs: 'version',
|
|
473
|
+
runs_on: 'ubuntu-latest',
|
|
474
|
+
steps: [
|
|
475
|
+
{
|
|
476
|
+
name: 'Deploy API',
|
|
477
|
+
run: 'echo "Deploying API"'
|
|
478
|
+
}
|
|
479
|
+
]
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
const ctx = {
|
|
486
|
+
ciProvider: 'github',
|
|
487
|
+
mergeStrategy: 'fast-forward',
|
|
488
|
+
requireConventionalCommits: true,
|
|
489
|
+
initialBranch: 'alpha',
|
|
490
|
+
finalBranch: 'epsilon',
|
|
491
|
+
branchFlow: ['alpha', 'beta', 'gamma', 'delta', 'epsilon'],
|
|
492
|
+
semver: { bumpRules: { feat: 'minor', fix: 'patch', breaking: 'major' } },
|
|
493
|
+
actions: { onDevelopMerge: ['runTests'], onStagingMerge: ['runTests'] },
|
|
494
|
+
domains: { 'fake-domain1': { paths: ['apps/fake-domain1/**'], description: 'fake-domain1' } },
|
|
495
|
+
existingPipeline,
|
|
496
|
+
cwd: TEST_DIR,
|
|
497
|
+
force: true
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
const result = createPathBasedPipeline(ctx)
|
|
501
|
+
const parsedYaml = parse(result.yamlContent)
|
|
502
|
+
|
|
503
|
+
// Verify user-managed sections are preserved
|
|
504
|
+
expect(parsedYaml.jobs['testing-section']['test-api']).toBeDefined()
|
|
505
|
+
expect(parsedYaml.jobs['testing-section']['test-api'].steps[0].name).toBe('Test API')
|
|
506
|
+
expect(parsedYaml.jobs['deployment-section']['deploy-api']).toBeDefined()
|
|
507
|
+
expect(parsedYaml.jobs['deployment-section']['deploy-api'].steps[0].name).toBe('Deploy API')
|
|
508
|
+
})
|
|
509
|
+
})
|
|
510
|
+
})
|