@paths.design/caws-cli 7.0.1 → 7.0.3

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 (121) hide show
  1. package/dist/budget-derivation.js +5 -4
  2. package/dist/commands/diagnose.js +26 -20
  3. package/dist/commands/init.js +72 -5
  4. package/dist/commands/specs.js +40 -1
  5. package/dist/commands/status.js +2 -2
  6. package/dist/commands/templates.js +10 -0
  7. package/dist/commands/tool.js +2 -3
  8. package/dist/commands/validate.js +12 -0
  9. package/dist/config/index.js +17 -8
  10. package/dist/generators/working-spec.js +42 -9
  11. package/dist/index.js +3 -1
  12. package/dist/scaffold/cursor-hooks.js +10 -2
  13. package/dist/scaffold/git-hooks.js +189 -32
  14. package/dist/scaffold/index.js +105 -17
  15. package/dist/templates/.caws/tools/README.md +20 -0
  16. package/dist/templates/.cursor/README.md +311 -0
  17. package/dist/templates/.cursor/hooks/audit.sh +55 -0
  18. package/dist/templates/.cursor/hooks/block-dangerous.sh +83 -0
  19. package/dist/templates/.cursor/hooks/caws-quality-check.sh +52 -0
  20. package/dist/templates/.cursor/hooks/caws-scope-guard.sh +130 -0
  21. package/dist/templates/.cursor/hooks/caws-tool-validation.sh +121 -0
  22. package/dist/templates/.cursor/hooks/format.sh +38 -0
  23. package/dist/templates/.cursor/hooks/naming-check.sh +64 -0
  24. package/dist/templates/.cursor/hooks/scan-secrets.sh +46 -0
  25. package/dist/templates/.cursor/hooks/scope-guard.sh +52 -0
  26. package/dist/templates/.cursor/hooks/validate-spec.sh +83 -0
  27. package/dist/templates/.cursor/hooks.json +59 -0
  28. package/dist/templates/.cursor/rules/00-claims-verification.mdc +144 -0
  29. package/dist/templates/.cursor/rules/01-working-style.mdc +50 -0
  30. package/dist/templates/.cursor/rules/02-quality-gates.mdc +370 -0
  31. package/dist/templates/.cursor/rules/03-naming-and-refactor.mdc +33 -0
  32. package/dist/templates/.cursor/rules/04-logging-language-style.mdc +23 -0
  33. package/dist/templates/.cursor/rules/05-safe-defaults-guards.mdc +23 -0
  34. package/dist/templates/.cursor/rules/06-typescript-conventions.mdc +36 -0
  35. package/dist/templates/.cursor/rules/07-process-ops.mdc +20 -0
  36. package/dist/templates/.cursor/rules/08-solid-and-architecture.mdc +16 -0
  37. package/dist/templates/.cursor/rules/09-docstrings.mdc +89 -0
  38. package/dist/templates/.cursor/rules/10-documentation-quality-standards.mdc +390 -0
  39. package/dist/templates/.cursor/rules/11-scope-management-waivers.mdc +385 -0
  40. package/dist/templates/.cursor/rules/12-implementation-completeness.mdc +516 -0
  41. package/dist/templates/.cursor/rules/13-language-agnostic-standards.mdc +588 -0
  42. package/dist/templates/.cursor/rules/README.md +148 -0
  43. package/dist/templates/.github/copilot/instructions.md +311 -0
  44. package/dist/templates/.idea/runConfigurations/CAWS_Evaluate.xml +5 -0
  45. package/dist/templates/.idea/runConfigurations/CAWS_Validate.xml +5 -0
  46. package/dist/templates/.vscode/launch.json +56 -0
  47. package/dist/templates/.vscode/settings.json +93 -0
  48. package/dist/templates/.windsurf/workflows/caws-guided-development.md +92 -0
  49. package/dist/templates/COMMIT_CONVENTIONS.md +86 -0
  50. package/dist/templates/OIDC_SETUP.md +300 -0
  51. package/dist/templates/agents.md +1047 -0
  52. package/dist/templates/codemod/README.md +1 -0
  53. package/dist/templates/codemod/test.js +93 -0
  54. package/dist/templates/docs/README.md +150 -0
  55. package/dist/templates/scripts/quality-gates/check-god-objects.js +146 -0
  56. package/dist/templates/scripts/quality-gates/run-quality-gates.js +50 -0
  57. package/dist/templates/scripts/v3/analysis/todo_analyzer.py +1997 -0
  58. package/dist/tool-loader.js +6 -1
  59. package/dist/tool-validator.js +8 -2
  60. package/dist/utils/detection.js +34 -6
  61. package/dist/utils/git-lock.js +118 -0
  62. package/dist/utils/gitignore-updater.js +148 -0
  63. package/dist/utils/quality-gates.js +47 -7
  64. package/dist/utils/spec-resolver.js +23 -3
  65. package/dist/utils/yaml-validation.js +155 -0
  66. package/dist/validation/spec-validation.js +105 -2
  67. package/package.json +2 -2
  68. package/templates/.caws/schemas/waivers.schema.json +30 -0
  69. package/templates/.caws/schemas/working-spec.schema.json +133 -0
  70. package/templates/.caws/templates/working-spec.template.yml +74 -0
  71. package/templates/.caws/tools/README.md +20 -0
  72. package/templates/.caws/tools/scope-guard.js +208 -0
  73. package/templates/.caws/tools-allow.json +331 -0
  74. package/templates/.caws/waivers.yml +19 -0
  75. package/templates/.cursor/hooks/scope-guard.sh +2 -2
  76. package/templates/.cursor/hooks/validate-spec.sh +42 -7
  77. package/templates/apps/tools/caws/COMPLETION_REPORT.md +0 -331
  78. package/templates/apps/tools/caws/MIGRATION_SUMMARY.md +0 -360
  79. package/templates/apps/tools/caws/README.md +0 -463
  80. package/templates/apps/tools/caws/TEST_STATUS.md +0 -365
  81. package/templates/apps/tools/caws/attest.js +0 -357
  82. package/templates/apps/tools/caws/ci-optimizer.js +0 -642
  83. package/templates/apps/tools/caws/config.ts +0 -245
  84. package/templates/apps/tools/caws/cross-functional.js +0 -876
  85. package/templates/apps/tools/caws/dashboard.js +0 -1112
  86. package/templates/apps/tools/caws/flake-detector.ts +0 -362
  87. package/templates/apps/tools/caws/gates.js +0 -198
  88. package/templates/apps/tools/caws/gates.ts +0 -271
  89. package/templates/apps/tools/caws/language-adapters.ts +0 -381
  90. package/templates/apps/tools/caws/language-support.d.ts +0 -367
  91. package/templates/apps/tools/caws/language-support.d.ts.map +0 -1
  92. package/templates/apps/tools/caws/language-support.js +0 -585
  93. package/templates/apps/tools/caws/legacy-assessment.ts +0 -408
  94. package/templates/apps/tools/caws/legacy-assessor.js +0 -764
  95. package/templates/apps/tools/caws/mutant-analyzer.js +0 -734
  96. package/templates/apps/tools/caws/perf-budgets.ts +0 -349
  97. package/templates/apps/tools/caws/prompt-lint.js.backup +0 -274
  98. package/templates/apps/tools/caws/property-testing.js +0 -707
  99. package/templates/apps/tools/caws/provenance.d.ts +0 -14
  100. package/templates/apps/tools/caws/provenance.d.ts.map +0 -1
  101. package/templates/apps/tools/caws/provenance.js +0 -132
  102. package/templates/apps/tools/caws/provenance.js.backup +0 -73
  103. package/templates/apps/tools/caws/provenance.ts +0 -211
  104. package/templates/apps/tools/caws/security-provenance.ts +0 -483
  105. package/templates/apps/tools/caws/shared/base-tool.ts +0 -281
  106. package/templates/apps/tools/caws/shared/config-manager.ts +0 -366
  107. package/templates/apps/tools/caws/shared/gate-checker.ts +0 -849
  108. package/templates/apps/tools/caws/shared/types.ts +0 -444
  109. package/templates/apps/tools/caws/shared/validator.ts +0 -305
  110. package/templates/apps/tools/caws/shared/waivers-manager.ts +0 -174
  111. package/templates/apps/tools/caws/spec-test-mapper.ts +0 -391
  112. package/templates/apps/tools/caws/test-quality.js +0 -578
  113. package/templates/apps/tools/caws/validate.js +0 -76
  114. package/templates/apps/tools/caws/validate.ts +0 -228
  115. package/templates/apps/tools/caws/waivers.js +0 -344
  116. /package/{templates/apps/tools/caws → dist/templates/.caws}/schemas/waivers.schema.json +0 -0
  117. /package/{templates/apps/tools/caws → dist/templates/.caws}/schemas/working-spec.schema.json +0 -0
  118. /package/{templates/apps/tools/caws → dist/templates/.caws}/templates/working-spec.template.yml +0 -0
  119. /package/{templates/apps/tools/caws → dist/templates/.caws/tools}/scope-guard.js +0 -0
  120. /package/{templates/apps/tools/caws → dist/templates/.caws}/tools-allow.json +0 -0
  121. /package/{templates/apps/tools/caws → dist/templates/.caws}/waivers.yml +0 -0
@@ -1,642 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * @fileoverview CAWS CI/CD Pipeline Optimizer
5
- * Implements risk-driven and change-driven optimizations for faster feedback
6
- * @author @darianrosebrook
7
- */
8
-
9
- const fs = require('fs');
10
- const path = require('path');
11
- const yaml = require('js-yaml');
12
-
13
- /**
14
- * CI optimization strategies
15
- */
16
- const OPTIMIZATION_STRATEGIES = {
17
- TIER_BASED_CONDITIONAL: {
18
- name: 'Tier-based Conditional Runs',
19
- description: 'Skip expensive checks for low-risk changes',
20
- impact: 'high',
21
- implementation: 'GitHub Actions conditionals',
22
- },
23
- SELECTIVE_TEST_EXECUTION: {
24
- name: 'Selective Test Execution',
25
- description: 'Run only tests related to changed files',
26
- impact: 'medium',
27
- implementation: 'Test selection by file paths',
28
- },
29
- TWO_PHASE_PIPELINE: {
30
- name: 'Two-phase Pipeline',
31
- description: 'Quick feedback for commits, full validation for PRs',
32
- impact: 'high',
33
- implementation: 'Separate push/PR workflows',
34
- },
35
- PARALLEL_EXECUTION: {
36
- name: 'Parallel Execution',
37
- description: 'Maximize parallelization of independent checks',
38
- impact: 'medium',
39
- implementation: 'Job dependencies and matrix strategies',
40
- },
41
- INCREMENTAL_BUILDS: {
42
- name: 'Incremental Builds',
43
- description: 'Skip unchanged parts of the build',
44
- impact: 'low',
45
- implementation: 'Build caching and conditional steps',
46
- },
47
- };
48
-
49
- /**
50
- * Generate optimized GitHub Actions workflow
51
- * @param {Object} options - Optimization options
52
- * @returns {string} GitHub Actions workflow YAML
53
- */
54
- function generateOptimizedWorkflow(options = {}) {
55
- const {
56
- language = 'javascript',
57
- tier = 2,
58
- enableTwoPhase = true,
59
- enableSelectiveTests = true,
60
- enableTierConditionals = true,
61
- } = options;
62
-
63
- const workflow = {
64
- name: 'CAWS Optimized CI/CD',
65
- on: {
66
- push: { branches: ['main', 'develop'] },
67
- pull_request: { branches: ['main', 'develop'] },
68
- },
69
- jobs: {},
70
- };
71
-
72
- // Setup job (always runs)
73
- workflow.jobs.setup = {
74
- 'runs-on': 'ubuntu-latest',
75
- outputs: {
76
- risk_tier: '${{ steps.detect.outputs.tier }}',
77
- changed_files: '${{ steps.detect.outputs.files }}',
78
- is_experimental: '${{ steps.detect.outputs.experimental }}',
79
- },
80
- steps: [
81
- {
82
- name: 'Checkout code',
83
- uses: 'actions/checkout@v4',
84
- with: { 'fetch-depth': 2 },
85
- },
86
- {
87
- id: 'detect',
88
- name: 'Detect CAWS configuration',
89
- run: `
90
- # Detect risk tier from working spec
91
- if [ -f .caws/working-spec.yaml ]; then
92
- TIER=$(grep 'risk_tier:' .caws/working-spec.yaml | cut -d':' -f2 | tr -d ' ')
93
- echo "tier=$TIER" >> $GITHUB_OUTPUT
94
-
95
- # Check for experimental mode
96
- if grep -q 'experimental_mode:' .caws/working-spec.yaml; then
97
- echo "experimental=true" >> $GITHUB_OUTPUT
98
- else
99
- echo "experimental=false" >> $GITHUB_OUTPUT
100
- fi
101
- else
102
- echo "tier=2" >> $GITHUB_OUTPUT
103
- echo "experimental=false" >> $GITHUB_OUTPUT
104
- fi
105
-
106
- # Get changed files
107
- if [ "$GITHUB_EVENT_NAME" = "pull_request" ]; then
108
- FILES=$(git diff --name-only "$GITHUB_BASE_SHA" "$GITHUB_SHA" | tr '\n' ' ')
109
- else
110
- FILES=$(git diff --name-only HEAD~1 HEAD | tr '\n' ' ')
111
- fi
112
- echo "files=$FILES" >> $GITHUB_OUTPUT
113
- `,
114
- },
115
- ],
116
- };
117
-
118
- // Quick feedback job (runs on every push)
119
- if (enableTwoPhase) {
120
- workflow.jobs.quick_feedback = {
121
- 'runs-on': 'ubuntu-latest',
122
- needs: 'setup',
123
- if: "github.event_name == 'push'",
124
- steps: [
125
- {
126
- name: 'Checkout code',
127
- uses: 'actions/checkout@v4',
128
- },
129
- {
130
- name: 'Setup Node.js',
131
- uses: 'actions/setup-node@v4',
132
- with: { 'node-version': '18', cache: 'npm' },
133
- },
134
- {
135
- name: 'Install dependencies',
136
- run: 'npm ci',
137
- },
138
- {
139
- name: 'Quick lint',
140
- run: 'npm run lint || true',
141
- },
142
- {
143
- name: 'Quick tests',
144
- run: 'npm run test -- --passWithNoTests || true',
145
- },
146
- ],
147
- };
148
- }
149
-
150
- // Main validation job (runs on PR and after successful quick feedback)
151
- const mainJobCondition = enableTwoPhase
152
- ? "github.event_name == 'pull_request' || (github.event_name == 'push' && needs.quick_feedback.result == 'success')"
153
- : 'true';
154
-
155
- workflow.jobs.validate = {
156
- 'runs-on': 'ubuntu-latest',
157
- needs: enableTwoPhase ? 'setup' : [],
158
- if: mainJobCondition,
159
- strategy: {
160
- matrix: {
161
- node: ['18', '20'],
162
- },
163
- },
164
- steps: [
165
- {
166
- name: 'Checkout code',
167
- uses: 'actions/checkout@v4',
168
- with: { 'fetch-depth': 0 },
169
- },
170
- {
171
- name: 'Setup Node.js ${{ matrix.node }}',
172
- uses: 'actions/setup-node@v4',
173
- with: {
174
- 'node-version': '${{ matrix.node }}',
175
- cache: 'npm',
176
- },
177
- },
178
- {
179
- name: 'Install dependencies',
180
- run: 'npm ci',
181
- },
182
- {
183
- name: 'Lint code',
184
- run: 'npm run lint',
185
- },
186
- {
187
- name: 'Run tests',
188
- run: getTestCommand(language, tier, enableSelectiveTests),
189
- },
190
- {
191
- name: 'Generate coverage',
192
- run: getCoverageCommand(language, tier),
193
- },
194
- {
195
- name: 'Upload coverage',
196
- uses: 'codecov/codecov-action@v3',
197
- if: "matrix.node == '18'",
198
- },
199
- ],
200
- };
201
-
202
- // Tier-based conditional jobs
203
- if (enableTierConditionals) {
204
- // Mutation testing (only for tier 1 and 2)
205
- workflow.jobs.mutation_test = {
206
- 'runs-on': 'ubuntu-latest',
207
- needs: ['setup', 'validate'],
208
- if: "(needs.setup.outputs.risk_tier == '1' || needs.setup.outputs.risk_tier == '2') && needs.setup.outputs.is_experimental == 'false'",
209
- steps: [
210
- {
211
- name: 'Checkout code',
212
- uses: 'actions/checkout@v4',
213
- },
214
- {
215
- name: 'Setup Node.js',
216
- uses: 'actions/setup-node@v4',
217
- with: { 'node-version': '18', cache: 'npm' },
218
- },
219
- {
220
- name: 'Install dependencies',
221
- run: 'npm ci',
222
- },
223
- {
224
- name: 'Run mutation tests',
225
- run: getMutationCommand(language, tier),
226
- },
227
- ],
228
- };
229
-
230
- // Contract tests (only for tier 1 and 2)
231
- workflow.jobs.contract_test = {
232
- 'runs-on': 'ubuntu-latest',
233
- needs: ['setup', 'validate'],
234
- if: "(needs.setup.outputs.risk_tier == '1' || needs.setup.outputs.risk_tier == '2') && needs.setup.outputs.is_experimental == 'false'",
235
- steps: [
236
- {
237
- name: 'Checkout code',
238
- uses: 'actions/checkout@v4',
239
- },
240
- {
241
- name: 'Setup Node.js',
242
- uses: 'actions/setup-node@v4',
243
- with: { 'node-version': '18', cache: 'npm' },
244
- },
245
- {
246
- name: 'Install dependencies',
247
- run: 'npm ci',
248
- },
249
- {
250
- name: 'Run contract tests',
251
- run: getContractCommand(language, tier),
252
- },
253
- ],
254
- };
255
-
256
- // Property-based testing (only for tier 1)
257
- workflow.jobs.property_tests = {
258
- 'runs-on': 'ubuntu-latest',
259
- needs: ['setup', 'validate'],
260
- if: "needs.setup.outputs.risk_tier == '1'",
261
- steps: [
262
- {
263
- name: 'Checkout code',
264
- uses: 'actions/checkout@v4',
265
- },
266
- {
267
- name: 'Setup Node.js',
268
- uses: 'actions/setup-node@v4',
269
- with: { 'node-version': '18', cache: 'npm' },
270
- },
271
- {
272
- name: 'Install dependencies',
273
- run: 'npm ci',
274
- },
275
- {
276
- name: 'Generate property tests',
277
- run: 'node apps/tools/caws/property-testing.js generate javascript idempotent,commutative,associative',
278
- },
279
- {
280
- name: 'Install property testing dependencies',
281
- run: 'npm install --save-dev fast-check',
282
- },
283
- {
284
- name: 'Run property tests',
285
- run: 'node apps/tools/caws/property-testing.js run javascript tests/property',
286
- },
287
- ],
288
- };
289
-
290
- // Security scan (only for tier 1)
291
- workflow.jobs.security_scan = {
292
- 'runs-on': 'ubuntu-latest',
293
- needs: ['setup', 'validate'],
294
- if: "needs.setup.outputs.risk_tier == '1'",
295
- steps: [
296
- {
297
- name: 'Checkout code',
298
- uses: 'actions/checkout@v4',
299
- },
300
- {
301
- name: 'Run security scan',
302
- uses: 'securecodewarrior/github-action-sast-scan@main',
303
- with: {
304
- language: 'javascript',
305
- },
306
- },
307
- ],
308
- };
309
-
310
- // Performance tests (only for tier 1 and 2)
311
- workflow.jobs.performance_test = {
312
- 'runs-on': 'ubuntu-latest',
313
- needs: ['setup', 'validate'],
314
- if: "(needs.setup.outputs.risk_tier == '1' || needs.setup.outputs.risk_tier == '2') && needs.setup.outputs.is_experimental == 'false'",
315
- steps: [
316
- {
317
- name: 'Checkout code',
318
- uses: 'actions/checkout@v4',
319
- },
320
- {
321
- name: 'Setup Node.js',
322
- uses: 'actions/setup-node@v4',
323
- with: { 'node-version': '18', cache: 'npm' },
324
- },
325
- {
326
- name: 'Install dependencies',
327
- run: 'npm ci',
328
- },
329
- {
330
- name: 'Run performance tests',
331
- run: 'npm run test:performance || true',
332
- },
333
- ],
334
- };
335
- }
336
-
337
- // Quality gates job
338
- workflow.jobs.quality_gates = {
339
- 'runs-on': 'ubuntu-latest',
340
- needs: enableTierConditionals
341
- ? ['setup', 'validate', 'mutation_test', 'contract_test', 'property_tests'].filter(Boolean)
342
- : ['setup', 'validate'],
343
- steps: [
344
- {
345
- name: 'Checkout code',
346
- uses: 'actions/checkout@v4',
347
- },
348
- {
349
- name: 'Setup Node.js',
350
- uses: 'actions/setup-node@v4',
351
- with: { 'node-version': '18', cache: 'npm' },
352
- },
353
- {
354
- name: 'Run quality gates',
355
- run: `
356
- node apps/tools/caws/gates.js coverage \${{ needs.setup.outputs.risk_tier }} 85
357
- node apps/tools/caws/gates.js mutation \${{ needs.setup.outputs.risk_tier }} 60
358
- node apps/tools/caws/gates.js trust \${{ needs.setup.outputs.risk_tier }} 82
359
- `,
360
- },
361
- ],
362
- };
363
-
364
- return yaml.dump(workflow, { indent: 2 });
365
- }
366
-
367
- /**
368
- * Get test command based on language and optimization settings
369
- */
370
- function getTestCommand(language, tier, enableSelectiveTests) {
371
- const baseCommands = {
372
- javascript: 'npm run test',
373
- python: 'pytest',
374
- java: 'mvn test',
375
- go: 'go test ./...',
376
- rust: 'cargo test',
377
- };
378
-
379
- let command = baseCommands[language] || 'npm run test';
380
-
381
- if (enableSelectiveTests) {
382
- // Add selective test execution based on changed files
383
- command += ' -- --findRelatedTests';
384
- }
385
-
386
- return command;
387
- }
388
-
389
- /**
390
- * Get coverage command based on language and tier
391
- */
392
- function getCoverageCommand(language, _tier) {
393
- const commands = {
394
- javascript: 'npm run test:coverage',
395
- python: 'pytest --cov',
396
- java: 'mvn test jacoco:report',
397
- go: 'go test -coverprofile=coverage.out ./...',
398
- rust: 'cargo test --no-run && tarpaulin',
399
- };
400
-
401
- return commands[language] || 'echo "Coverage not configured for this language"';
402
- }
403
-
404
- /**
405
- * Get mutation testing command based on language and tier
406
- */
407
- function getMutationCommand(language, _tier) {
408
- const commands = {
409
- javascript: 'npx stryker run',
410
- python: 'mutmut run --paths-to-mutate src/',
411
- java: 'mvn org.pitest:pitest-maven:mutationCoverage',
412
- go: 'gremlins -path .',
413
- rust: 'cargo mutagen',
414
- };
415
-
416
- return commands[language] || 'echo "Mutation testing not configured for this language"';
417
- }
418
-
419
- /**
420
- * Get contract testing command based on language and tier
421
- */
422
- function getContractCommand(language, _tier) {
423
- const commands = {
424
- javascript: 'npm run test:contracts',
425
- python: 'schemathesis run --checks all http://localhost:3000/api/openapi.json',
426
- java: 'pact-jvm-provider-maven',
427
- go: 'pact-go',
428
- rust: 'pact-rust',
429
- };
430
-
431
- return commands[language] || 'echo "Contract testing not configured for this language"';
432
- }
433
-
434
- /**
435
- * Analyze current workflow for optimization opportunities
436
- * @param {string} workflowPath - Path to current workflow file
437
- * @returns {Object} Analysis results
438
- */
439
- function analyzeCurrentWorkflow(workflowPath = '.github/workflows/ci.yml') {
440
- const results = {
441
- currentOptimizations: [],
442
- missingOptimizations: [],
443
- recommendations: [],
444
- estimatedTimeSavings: 0,
445
- };
446
-
447
- try {
448
- if (!fs.existsSync(workflowPath)) {
449
- results.missingOptimizations.push('No GitHub Actions workflow found');
450
- results.recommendations.push('Create a GitHub Actions workflow with CAWS optimizations');
451
- return results;
452
- }
453
-
454
- const workflowContent = fs.readFileSync(workflowPath, 'utf8');
455
- const workflow = yaml.load(workflowContent);
456
-
457
- // Check for existing optimizations
458
- if (workflow.jobs?.setup?.outputs) {
459
- results.currentOptimizations.push('Setup job with outputs');
460
- }
461
-
462
- if (workflow.on?.pull_request && workflow.on?.push) {
463
- results.currentOptimizations.push('Multi-trigger workflow');
464
- }
465
-
466
- if (workflow.jobs?.validate?.strategy?.matrix) {
467
- results.currentOptimizations.push('Matrix strategy for multi-version testing');
468
- }
469
-
470
- // Check for missing optimizations
471
- if (!workflow.jobs?.quick_feedback) {
472
- results.missingOptimizations.push('Two-phase pipeline (quick feedback)');
473
- results.recommendations.push('Add quick feedback job for faster iteration');
474
- results.estimatedTimeSavings += 30; // seconds
475
- }
476
-
477
- if (!workflow.jobs?.mutation_test?.if) {
478
- results.missingOptimizations.push('Tier-based conditional execution');
479
- results.recommendations.push('Add conditional execution based on risk tier');
480
- results.estimatedTimeSavings += 60; // seconds
481
- }
482
-
483
- // Calculate potential improvements
484
- if (results.missingOptimizations.length > 0) {
485
- results.estimatedTimeSavings += results.missingOptimizations.length * 20;
486
- }
487
- } catch (error) {
488
- results.missingOptimizations.push(`Error analyzing workflow: ${error.message}`);
489
- }
490
-
491
- return results;
492
- }
493
-
494
- /**
495
- * Generate optimization recommendations
496
- * @param {Object} analysis - Workflow analysis results
497
- * @returns {Array} Detailed recommendations
498
- */
499
- function generateOptimizationRecommendations(analysis) {
500
- const recommendations = [];
501
-
502
- if (analysis.missingOptimizations.includes('Two-phase pipeline (quick feedback)')) {
503
- recommendations.push({
504
- strategy: OPTIMIZATION_STRATEGIES.TWO_PHASE_PIPELINE,
505
- priority: 'high',
506
- effort: 'medium',
507
- description: 'Implement quick feedback for commits and full validation for PRs',
508
- benefits: [
509
- 'Faster developer feedback',
510
- 'Reduced CI queue time',
511
- 'Better development velocity',
512
- ],
513
- implementation: [
514
- 'Add quick_feedback job for push events',
515
- 'Run full validation only on pull_request events',
516
- 'Use job dependencies to ensure proper execution order',
517
- ],
518
- });
519
- }
520
-
521
- if (analysis.missingOptimizations.includes('Tier-based conditional execution')) {
522
- recommendations.push({
523
- strategy: OPTIMIZATION_STRATEGIES.TIER_BASED_CONDITIONAL,
524
- priority: 'high',
525
- effort: 'low',
526
- description: 'Skip expensive checks for low-risk changes',
527
- benefits: [
528
- 'Faster CI for low-risk changes',
529
- 'Better resource utilization',
530
- 'Maintained quality for high-risk changes',
531
- ],
532
- implementation: [
533
- 'Add setup job to detect risk tier from working spec',
534
- 'Use job conditions based on risk tier',
535
- 'Skip mutation tests for Tier 3 changes',
536
- ],
537
- });
538
- }
539
-
540
- return recommendations;
541
- }
542
-
543
- // CLI interface
544
- if (require.main === module) {
545
- const command = process.argv[2];
546
-
547
- switch (command) {
548
- case 'analyze':
549
- console.log('šŸ” Analyzing current CI/CD setup for optimization opportunities...');
550
-
551
- const analysis = analyzeCurrentWorkflow();
552
-
553
- console.log('\nšŸ“Š Current Workflow Analysis:');
554
- console.log(`āœ… Current optimizations: ${analysis.currentOptimizations.length}`);
555
- analysis.currentOptimizations.forEach((opt) => console.log(` - ${opt}`));
556
-
557
- console.log(`\nāŒ Missing optimizations: ${analysis.missingOptimizations.length}`);
558
- analysis.missingOptimizations.forEach((opt) => console.log(` - ${opt}`));
559
-
560
- if (analysis.recommendations.length > 0) {
561
- console.log('\nšŸ’” Quick recommendations:');
562
- analysis.recommendations.forEach((rec) => console.log(` - ${rec}`));
563
- }
564
-
565
- if (analysis.estimatedTimeSavings > 0) {
566
- console.log(`\nā±ļø Estimated time savings: ${analysis.estimatedTimeSavings}s per run`);
567
- }
568
-
569
- const detailedRecommendations = generateOptimizationRecommendations(analysis);
570
- if (detailedRecommendations.length > 0) {
571
- console.log('\nšŸ“‹ Detailed Optimization Plan:');
572
- detailedRecommendations.forEach((rec, index) => {
573
- console.log(`\n${index + 1}. ${rec.strategy.name} [${rec.priority} priority]`);
574
- console.log(` ${rec.description}`);
575
- console.log(` Effort: ${rec.effort} | Impact: ${rec.strategy.impact}`);
576
- console.log(` Benefits: ${rec.benefits.join(', ')}`);
577
- console.log(` Implementation steps:`);
578
- rec.implementation.forEach((step) => console.log(` - ${step}`));
579
- });
580
- }
581
- break;
582
-
583
- case 'generate':
584
- const language = process.argv[3] || 'javascript';
585
- const tier = parseInt(process.argv[4]) || 2;
586
- const outputPath = process.argv[5] || '.github/workflows/caws-ci.yml';
587
-
588
- console.log(`šŸš€ Generating optimized workflow for ${language} (Tier ${tier})...`);
589
-
590
- try {
591
- const workflow = generateOptimizedWorkflow({
592
- language,
593
- tier,
594
- enableTwoPhase: true,
595
- enableSelectiveTests: true,
596
- enableTierConditionals: true,
597
- });
598
-
599
- // Ensure directory exists
600
- const dir = path.dirname(outputPath);
601
- if (!fs.existsSync(dir)) {
602
- fs.mkdirSync(dir, { recursive: true });
603
- }
604
-
605
- fs.writeFileSync(outputPath, workflow);
606
- console.log(`āœ… Generated optimized workflow: ${outputPath}`);
607
-
608
- console.log('\nšŸ”§ Next steps:');
609
- console.log(' 1. Review the generated workflow file');
610
- console.log(' 2. Commit and push to trigger the new pipeline');
611
- console.log(' 3. Monitor CI performance and adjust as needed');
612
- console.log(' 4. Consider enabling branch protection rules');
613
- } catch (error) {
614
- console.error('āŒ Error generating workflow:', error.message);
615
- process.exit(1);
616
- }
617
- break;
618
-
619
- default:
620
- console.log('CAWS CI/CD Pipeline Optimizer');
621
- console.log('Usage:');
622
- console.log(' node ci-optimizer.js analyze [workflow-path]');
623
- console.log(' node ci-optimizer.js generate [language] [tier] [output-path]');
624
- console.log('');
625
- console.log('Optimization strategies:');
626
- Object.values(OPTIMIZATION_STRATEGIES).forEach((strategy) => {
627
- console.log(` - ${strategy.name}: ${strategy.description} (${strategy.impact} impact)`);
628
- });
629
- console.log('');
630
- console.log('Examples:');
631
- console.log(' node ci-optimizer.js analyze');
632
- console.log(' node ci-optimizer.js generate python 2 .github/workflows/ci.yml');
633
- process.exit(1);
634
- }
635
- }
636
-
637
- module.exports = {
638
- OPTIMIZATION_STRATEGIES,
639
- generateOptimizedWorkflow,
640
- analyzeCurrentWorkflow,
641
- generateOptimizationRecommendations,
642
- };