create-qa-architect 5.0.7 ā 5.3.1
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/.github/workflows/auto-release.yml +49 -0
- package/README.md +46 -1
- package/docs/ADOPTION-SUMMARY.md +41 -0
- package/docs/ARCHITECTURE-REVIEW.md +67 -0
- package/docs/ARCHITECTURE.md +29 -45
- package/docs/CODE-REVIEW.md +100 -0
- package/docs/REQUIREMENTS.md +148 -0
- package/docs/SECURITY-AUDIT.md +68 -0
- package/docs/test-trace-matrix.md +28 -0
- package/lib/commands/deps.js +245 -0
- package/lib/commands/index.js +25 -0
- package/lib/commands/validate.js +85 -0
- package/lib/error-reporter.js +13 -1
- package/lib/github-api.js +108 -13
- package/lib/license-signing.js +110 -0
- package/lib/license-validator.js +359 -71
- package/lib/licensing.js +333 -99
- package/lib/prelaunch-validator.js +828 -0
- package/lib/quality-tools-generator.js +495 -0
- package/lib/result-types.js +112 -0
- package/lib/security-enhancements.js +1 -1
- package/lib/smart-strategy-generator.js +28 -9
- package/lib/template-loader.js +52 -19
- package/lib/validation/cache-manager.js +36 -6
- package/lib/validation/config-security.js +78 -15
- package/lib/validation/workflow-validation.js +28 -7
- package/package.json +2 -4
- package/scripts/check-test-coverage.sh +46 -0
- package/setup.js +350 -284
- package/create-saas-monetization.js +0 -1513
package/setup.js
CHANGED
|
@@ -1,5 +1,68 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* DR26 fix: Architectural Refactoring Plan for setup.js (2201 lines)
|
|
5
|
+
*
|
|
6
|
+
* PRIORITY: This file should be split into focused modules to improve
|
|
7
|
+
* maintainability, testability, and reduce cognitive load.
|
|
8
|
+
*
|
|
9
|
+
* PROPOSED MODULE STRUCTURE (target: < 500 lines per module):
|
|
10
|
+
*
|
|
11
|
+
* 1. lib/commands/validate.js (~300 lines)
|
|
12
|
+
* - Validation command logic
|
|
13
|
+
* - Config validation workflows
|
|
14
|
+
* - Prelaunch validation integration
|
|
15
|
+
*
|
|
16
|
+
* 2. lib/commands/deps.js (~200 lines)
|
|
17
|
+
* - Dependency monitoring setup
|
|
18
|
+
* - Dependabot configuration
|
|
19
|
+
* - GitHub API integration calls
|
|
20
|
+
*
|
|
21
|
+
* 3. lib/commands/activate.js (~150 lines)
|
|
22
|
+
* - License activation flow
|
|
23
|
+
* - Interactive license prompts
|
|
24
|
+
* - License validation integration
|
|
25
|
+
*
|
|
26
|
+
* 4. lib/commands/setup-main.js (~800 lines)
|
|
27
|
+
* - Main setup orchestration
|
|
28
|
+
* - Template generation
|
|
29
|
+
* - File writing operations
|
|
30
|
+
* - Husky/lint-staged configuration
|
|
31
|
+
*
|
|
32
|
+
* 5. lib/setup-config.js (~200 lines)
|
|
33
|
+
* - Configuration merging logic
|
|
34
|
+
* - Package.json updates
|
|
35
|
+
* - Workflow injection helpers
|
|
36
|
+
*
|
|
37
|
+
* 6. setup.js (core CLI, ~200 lines)
|
|
38
|
+
* - Argument parsing
|
|
39
|
+
* - Command routing
|
|
40
|
+
* - Help/version display
|
|
41
|
+
* - Exit code handling
|
|
42
|
+
*
|
|
43
|
+
* MIGRATION CHECKLIST:
|
|
44
|
+
* - [ ] Extract validation command to lib/commands/validate.js
|
|
45
|
+
* - [ ] Extract deps command to lib/commands/deps.js
|
|
46
|
+
* - [ ] Extract license activation to lib/commands/activate.js
|
|
47
|
+
* - [ ] Extract main setup flow to lib/commands/setup-main.js
|
|
48
|
+
* - [ ] Extract config helpers to lib/setup-config.js
|
|
49
|
+
* - [ ] Update all tests to use new module structure
|
|
50
|
+
* - [ ] Verify all CLI commands still work (--help, --deps, --validate, etc.)
|
|
51
|
+
* - [ ] Update integration tests
|
|
52
|
+
* - [ ] Run full test suite and ensure 100% pass rate
|
|
53
|
+
*
|
|
54
|
+
* BENEFITS:
|
|
55
|
+
* - Easier to test individual commands
|
|
56
|
+
* - Reduced cognitive load when modifying specific features
|
|
57
|
+
* - Better code organization and discoverability
|
|
58
|
+
* - Easier to add new commands in the future
|
|
59
|
+
* - Faster development cycles (smaller files to navigate)
|
|
60
|
+
*
|
|
61
|
+
* BLOCKED BY: None (can be done incrementally)
|
|
62
|
+
* ESTIMATED EFFORT: 2-3 days with full test coverage
|
|
63
|
+
* RISK: Medium (need to ensure no regressions in CLI behavior)
|
|
64
|
+
*/
|
|
65
|
+
|
|
3
66
|
const fs = require('fs')
|
|
4
67
|
const path = require('path')
|
|
5
68
|
const { execSync } = require('child_process')
|
|
@@ -49,29 +112,23 @@ const {
|
|
|
49
112
|
} = require('./config/defaults')
|
|
50
113
|
|
|
51
114
|
// Enhanced validation capabilities
|
|
52
|
-
const { ValidationRunner } = require('./lib/validation')
|
|
53
115
|
const { validateQualityConfig } = require('./lib/config-validator')
|
|
54
116
|
|
|
55
117
|
// Interactive mode capabilities
|
|
56
118
|
const { InteractivePrompt } = require('./lib/interactive/prompt')
|
|
57
119
|
const { runInteractiveFlow } = require('./lib/interactive/questions')
|
|
58
120
|
|
|
59
|
-
//
|
|
60
|
-
const {
|
|
61
|
-
hasNpmProject,
|
|
62
|
-
generateBasicDependabotConfig,
|
|
63
|
-
writeBasicDependabotConfig,
|
|
64
|
-
} = require('./lib/dependency-monitoring-basic')
|
|
65
|
-
|
|
66
|
-
// Premium dependency monitoring (Pro/Team/Enterprise Tiers)
|
|
67
|
-
const {
|
|
68
|
-
generatePremiumDependabotConfig,
|
|
69
|
-
writePremiumDependabotConfig,
|
|
70
|
-
} = require('./lib/dependency-monitoring-premium')
|
|
121
|
+
// Note: Dependency monitoring imports moved to ./lib/commands/deps.js
|
|
71
122
|
|
|
72
123
|
// Custom template loading
|
|
73
124
|
const { TemplateLoader } = require('./lib/template-loader')
|
|
74
125
|
|
|
126
|
+
// Command handlers (extracted for maintainability)
|
|
127
|
+
const {
|
|
128
|
+
handleValidationCommands,
|
|
129
|
+
handleDependencyMonitoring,
|
|
130
|
+
} = require('./lib/commands')
|
|
131
|
+
|
|
75
132
|
// Licensing system
|
|
76
133
|
const {
|
|
77
134
|
getLicenseInfo,
|
|
@@ -91,6 +148,26 @@ const {
|
|
|
91
148
|
getTestTierScripts,
|
|
92
149
|
} = require('./lib/smart-strategy-generator')
|
|
93
150
|
|
|
151
|
+
// Quality Tools Generator (Lighthouse, size-limit, axe-core, commitlint, coverage)
|
|
152
|
+
const {
|
|
153
|
+
writeLighthouseConfig,
|
|
154
|
+
writeSizeLimitConfig,
|
|
155
|
+
writeCommitlintConfig,
|
|
156
|
+
writeCommitMsgHook,
|
|
157
|
+
writeAxeTestSetup,
|
|
158
|
+
getQualityToolsDependencies,
|
|
159
|
+
getQualityToolsScripts,
|
|
160
|
+
} = require('./lib/quality-tools-generator')
|
|
161
|
+
|
|
162
|
+
// Pre-Launch Validation (SEO, links, a11y, docs, env)
|
|
163
|
+
const {
|
|
164
|
+
writeValidationScripts,
|
|
165
|
+
writeEnvValidator,
|
|
166
|
+
writePa11yConfig,
|
|
167
|
+
getPrelaunchScripts,
|
|
168
|
+
getPrelaunchDependencies,
|
|
169
|
+
} = require('./lib/prelaunch-validator')
|
|
170
|
+
|
|
94
171
|
// Telemetry (opt-in usage tracking)
|
|
95
172
|
const { TelemetrySession, showTelemetryStatus } = require('./lib/telemetry')
|
|
96
173
|
|
|
@@ -103,7 +180,6 @@ const {
|
|
|
103
180
|
// Critical setup enhancements (fixes production quality gaps)
|
|
104
181
|
const {
|
|
105
182
|
applyProductionQualityFixes,
|
|
106
|
-
// generateEnhancedPreCommitHook,
|
|
107
183
|
validateProjectSetup,
|
|
108
184
|
} = require('./lib/setup-enhancements')
|
|
109
185
|
|
|
@@ -151,7 +227,12 @@ function injectCollaborationSteps(workflowContent, options = {}) {
|
|
|
151
227
|
const safeReadDir = dir => {
|
|
152
228
|
try {
|
|
153
229
|
return fs.readdirSync(dir, { withFileTypes: true })
|
|
154
|
-
} catch {
|
|
230
|
+
} catch (error) {
|
|
231
|
+
// Silent failure fix: Log non-ENOENT errors in DEBUG mode
|
|
232
|
+
// ENOENT is expected (dir doesn't exist), other errors may indicate issues
|
|
233
|
+
if (process.env.DEBUG && error?.code !== 'ENOENT') {
|
|
234
|
+
console.warn(`ā ļø Could not read directory ${dir}: ${error.message}`)
|
|
235
|
+
}
|
|
155
236
|
return []
|
|
156
237
|
}
|
|
157
238
|
}
|
|
@@ -332,6 +413,7 @@ function parseArguments(rawArgs) {
|
|
|
332
413
|
const isCheckMaturityMode = sanitizedArgs.includes('--check-maturity')
|
|
333
414
|
const isValidateConfigMode = sanitizedArgs.includes('--validate-config')
|
|
334
415
|
const isActivateLicenseMode = sanitizedArgs.includes('--activate-license')
|
|
416
|
+
const isPrelaunchMode = sanitizedArgs.includes('--prelaunch')
|
|
335
417
|
const isDryRun = sanitizedArgs.includes('--dry-run')
|
|
336
418
|
const ciProviderIndex = sanitizedArgs.findIndex(arg => arg === '--ci')
|
|
337
419
|
const ciProvider =
|
|
@@ -372,6 +454,7 @@ function parseArguments(rawArgs) {
|
|
|
372
454
|
isCheckMaturityMode,
|
|
373
455
|
isValidateConfigMode,
|
|
374
456
|
isActivateLicenseMode,
|
|
457
|
+
isPrelaunchMode,
|
|
375
458
|
isDryRun,
|
|
376
459
|
ciProvider,
|
|
377
460
|
enableSlackAlerts,
|
|
@@ -410,6 +493,7 @@ function parseArguments(rawArgs) {
|
|
|
410
493
|
isCheckMaturityMode,
|
|
411
494
|
isValidateConfigMode,
|
|
412
495
|
isActivateLicenseMode,
|
|
496
|
+
isPrelaunchMode,
|
|
413
497
|
isDryRun,
|
|
414
498
|
ciProvider,
|
|
415
499
|
enableSlackAlerts,
|
|
@@ -535,6 +619,7 @@ VALIDATION OPTIONS:
|
|
|
535
619
|
--validate-docs Run documentation validation only
|
|
536
620
|
--validate-config Validate .qualityrc.json configuration file
|
|
537
621
|
--check-maturity Detect and display project maturity level
|
|
622
|
+
--prelaunch Add pre-launch validation suite (SEO, links, a11y, docs)
|
|
538
623
|
|
|
539
624
|
LICENSE, TELEMETRY & ERROR REPORTING:
|
|
540
625
|
--license-status Show current license tier and available features
|
|
@@ -576,6 +661,9 @@ EXAMPLES:
|
|
|
576
661
|
npx create-qa-architect@latest --check-maturity
|
|
577
662
|
ā Detect project maturity level (minimal, bootstrap, development, production-ready)
|
|
578
663
|
|
|
664
|
+
npx create-qa-architect@latest --prelaunch
|
|
665
|
+
ā Add pre-launch validation: SEO (sitemap, robots, meta), links, a11y, docs
|
|
666
|
+
|
|
579
667
|
npx create-qa-architect@latest --validate-config
|
|
580
668
|
ā Validate .qualityrc.json configuration file against JSON Schema
|
|
581
669
|
|
|
@@ -648,258 +736,8 @@ HELP:
|
|
|
648
736
|
process.exit(0)
|
|
649
737
|
}
|
|
650
738
|
|
|
651
|
-
//
|
|
652
|
-
|
|
653
|
-
const validationOptions = {
|
|
654
|
-
disableNpmAudit,
|
|
655
|
-
disableGitleaks,
|
|
656
|
-
disableActionlint,
|
|
657
|
-
disableMarkdownlint,
|
|
658
|
-
disableEslintSecurity,
|
|
659
|
-
allowLatestGitleaks,
|
|
660
|
-
}
|
|
661
|
-
const validator = new ValidationRunner(validationOptions)
|
|
662
|
-
|
|
663
|
-
if (isConfigSecurityMode) {
|
|
664
|
-
try {
|
|
665
|
-
await validator.runConfigSecurity()
|
|
666
|
-
process.exit(0)
|
|
667
|
-
} catch (error) {
|
|
668
|
-
console.error(
|
|
669
|
-
`\nā Configuration security validation failed:\n${error.message}`
|
|
670
|
-
)
|
|
671
|
-
process.exit(1)
|
|
672
|
-
}
|
|
673
|
-
}
|
|
674
|
-
|
|
675
|
-
if (isDocsValidationMode) {
|
|
676
|
-
try {
|
|
677
|
-
await validator.runDocumentationValidation()
|
|
678
|
-
process.exit(0)
|
|
679
|
-
} catch (error) {
|
|
680
|
-
console.error(`\nā Documentation validation failed:\n${error.message}`)
|
|
681
|
-
process.exit(1)
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
if (isComprehensiveMode || isValidationMode) {
|
|
686
|
-
try {
|
|
687
|
-
// Use parallel validation for 3-5x speedup (runs checks concurrently)
|
|
688
|
-
await validator.runComprehensiveCheckParallel()
|
|
689
|
-
process.exit(0)
|
|
690
|
-
} catch (error) {
|
|
691
|
-
console.error(`\nā Comprehensive validation failed:\n${error.message}`)
|
|
692
|
-
process.exit(1)
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
// Detect Python project
|
|
698
|
-
function detectPythonProject(projectPath) {
|
|
699
|
-
const pythonFiles = [
|
|
700
|
-
'pyproject.toml',
|
|
701
|
-
'requirements.txt',
|
|
702
|
-
'setup.py',
|
|
703
|
-
'Pipfile',
|
|
704
|
-
]
|
|
705
|
-
return pythonFiles.some(file => fs.existsSync(path.join(projectPath, file)))
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
// Detect Rust project
|
|
709
|
-
function detectRustProject(projectPath) {
|
|
710
|
-
return fs.existsSync(path.join(projectPath, 'Cargo.toml'))
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
// Detect Ruby project
|
|
714
|
-
function detectRubyProject(projectPath) {
|
|
715
|
-
return fs.existsSync(path.join(projectPath, 'Gemfile'))
|
|
716
|
-
}
|
|
717
|
-
|
|
718
|
-
// Handle dependency monitoring (Free/Pro/Team/Enterprise)
|
|
719
|
-
async function handleDependencyMonitoring() {
|
|
720
|
-
const projectPath = process.cwd()
|
|
721
|
-
const license = getLicenseInfo()
|
|
722
|
-
|
|
723
|
-
// Detect all supported ecosystems (npm, Python, Ruby, Rust, etc.)
|
|
724
|
-
const hasNpm = hasNpmProject(projectPath)
|
|
725
|
-
const hasPython = detectPythonProject(projectPath)
|
|
726
|
-
const hasRust = detectRustProject(projectPath)
|
|
727
|
-
const hasRuby = detectRubyProject(projectPath)
|
|
728
|
-
|
|
729
|
-
if (!hasNpm && !hasPython && !hasRust && !hasRuby) {
|
|
730
|
-
console.error(
|
|
731
|
-
'ā No supported dependency file found (package.json, pyproject.toml, requirements.txt, Gemfile, Cargo.toml).'
|
|
732
|
-
)
|
|
733
|
-
console.log("š” Make sure you're in a directory with dependency files.")
|
|
734
|
-
process.exit(1)
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
if (hasNpm) console.log('š¦ Detected: npm project')
|
|
738
|
-
if (hasPython) console.log('š Detected: Python project')
|
|
739
|
-
if (hasRust) console.log('š¦ Detected: Rust project')
|
|
740
|
-
if (hasRuby) console.log('š Detected: Ruby project')
|
|
741
|
-
console.log(`š License tier: ${license.tier.toUpperCase()}`)
|
|
742
|
-
|
|
743
|
-
// Enforce Free tier caps for dependency monitoring (counted as dependency PRs)
|
|
744
|
-
if (license.tier === 'FREE') {
|
|
745
|
-
const capCheck = checkUsageCaps('dependency-pr')
|
|
746
|
-
if (!capCheck.allowed) {
|
|
747
|
-
console.error(`ā ${capCheck.reason}`)
|
|
748
|
-
console.error(
|
|
749
|
-
' Upgrade to Pro, Team, or Enterprise for unlimited runs: https://vibebuildlab.com/qa-architect'
|
|
750
|
-
)
|
|
751
|
-
process.exit(1)
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
const increment = incrementUsage('dependency-pr')
|
|
755
|
-
const usage = increment.usage || capCheck.usage
|
|
756
|
-
const caps = capCheck.caps
|
|
757
|
-
if (usage && caps && caps.maxDependencyPRsPerMonth !== undefined) {
|
|
758
|
-
console.log(
|
|
759
|
-
`š§® Usage: ${usage.dependencyPRs}/${caps.maxDependencyPRsPerMonth} dependency monitoring runs used this month`
|
|
760
|
-
)
|
|
761
|
-
}
|
|
762
|
-
}
|
|
763
|
-
|
|
764
|
-
const dependabotPath = path.join(projectPath, '.github', 'dependabot.yml')
|
|
765
|
-
|
|
766
|
-
// Use premium or basic config based on license tier
|
|
767
|
-
// Free beta ended with v4.1.1 - Premium features now require Pro/Team/Enterprise tier
|
|
768
|
-
// Pro/Team/Enterprise: Framework-aware dependency monitoring with grouping
|
|
769
|
-
// Free: Basic npm-only dependency monitoring
|
|
770
|
-
const shouldUsePremium =
|
|
771
|
-
license.tier === 'PRO' ||
|
|
772
|
-
license.tier === 'TEAM' ||
|
|
773
|
-
license.tier === 'ENTERPRISE'
|
|
774
|
-
|
|
775
|
-
// Free tier only supports npm projects. Fail fast with a clear message.
|
|
776
|
-
if (!shouldUsePremium && !hasNpm && (hasPython || hasRust || hasRuby)) {
|
|
777
|
-
console.error(
|
|
778
|
-
'ā Dependency monitoring for this project requires a Pro, Team, or Enterprise license.'
|
|
779
|
-
)
|
|
780
|
-
console.error(
|
|
781
|
-
' Free tier supports npm projects only. Detected non-npm ecosystems.'
|
|
782
|
-
)
|
|
783
|
-
console.error(
|
|
784
|
-
' Options: add npm/package.json, or upgrade and re-run: npx create-qa-architect@latest --deps after activation.'
|
|
785
|
-
)
|
|
786
|
-
process.exit(1)
|
|
787
|
-
}
|
|
788
|
-
|
|
789
|
-
if (shouldUsePremium) {
|
|
790
|
-
console.log(
|
|
791
|
-
'\nš Setting up framework-aware dependency monitoring (Premium)...\n'
|
|
792
|
-
)
|
|
793
|
-
|
|
794
|
-
const configData = generatePremiumDependabotConfig({
|
|
795
|
-
projectPath,
|
|
796
|
-
schedule: 'weekly',
|
|
797
|
-
})
|
|
798
|
-
|
|
799
|
-
if (configData) {
|
|
800
|
-
const { ecosystems } = configData
|
|
801
|
-
const ecosystemNames = Object.keys(ecosystems)
|
|
802
|
-
|
|
803
|
-
if (ecosystemNames.length > 0) {
|
|
804
|
-
console.log('š Detected ecosystems:')
|
|
805
|
-
|
|
806
|
-
// Find primary ecosystem and total package count
|
|
807
|
-
let primaryEcosystem = null
|
|
808
|
-
ecosystemNames.forEach(ecoName => {
|
|
809
|
-
const eco = ecosystems[ecoName]
|
|
810
|
-
const frameworks = Object.keys(eco.detected || {})
|
|
811
|
-
const totalPackages = frameworks.reduce((sum, fw) => {
|
|
812
|
-
return sum + (eco.detected[fw]?.count || 0)
|
|
813
|
-
}, 0)
|
|
814
|
-
|
|
815
|
-
console.log(` ⢠${ecoName}: ${totalPackages} packages`)
|
|
816
|
-
|
|
817
|
-
if (eco.primary) {
|
|
818
|
-
primaryEcosystem = ecoName
|
|
819
|
-
}
|
|
820
|
-
})
|
|
821
|
-
|
|
822
|
-
if (primaryEcosystem) {
|
|
823
|
-
console.log(`\nšÆ Primary ecosystem: ${primaryEcosystem}`)
|
|
824
|
-
}
|
|
825
|
-
}
|
|
826
|
-
|
|
827
|
-
writePremiumDependabotConfig(configData, dependabotPath)
|
|
828
|
-
console.log(
|
|
829
|
-
'\nā
Created .github/dependabot.yml with framework grouping'
|
|
830
|
-
)
|
|
831
|
-
|
|
832
|
-
console.log('\nš Premium dependency monitoring setup complete!')
|
|
833
|
-
console.log('\nš What was added (Pro Tier):')
|
|
834
|
-
console.log(' ⢠Framework-aware dependency grouping')
|
|
835
|
-
console.log(
|
|
836
|
-
` ⢠${Object.keys(configData.config.updates[0].groups || {}).length} dependency groups created`
|
|
837
|
-
)
|
|
838
|
-
console.log(' ⢠Intelligent update batching (reduces PRs by 60%+)')
|
|
839
|
-
console.log(' ⢠GitHub Actions dependency monitoring')
|
|
840
|
-
}
|
|
841
|
-
} else {
|
|
842
|
-
console.log(
|
|
843
|
-
'\nš Setting up basic dependency monitoring (Free Tier)...\n'
|
|
844
|
-
)
|
|
845
|
-
|
|
846
|
-
const dependabotConfig = generateBasicDependabotConfig({
|
|
847
|
-
projectPath,
|
|
848
|
-
schedule: 'weekly',
|
|
849
|
-
})
|
|
850
|
-
|
|
851
|
-
if (dependabotConfig) {
|
|
852
|
-
writeBasicDependabotConfig(dependabotConfig, dependabotPath)
|
|
853
|
-
console.log('ā
Created .github/dependabot.yml')
|
|
854
|
-
}
|
|
855
|
-
|
|
856
|
-
console.log('\nš Basic dependency monitoring setup complete!')
|
|
857
|
-
console.log('\nš What was added (Free Tier):')
|
|
858
|
-
console.log(' ⢠Basic Dependabot configuration for npm packages')
|
|
859
|
-
console.log(' ⢠Weekly dependency updates on Monday 9am')
|
|
860
|
-
console.log(' ⢠GitHub Actions dependency monitoring')
|
|
861
|
-
|
|
862
|
-
// Show upgrade message for premium features
|
|
863
|
-
console.log('\nš Premium features now available:')
|
|
864
|
-
console.log(
|
|
865
|
-
' ā
Framework-aware package grouping (React, Vue, Angular)'
|
|
866
|
-
)
|
|
867
|
-
console.log(' ⢠Coming soon: Multi-language support (Python, Rust, Go)')
|
|
868
|
-
console.log(' ⢠Planned: Advanced security audit workflows')
|
|
869
|
-
console.log(' ⢠Planned: Custom update schedules and notifications')
|
|
870
|
-
|
|
871
|
-
showUpgradeMessage('Framework-Aware Dependency Grouping')
|
|
872
|
-
}
|
|
873
|
-
|
|
874
|
-
// Auto-enable Dependabot on GitHub if token available
|
|
875
|
-
console.log('\nš§ Attempting to enable Dependabot on GitHub...')
|
|
876
|
-
try {
|
|
877
|
-
const { setupDependabot } = require('./lib/github-api')
|
|
878
|
-
const result = await setupDependabot(projectPath, { verbose: true })
|
|
879
|
-
|
|
880
|
-
if (result.success) {
|
|
881
|
-
console.log('ā
Dependabot alerts and security updates enabled!')
|
|
882
|
-
} else if (result.errors.length > 0) {
|
|
883
|
-
console.log('ā ļø Could not auto-enable Dependabot:')
|
|
884
|
-
result.errors.forEach(err => console.log(` ⢠${err}`))
|
|
885
|
-
console.log('\nš” Manual steps needed:')
|
|
886
|
-
console.log(' ⢠Go to GitHub repo ā Settings ā Code security')
|
|
887
|
-
console.log(
|
|
888
|
-
' ⢠Enable "Dependabot alerts" and "Dependabot security updates"'
|
|
889
|
-
)
|
|
890
|
-
}
|
|
891
|
-
} catch (error) {
|
|
892
|
-
console.log('ā ļø Could not auto-enable Dependabot:', error.message)
|
|
893
|
-
console.log('\nš” Manual steps:')
|
|
894
|
-
console.log(' ⢠Enable Dependabot in GitHub repo settings')
|
|
895
|
-
}
|
|
896
|
-
|
|
897
|
-
console.log('\nš” Next steps:')
|
|
898
|
-
console.log(' ⢠Review and commit .github/dependabot.yml')
|
|
899
|
-
console.log(
|
|
900
|
-
' ⢠Dependabot will start monitoring weekly for dependency updates'
|
|
901
|
-
)
|
|
902
|
-
}
|
|
739
|
+
// Note: handleValidationCommands, handleDependencyMonitoring, detectPythonProject,
|
|
740
|
+
// detectRustProject, detectRubyProject are now imported from ./lib/commands
|
|
903
741
|
|
|
904
742
|
// Handle license status command
|
|
905
743
|
if (isLicenseStatusMode) {
|
|
@@ -969,6 +807,83 @@ HELP:
|
|
|
969
807
|
})()
|
|
970
808
|
}
|
|
971
809
|
|
|
810
|
+
// Handle pre-launch validation setup command
|
|
811
|
+
if (isPrelaunchMode) {
|
|
812
|
+
return (async () => {
|
|
813
|
+
try {
|
|
814
|
+
const projectPath = process.cwd()
|
|
815
|
+
const PackageJson = checkNodeVersionAndLoadPackageJson()
|
|
816
|
+
const pkgJson = await PackageJson.load(projectPath)
|
|
817
|
+
const license = getLicenseInfo()
|
|
818
|
+
const isPro =
|
|
819
|
+
license.tier === 'PRO' ||
|
|
820
|
+
license.tier === 'TEAM' ||
|
|
821
|
+
license.tier === 'ENTERPRISE'
|
|
822
|
+
|
|
823
|
+
console.log('\nš Setting up pre-launch validation suite...\n')
|
|
824
|
+
console.log(` License tier: ${license.tier.toUpperCase()}`)
|
|
825
|
+
|
|
826
|
+
// Check feature availability
|
|
827
|
+
if (!hasFeature('prelaunchValidation')) {
|
|
828
|
+
console.error('ā Pre-launch validation requires a valid license.')
|
|
829
|
+
showUpgradeMessage('Pre-launch validation')
|
|
830
|
+
process.exit(1)
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
// Write validation scripts
|
|
834
|
+
const scriptsWritten = writeValidationScripts(projectPath)
|
|
835
|
+
console.log(` ā
Created ${scriptsWritten.length} validation scripts`)
|
|
836
|
+
|
|
837
|
+
// Write pa11y config
|
|
838
|
+
writePa11yConfig(projectPath)
|
|
839
|
+
console.log(' ā
Created .pa11yci config')
|
|
840
|
+
|
|
841
|
+
// Write env validator for Pro+
|
|
842
|
+
if (isPro && hasFeature('envValidation')) {
|
|
843
|
+
writeEnvValidator(projectPath)
|
|
844
|
+
console.log(' ā
Created env vars validator (Pro)')
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
// Add scripts to package.json
|
|
848
|
+
const prelaunchScripts = getPrelaunchScripts(isPro)
|
|
849
|
+
const prelaunchDeps = getPrelaunchDependencies(isPro)
|
|
850
|
+
|
|
851
|
+
// Merge scripts
|
|
852
|
+
const existingScripts = pkgJson.content.scripts || {}
|
|
853
|
+
pkgJson.update({
|
|
854
|
+
scripts: { ...existingScripts, ...prelaunchScripts },
|
|
855
|
+
})
|
|
856
|
+
|
|
857
|
+
// Merge devDependencies
|
|
858
|
+
const existingDevDeps = pkgJson.content.devDependencies || {}
|
|
859
|
+
pkgJson.update({
|
|
860
|
+
devDependencies: { ...existingDevDeps, ...prelaunchDeps },
|
|
861
|
+
})
|
|
862
|
+
|
|
863
|
+
await pkgJson.save()
|
|
864
|
+
|
|
865
|
+
console.log('\nā
Pre-launch validation setup complete!\n')
|
|
866
|
+
console.log('Available scripts:')
|
|
867
|
+
console.log(' npm run validate:sitemap - Check sitemap.xml')
|
|
868
|
+
console.log(' npm run validate:robots - Check robots.txt')
|
|
869
|
+
console.log(' npm run validate:meta - Check meta tags')
|
|
870
|
+
console.log(' npm run validate:links - Check for broken links')
|
|
871
|
+
console.log(' npm run validate:a11y - Run accessibility audit')
|
|
872
|
+
console.log(' npm run validate:docs - Check documentation')
|
|
873
|
+
if (isPro) {
|
|
874
|
+
console.log(' npm run validate:env - Audit env vars (Pro)')
|
|
875
|
+
}
|
|
876
|
+
console.log(' npm run validate:prelaunch - Run all checks')
|
|
877
|
+
console.log('\nš” Run: npm install && npm run validate:prelaunch')
|
|
878
|
+
|
|
879
|
+
process.exit(0)
|
|
880
|
+
} catch (error) {
|
|
881
|
+
console.error('Pre-launch validation setup error:', error.message)
|
|
882
|
+
process.exit(1)
|
|
883
|
+
}
|
|
884
|
+
})()
|
|
885
|
+
}
|
|
886
|
+
|
|
972
887
|
// Run validation commands if requested
|
|
973
888
|
if (
|
|
974
889
|
isValidationMode ||
|
|
@@ -979,13 +894,152 @@ HELP:
|
|
|
979
894
|
// Handle validation commands and exit
|
|
980
895
|
return (async () => {
|
|
981
896
|
try {
|
|
982
|
-
await handleValidationCommands(
|
|
897
|
+
await handleValidationCommands({
|
|
898
|
+
isConfigSecurityMode,
|
|
899
|
+
isDocsValidationMode,
|
|
900
|
+
isComprehensiveMode,
|
|
901
|
+
isValidationMode,
|
|
902
|
+
disableNpmAudit,
|
|
903
|
+
disableGitleaks,
|
|
904
|
+
disableActionlint,
|
|
905
|
+
disableMarkdownlint,
|
|
906
|
+
disableEslintSecurity,
|
|
907
|
+
allowLatestGitleaks,
|
|
908
|
+
})
|
|
983
909
|
} catch (error) {
|
|
984
910
|
console.error('Validation error:', error.message)
|
|
985
911
|
process.exit(1)
|
|
986
912
|
}
|
|
987
913
|
})()
|
|
988
914
|
} else {
|
|
915
|
+
/**
|
|
916
|
+
* Setup quality tools based on license tier
|
|
917
|
+
* - Lighthouse CI (Free: basic, Pro: with thresholds)
|
|
918
|
+
* - Bundle size limits (Pro only)
|
|
919
|
+
* - axe-core accessibility (Free)
|
|
920
|
+
* - Conventional commits (Free)
|
|
921
|
+
* - Coverage thresholds (Pro only)
|
|
922
|
+
*/
|
|
923
|
+
async function setupQualityTools(_usesTypeScript, _packageJson) {
|
|
924
|
+
const qualitySpinner = showProgress('Setting up quality tools...')
|
|
925
|
+
|
|
926
|
+
try {
|
|
927
|
+
const projectPath = process.cwd()
|
|
928
|
+
const PackageJson = checkNodeVersionAndLoadPackageJson()
|
|
929
|
+
const pkgJson = await PackageJson.load(projectPath)
|
|
930
|
+
const addedTools = []
|
|
931
|
+
|
|
932
|
+
// Determine which features are available
|
|
933
|
+
const hasLighthouse = hasFeature('lighthouseCI')
|
|
934
|
+
const hasLighthouseThresholds = hasFeature('lighthouseThresholds')
|
|
935
|
+
const hasBundleSizeLimits = hasFeature('bundleSizeLimits')
|
|
936
|
+
const hasAxeAccessibility = hasFeature('axeAccessibility')
|
|
937
|
+
const hasConventionalCommits = hasFeature('conventionalCommits')
|
|
938
|
+
const hasCoverageThresholds = hasFeature('coverageThresholds')
|
|
939
|
+
|
|
940
|
+
// 1. Lighthouse CI - available to all, thresholds for Pro+
|
|
941
|
+
if (hasLighthouse) {
|
|
942
|
+
const lighthousePath = path.join(projectPath, 'lighthouserc.js')
|
|
943
|
+
if (!fs.existsSync(lighthousePath)) {
|
|
944
|
+
writeLighthouseConfig(projectPath, {
|
|
945
|
+
hasThresholds: hasLighthouseThresholds,
|
|
946
|
+
})
|
|
947
|
+
addedTools.push(
|
|
948
|
+
hasLighthouseThresholds
|
|
949
|
+
? 'Lighthouse CI (with thresholds)'
|
|
950
|
+
: 'Lighthouse CI (basic)'
|
|
951
|
+
)
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
// 2. Bundle size limits - Pro only
|
|
956
|
+
if (hasBundleSizeLimits) {
|
|
957
|
+
if (!pkgJson.content['size-limit']) {
|
|
958
|
+
writeSizeLimitConfig(projectPath)
|
|
959
|
+
addedTools.push('Bundle size limits (size-limit)')
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
// 3. axe-core accessibility testing - available to all
|
|
964
|
+
if (hasAxeAccessibility) {
|
|
965
|
+
const axeTestPath = path.join(
|
|
966
|
+
projectPath,
|
|
967
|
+
'tests',
|
|
968
|
+
'accessibility.test.js'
|
|
969
|
+
)
|
|
970
|
+
if (!fs.existsSync(axeTestPath)) {
|
|
971
|
+
writeAxeTestSetup(projectPath)
|
|
972
|
+
addedTools.push('axe-core accessibility tests')
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
// 4. Conventional commits (commitlint) - available to all
|
|
977
|
+
if (hasConventionalCommits) {
|
|
978
|
+
const commitlintPath = path.join(projectPath, 'commitlint.config.js')
|
|
979
|
+
if (!fs.existsSync(commitlintPath)) {
|
|
980
|
+
writeCommitlintConfig(projectPath)
|
|
981
|
+
writeCommitMsgHook(projectPath)
|
|
982
|
+
addedTools.push('Conventional commits (commitlint)')
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
// 5. Coverage thresholds - Pro only (info message handled elsewhere)
|
|
987
|
+
if (hasCoverageThresholds) {
|
|
988
|
+
addedTools.push('Coverage thresholds (70% lines, 70% functions)')
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
// Add dependencies for enabled features
|
|
992
|
+
const deps = getQualityToolsDependencies({
|
|
993
|
+
lighthouse: hasLighthouse,
|
|
994
|
+
sizeLimit: hasBundleSizeLimits,
|
|
995
|
+
commitlint: hasConventionalCommits,
|
|
996
|
+
axeCore: hasAxeAccessibility,
|
|
997
|
+
})
|
|
998
|
+
|
|
999
|
+
// Add scripts for enabled features
|
|
1000
|
+
const scripts = getQualityToolsScripts({
|
|
1001
|
+
lighthouse: hasLighthouse,
|
|
1002
|
+
sizeLimit: hasBundleSizeLimits,
|
|
1003
|
+
axeCore: hasAxeAccessibility,
|
|
1004
|
+
coverage: hasCoverageThresholds,
|
|
1005
|
+
})
|
|
1006
|
+
|
|
1007
|
+
// Merge dependencies and scripts
|
|
1008
|
+
pkgJson.content.devDependencies = mergeDevDependencies(
|
|
1009
|
+
pkgJson.content.devDependencies || {},
|
|
1010
|
+
deps
|
|
1011
|
+
)
|
|
1012
|
+
pkgJson.content.scripts = mergeScripts(
|
|
1013
|
+
pkgJson.content.scripts || {},
|
|
1014
|
+
scripts
|
|
1015
|
+
)
|
|
1016
|
+
await pkgJson.save()
|
|
1017
|
+
|
|
1018
|
+
if (addedTools.length > 0) {
|
|
1019
|
+
qualitySpinner.succeed(
|
|
1020
|
+
`Quality tools configured: ${addedTools.length} tools`
|
|
1021
|
+
)
|
|
1022
|
+
addedTools.forEach(tool => console.log(` ā
${tool}`))
|
|
1023
|
+
|
|
1024
|
+
// Show Pro upsell for missing features
|
|
1025
|
+
if (!hasBundleSizeLimits || !hasCoverageThresholds) {
|
|
1026
|
+
console.log('\nš Upgrade to Pro for additional quality tools:')
|
|
1027
|
+
if (!hasBundleSizeLimits) {
|
|
1028
|
+
console.log(' ⢠Bundle size limits (size-limit)')
|
|
1029
|
+
}
|
|
1030
|
+
if (!hasCoverageThresholds) {
|
|
1031
|
+
console.log(' ⢠Coverage threshold enforcement')
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
} else {
|
|
1035
|
+
qualitySpinner.succeed('Quality tools already configured')
|
|
1036
|
+
}
|
|
1037
|
+
} catch (error) {
|
|
1038
|
+
qualitySpinner.warn('Could not set up some quality tools')
|
|
1039
|
+
console.warn('ā ļø Quality tools setup error:', error.message)
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
|
|
989
1043
|
// Normal setup flow
|
|
990
1044
|
async function runMainSetup() {
|
|
991
1045
|
// Record telemetry start event (opt-in only, fails silently)
|
|
@@ -1133,7 +1187,7 @@ HELP:
|
|
|
1133
1187
|
const hasTypeScriptDependency = Boolean(
|
|
1134
1188
|
(packageJson.devDependencies &&
|
|
1135
1189
|
packageJson.devDependencies.typescript) ||
|
|
1136
|
-
|
|
1190
|
+
(packageJson.dependencies && packageJson.dependencies.typescript)
|
|
1137
1191
|
)
|
|
1138
1192
|
|
|
1139
1193
|
const tsconfigCandidates = ['tsconfig.json', 'tsconfig.base.json']
|
|
@@ -1204,7 +1258,17 @@ HELP:
|
|
|
1204
1258
|
}
|
|
1205
1259
|
|
|
1206
1260
|
return false
|
|
1207
|
-
} catch {
|
|
1261
|
+
} catch (error) {
|
|
1262
|
+
// Silent failure fix: Log unexpected errors in debug mode
|
|
1263
|
+
if (
|
|
1264
|
+
process.env.DEBUG &&
|
|
1265
|
+
error.code !== 'ENOENT' &&
|
|
1266
|
+
error.code !== 'EACCES'
|
|
1267
|
+
) {
|
|
1268
|
+
console.warn(
|
|
1269
|
+
`ā ļø Could not scan ${dir} for Python files: ${error.message}`
|
|
1270
|
+
)
|
|
1271
|
+
}
|
|
1208
1272
|
return false
|
|
1209
1273
|
}
|
|
1210
1274
|
}
|
|
@@ -1379,20 +1443,19 @@ HELP:
|
|
|
1379
1443
|
})
|
|
1380
1444
|
}
|
|
1381
1445
|
} else {
|
|
1382
|
-
//
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
// }
|
|
1446
|
+
// TD8 fix: Re-enabled validation (was disabled for debugging)
|
|
1447
|
+
const validationResult = validateQualityConfig(qualityrcPath)
|
|
1448
|
+
if (!validationResult.valid) {
|
|
1449
|
+
console.warn(
|
|
1450
|
+
'ā ļø Warning: Existing .qualityrc.json has validation issues:'
|
|
1451
|
+
)
|
|
1452
|
+
validationResult.errors.forEach(error => {
|
|
1453
|
+
console.warn(` - ${error}`)
|
|
1454
|
+
})
|
|
1455
|
+
console.warn(
|
|
1456
|
+
' Setup will continue, but you may want to fix these issues.\n'
|
|
1457
|
+
)
|
|
1458
|
+
}
|
|
1396
1459
|
}
|
|
1397
1460
|
|
|
1398
1461
|
// Load and merge templates (custom + defaults)
|
|
@@ -2007,6 +2070,9 @@ echo "ā
Pre-push validation passed!"
|
|
|
2007
2070
|
showUpgradeMessage('Smart Test Strategy')
|
|
2008
2071
|
}
|
|
2009
2072
|
|
|
2073
|
+
// Quality Tools Integration
|
|
2074
|
+
await setupQualityTools(usesTypeScript, packageJson)
|
|
2075
|
+
|
|
2010
2076
|
// Generate placeholder test file with helpful documentation
|
|
2011
2077
|
const testsDir = path.join(process.cwd(), 'tests')
|
|
2012
2078
|
const testExtension = usesTypeScript ? 'ts' : 'js'
|