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.
- package/README.md +126 -108
- package/dist/cli/index.d.ts +69 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +94 -22
- package/dist/cli/index.js.map +1 -1
- package/dist/generators/init.tpl.d.ts +70 -0
- package/dist/generators/init.tpl.d.ts.map +1 -1
- package/dist/generators/init.tpl.js +100 -8
- package/dist/generators/init.tpl.js.map +1 -1
- package/dist/generators/workflows.tpl.d.ts +86 -0
- package/dist/generators/workflows.tpl.d.ts.map +1 -1
- package/dist/generators/workflows.tpl.js +101 -9
- package/dist/generators/workflows.tpl.js.map +1 -1
- package/dist/templates/actions/calculate-version.yml.tpl.d.ts +47 -0
- package/dist/templates/actions/calculate-version.yml.tpl.d.ts.map +1 -1
- package/dist/templates/actions/calculate-version.yml.tpl.js +72 -3
- package/dist/templates/actions/calculate-version.yml.tpl.js.map +1 -1
- package/dist/templates/actions/create-pr.yml.tpl.d.ts +14 -0
- package/dist/templates/actions/create-pr.yml.tpl.d.ts.map +1 -1
- package/dist/templates/actions/create-pr.yml.tpl.js +22 -2
- package/dist/templates/actions/create-pr.yml.tpl.js.map +1 -1
- package/dist/templates/actions/create-release.yml.tpl.d.ts +18 -0
- package/dist/templates/actions/create-release.yml.tpl.d.ts.map +1 -0
- package/dist/templates/actions/create-release.yml.tpl.js +141 -0
- package/dist/templates/actions/create-release.yml.tpl.js.map +1 -0
- package/dist/templates/actions/create-tag.yml.tpl.d.ts +14 -0
- package/dist/templates/actions/create-tag.yml.tpl.d.ts.map +1 -1
- package/dist/templates/actions/create-tag.yml.tpl.js +22 -2
- package/dist/templates/actions/create-tag.yml.tpl.js.map +1 -1
- package/dist/templates/actions/detect-changes.yml.tpl.d.ts +70 -0
- package/dist/templates/actions/detect-changes.yml.tpl.d.ts.map +1 -1
- package/dist/templates/actions/detect-changes.yml.tpl.js +98 -2
- package/dist/templates/actions/detect-changes.yml.tpl.js.map +1 -1
- package/dist/templates/actions/manage-branch.yml.tpl.d.ts +14 -0
- package/dist/templates/actions/manage-branch.yml.tpl.d.ts.map +1 -1
- package/dist/templates/actions/manage-branch.yml.tpl.js +22 -2
- package/dist/templates/actions/manage-branch.yml.tpl.js.map +1 -1
- package/dist/templates/actions/promote-branch.yml.tpl.d.ts +14 -0
- package/dist/templates/actions/promote-branch.yml.tpl.d.ts.map +1 -1
- package/dist/templates/actions/promote-branch.yml.tpl.js +50 -7
- package/dist/templates/actions/promote-branch.yml.tpl.js.map +1 -1
- package/dist/templates/workflows/pipeline-path-based.yml.tpl.d.ts +114 -1
- package/dist/templates/workflows/pipeline-path-based.yml.tpl.d.ts.map +1 -1
- package/dist/templates/workflows/pipeline-path-based.yml.tpl.js +479 -74
- package/dist/templates/workflows/pipeline-path-based.yml.tpl.js.map +1 -1
- package/dist/types/index.d.ts +231 -8
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +9 -0
- package/dist/types/index.js.map +1 -1
- package/dist/utils/ast-path-operations.d.ts.map +1 -1
- package/dist/utils/ast-path-operations.js +24 -11
- package/dist/utils/ast-path-operations.js.map +1 -1
- package/dist/utils/config.d.ts +63 -0
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +71 -0
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/github-setup.d.ts +323 -2
- package/dist/utils/github-setup.d.ts.map +1 -1
- package/dist/utils/github-setup.js +551 -23
- package/dist/utils/github-setup.js.map +1 -1
- package/dist/utils/idempotency.d.ts +147 -7
- package/dist/utils/idempotency.d.ts.map +1 -1
- package/dist/utils/idempotency.js +143 -15
- package/dist/utils/idempotency.js.map +1 -1
- package/dist/utils/logger.d.ts +134 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +153 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/preflight.d.ts +223 -12
- package/dist/utils/preflight.d.ts.map +1 -1
- package/dist/utils/preflight.js +216 -16
- package/dist/utils/preflight.js.map +1 -1
- package/dist/utils/versioning.d.ts +160 -8
- package/dist/utils/versioning.d.ts.map +1 -1
- package/dist/utils/versioning.js +179 -15
- package/dist/utils/versioning.js.map +1 -1
- package/package.json +26 -5
- package/.claude/settings.local.json +0 -35
- package/.github/actions/calculate-version/action.yml +0 -106
- package/.github/actions/create-pr/action.yml +0 -122
- package/.github/actions/create-release/action.yml +0 -74
- package/.github/actions/create-tag/action.yml +0 -94
- package/.github/actions/detect-changes/action.yml +0 -62
- package/.github/actions/manage-branch/action.yml +0 -113
- package/.github/actions/promote-branch/action.yml +0 -352
- package/.github/example/workflows/job.analyze.code.yml +0 -26
- package/.github/example/workflows/job.analyze.docker.yml +0 -32
- package/.github/example/workflows/job.app.api.deploy.yml +0 -127
- package/.github/example/workflows/job.app.api.test.yml +0 -102
- package/.github/example/workflows/job.app.docs.deploy.yml +0 -40
- package/.github/example/workflows/job.app.docs.test.yml +0 -50
- package/.github/example/workflows/job.app.web.deploy.yml +0 -96
- package/.github/example/workflows/job.app.web.test.yml +0 -49
- package/.github/example/workflows/job.changes.yml +0 -82
- package/.github/example/workflows/job.create-pr.yml +0 -96
- package/.github/example/workflows/job.env-check.yml +0 -43
- package/.github/example/workflows/job.fast-forward.yml +0 -103
- package/.github/example/workflows/job.lint.yml +0 -64
- package/.github/example/workflows/job.pr-name.yml +0 -70
- package/.github/example/workflows/job.pr-squash-name.yml +0 -27
- package/.github/example/workflows/job.tag.yml +0 -38
- package/.github/example/workflows/job.version.yml +0 -99
- package/.github/example/workflows/lib.plugin-base.publish.yml +0 -59
- package/.github/example/workflows/pipe.yml +0 -178
- package/.github/example/workflows/scripts/fastforward.sh +0 -51
- package/.github/example/workflows/scripts/pipe-cleaner.sh +0 -70
- package/.github/scripts/fastforward.sh +0 -51
- package/.github/scripts/pipe-cleaner.sh +0 -70
- package/.github/workflows/pipeline.yml +0 -220
- package/.github/workflows/pr-title-check.yml +0 -70
- package/.github/workflows/publish.yml +0 -39
- package/.pipecraftrc.json +0 -78
- package/.release-it.cjs +0 -71
- package/PIPELINE_TESTING_PLAN.md +0 -499
- package/TRUNK_FLOW_PLAN.md +0 -401
- package/assets/logo_banner.png +0 -0
- package/assets/logo_banner.webp +0 -0
- package/docs/USER_JOURNEY_ERRORS.md +0 -352
- package/eslint.config.js +0 -77
- package/examples/basic-config.json +0 -41
- package/examples/monorepo-config.json +0 -49
- package/examples/usage.md +0 -289
- package/scripts/debug-workflows.sh +0 -339
- package/scripts/parse-pipeline.js +0 -29
- package/scripts/test-job-order.cjs +0 -140
- package/scripts/validate-pipeline.cjs +0 -379
- package/scripts/verify-job-order.sh +0 -30
- package/src/cli/index.ts +0 -414
- package/src/generators/init.tpl.ts +0 -126
- package/src/generators/workflows.tpl.ts +0 -80
- package/src/templates/actions/calculate-version.yml.tpl.ts +0 -124
- package/src/templates/actions/create-pr.yml.tpl.ts +0 -147
- package/src/templates/actions/create-tag.yml.tpl.ts +0 -112
- package/src/templates/actions/detect-changes.yml.tpl.ts +0 -87
- package/src/templates/actions/manage-branch.yml.tpl.ts +0 -132
- package/src/templates/actions/promote-branch.yml.tpl.ts +0 -364
- package/src/templates/workflows/pipeline-path-based.yml.tpl.ts +0 -706
- package/src/types/index.ts +0 -64
- package/src/utils/README-ast-path-operations.md +0 -390
- package/src/utils/ast-path-operations.ts +0 -581
- package/src/utils/config.ts +0 -64
- package/src/utils/github-setup.ts +0 -558
- package/src/utils/idempotency.ts +0 -215
- package/src/utils/preflight.ts +0 -306
- package/src/utils/versioning.ts +0 -244
- package/tests/README.md +0 -229
- package/tests/TEST_STRUCTURE.md +0 -256
- package/tests/act/run-act-tests.sh +0 -345
- package/tests/debugging/debug-utils.ts +0 -538
- package/tests/debugging/debug-workflow.test.ts +0 -339
- package/tests/debugging/debug-workflows.sh +0 -339
- package/tests/debugging/iterative-debug.ts +0 -652
- package/tests/debugging/run-debug-tests.sh +0 -431
- package/tests/fixtures/basic-config.json +0 -51
- package/tests/fixtures/invalid-config.json +0 -9
- package/tests/fixtures/pipeline-generated.yml +0 -235
- package/tests/fixtures/pipeline-preserve-comments.yml +0 -245
- package/tests/fixtures/pipeline-user-modified.yml +0 -245
- package/tests/fixtures/test-config.json +0 -58
- package/tests/github-live/README.md +0 -250
- package/tests/github-local/JOB_WORKFLOW_TESTS.md +0 -296
- package/tests/github-local/README.md +0 -240
- package/tests/github-local/run-all-tests.sh +0 -422
- package/tests/github-local/test-job-workflows.sh +0 -631
- package/tests/github-local/test-pipeline-workflow.sh +0 -440
- package/tests/integration/generators.test.ts +0 -578
- package/tests/integration/path-based-template.test.ts +0 -510
- package/tests/integration/simple-path-based.test.ts +0 -415
- package/tests/setup.ts +0 -56
- package/tests/unit/ast-path-operations-extended.test.ts +0 -302
- package/tests/unit/cli.test.ts +0 -541
- package/tests/unit/config-extended.test.ts +0 -412
- package/tests/unit/config.test.ts +0 -152
- package/tests/unit/github-setup.test.ts +0 -189
- package/tests/unit/idempotency-isolated.test.ts +0 -297
- package/tests/unit/job-order.test.ts +0 -157
- package/tests/unit/pipeline-path-based.test.ts +0 -511
- package/tests/unit/validate-pipeline.test.ts +0 -384
- package/tests/unit/versioning-extended.test.ts +0 -279
- package/tests/unit/versioning.test.ts +0 -241
- package/tsconfig.debug.json +0 -17
- package/tsconfig.json +0 -28
- package/vitest.config.ts +0 -51
package/tests/unit/cli.test.ts
DELETED
|
@@ -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
|
-
})
|