@sun-asterisk/sunlint 1.0.7 → 1.1.4
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/.sunlint.json +35 -0
- package/CHANGELOG.md +30 -3
- package/CONTRIBUTING.md +235 -0
- package/PROJECT_STRUCTURE.md +60 -0
- package/README.md +146 -58
- package/cli.js +1 -0
- package/config/README.md +88 -0
- package/config/defaults/ai-rules-context.json +231 -0
- package/config/engines/engines.json +49 -0
- package/config/engines/eslint-rule-mapping.json +74 -0
- package/config/eslint-rule-mapping.json +126 -0
- package/config/integrations/eslint/base.config.js +125 -0
- package/config/integrations/eslint/simple.config.js +24 -0
- package/config/presets/strict.json +0 -1
- package/config/rule-analysis-strategies.js +74 -0
- package/config/{rules-registry.json → rules/rules-registry.json} +30 -7
- package/core/analysis-orchestrator.js +383 -591
- package/core/ast-modules/README.md +103 -0
- package/core/ast-modules/base-parser.js +90 -0
- package/core/ast-modules/index.js +97 -0
- package/core/ast-modules/package.json +37 -0
- package/core/ast-modules/parsers/eslint-js-parser.js +153 -0
- package/core/ast-modules/parsers/eslint-ts-parser.js +98 -0
- package/core/ast-modules/parsers/javascript-parser.js +187 -0
- package/core/ast-modules/parsers/typescript-parser.js +187 -0
- package/core/cli-action-handler.js +271 -255
- package/core/cli-program.js +18 -4
- package/core/config-manager.js +9 -3
- package/core/config-merger.js +40 -1
- package/core/config-validator.js +2 -2
- package/core/dependency-checker.js +125 -0
- package/core/enhanced-rules-registry.js +331 -0
- package/core/file-targeting-service.js +92 -23
- package/core/interfaces/analysis-engine.interface.js +100 -0
- package/core/multi-rule-runner.js +0 -221
- package/core/output-service.js +1 -1
- package/core/rule-mapping-service.js +1 -1
- package/core/rule-selection-service.js +10 -2
- package/core/smart-installer.js +164 -0
- package/docs/AI.md +163 -0
- package/docs/ARCHITECTURE.md +78 -0
- package/docs/CI-CD-GUIDE.md +315 -0
- package/docs/COMMAND-EXAMPLES.md +256 -0
- package/docs/CONFIGURATION.md +414 -0
- package/docs/DEBUG.md +86 -0
- package/docs/DEPENDENCIES.md +90 -0
- package/docs/DEPLOYMENT-STRATEGIES.md +270 -0
- package/docs/DISTRIBUTION.md +153 -0
- package/docs/ESLINT-INTEGRATION-STRATEGY.md +392 -0
- package/docs/ESLINT_INTEGRATION.md +238 -0
- package/docs/FOLDER_STRUCTURE.md +59 -0
- package/docs/FUTURE_PACKAGES.md +83 -0
- package/docs/HEURISTIC_VS_AI.md +113 -0
- package/docs/PRODUCTION_DEPLOYMENT_ANALYSIS.md +112 -0
- package/docs/PRODUCTION_SIZE_IMPACT.md +183 -0
- package/docs/README.md +32 -0
- package/docs/RELEASE_GUIDE.md +230 -0
- package/engines/eslint-engine.js +610 -0
- package/engines/heuristic-engine.js +864 -0
- package/engines/openai-engine.js +374 -0
- package/engines/tree-sitter-parser.js +0 -0
- package/engines/universal-ast-engine.js +0 -0
- package/integrations/eslint/README.md +99 -0
- package/integrations/eslint/configs/.eslintrc.js +98 -0
- package/integrations/eslint/configs/eslint.config.js +133 -0
- package/integrations/eslint/configs/eslint.config.simple.js +24 -0
- package/integrations/eslint/package.json +23 -0
- package/integrations/eslint/plugin/index.js +164 -0
- package/integrations/eslint/plugin/package.json +13 -0
- package/integrations/eslint/plugin/rules/common/c002-no-duplicate-code.js +204 -0
- package/integrations/eslint/plugin/rules/common/c003-no-vague-abbreviations.js +246 -0
- package/integrations/eslint/plugin/rules/common/c006-function-name-verb-noun.js +216 -0
- package/integrations/eslint/plugin/rules/common/c010-limit-block-nesting.js +90 -0
- package/integrations/eslint/plugin/rules/common/c013-no-dead-code.js +78 -0
- package/integrations/eslint/plugin/rules/common/c014-abstract-dependency-preferred.js +38 -0
- package/integrations/eslint/plugin/rules/common/c017-limit-constructor-logic.js +146 -0
- package/integrations/eslint/plugin/rules/common/c018-no-generic-throw.js +335 -0
- package/integrations/eslint/plugin/rules/common/c023-no-duplicate-variable-name-in-scope.js +142 -0
- package/integrations/eslint/plugin/rules/common/c029-catch-block-logging.js +115 -0
- package/integrations/eslint/plugin/rules/common/c030-use-custom-error-classes.js +294 -0
- package/integrations/eslint/plugin/rules/common/c035-no-empty-catch.js +162 -0
- package/integrations/eslint/plugin/rules/common/c041-no-config-inline.js +122 -0
- package/integrations/eslint/plugin/rules/common/c042-boolean-name-prefix.js +406 -0
- package/integrations/eslint/plugin/rules/common/c043-no-console-or-print.js +300 -0
- package/integrations/eslint/plugin/rules/common/c047-no-duplicate-retry-logic.js +239 -0
- package/integrations/eslint/plugin/rules/common/c072-one-assert-per-test.js +184 -0
- package/integrations/eslint/plugin/rules/common/c075-explicit-function-return-types.js +168 -0
- package/integrations/eslint/plugin/rules/common/c076-single-behavior-per-test.js +254 -0
- package/integrations/eslint/plugin/rules/security/s001-fail-securely.js +381 -0
- package/integrations/eslint/plugin/rules/security/s002-idor-check.js +945 -0
- package/integrations/eslint/plugin/rules/security/s003-no-unvalidated-redirect.js +86 -0
- package/integrations/eslint/plugin/rules/security/s007-no-plaintext-otp.js +74 -0
- package/integrations/eslint/plugin/rules/security/s013-verify-tls-connection.js +47 -0
- package/integrations/eslint/plugin/rules/security/s047-secure-random-passwords.js +108 -0
- package/integrations/eslint/plugin/rules/security/s055-verification-rest-check-the-incoming-content-type.js +143 -0
- package/integrations/eslint/plugin/rules/typescript/t002-interface-prefix-i.js +42 -0
- package/integrations/eslint/plugin/rules/typescript/t003-ts-ignore-reason.js +48 -0
- package/integrations/eslint/plugin/rules/typescript/t004-no-empty-type.js +95 -0
- package/integrations/eslint/plugin/rules/typescript/t007-no-fn-in-constructor.js +52 -0
- package/integrations/eslint/plugin/rules/typescript/t010-no-nested-union-tuple.js +48 -0
- package/integrations/eslint/plugin/rules/typescript/t019-no-this-assign.js +81 -0
- package/integrations/eslint/plugin/rules/typescript/t020-no-default-multi-export.js +127 -0
- package/integrations/eslint/plugin/rules/typescript/t021-limit-nested-generics.js +150 -0
- package/integrations/eslint/tsconfig.json +27 -0
- package/package.json +61 -21
- package/rules/README.md +252 -0
- package/rules/common/C002_no_duplicate_code/analyzer.js +65 -0
- package/rules/common/C002_no_duplicate_code/config.json +23 -0
- package/rules/common/C003_no_vague_abbreviations/analyzer.js +418 -0
- package/rules/common/C003_no_vague_abbreviations/config.json +35 -0
- package/rules/{C006_function_naming → common/C006_function_naming}/analyzer.js +13 -2
- package/rules/common/C010_limit_block_nesting/analyzer.js +389 -0
- package/rules/common/C013_no_dead_code/analyzer.js +206 -0
- package/rules/common/C014_dependency_injection/analyzer.js +338 -0
- package/rules/common/C017_constructor_logic/analyzer.js +314 -0
- package/rules/{C019_log_level_usage → common/C019_log_level_usage}/analyzer.js +5 -2
- package/rules/{C029_catch_block_logging → common/C029_catch_block_logging}/analyzer.js +49 -15
- package/rules/common/C041_no_sensitive_hardcode/analyzer.js +292 -0
- package/rules/common/C042_boolean_name_prefix/analyzer.js +300 -0
- package/rules/common/C043_no_console_or_print/analyzer.js +304 -0
- package/rules/common/C047_no_duplicate_retry_logic/analyzer.js +351 -0
- package/rules/common/C075_explicit_return_types/analyzer.js +103 -0
- package/rules/common/C076_single_test_behavior/analyzer.js +121 -0
- package/rules/docs/C002_no_duplicate_code.md +57 -0
- package/rules/index.js +149 -0
- package/rules/migration/converter.js +385 -0
- package/rules/migration/mapping.json +164 -0
- package/rules/security/S026_json_schema_validation/analyzer.js +251 -0
- package/rules/security/S026_json_schema_validation/config.json +27 -0
- package/rules/security/S027_no_hardcoded_secrets/analyzer.js +263 -0
- package/rules/security/S027_no_hardcoded_secrets/config.json +29 -0
- package/rules/security/S029_csrf_protection/analyzer.js +264 -0
- package/rules/tests/C002_no_duplicate_code.test.js +50 -0
- package/rules/universal/C010/generic.js +0 -0
- package/rules/universal/C010/tree-sitter-analyzer.js +0 -0
- package/rules/utils/ast-utils.js +191 -0
- package/rules/utils/base-analyzer.js +98 -0
- package/rules/utils/pattern-matchers.js +239 -0
- package/rules/utils/rule-helpers.js +264 -0
- package/rules/utils/severity-constants.js +93 -0
- package/scripts/build-release.sh +117 -0
- package/scripts/ci-report.js +179 -0
- package/scripts/install.sh +196 -0
- package/scripts/manual-release.sh +338 -0
- package/scripts/merge-reports.js +424 -0
- package/scripts/pre-release-test.sh +175 -0
- package/scripts/prepare-release.sh +202 -0
- package/scripts/setup-github-registry.sh +42 -0
- package/scripts/test-scripts/README.md +22 -0
- package/scripts/test-scripts/test-c041-comparison.js +114 -0
- package/scripts/test-scripts/test-c041-eslint.js +67 -0
- package/scripts/test-scripts/test-eslint-rules.js +146 -0
- package/scripts/test-scripts/test-real-world.js +44 -0
- package/scripts/test-scripts/test-rules-on-real-projects.js +86 -0
- package/scripts/trigger-release.sh +285 -0
- package/scripts/validate-rule-structure.js +148 -0
- package/scripts/verify-install.sh +82 -0
- package/config/sunlint-schema.json +0 -159
- package/config/typescript/custom-rules.js +0 -9
- package/config/typescript/package-lock.json +0 -1585
- package/config/typescript/package.json +0 -13
- package/config/typescript/security-rules/index.js +0 -90
- package/config/typescript/tsconfig.json +0 -29
- package/core/ai-analyzer.js +0 -169
- package/core/eslint-engine-service.js +0 -312
- package/core/eslint-instance-manager.js +0 -104
- package/core/eslint-integration-service.js +0 -363
- package/core/sunlint-engine-service.js +0 -23
- package/core/typescript-analyzer.js +0 -262
- package/core/typescript-engine.js +0 -313
- /package/config/{default.json → defaults/default.json} +0 -0
- /package/config/{typescript/eslint.config.js → integrations/eslint/typescript.config.js} +0 -0
- /package/config/{typescript/custom-rules-new.js → schemas/sunlint-schema.json} +0 -0
- /package/config/{typescript → testing}/test-s005-working.ts +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s005-no-origin-auth.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s006-activation-recovery-secret-not-plaintext.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s008-crypto-agility.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s009-no-insecure-crypto.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s010-no-insecure-random-in-sensitive-context.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s011-no-insecure-uuid.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s012-hardcode-secret.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s014-insecure-tls-version.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s015-insecure-tls-certificate.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s016-sensitive-query-parameter.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s017-no-sql-injection.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s018-positive-input-validation.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s019-no-raw-user-input-in-email.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s020-no-eval-dynamic-execution.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s022-output-encoding.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s023-no-json-injection.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s025-server-side-input-validation.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s026-json-schema-validation.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s027-no-hardcoded-secrets.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s029-require-csrf-protection.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s030-no-directory-browsing.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s033-require-samesite-cookie.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s034-require-host-cookie-prefix.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s035-cookie-specific-path.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s036-no-unsafe-file-include.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s037-require-anti-cache-headers.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s038-no-version-disclosure.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s039-no-session-token-in-url.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s041-require-session-invalidate-on-logout.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s042-require-periodic-reauthentication.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s043-terminate-sessions-on-password-change.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s044-require-full-session-for-sensitive-operations.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s045-anti-automation-controls.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s046-secure-notification-on-auth-change.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s048-password-credential-recovery.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s050-session-token-weak-hash.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s052-secure-random-authentication-code.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s054-verification-default-account.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s057-utc-logging.js +0 -0
- /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s058-no-ssrf.js +0 -0
- /package/rules/{C006_function_naming → common/C006_function_naming}/config.json +0 -0
- /package/rules/{C019_log_level_usage → common/C019_log_level_usage}/config.json +0 -0
- /package/rules/{C029_catch_block_logging → common/C029_catch_block_logging}/config.json +0 -0
- /package/rules/{C031_validation_separation → common/C031_validation_separation}/analyzer.js +0 -0
- /package/rules/{C031_validation_separation/README.md → docs/C031_validation_separation.md} +0 -0
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# SunLint Release Packaging Script v1.0.4
|
|
4
|
+
# Following Rule C005: Single responsibility - handle release packaging only
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
|
|
8
|
+
echo "🚀 Building SunLint v1.0.4 Release Package..."
|
|
9
|
+
|
|
10
|
+
# Clean previous builds
|
|
11
|
+
echo "🧹 Cleaning previous builds..."
|
|
12
|
+
rm -rf *.tgz
|
|
13
|
+
rm -rf coverage/
|
|
14
|
+
rm -rf reports/
|
|
15
|
+
rm -rf *.log
|
|
16
|
+
|
|
17
|
+
# Verify package.json version
|
|
18
|
+
echo "📋 Verifying package version..."
|
|
19
|
+
PACKAGE_VERSION=$(node -p "require('./package.json').version")
|
|
20
|
+
if [ "$PACKAGE_VERSION" != "1.0.4" ]; then
|
|
21
|
+
echo "❌ Package version mismatch. Expected 1.0.4, got $PACKAGE_VERSION"
|
|
22
|
+
exit 1
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
# Run tests before packaging (skip if not available)
|
|
26
|
+
echo "🧪 Running tests..."
|
|
27
|
+
if [ -f "test/unit/test-runner.js" ]; then
|
|
28
|
+
npm test || {
|
|
29
|
+
echo "❌ Tests failed. Aborting release."
|
|
30
|
+
exit 1
|
|
31
|
+
}
|
|
32
|
+
else
|
|
33
|
+
echo "⚠️ Test files not found, skipping tests..."
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
# Lint the codebase
|
|
37
|
+
echo "🔍 Running self-lint check..."
|
|
38
|
+
node cli.js --quality --typescript --input=core/ || {
|
|
39
|
+
echo "❌ Self-lint check failed. Fix issues before release."
|
|
40
|
+
exit 1
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
# Security self-check
|
|
44
|
+
echo "🔒 Running security self-check..."
|
|
45
|
+
node cli.js --security --typescript --input=core/ || {
|
|
46
|
+
echo "⚠️ Security issues detected, but continuing with release..."
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
# Verify critical files exist
|
|
50
|
+
echo "📁 Verifying critical files..."
|
|
51
|
+
CRITICAL_FILES=(
|
|
52
|
+
"cli.js"
|
|
53
|
+
"package.json"
|
|
54
|
+
"README.md"
|
|
55
|
+
"CHANGELOG.md"
|
|
56
|
+
"config/rules/rules-registry.json"
|
|
57
|
+
"core/cli-program.js"
|
|
58
|
+
"core/cli-action-handler.js"
|
|
59
|
+
"core/typescript-engine.js"
|
|
60
|
+
"core/analysis-orchestrator.js"
|
|
61
|
+
"core/rule-selection-service.js"
|
|
62
|
+
"core/rule-mapping-service.js"
|
|
63
|
+
"integrations/eslint/configs/.eslintrc.js"
|
|
64
|
+
"integrations/eslint/plugin/index.js"
|
|
65
|
+
"integrations/eslint/plugin/package.json"
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
for file in "${CRITICAL_FILES[@]}"; do
|
|
69
|
+
if [ ! -f "$file" ]; then
|
|
70
|
+
echo "❌ Critical file missing: $file"
|
|
71
|
+
exit 1
|
|
72
|
+
fi
|
|
73
|
+
done
|
|
74
|
+
|
|
75
|
+
# Verify security rules are present
|
|
76
|
+
echo "🔒 Verifying security rules..."
|
|
77
|
+
SECURITY_RULE_COUNT=$(ls integrations/eslint/plugin/rules/security/s*.js 2>/dev/null | wc -l)
|
|
78
|
+
if [ "$SECURITY_RULE_COUNT" -lt 40 ]; then
|
|
79
|
+
echo "❌ Expected 40+ security rules, found $SECURITY_RULE_COUNT"
|
|
80
|
+
exit 1
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
# Create npm package
|
|
84
|
+
echo "📦 Creating npm package..."
|
|
85
|
+
npm pack
|
|
86
|
+
|
|
87
|
+
# Verify package was created
|
|
88
|
+
PACKAGE_FILE="sun-sunlint-1.0.4.tgz"
|
|
89
|
+
if [ ! -f "$PACKAGE_FILE" ]; then
|
|
90
|
+
echo "❌ Package file not created: $PACKAGE_FILE"
|
|
91
|
+
exit 1
|
|
92
|
+
fi
|
|
93
|
+
|
|
94
|
+
# Get package size
|
|
95
|
+
PACKAGE_SIZE=$(du -h "$PACKAGE_FILE" | cut -f1)
|
|
96
|
+
|
|
97
|
+
echo "✅ Release package created successfully!"
|
|
98
|
+
echo ""
|
|
99
|
+
echo "📦 Package Details:"
|
|
100
|
+
echo " 📄 File: $PACKAGE_FILE"
|
|
101
|
+
echo " 📊 Size: $PACKAGE_SIZE"
|
|
102
|
+
echo " 🔢 Version: 1.0.4"
|
|
103
|
+
echo " 📅 Date: $(date)"
|
|
104
|
+
echo ""
|
|
105
|
+
echo "🎯 Release Features:"
|
|
106
|
+
echo " ✅ 40 Security Rules (S005-S058)"
|
|
107
|
+
echo " ✅ 4 Quality Rules (C006, C019, C029, C031)"
|
|
108
|
+
echo " ✅ Category-based filtering (--security, --quality)"
|
|
109
|
+
echo " ✅ Dynamic rule configuration"
|
|
110
|
+
echo " ✅ Enhanced ESLint integration"
|
|
111
|
+
echo ""
|
|
112
|
+
echo "🚀 Installation Commands:"
|
|
113
|
+
echo " Global: npm install -g ./$PACKAGE_FILE"
|
|
114
|
+
echo " Local: npm install ./$PACKAGE_FILE"
|
|
115
|
+
echo " Direct: npm install -g https://github.com/sun-asterisk/engineer-excellence/releases/download/sunlint-v1.0.4/$PACKAGE_FILE"
|
|
116
|
+
echo ""
|
|
117
|
+
echo "🎉 Ready for release!"
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* CI Report Generator - Creates CI/CD optimized reports
|
|
5
|
+
* Usage: node ci-report.js eslint-results.json sunlint-results.json
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const chalk = require('chalk');
|
|
11
|
+
|
|
12
|
+
class CIReporter {
|
|
13
|
+
constructor() {
|
|
14
|
+
this.isCI = process.env.CI === 'true' || process.env.GITHUB_ACTIONS === 'true';
|
|
15
|
+
this.isGitHub = process.env.GITHUB_ACTIONS === 'true';
|
|
16
|
+
this.isGitLab = process.env.GITLAB_CI === 'true';
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async generateCIReport(eslintPath, sunlintPath) {
|
|
20
|
+
const ReportMerger = require('./merge-reports.js');
|
|
21
|
+
const merger = new ReportMerger();
|
|
22
|
+
|
|
23
|
+
const unifiedReport = await merger.mergeReports(eslintPath, sunlintPath);
|
|
24
|
+
|
|
25
|
+
if (this.isGitHub) {
|
|
26
|
+
this.generateGitHubReport(unifiedReport);
|
|
27
|
+
} else if (this.isGitLab) {
|
|
28
|
+
this.generateGitLabReport(unifiedReport);
|
|
29
|
+
} else {
|
|
30
|
+
this.generateGenericReport(unifiedReport);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return this.determineExitCode(unifiedReport);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
generateGitHubReport(report) {
|
|
37
|
+
console.log('::group::📊 Code Quality Summary');
|
|
38
|
+
console.log(this.formatSummaryForCI(report));
|
|
39
|
+
console.log('::endgroup::');
|
|
40
|
+
|
|
41
|
+
// Create annotations for errors
|
|
42
|
+
const errors = report.violations.filter(v => v.severity === 'error').slice(0, 10);
|
|
43
|
+
errors.forEach(violation => {
|
|
44
|
+
console.log(`::error file=${violation.file},line=${violation.line},col=${violation.column},title=${violation.ruleId}::${violation.message}`);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// Create warnings
|
|
48
|
+
const warnings = report.violations.filter(v => v.severity === 'warning').slice(0, 10);
|
|
49
|
+
warnings.forEach(violation => {
|
|
50
|
+
console.log(`::warning file=${violation.file},line=${violation.line},col=${violation.column},title=${violation.ruleId}::${violation.message}`);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// Set output variables
|
|
54
|
+
console.log(`::set-output name=total-violations::${report.summary.total.violations}`);
|
|
55
|
+
console.log(`::set-output name=errors::${report.summary.total.errors}`);
|
|
56
|
+
console.log(`::set-output name=warnings::${report.summary.total.warnings}`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
generateGitLabReport(report) {
|
|
60
|
+
console.log(chalk.blue('📊 GitLab CI Code Quality Report'));
|
|
61
|
+
console.log(this.formatSummaryForCI(report));
|
|
62
|
+
|
|
63
|
+
// GitLab Code Quality format
|
|
64
|
+
const gitlabReport = this.convertToGitLabFormat(report);
|
|
65
|
+
fs.writeFileSync('gl-code-quality-report.json', JSON.stringify(gitlabReport, null, 2));
|
|
66
|
+
|
|
67
|
+
console.log('✅ GitLab Code Quality report: gl-code-quality-report.json');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
generateGenericReport(report) {
|
|
71
|
+
console.log(chalk.blue('📊 CI Code Quality Report'));
|
|
72
|
+
console.log(this.formatSummaryForCI(report));
|
|
73
|
+
|
|
74
|
+
// Save JSON for further processing
|
|
75
|
+
fs.writeFileSync('ci-report.json', JSON.stringify(report, null, 2));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
formatSummaryForCI(report) {
|
|
79
|
+
const { summary } = report;
|
|
80
|
+
|
|
81
|
+
return `
|
|
82
|
+
Files analyzed: ${summary.total.files}
|
|
83
|
+
Total violations: ${summary.total.violations}
|
|
84
|
+
├─ Errors: ${summary.total.errors}
|
|
85
|
+
├─ Warnings: ${summary.total.warnings}
|
|
86
|
+
└─ Info: ${summary.total.info}
|
|
87
|
+
|
|
88
|
+
Tool breakdown:
|
|
89
|
+
├─ ESLint: ${summary.by_tool.eslint.violations} violations
|
|
90
|
+
└─ SunLint: ${summary.by_tool.sunlint.violations} violations
|
|
91
|
+
|
|
92
|
+
Quality Score: ${this.calculateQualityScore(report)}%
|
|
93
|
+
`;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
calculateQualityScore(report) {
|
|
97
|
+
const { total } = report.summary;
|
|
98
|
+
const totalFiles = total.files;
|
|
99
|
+
const violations = total.violations;
|
|
100
|
+
|
|
101
|
+
if (totalFiles === 0) return 100;
|
|
102
|
+
|
|
103
|
+
// Quality score formula: base 100, deduct points for violations
|
|
104
|
+
// Errors: -5 points, Warnings: -2 points, Info: -1 point
|
|
105
|
+
const penalty = (total.errors * 5) + (total.warnings * 2) + (total.info * 1);
|
|
106
|
+
const maxPenalty = totalFiles * 10; // Max 10 points per file
|
|
107
|
+
|
|
108
|
+
const score = Math.max(0, 100 - Math.round((penalty / maxPenalty) * 100));
|
|
109
|
+
return score;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
convertToGitLabFormat(report) {
|
|
113
|
+
return report.violations.map(violation => ({
|
|
114
|
+
description: violation.message,
|
|
115
|
+
check_name: violation.ruleId,
|
|
116
|
+
fingerprint: this.generateFingerprint(violation),
|
|
117
|
+
severity: this.mapSeverityForGitLab(violation.severity),
|
|
118
|
+
location: {
|
|
119
|
+
path: violation.file,
|
|
120
|
+
lines: {
|
|
121
|
+
begin: violation.line
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}));
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
generateFingerprint(violation) {
|
|
128
|
+
const crypto = require('crypto');
|
|
129
|
+
const content = `${violation.file}:${violation.line}:${violation.ruleId}`;
|
|
130
|
+
return crypto.createHash('md5').update(content).digest('hex');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
mapSeverityForGitLab(severity) {
|
|
134
|
+
switch (severity) {
|
|
135
|
+
case 'error': return 'major';
|
|
136
|
+
case 'warning': return 'minor';
|
|
137
|
+
case 'info': return 'info';
|
|
138
|
+
default: return 'info';
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
determineExitCode(report) {
|
|
143
|
+
const { total } = report.summary;
|
|
144
|
+
|
|
145
|
+
// Exit with error if there are any errors
|
|
146
|
+
if (total.errors > 0) {
|
|
147
|
+
console.log(chalk.red(`❌ Quality gate failed: ${total.errors} errors found`));
|
|
148
|
+
return 1;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Warning if too many warnings
|
|
152
|
+
if (total.warnings > 50) {
|
|
153
|
+
console.log(chalk.yellow(`⚠️ Quality gate warning: ${total.warnings} warnings found`));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
console.log(chalk.green('✅ Quality gate passed'));
|
|
157
|
+
return 0;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// CLI execution
|
|
162
|
+
if (require.main === module) {
|
|
163
|
+
const [eslintReport, sunlintReport] = process.argv.slice(2);
|
|
164
|
+
|
|
165
|
+
if (!eslintReport || !sunlintReport) {
|
|
166
|
+
console.error('Usage: node ci-report.js <eslint-report.json> <sunlint-report.json>');
|
|
167
|
+
process.exit(1);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const reporter = new CIReporter();
|
|
171
|
+
reporter.generateCIReport(eslintReport, sunlintReport)
|
|
172
|
+
.then(exitCode => process.exit(exitCode))
|
|
173
|
+
.catch(error => {
|
|
174
|
+
console.error(chalk.red('❌ CI report generation failed:'), error.message);
|
|
175
|
+
process.exit(1);
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
module.exports = CIReporter;
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# SunLint CLI Installer Script
|
|
4
|
+
# Install SunLint from GitHub release
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
|
|
8
|
+
# Colors for output
|
|
9
|
+
RED='\033[0;31m'
|
|
10
|
+
GREEN='\033[0;32m'
|
|
11
|
+
YELLOW='\033[1;33m'
|
|
12
|
+
BLUE='\033[0;34m'
|
|
13
|
+
NC='\033[0m' # No Color
|
|
14
|
+
|
|
15
|
+
# Configuration
|
|
16
|
+
REPO_URL="https://github.com/sun-asterisk/engineer-excellence"
|
|
17
|
+
LATEST_RELEASE_URL="https://api.github.com/repos/sun-asterisk/engineer-excellence/releases/latest"
|
|
18
|
+
PACKAGE_NAME="@sun/sunlint"
|
|
19
|
+
|
|
20
|
+
echo -e "${BLUE}☀️ SunLint CLI Installer${NC}"
|
|
21
|
+
echo -e "${BLUE}=================================${NC}"
|
|
22
|
+
|
|
23
|
+
# Check if Node.js and npm are installed
|
|
24
|
+
check_prerequisites() {
|
|
25
|
+
echo -e "${YELLOW}Checking prerequisites...${NC}"
|
|
26
|
+
|
|
27
|
+
if ! command -v node &> /dev/null; then
|
|
28
|
+
echo -e "${RED}❌ Node.js is required but not installed.${NC}"
|
|
29
|
+
echo -e "${YELLOW}Please install Node.js from: https://nodejs.org/${NC}"
|
|
30
|
+
exit 1
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
if ! command -v npm &> /dev/null; then
|
|
34
|
+
echo -e "${RED}❌ npm is required but not installed.${NC}"
|
|
35
|
+
exit 1
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
echo -e "${GREEN}✅ Node.js $(node --version) and npm $(npm --version) found${NC}"
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
# Get latest release version
|
|
42
|
+
get_latest_version() {
|
|
43
|
+
echo -e "${YELLOW}Fetching latest release...${NC}"
|
|
44
|
+
|
|
45
|
+
if command -v curl &> /dev/null; then
|
|
46
|
+
LATEST_TAG=$(curl -s "$LATEST_RELEASE_URL" | grep '"tag_name":' | grep 'sunlint-v' | cut -d '"' -f 4 | head -1)
|
|
47
|
+
elif command -v wget &> /dev/null; then
|
|
48
|
+
LATEST_TAG=$(wget -qO- "$LATEST_RELEASE_URL" | grep '"tag_name":' | grep 'sunlint-v' | cut -d '"' -f 4 | head -1)
|
|
49
|
+
else
|
|
50
|
+
echo -e "${RED}❌ Neither curl nor wget found. Cannot fetch latest release.${NC}"
|
|
51
|
+
echo -e "${YELLOW}Please install curl or wget, or use manual installation.${NC}"
|
|
52
|
+
exit 1
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
if [ -z "$LATEST_TAG" ]; then
|
|
56
|
+
echo -e "${RED}❌ Could not find latest SunLint release.${NC}"
|
|
57
|
+
echo -e "${YELLOW}Using default version: sunlint-v1.0.0${NC}"
|
|
58
|
+
LATEST_TAG="sunlint-v1.0.0"
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
# Extract version number (remove 'sunlint-v' prefix)
|
|
62
|
+
VERSION=${LATEST_TAG#sunlint-v}
|
|
63
|
+
echo -e "${GREEN}✅ Latest version: ${VERSION}${NC}"
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
# Uninstall existing version
|
|
67
|
+
uninstall_existing() {
|
|
68
|
+
if npm list -g "$PACKAGE_NAME" &> /dev/null; then
|
|
69
|
+
echo -e "${YELLOW}Removing existing SunLint installation...${NC}"
|
|
70
|
+
npm uninstall -g "$PACKAGE_NAME" || true
|
|
71
|
+
fi
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
# Install SunLint
|
|
75
|
+
install_sunlint() {
|
|
76
|
+
echo -e "${YELLOW}Installing SunLint CLI v${VERSION}...${NC}"
|
|
77
|
+
|
|
78
|
+
DOWNLOAD_URL="${REPO_URL}/releases/download/${LATEST_TAG}/sun-sunlint-${VERSION}.tgz"
|
|
79
|
+
|
|
80
|
+
echo -e "${BLUE}Download URL: ${DOWNLOAD_URL}${NC}"
|
|
81
|
+
|
|
82
|
+
# Install from GitHub release
|
|
83
|
+
if npm install -g "$DOWNLOAD_URL"; then
|
|
84
|
+
echo -e "${GREEN}✅ SunLint CLI v${VERSION} installed successfully!${NC}"
|
|
85
|
+
else
|
|
86
|
+
echo -e "${RED}❌ Installation failed.${NC}"
|
|
87
|
+
echo -e "${YELLOW}Trying alternative installation method...${NC}"
|
|
88
|
+
|
|
89
|
+
# Fallback: Clone and install
|
|
90
|
+
TEMP_DIR=$(mktemp -d)
|
|
91
|
+
cd "$TEMP_DIR"
|
|
92
|
+
|
|
93
|
+
echo -e "${YELLOW}Cloning repository...${NC}"
|
|
94
|
+
if git clone "$REPO_URL.git"; then
|
|
95
|
+
cd engineer-excellence/coding-quality/extensions/sunlint
|
|
96
|
+
echo -e "${YELLOW}Installing from source...${NC}"
|
|
97
|
+
if npm install -g .; then
|
|
98
|
+
echo -e "${GREEN}✅ SunLint CLI installed from source!${NC}"
|
|
99
|
+
else
|
|
100
|
+
echo -e "${RED}❌ Source installation also failed.${NC}"
|
|
101
|
+
exit 1
|
|
102
|
+
fi
|
|
103
|
+
else
|
|
104
|
+
echo -e "${RED}❌ Could not clone repository.${NC}"
|
|
105
|
+
exit 1
|
|
106
|
+
fi
|
|
107
|
+
|
|
108
|
+
# Cleanup
|
|
109
|
+
cd /
|
|
110
|
+
rm -rf "$TEMP_DIR"
|
|
111
|
+
fi
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
# Verify installation
|
|
115
|
+
verify_installation() {
|
|
116
|
+
echo -e "${YELLOW}Verifying installation...${NC}"
|
|
117
|
+
|
|
118
|
+
if command -v sunlint &> /dev/null; then
|
|
119
|
+
INSTALLED_VERSION=$(sunlint --version)
|
|
120
|
+
echo -e "${GREEN}✅ SunLint CLI is working!${NC}"
|
|
121
|
+
echo -e "${GREEN} Version: ${INSTALLED_VERSION}${NC}"
|
|
122
|
+
echo -e "${GREEN} Location: $(which sunlint)${NC}"
|
|
123
|
+
|
|
124
|
+
echo -e "${BLUE}🚀 Quick Test:${NC}"
|
|
125
|
+
echo -e "${YELLOW}sunlint --help${NC}"
|
|
126
|
+
return 0
|
|
127
|
+
else
|
|
128
|
+
echo -e "${RED}❌ SunLint command not found after installation.${NC}"
|
|
129
|
+
echo -e "${YELLOW}Try restarting your terminal or check your PATH.${NC}"
|
|
130
|
+
return 1
|
|
131
|
+
fi
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
# Usage examples
|
|
135
|
+
show_usage() {
|
|
136
|
+
echo -e "${BLUE}📋 Usage Examples:${NC}"
|
|
137
|
+
echo -e "${YELLOW}# Check code quality${NC}"
|
|
138
|
+
echo -e "sunlint --quality --input=src"
|
|
139
|
+
echo ""
|
|
140
|
+
echo -e "${YELLOW}# TypeScript analysis${NC}"
|
|
141
|
+
echo -e "sunlint --typescript --input=src"
|
|
142
|
+
echo ""
|
|
143
|
+
echo -e "${YELLOW}# All rules with JSON output (CI/CD)${NC}"
|
|
144
|
+
echo -e "sunlint --all --format=json --quiet --input=src"
|
|
145
|
+
echo ""
|
|
146
|
+
echo -e "${YELLOW}# Get help${NC}"
|
|
147
|
+
echo -e "sunlint --help"
|
|
148
|
+
echo ""
|
|
149
|
+
echo -e "${BLUE}📖 Documentation:${NC}"
|
|
150
|
+
echo -e "${BLUE}https://github.com/sun-asterisk/engineer-excellence/tree/main/coding-quality/extensions/sunlint${NC}"
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
# Main execution
|
|
154
|
+
main() {
|
|
155
|
+
check_prerequisites
|
|
156
|
+
get_latest_version
|
|
157
|
+
uninstall_existing
|
|
158
|
+
install_sunlint
|
|
159
|
+
|
|
160
|
+
if verify_installation; then
|
|
161
|
+
echo ""
|
|
162
|
+
echo -e "${GREEN}🎉 Installation completed successfully!${NC}"
|
|
163
|
+
echo ""
|
|
164
|
+
show_usage
|
|
165
|
+
else
|
|
166
|
+
echo -e "${RED}❌ Installation verification failed.${NC}"
|
|
167
|
+
exit 1
|
|
168
|
+
fi
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
# Handle script arguments
|
|
172
|
+
case "${1:-}" in
|
|
173
|
+
--help|-h)
|
|
174
|
+
echo "SunLint CLI Installer"
|
|
175
|
+
echo ""
|
|
176
|
+
echo "Usage: $0 [options]"
|
|
177
|
+
echo ""
|
|
178
|
+
echo "Options:"
|
|
179
|
+
echo " --help, -h Show this help message"
|
|
180
|
+
echo " --version, -v Show installer version"
|
|
181
|
+
echo ""
|
|
182
|
+
echo "This script will:"
|
|
183
|
+
echo "1. Check for Node.js and npm"
|
|
184
|
+
echo "2. Fetch the latest SunLint release"
|
|
185
|
+
echo "3. Install SunLint CLI globally"
|
|
186
|
+
echo "4. Verify the installation"
|
|
187
|
+
exit 0
|
|
188
|
+
;;
|
|
189
|
+
--version|-v)
|
|
190
|
+
echo "SunLint Installer v1.0.0"
|
|
191
|
+
exit 0
|
|
192
|
+
;;
|
|
193
|
+
*)
|
|
194
|
+
main "$@"
|
|
195
|
+
;;
|
|
196
|
+
esac
|