create-qa-architect 5.0.0 โ 5.0.6
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/RELEASE_CHECKLIST.md +2 -4
- package/.github/workflows/daily-deploy-check.yml +136 -0
- package/.github/workflows/nightly-gitleaks-verification.yml +1 -1
- package/.github/workflows/quality.yml +3 -0
- package/.github/workflows/release.yml +12 -10
- package/.github/workflows/weekly-audit.yml +173 -0
- package/LICENSE +66 -0
- package/README.md +44 -30
- package/config/defaults.js +22 -1
- package/config/quality-config.schema.json +1 -1
- package/create-saas-monetization.js +75 -27
- package/docs/ARCHITECTURE.md +53 -0
- package/docs/DEPLOYMENT.md +62 -0
- package/docs/PREFLIGHT_REPORT.md +108 -0
- package/docs/SLA_GATES.md +28 -0
- package/docs/TESTING.md +61 -0
- package/docs/security/SOC2_STARTER.md +29 -0
- package/lib/config-validator.js +8 -2
- package/lib/dependency-monitoring-basic.js +73 -26
- package/lib/dependency-monitoring-premium.js +21 -19
- package/lib/github-api.js +249 -0
- package/lib/interactive/questions.js +4 -0
- package/lib/license-validator.js +1 -1
- package/lib/licensing.js +11 -10
- package/lib/package-utils.js +224 -8
- package/lib/project-maturity.js +1 -1
- package/lib/setup-enhancements.js +33 -0
- package/lib/template-loader.js +2 -0
- package/lib/ui-helpers.js +2 -1
- package/lib/validation/base-validator.js +5 -1
- package/lib/validation/cache-manager.js +1 -0
- package/lib/validation/config-security.js +5 -4
- package/lib/validation/validation-factory.js +1 -1
- package/lib/yaml-utils.js +15 -10
- package/package.json +18 -13
- package/scripts/check-docs.sh +63 -0
- package/scripts/smart-test-strategy.sh +98 -0
- package/scripts/test-e2e-package.sh +283 -0
- package/scripts/validate-command-patterns.js +112 -0
- package/setup.js +161 -44
- package/templates/QUALITY_TROUBLESHOOTING.md +403 -0
- package/templates/ci/circleci-config.yml +35 -0
- package/templates/ci/gitlab-ci.yml +47 -0
- package/templates/integration-tests/api-service.test.js +244 -0
- package/templates/integration-tests/frontend-app.test.js +267 -0
- package/templates/scripts/smart-test-strategy.sh +109 -0
- package/templates/test-stubs/e2e.smoke.test.js +12 -0
- package/templates/test-stubs/unit.test.js +7 -0
- package/legal/README.md +0 -106
- package/legal/copyright.md +0 -76
- package/legal/disclaimer.md +0 -146
- package/legal/privacy-policy.html +0 -324
- package/legal/privacy-policy.md +0 -196
- package/legal/terms-of-service.md +0 -224
- package/marketing/beta-user-email-campaign.md +0 -372
- package/marketing/landing-page.html +0 -721
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Smart Test Strategy - QA Architect
|
|
3
|
+
set -e
|
|
4
|
+
|
|
5
|
+
echo "๐ง Analyzing changes for optimal test strategy..."
|
|
6
|
+
|
|
7
|
+
# =============================================================================
|
|
8
|
+
# SECURITY: Always run npm audit for critical vulnerabilities (fast, ~2 seconds)
|
|
9
|
+
# =============================================================================
|
|
10
|
+
echo ""
|
|
11
|
+
echo "๐ Running security audit (critical vulnerabilities only)..."
|
|
12
|
+
if npm audit --audit-level=critical --omit=dev 2>/dev/null; then
|
|
13
|
+
echo "โ
No critical vulnerabilities found"
|
|
14
|
+
else
|
|
15
|
+
echo "โ CRITICAL vulnerabilities detected! Fix before pushing."
|
|
16
|
+
echo " Run: npm audit fix"
|
|
17
|
+
exit 1
|
|
18
|
+
fi
|
|
19
|
+
echo ""
|
|
20
|
+
|
|
21
|
+
# Collect metrics
|
|
22
|
+
CHANGED_FILES=$(git diff --name-only HEAD~1..HEAD 2>/dev/null | wc -l | tr -d ' ')
|
|
23
|
+
CHANGED_LINES=$(git diff --stat HEAD~1..HEAD 2>/dev/null | tail -1 | grep -o '[0-9]* insertions' | grep -o '[0-9]*' || echo "0")
|
|
24
|
+
CURRENT_BRANCH=$(git branch --show-current)
|
|
25
|
+
HOUR=$(date +%H)
|
|
26
|
+
DAY_OF_WEEK=$(date +%u)
|
|
27
|
+
|
|
28
|
+
# Project-specific high-risk patterns
|
|
29
|
+
HIGH_RISK_FILES=$(git diff --name-only HEAD~1..HEAD 2>/dev/null | grep -E "(setup\.js|lib/.*|templates/.*|config/.*)" || true)
|
|
30
|
+
API_FILES=$(git diff --name-only HEAD~1..HEAD 2>/dev/null | grep -E "api/" || true)
|
|
31
|
+
CONFIG_FILES=$(git diff --name-only HEAD~1..HEAD 2>/dev/null | grep -E "(package\.json|\.env|config)" || true)
|
|
32
|
+
TEST_FILES=$(git diff --name-only HEAD~1..HEAD 2>/dev/null | grep -E "test|spec" || true)
|
|
33
|
+
|
|
34
|
+
# Calculate risk score (0-10)
|
|
35
|
+
RISK_SCORE=0
|
|
36
|
+
|
|
37
|
+
# File-based risk
|
|
38
|
+
[[ -n "$HIGH_RISK_FILES" ]] && RISK_SCORE=$((RISK_SCORE + 4))
|
|
39
|
+
[[ -n "$API_FILES" ]] && RISK_SCORE=$((RISK_SCORE + 2))
|
|
40
|
+
[[ -n "$CONFIG_FILES" ]] && RISK_SCORE=$((RISK_SCORE + 2))
|
|
41
|
+
|
|
42
|
+
# Size-based risk
|
|
43
|
+
[[ $CHANGED_FILES -gt 10 ]] && RISK_SCORE=$((RISK_SCORE + 2))
|
|
44
|
+
[[ $CHANGED_FILES -gt 20 ]] && RISK_SCORE=$((RISK_SCORE + 3))
|
|
45
|
+
[[ $CHANGED_LINES -gt 200 ]] && RISK_SCORE=$((RISK_SCORE + 2))
|
|
46
|
+
|
|
47
|
+
# Branch-based risk
|
|
48
|
+
case $CURRENT_BRANCH in
|
|
49
|
+
main|master|production) RISK_SCORE=$((RISK_SCORE + 3)) ;;
|
|
50
|
+
hotfix/*) RISK_SCORE=$((RISK_SCORE + 4)) ;;
|
|
51
|
+
release/*) RISK_SCORE=$((RISK_SCORE + 2)) ;;
|
|
52
|
+
develop) RISK_SCORE=$((RISK_SCORE + 1)) ;;
|
|
53
|
+
esac
|
|
54
|
+
|
|
55
|
+
# Time pressure adjustment (strip leading zeros)
|
|
56
|
+
HOUR_NUM=$((10#$HOUR))
|
|
57
|
+
if [[ $HOUR_NUM -ge 9 && $HOUR_NUM -le 17 && $DAY_OF_WEEK -le 5 ]]; then
|
|
58
|
+
SPEED_BONUS=true
|
|
59
|
+
else
|
|
60
|
+
SPEED_BONUS=false
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
# Display analysis
|
|
64
|
+
echo "๐ Analysis Results:"
|
|
65
|
+
echo " ๐ Files: $CHANGED_FILES"
|
|
66
|
+
echo " ๐ Lines: $CHANGED_LINES"
|
|
67
|
+
echo " ๐ฟ Branch: $CURRENT_BRANCH"
|
|
68
|
+
echo " ๐ฏ Risk Score: $RISK_SCORE/10"
|
|
69
|
+
echo " โก Speed Bonus: $SPEED_BONUS"
|
|
70
|
+
echo ""
|
|
71
|
+
|
|
72
|
+
# Decision logic
|
|
73
|
+
# NOTE: test:commands and test:e2e are ALWAYS excluded from pre-push (run in CI only)
|
|
74
|
+
# - test:commands: Takes 60+ seconds, verifies npm scripts work in isolated env
|
|
75
|
+
# - test:e2e: Requires browser/package build, CI has better infrastructure
|
|
76
|
+
# These run in GitHub Actions on every PR and push to main
|
|
77
|
+
|
|
78
|
+
if [[ $RISK_SCORE -ge 7 ]]; then
|
|
79
|
+
echo "๐ด HIGH RISK - Comprehensive validation (pre-push)"
|
|
80
|
+
echo " โข Patterns + unit tests + security audit"
|
|
81
|
+
echo " โข (command + e2e tests run in CI only)"
|
|
82
|
+
npm run test:patterns && npm test && npm run security:audit
|
|
83
|
+
elif [[ $RISK_SCORE -ge 4 ]]; then
|
|
84
|
+
echo "๐ก MEDIUM RISK - Standard validation"
|
|
85
|
+
echo " โข Fast tests + patterns"
|
|
86
|
+
npm run test:patterns && npm run test:fast
|
|
87
|
+
elif [[ $RISK_SCORE -ge 2 || "$SPEED_BONUS" == "false" ]]; then
|
|
88
|
+
echo "๐ข LOW RISK - Fast validation"
|
|
89
|
+
echo " โข Unit tests only"
|
|
90
|
+
npm run test:fast
|
|
91
|
+
else
|
|
92
|
+
echo "โช MINIMAL RISK - Quality checks only"
|
|
93
|
+
echo " โข Lint + format check"
|
|
94
|
+
npm run lint && npm run format:check
|
|
95
|
+
fi
|
|
96
|
+
|
|
97
|
+
echo ""
|
|
98
|
+
echo "๐ก Tip: Run 'npm run test:comprehensive' locally for full validation"
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# E2E Package Test - Validates the package works for consumers
|
|
3
|
+
# Catches issues like Codex findings before release
|
|
4
|
+
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
# Use isolated npm cache to avoid permission issues on shared caches
|
|
8
|
+
export npm_config_cache="${npm_config_cache:-$(mktemp -d)}"
|
|
9
|
+
export NPM_CONFIG_CACHE="$npm_config_cache"
|
|
10
|
+
# Disable husky during packaging so pack works in CI/sandboxed environments
|
|
11
|
+
export HUSKY=0
|
|
12
|
+
|
|
13
|
+
echo "๐งช E2E Package Validation Test"
|
|
14
|
+
echo "================================"
|
|
15
|
+
echo ""
|
|
16
|
+
|
|
17
|
+
# Colors
|
|
18
|
+
RED='\033[0;31m'
|
|
19
|
+
GREEN='\033[0;32m'
|
|
20
|
+
YELLOW='\033[1;33m'
|
|
21
|
+
NC='\033[0m' # No Color
|
|
22
|
+
|
|
23
|
+
# Track failures
|
|
24
|
+
FAILURES=0
|
|
25
|
+
|
|
26
|
+
fail() {
|
|
27
|
+
echo -e "${RED}โ $1${NC}"
|
|
28
|
+
FAILURES=$((FAILURES + 1))
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
pass() {
|
|
32
|
+
echo -e "${GREEN}โ
$1${NC}"
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
warn() {
|
|
36
|
+
echo -e "${YELLOW}โ ๏ธ $1${NC}"
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
# 1. Package Contents Validation
|
|
40
|
+
echo "๐ฆ Step 1: Validating package contents..."
|
|
41
|
+
echo "Running: npm pack (scripts disabled)"
|
|
42
|
+
TARBALL=$(npm pack --ignore-scripts 2>&1 | tail -1)
|
|
43
|
+
|
|
44
|
+
if [ ! -f "$TARBALL" ]; then
|
|
45
|
+
fail "npm pack failed to create tarball"
|
|
46
|
+
exit 1
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
pass "Created tarball: $TARBALL"
|
|
50
|
+
|
|
51
|
+
# Extract tarball and check files
|
|
52
|
+
EXTRACT_DIR=$(mktemp -d)
|
|
53
|
+
tar -xzf "$TARBALL" -C "$EXTRACT_DIR"
|
|
54
|
+
PKG_DIR="$EXTRACT_DIR/package"
|
|
55
|
+
|
|
56
|
+
echo " Checking required files in package..."
|
|
57
|
+
REQUIRED_FILES=(
|
|
58
|
+
"setup.js"
|
|
59
|
+
".prettierrc"
|
|
60
|
+
".prettierignore"
|
|
61
|
+
"eslint.config.cjs"
|
|
62
|
+
"eslint.config.ts.cjs"
|
|
63
|
+
".stylelintrc.json"
|
|
64
|
+
".editorconfig"
|
|
65
|
+
".nvmrc"
|
|
66
|
+
"config/defaults.js"
|
|
67
|
+
"lib/validation/index.js"
|
|
68
|
+
".github/workflows/quality.yml"
|
|
69
|
+
)
|
|
70
|
+
# Note: .npmrc is intentionally excluded - npm won't package it anyway (local config only)
|
|
71
|
+
|
|
72
|
+
for file in "${REQUIRED_FILES[@]}"; do
|
|
73
|
+
if [ -f "$PKG_DIR/$file" ] || [ -d "$PKG_DIR/$file" ]; then
|
|
74
|
+
pass " $file"
|
|
75
|
+
else
|
|
76
|
+
fail " Missing required file: $file"
|
|
77
|
+
fi
|
|
78
|
+
done
|
|
79
|
+
|
|
80
|
+
# 2. Consumer Installation Simulation
|
|
81
|
+
echo ""
|
|
82
|
+
echo "๐๏ธ Step 2: Simulating consumer installation..."
|
|
83
|
+
TEST_DIR=$(mktemp -d)
|
|
84
|
+
cd "$TEST_DIR"
|
|
85
|
+
|
|
86
|
+
echo " Creating test project..."
|
|
87
|
+
git init -q
|
|
88
|
+
git config user.email "test@example.com"
|
|
89
|
+
git config user.name "Test User"
|
|
90
|
+
|
|
91
|
+
cat > package.json <<'EOF'
|
|
92
|
+
{
|
|
93
|
+
"name": "e2e-test-consumer",
|
|
94
|
+
"version": "1.0.0",
|
|
95
|
+
"description": "E2E test consumer",
|
|
96
|
+
"keywords": ["test"],
|
|
97
|
+
"license": "MIT"
|
|
98
|
+
}
|
|
99
|
+
EOF
|
|
100
|
+
|
|
101
|
+
pass "Test project created"
|
|
102
|
+
|
|
103
|
+
echo " Installing from tarball..."
|
|
104
|
+
npm install "$OLDPWD/$TARBALL" --silent 2>&1 > /dev/null || {
|
|
105
|
+
fail "npm install from tarball failed"
|
|
106
|
+
cd "$OLDPWD"
|
|
107
|
+
rm -rf "$TEST_DIR" "$EXTRACT_DIR"
|
|
108
|
+
rm -f "$TARBALL"
|
|
109
|
+
exit 1
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
pass "Package installed"
|
|
113
|
+
|
|
114
|
+
# 3. Run setup
|
|
115
|
+
echo ""
|
|
116
|
+
echo "๐ Step 3: Running setup..."
|
|
117
|
+
SETUP_OUTPUT=$(QAA_DEVELOPER=true node ./node_modules/create-qa-architect/setup.js 2>&1)
|
|
118
|
+
echo "$SETUP_OUTPUT" | grep -q "Setting up Quality Automation" && pass "Setup executed" || fail "Setup failed"
|
|
119
|
+
echo " Setup output:"
|
|
120
|
+
echo "$SETUP_OUTPUT" | head -20
|
|
121
|
+
|
|
122
|
+
# 4. Verify generated files
|
|
123
|
+
echo ""
|
|
124
|
+
echo "๐ Step 4: Verifying generated files..."
|
|
125
|
+
EXPECTED_FILES=(
|
|
126
|
+
".prettierrc"
|
|
127
|
+
".prettierignore"
|
|
128
|
+
"eslint.config.cjs"
|
|
129
|
+
".stylelintrc.json"
|
|
130
|
+
".editorconfig"
|
|
131
|
+
".nvmrc"
|
|
132
|
+
".npmrc"
|
|
133
|
+
".github/workflows/quality.yml"
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
for file in "${EXPECTED_FILES[@]}"; do
|
|
137
|
+
if [ -f "$file" ]; then
|
|
138
|
+
pass " Generated: $file"
|
|
139
|
+
else
|
|
140
|
+
fail " Missing generated file: $file"
|
|
141
|
+
fi
|
|
142
|
+
done
|
|
143
|
+
|
|
144
|
+
# 5. Validate package.json modifications
|
|
145
|
+
echo ""
|
|
146
|
+
echo "๐ Step 5: Validating package.json modifications..."
|
|
147
|
+
|
|
148
|
+
if grep -q "\"format\":" package.json; then
|
|
149
|
+
pass " npm scripts added"
|
|
150
|
+
else
|
|
151
|
+
fail " npm scripts not added"
|
|
152
|
+
fi
|
|
153
|
+
|
|
154
|
+
if grep -q "husky" package.json; then
|
|
155
|
+
pass " devDependencies added"
|
|
156
|
+
else
|
|
157
|
+
fail " devDependencies not added"
|
|
158
|
+
fi
|
|
159
|
+
|
|
160
|
+
if grep -q "lint-staged" package.json; then
|
|
161
|
+
pass " lint-staged config added"
|
|
162
|
+
else
|
|
163
|
+
fail " lint-staged config not added"
|
|
164
|
+
fi
|
|
165
|
+
|
|
166
|
+
# 6. Test npm scripts use npx (not node setup.js)
|
|
167
|
+
echo ""
|
|
168
|
+
echo "๐ Step 6: Validating npm scripts use npx..."
|
|
169
|
+
|
|
170
|
+
if grep -q "\"security:config.*npx create-qa-architect" package.json; then
|
|
171
|
+
pass " security:config uses npx"
|
|
172
|
+
else
|
|
173
|
+
fail " security:config doesn't use npx (Codex finding regression!)"
|
|
174
|
+
fi
|
|
175
|
+
|
|
176
|
+
if grep -q "\"validate:docs.*npx create-qa-architect" package.json; then
|
|
177
|
+
pass " validate:docs uses npx"
|
|
178
|
+
else
|
|
179
|
+
fail " validate:docs doesn't use npx (Codex finding regression!)"
|
|
180
|
+
fi
|
|
181
|
+
|
|
182
|
+
# 7. Validate workflow doesn't have UNCONDITIONAL setup.js references
|
|
183
|
+
echo ""
|
|
184
|
+
echo "๐ง Step 7: Validating generated workflow..."
|
|
185
|
+
|
|
186
|
+
# The workflow can have conditional references like:
|
|
187
|
+
# if [ -f "setup.js" ]; then
|
|
188
|
+
# node setup.js --something
|
|
189
|
+
# fi
|
|
190
|
+
# But should NOT have unconditional references like the old:
|
|
191
|
+
# node "$GITHUB_WORKSPACE/setup.js"
|
|
192
|
+
#
|
|
193
|
+
# Check for the specific bad pattern we fixed (Codex finding)
|
|
194
|
+
if grep -q 'node "$GITHUB_WORKSPACE/setup.js"' .github/workflows/quality.yml; then
|
|
195
|
+
fail " Workflow has unconditional GITHUB_WORKSPACE setup.js reference (Codex finding regression!)"
|
|
196
|
+
else
|
|
197
|
+
pass " Workflow doesn't have unconditional setup.js references"
|
|
198
|
+
fi
|
|
199
|
+
|
|
200
|
+
# Conditional references with guards are OK (will fallback in consumer repos)
|
|
201
|
+
|
|
202
|
+
# 8. NEW: Actually run the generated commands (catches broken CLI flags!)
|
|
203
|
+
echo ""
|
|
204
|
+
echo "๐ Step 8: Testing generated commands actually work..."
|
|
205
|
+
echo " This step would have caught the ESLint --ext bug!"
|
|
206
|
+
|
|
207
|
+
# Install devDependencies first
|
|
208
|
+
echo " Installing devDependencies..."
|
|
209
|
+
npm install --silent > /dev/null 2>&1 || {
|
|
210
|
+
fail " npm install failed"
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
# Create test files for commands to process
|
|
214
|
+
# Use valid code that won't trigger linting errors
|
|
215
|
+
echo "module.exports = { name: 'test' };" > test.js
|
|
216
|
+
echo "body { color: red; }" > test.css
|
|
217
|
+
|
|
218
|
+
# Test format:check - should work (even if files need formatting)
|
|
219
|
+
echo " Testing: npm run format:check"
|
|
220
|
+
# Format the files first so format:check passes
|
|
221
|
+
npm run format >/dev/null 2>&1
|
|
222
|
+
if npm run format:check 2>&1 >/dev/null; then
|
|
223
|
+
pass " format:check works"
|
|
224
|
+
else
|
|
225
|
+
fail " format:check failed (check Prettier flags!)"
|
|
226
|
+
fi
|
|
227
|
+
|
|
228
|
+
# Test lint (CRITICAL: this would have caught --ext bug!)
|
|
229
|
+
echo " Testing: npm run lint"
|
|
230
|
+
LINT_OUTPUT=$(npm run lint 2>&1)
|
|
231
|
+
if echo "$LINT_OUTPUT" | grep -q "error"; then
|
|
232
|
+
fail " lint failed (check for deprecated flags like --ext!)"
|
|
233
|
+
echo " ESLint error output:"
|
|
234
|
+
echo "$LINT_OUTPUT" | grep -A 5 "error" | head -10
|
|
235
|
+
else
|
|
236
|
+
pass " lint works"
|
|
237
|
+
fi
|
|
238
|
+
|
|
239
|
+
# Test direct ESLint
|
|
240
|
+
echo " Testing: npx eslint test.js"
|
|
241
|
+
if npx eslint test.js 2>&1 >/dev/null; then
|
|
242
|
+
pass " Direct ESLint works"
|
|
243
|
+
else
|
|
244
|
+
fail " Direct ESLint failed"
|
|
245
|
+
fi
|
|
246
|
+
|
|
247
|
+
# Test stylelint
|
|
248
|
+
echo " Testing: npx stylelint test.css"
|
|
249
|
+
if npx stylelint test.css 2>&1 >/dev/null; then
|
|
250
|
+
pass " Stylelint works"
|
|
251
|
+
else
|
|
252
|
+
fail " Stylelint failed"
|
|
253
|
+
fi
|
|
254
|
+
|
|
255
|
+
# 9. Test --dry-run mode
|
|
256
|
+
echo ""
|
|
257
|
+
echo "๐งช Step 9: Testing --dry-run mode..."
|
|
258
|
+
cd "$OLDPWD"
|
|
259
|
+
if node ./setup.js --dry-run 2>&1 | grep -q "DRY RUN MODE"; then
|
|
260
|
+
pass "--dry-run mode works"
|
|
261
|
+
else
|
|
262
|
+
fail "--dry-run mode doesn't work"
|
|
263
|
+
fi
|
|
264
|
+
|
|
265
|
+
# Cleanup
|
|
266
|
+
cd "$OLDPWD"
|
|
267
|
+
rm -rf "$TEST_DIR" "$EXTRACT_DIR"
|
|
268
|
+
rm -f "$TARBALL"
|
|
269
|
+
|
|
270
|
+
# Report
|
|
271
|
+
echo ""
|
|
272
|
+
echo "================================"
|
|
273
|
+
if [ $FAILURES -eq 0 ]; then
|
|
274
|
+
echo -e "${GREEN}โ
All E2E tests passed!${NC}"
|
|
275
|
+
echo ""
|
|
276
|
+
echo "Package is ready for release."
|
|
277
|
+
exit 0
|
|
278
|
+
else
|
|
279
|
+
echo -e "${RED}โ $FAILURES test(s) failed${NC}"
|
|
280
|
+
echo ""
|
|
281
|
+
echo "Fix these issues before releasing."
|
|
282
|
+
exit 1
|
|
283
|
+
fi
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Validates that command patterns in config/defaults.js
|
|
6
|
+
* don't contain known deprecated patterns
|
|
7
|
+
*
|
|
8
|
+
* This prevents issues like the ESLint --ext bug from being committed
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const fs = require('fs')
|
|
12
|
+
const path = require('path')
|
|
13
|
+
|
|
14
|
+
const DEPRECATED_PATTERNS = [
|
|
15
|
+
{
|
|
16
|
+
pattern: /eslint.*--ext\s+\S+/,
|
|
17
|
+
message: 'ESLint --ext flag is deprecated in ESLint 9 flat config',
|
|
18
|
+
file: 'config/defaults.js',
|
|
19
|
+
suggestion: 'Use "eslint ." - file selection is in eslint.config.js',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
pattern: /husky install/,
|
|
23
|
+
message: 'husky install is deprecated in Husky 9+',
|
|
24
|
+
file: 'config/defaults.js',
|
|
25
|
+
suggestion: 'Use just "husky" as the prepare script',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
pattern: /prettier.*--no-semi/,
|
|
29
|
+
message: '--no-semi is deprecated in Prettier 3+',
|
|
30
|
+
file: 'config/defaults.js',
|
|
31
|
+
suggestion: 'Use .prettierrc configuration file',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
pattern: /stylelint.*--config\s+\S+/,
|
|
35
|
+
message: 'Stylelint --config flag should use config file',
|
|
36
|
+
file: 'config/defaults.js',
|
|
37
|
+
suggestion: 'Use .stylelintrc.json instead',
|
|
38
|
+
},
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
const FILES_TO_CHECK = [
|
|
42
|
+
'config/defaults.js',
|
|
43
|
+
'setup.js',
|
|
44
|
+
'lib/package-utils.js',
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
function validateFile(filePath, patterns) {
|
|
48
|
+
const fullPath = path.join(__dirname, '..', filePath)
|
|
49
|
+
|
|
50
|
+
if (!fs.existsSync(fullPath)) {
|
|
51
|
+
console.warn(`โ ๏ธ File not found: ${filePath} (skipping)`)
|
|
52
|
+
return []
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const content = fs.readFileSync(fullPath, 'utf8')
|
|
56
|
+
const errors = []
|
|
57
|
+
|
|
58
|
+
patterns.forEach(({ pattern, message, file, suggestion }) => {
|
|
59
|
+
// Only check patterns for this file
|
|
60
|
+
if (file && file !== filePath) {
|
|
61
|
+
return
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (pattern.test(content)) {
|
|
65
|
+
errors.push({
|
|
66
|
+
file: filePath,
|
|
67
|
+
message,
|
|
68
|
+
suggestion,
|
|
69
|
+
pattern: pattern.toString(),
|
|
70
|
+
})
|
|
71
|
+
}
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
return errors
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function main() {
|
|
78
|
+
console.log('๐ Validating command patterns...\n')
|
|
79
|
+
|
|
80
|
+
let totalErrors = 0
|
|
81
|
+
const allErrors = []
|
|
82
|
+
|
|
83
|
+
FILES_TO_CHECK.forEach(filePath => {
|
|
84
|
+
const errors = validateFile(filePath, DEPRECATED_PATTERNS)
|
|
85
|
+
totalErrors += errors.length
|
|
86
|
+
allErrors.push(...errors)
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
if (totalErrors > 0) {
|
|
90
|
+
console.error(`โ Found ${totalErrors} deprecated pattern(s):\n`)
|
|
91
|
+
|
|
92
|
+
allErrors.forEach(({ file, message, suggestion, pattern }) => {
|
|
93
|
+
console.error(` ${file}:`)
|
|
94
|
+
console.error(` โ ${message}`)
|
|
95
|
+
console.error(` ๐ก ${suggestion}`)
|
|
96
|
+
console.error(` ๐ Pattern: ${pattern}`)
|
|
97
|
+
console.error('')
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
console.error('Fix these before committing!\n')
|
|
101
|
+
process.exit(1)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
console.log('โ
No deprecated command patterns found')
|
|
105
|
+
process.exit(0)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (require.main === module) {
|
|
109
|
+
main()
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
module.exports = { validateFile, DEPRECATED_PATTERNS }
|