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,415 @@
|
|
|
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 } from '../setup'
|
|
5
|
+
import { parse } from 'yaml'
|
|
6
|
+
import { applyPathOperations, PathOperationConfig, createValueFromString, createValueFromObject } from '../../src/utils/ast-path-operations'
|
|
7
|
+
import { parseDocument, stringify } from 'yaml'
|
|
8
|
+
|
|
9
|
+
describe('Simple Path-Based Template Tests', () => {
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
// Clean up test files
|
|
12
|
+
const filesToClean = ['.pipecraft-cache.json']
|
|
13
|
+
filesToClean.forEach(file => {
|
|
14
|
+
const fullPath = join(TEST_DIR, file)
|
|
15
|
+
if (existsSync(fullPath)) {
|
|
16
|
+
rmSync(fullPath, { recursive: true, force: true })
|
|
17
|
+
}
|
|
18
|
+
})
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
afterEach(() => {
|
|
22
|
+
// Clean up after each test
|
|
23
|
+
const filesToClean = ['.pipecraft-cache.json']
|
|
24
|
+
filesToClean.forEach(file => {
|
|
25
|
+
const fullPath = join(TEST_DIR, file)
|
|
26
|
+
if (existsSync(fullPath)) {
|
|
27
|
+
rmSync(fullPath, { recursive: true, force: true })
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
describe('Path Operations with Simple YAML', () => {
|
|
33
|
+
it('should apply set operations for workflow inputs', () => {
|
|
34
|
+
// Create a simple YAML document
|
|
35
|
+
const simpleYaml = `name: "Test Pipeline"
|
|
36
|
+
on:
|
|
37
|
+
pull_request:
|
|
38
|
+
branches: [develop]
|
|
39
|
+
jobs:
|
|
40
|
+
test:
|
|
41
|
+
runs-on: ubuntu-latest
|
|
42
|
+
steps:
|
|
43
|
+
- name: Test
|
|
44
|
+
run: echo "test"`
|
|
45
|
+
|
|
46
|
+
const doc = parseDocument(simpleYaml)
|
|
47
|
+
|
|
48
|
+
// Apply path operations
|
|
49
|
+
const operations: PathOperationConfig[] = [
|
|
50
|
+
{
|
|
51
|
+
path: 'on.workflow_call.inputs.version',
|
|
52
|
+
operation: 'set',
|
|
53
|
+
value: {
|
|
54
|
+
description: 'The version to deploy',
|
|
55
|
+
required: false,
|
|
56
|
+
type: 'string'
|
|
57
|
+
},
|
|
58
|
+
required: true
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
path: 'on.workflow_call.inputs.baseRef',
|
|
62
|
+
operation: 'set',
|
|
63
|
+
value: {
|
|
64
|
+
description: 'The base reference for comparison',
|
|
65
|
+
required: false,
|
|
66
|
+
type: 'string'
|
|
67
|
+
},
|
|
68
|
+
required: true
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
applyPathOperations(doc.contents, operations)
|
|
73
|
+
|
|
74
|
+
// Stringify and parse to verify
|
|
75
|
+
const result = stringify(doc)
|
|
76
|
+
const parsed = parse(result)
|
|
77
|
+
|
|
78
|
+
expect(parsed.on.workflow_call?.inputs?.version).toEqual({
|
|
79
|
+
description: 'The version to deploy',
|
|
80
|
+
required: false,
|
|
81
|
+
type: 'string'
|
|
82
|
+
})
|
|
83
|
+
expect(parsed.on.workflow_call?.inputs?.baseRef).toEqual({
|
|
84
|
+
description: 'The base reference for comparison',
|
|
85
|
+
required: false,
|
|
86
|
+
type: 'string'
|
|
87
|
+
})
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
it('should apply merge operations for branch configuration', () => {
|
|
91
|
+
// Create a simple YAML document with existing branches
|
|
92
|
+
const simpleYaml = `name: "Test Pipeline"
|
|
93
|
+
on:
|
|
94
|
+
pull_request:
|
|
95
|
+
branches: [develop, feature]
|
|
96
|
+
jobs:
|
|
97
|
+
test:
|
|
98
|
+
runs-on: ubuntu-latest
|
|
99
|
+
steps:
|
|
100
|
+
- name: Test
|
|
101
|
+
run: echo "test"`
|
|
102
|
+
|
|
103
|
+
const doc = parseDocument(simpleYaml)
|
|
104
|
+
|
|
105
|
+
// Apply merge operation for branches
|
|
106
|
+
const operations: PathOperationConfig[] = [
|
|
107
|
+
{
|
|
108
|
+
path: 'on.pull_request.branches',
|
|
109
|
+
operation: 'merge',
|
|
110
|
+
value: ['alpha', 'beta', 'gamma', 'delta', 'epsilon'],
|
|
111
|
+
required: true
|
|
112
|
+
}
|
|
113
|
+
]
|
|
114
|
+
|
|
115
|
+
applyPathOperations(doc.contents, operations)
|
|
116
|
+
|
|
117
|
+
// Stringify and parse to verify
|
|
118
|
+
const result = stringify(doc)
|
|
119
|
+
const parsed = parse(result)
|
|
120
|
+
|
|
121
|
+
// Should contain both existing and new branches
|
|
122
|
+
expect(parsed.on.pull_request.branches).toContain('develop')
|
|
123
|
+
expect(parsed.on.pull_request.branches).toContain('feature')
|
|
124
|
+
expect(parsed.on.pull_request.branches).toContain('alpha')
|
|
125
|
+
expect(parsed.on.pull_request.branches).toContain('beta')
|
|
126
|
+
expect(parsed.on.pull_request.branches).toContain('gamma')
|
|
127
|
+
expect(parsed.on.pull_request.branches).toContain('delta')
|
|
128
|
+
expect(parsed.on.pull_request.branches).toContain('epsilon')
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
it('should apply overwrite operations for core jobs', () => {
|
|
132
|
+
// Create a simple YAML document with existing jobs
|
|
133
|
+
const simpleYaml = `name: "Test Pipeline"
|
|
134
|
+
on:
|
|
135
|
+
pull_request:
|
|
136
|
+
branches: [develop]
|
|
137
|
+
jobs:
|
|
138
|
+
changes:
|
|
139
|
+
runs-on: ubuntu-latest
|
|
140
|
+
steps:
|
|
141
|
+
- name: Old Changes Job
|
|
142
|
+
run: echo "This should be overwritten"
|
|
143
|
+
version:
|
|
144
|
+
runs-on: ubuntu-latest
|
|
145
|
+
steps:
|
|
146
|
+
- name: Old Version Job
|
|
147
|
+
run: echo "This should be overwritten"`
|
|
148
|
+
|
|
149
|
+
const doc = parseDocument(simpleYaml)
|
|
150
|
+
|
|
151
|
+
// Apply overwrite operations for core jobs
|
|
152
|
+
const operations: PathOperationConfig[] = [
|
|
153
|
+
{
|
|
154
|
+
path: 'jobs.changes',
|
|
155
|
+
operation: 'overwrite',
|
|
156
|
+
value: createValueFromString(`
|
|
157
|
+
runs-on: ubuntu-latest
|
|
158
|
+
steps:
|
|
159
|
+
- uses: ./.github/actions/detect-changes
|
|
160
|
+
with:
|
|
161
|
+
baseRef: \${{ inputs.baseRef || 'main' }}
|
|
162
|
+
`),
|
|
163
|
+
required: true
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
path: 'jobs.version',
|
|
167
|
+
operation: 'overwrite',
|
|
168
|
+
value: createValueFromString(`
|
|
169
|
+
if: github.ref_name == 'alpha'
|
|
170
|
+
needs: changes
|
|
171
|
+
runs-on: ubuntu-latest
|
|
172
|
+
steps:
|
|
173
|
+
- uses: ./.github/actions/calculate-version
|
|
174
|
+
with:
|
|
175
|
+
baseRef: \${{ inputs.baseRef || 'main' }}
|
|
176
|
+
`),
|
|
177
|
+
required: true
|
|
178
|
+
}
|
|
179
|
+
]
|
|
180
|
+
|
|
181
|
+
applyPathOperations(doc.contents, operations)
|
|
182
|
+
|
|
183
|
+
// Stringify and parse to verify
|
|
184
|
+
const result = stringify(doc)
|
|
185
|
+
const parsed = parse(result)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
// Verify core jobs are overwritten
|
|
189
|
+
expect(parsed.jobs.changes).toBeDefined()
|
|
190
|
+
expect(parsed.jobs.version).toBeDefined()
|
|
191
|
+
|
|
192
|
+
// Check if steps exist and have the expected structure
|
|
193
|
+
if (parsed.jobs.changes.steps && parsed.jobs.changes.steps.length > 0) {
|
|
194
|
+
expect(parsed.jobs.changes.steps[0].uses).toBe('./.github/actions/detect-changes')
|
|
195
|
+
expect(parsed.jobs.changes.steps[0].name).toBeUndefined() // No custom name
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (parsed.jobs.version.steps && parsed.jobs.version.steps.length > 0) {
|
|
199
|
+
expect(parsed.jobs.version.steps[0].uses).toBe('./.github/actions/calculate-version')
|
|
200
|
+
expect(parsed.jobs.version.steps[0].name).toBeUndefined() // No custom name
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Check if the if condition exists
|
|
204
|
+
if (parsed.jobs.version.if) {
|
|
205
|
+
expect(parsed.jobs.version.if).toBe("github.ref_name == 'alpha'")
|
|
206
|
+
}
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
it('should apply preserve operations for user-managed sections', () => {
|
|
210
|
+
// Create a simple YAML document with user jobs
|
|
211
|
+
const simpleYaml = `name: "Test Pipeline"
|
|
212
|
+
on:
|
|
213
|
+
pull_request:
|
|
214
|
+
branches: [develop]
|
|
215
|
+
jobs:
|
|
216
|
+
testing-section:
|
|
217
|
+
test-api:
|
|
218
|
+
needs: changes
|
|
219
|
+
runs-on: ubuntu-latest
|
|
220
|
+
steps:
|
|
221
|
+
- name: Test API
|
|
222
|
+
run: echo "Running API tests"
|
|
223
|
+
deployment-section:
|
|
224
|
+
deploy-api:
|
|
225
|
+
needs: version
|
|
226
|
+
runs-on: ubuntu-latest
|
|
227
|
+
steps:
|
|
228
|
+
- name: Deploy API
|
|
229
|
+
run: echo "Deploying API"`
|
|
230
|
+
|
|
231
|
+
const doc = parseDocument(simpleYaml)
|
|
232
|
+
|
|
233
|
+
// Apply preserve operations for user-managed sections
|
|
234
|
+
const operations: PathOperationConfig[] = [
|
|
235
|
+
{
|
|
236
|
+
path: 'jobs.testing-section',
|
|
237
|
+
operation: 'preserve',
|
|
238
|
+
value: createValueFromString(`
|
|
239
|
+
# Add your testing jobs here
|
|
240
|
+
# Example:
|
|
241
|
+
# test-api:
|
|
242
|
+
# needs: changes
|
|
243
|
+
# runs-on: ubuntu-latest
|
|
244
|
+
# steps:
|
|
245
|
+
# - name: Test API
|
|
246
|
+
# run: echo "Run API tests"
|
|
247
|
+
`),
|
|
248
|
+
required: false
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
path: 'jobs.deployment-section',
|
|
252
|
+
operation: 'preserve',
|
|
253
|
+
value: createValueFromString(`
|
|
254
|
+
# Add your deployment jobs here
|
|
255
|
+
# Example:
|
|
256
|
+
# deploy-api:
|
|
257
|
+
# needs: version
|
|
258
|
+
# runs-on: ubuntu-latest
|
|
259
|
+
# steps:
|
|
260
|
+
# - name: Deploy API
|
|
261
|
+
# run: echo "Deploy API to production"
|
|
262
|
+
`),
|
|
263
|
+
required: false
|
|
264
|
+
}
|
|
265
|
+
]
|
|
266
|
+
|
|
267
|
+
applyPathOperations(doc.contents, operations)
|
|
268
|
+
|
|
269
|
+
// Stringify and parse to verify
|
|
270
|
+
const result = stringify(doc)
|
|
271
|
+
const parsed = parse(result)
|
|
272
|
+
|
|
273
|
+
// Verify user-managed sections are preserved
|
|
274
|
+
expect(parsed.jobs['testing-section']['test-api']).toBeDefined()
|
|
275
|
+
expect(parsed.jobs['testing-section']['test-api'].steps[0].name).toBe('Test API')
|
|
276
|
+
expect(parsed.jobs['deployment-section']['deploy-api']).toBeDefined()
|
|
277
|
+
expect(parsed.jobs['deployment-section']['deploy-api'].steps[0].name).toBe('Deploy API')
|
|
278
|
+
})
|
|
279
|
+
})
|
|
280
|
+
|
|
281
|
+
describe('CLI Integration with Custom Files', () => {
|
|
282
|
+
it('should handle custom config file with unexpected variables', async () => {
|
|
283
|
+
// Create custom config with unexpected variables
|
|
284
|
+
const customConfig = {
|
|
285
|
+
ciProvider: 'github',
|
|
286
|
+
mergeStrategy: 'fast-forward',
|
|
287
|
+
requireConventionalCommits: true,
|
|
288
|
+
initialBranch: 'alpha',
|
|
289
|
+
finalBranch: 'epsilon',
|
|
290
|
+
branchFlow: ['alpha', 'beta', 'gamma', 'delta', 'epsilon'],
|
|
291
|
+
semver: {
|
|
292
|
+
bumpRules: {
|
|
293
|
+
feat: 'minor',
|
|
294
|
+
fix: 'patch',
|
|
295
|
+
breaking: 'major'
|
|
296
|
+
}
|
|
297
|
+
},
|
|
298
|
+
actions: {
|
|
299
|
+
onDevelopMerge: ['runTests', 'fastForwardToStaging'],
|
|
300
|
+
onStagingMerge: ['runTests', 'calculateVersion', 'createOrFastForwardToMain']
|
|
301
|
+
},
|
|
302
|
+
domains: {
|
|
303
|
+
'fake-domain1': {
|
|
304
|
+
paths: ['apps/fake-domain1/**'],
|
|
305
|
+
description: 'fake-domain1 application changes'
|
|
306
|
+
},
|
|
307
|
+
'fake-domain2': {
|
|
308
|
+
paths: ['apps/fake-domain2/**'],
|
|
309
|
+
description: 'fake-domain2 application changes'
|
|
310
|
+
},
|
|
311
|
+
'fake-domain3': {
|
|
312
|
+
paths: ['libs/fake-domain3/**'],
|
|
313
|
+
description: 'fake-domain3 application changes'
|
|
314
|
+
},
|
|
315
|
+
'fake-domain4': {
|
|
316
|
+
paths: ['.github/workflows/fake-domain4/**'],
|
|
317
|
+
description: 'fake-domain4 application changes'
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
const configPath = join(TEST_DIR, 'custom-pipecraftrc.json')
|
|
323
|
+
writeFileSync(configPath, JSON.stringify(customConfig, null, 2))
|
|
324
|
+
|
|
325
|
+
// Test that the config can be loaded and parsed
|
|
326
|
+
const loadedConfig = JSON.parse(readFileSync(configPath, 'utf8'))
|
|
327
|
+
expect(loadedConfig.initialBranch).toBe('alpha')
|
|
328
|
+
expect(loadedConfig.finalBranch).toBe('epsilon')
|
|
329
|
+
expect(loadedConfig.branchFlow).toEqual(['alpha', 'beta', 'gamma', 'delta', 'epsilon'])
|
|
330
|
+
expect(loadedConfig.domains['fake-domain1']).toBeDefined()
|
|
331
|
+
expect(loadedConfig.domains['fake-domain2']).toBeDefined()
|
|
332
|
+
expect(loadedConfig.domains['fake-domain3']).toBeDefined()
|
|
333
|
+
expect(loadedConfig.domains['fake-domain4']).toBeDefined()
|
|
334
|
+
})
|
|
335
|
+
|
|
336
|
+
it('should handle custom pipeline file with user customizations', async () => {
|
|
337
|
+
// Create existing pipeline with user customizations
|
|
338
|
+
const existingPipeline = {
|
|
339
|
+
name: "USER NAME",
|
|
340
|
+
on: {
|
|
341
|
+
pull_request: {
|
|
342
|
+
paths: ['**/*.yml', '**/*.yaml', '**/*.json', '**/*.ts', '**/*.js', '**/*.tsx'],
|
|
343
|
+
branches: ['develop', 'feature']
|
|
344
|
+
},
|
|
345
|
+
workflow_call: {
|
|
346
|
+
inputs: {
|
|
347
|
+
fakevar1: {
|
|
348
|
+
description: 'The fake version to deploy',
|
|
349
|
+
required: false,
|
|
350
|
+
type: 'string'
|
|
351
|
+
},
|
|
352
|
+
version: {
|
|
353
|
+
description: 'The version to deploy',
|
|
354
|
+
required: false,
|
|
355
|
+
type: 'string'
|
|
356
|
+
},
|
|
357
|
+
fakevar2: {
|
|
358
|
+
description: 'The fake version to deploy',
|
|
359
|
+
required: false,
|
|
360
|
+
type: 'string'
|
|
361
|
+
}
|
|
362
|
+
},
|
|
363
|
+
outputs: {
|
|
364
|
+
fakevar3: {
|
|
365
|
+
value: 'fakevalue3'
|
|
366
|
+
},
|
|
367
|
+
fakevar4: {
|
|
368
|
+
value: 'fakevalue4'
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
},
|
|
373
|
+
jobs: {
|
|
374
|
+
'fake-job-1': {
|
|
375
|
+
runs_on: 'ubuntu-latest',
|
|
376
|
+
steps: [
|
|
377
|
+
{
|
|
378
|
+
name: 'Fake Job',
|
|
379
|
+
run: 'echo "Running fake job"'
|
|
380
|
+
}
|
|
381
|
+
]
|
|
382
|
+
},
|
|
383
|
+
changes: {
|
|
384
|
+
runs_on: 'ubuntu-latest',
|
|
385
|
+
steps: [
|
|
386
|
+
{
|
|
387
|
+
uses: './.github/actions/detect-changes',
|
|
388
|
+
with: {
|
|
389
|
+
baseRef: '${{ inputs.baseRef || \'main\' }}'
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
]
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
const pipelinePath = join(TEST_DIR, 'custom-pipeline.yml')
|
|
398
|
+
writeFileSync(pipelinePath, stringify(existingPipeline))
|
|
399
|
+
|
|
400
|
+
// Test that the pipeline can be loaded and parsed
|
|
401
|
+
const loadedPipeline = parse(readFileSync(pipelinePath, 'utf8'))
|
|
402
|
+
expect(loadedPipeline.name).toBe('USER NAME')
|
|
403
|
+
expect(loadedPipeline.on.pull_request.paths).toContain('**/*.yml')
|
|
404
|
+
expect(loadedPipeline.on.pull_request.branches).toContain('develop')
|
|
405
|
+
expect(loadedPipeline.on.pull_request.branches).toContain('feature')
|
|
406
|
+
expect(loadedPipeline.on.workflow_call.inputs.fakevar1).toBeDefined()
|
|
407
|
+
expect(loadedPipeline.on.workflow_call.inputs.version).toBeDefined()
|
|
408
|
+
expect(loadedPipeline.on.workflow_call.inputs.fakevar2).toBeDefined()
|
|
409
|
+
expect(loadedPipeline.on.workflow_call.outputs.fakevar3).toBeDefined()
|
|
410
|
+
expect(loadedPipeline.on.workflow_call.outputs.fakevar4).toBeDefined()
|
|
411
|
+
expect(loadedPipeline.jobs['fake-job-1']).toBeDefined()
|
|
412
|
+
expect(loadedPipeline.jobs.changes).toBeDefined()
|
|
413
|
+
})
|
|
414
|
+
})
|
|
415
|
+
})
|
package/tests/setup.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { beforeAll, afterAll, beforeEach, afterEach, vi } from 'vitest'
|
|
2
|
+
import { mkdirSync, rmSync, existsSync } from 'fs'
|
|
3
|
+
import { join } from 'path'
|
|
4
|
+
|
|
5
|
+
// Test utilities
|
|
6
|
+
export const TEST_DIR = join(process.cwd(), 'test-temp')
|
|
7
|
+
export const FIXTURES_DIR = join(__dirname, 'fixtures')
|
|
8
|
+
|
|
9
|
+
// Setup test environment
|
|
10
|
+
beforeAll(() => {
|
|
11
|
+
// Create test directory
|
|
12
|
+
if (existsSync(TEST_DIR)) {
|
|
13
|
+
try {
|
|
14
|
+
rmSync(TEST_DIR, { recursive: true, force: true })
|
|
15
|
+
} catch (error) {
|
|
16
|
+
// If directory is not empty, try to remove contents first
|
|
17
|
+
if (error.code === 'ENOTEMPTY') {
|
|
18
|
+
rmSync(TEST_DIR, { recursive: true, force: true, maxRetries: 3 })
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
mkdirSync(TEST_DIR, { recursive: true })
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
afterAll(() => {
|
|
26
|
+
// Don't delete TEST_DIR as other test files may still need it
|
|
27
|
+
// The directory will be cleaned up at the start of the next test run by beforeAll
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
beforeEach(() => {
|
|
31
|
+
// Reset test environment before each test
|
|
32
|
+
// Ensure TEST_DIR exists but DON'T chdir to it globally
|
|
33
|
+
// Individual tests should manage their own working directories
|
|
34
|
+
if (!existsSync(TEST_DIR)) {
|
|
35
|
+
mkdirSync(TEST_DIR, { recursive: true })
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
afterEach(() => {
|
|
40
|
+
// Clean up after each test
|
|
41
|
+
if (existsSync(join(TEST_DIR, '.pipecraft-cache.json'))) {
|
|
42
|
+
rmSync(join(TEST_DIR, '.pipecraft-cache.json'))
|
|
43
|
+
}
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
// Mock console methods to avoid noise in tests
|
|
47
|
+
const originalConsole = { ...console }
|
|
48
|
+
beforeEach(() => {
|
|
49
|
+
console.log = vi.fn()
|
|
50
|
+
console.error = vi.fn()
|
|
51
|
+
console.warn = vi.fn()
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
afterEach(() => {
|
|
55
|
+
Object.assign(console, originalConsole)
|
|
56
|
+
})
|