@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.
Files changed (219) hide show
  1. package/.sunlint.json +35 -0
  2. package/CHANGELOG.md +30 -3
  3. package/CONTRIBUTING.md +235 -0
  4. package/PROJECT_STRUCTURE.md +60 -0
  5. package/README.md +146 -58
  6. package/cli.js +1 -0
  7. package/config/README.md +88 -0
  8. package/config/defaults/ai-rules-context.json +231 -0
  9. package/config/engines/engines.json +49 -0
  10. package/config/engines/eslint-rule-mapping.json +74 -0
  11. package/config/eslint-rule-mapping.json +126 -0
  12. package/config/integrations/eslint/base.config.js +125 -0
  13. package/config/integrations/eslint/simple.config.js +24 -0
  14. package/config/presets/strict.json +0 -1
  15. package/config/rule-analysis-strategies.js +74 -0
  16. package/config/{rules-registry.json → rules/rules-registry.json} +30 -7
  17. package/core/analysis-orchestrator.js +383 -591
  18. package/core/ast-modules/README.md +103 -0
  19. package/core/ast-modules/base-parser.js +90 -0
  20. package/core/ast-modules/index.js +97 -0
  21. package/core/ast-modules/package.json +37 -0
  22. package/core/ast-modules/parsers/eslint-js-parser.js +153 -0
  23. package/core/ast-modules/parsers/eslint-ts-parser.js +98 -0
  24. package/core/ast-modules/parsers/javascript-parser.js +187 -0
  25. package/core/ast-modules/parsers/typescript-parser.js +187 -0
  26. package/core/cli-action-handler.js +271 -255
  27. package/core/cli-program.js +18 -4
  28. package/core/config-manager.js +9 -3
  29. package/core/config-merger.js +40 -1
  30. package/core/config-validator.js +2 -2
  31. package/core/dependency-checker.js +125 -0
  32. package/core/enhanced-rules-registry.js +331 -0
  33. package/core/file-targeting-service.js +92 -23
  34. package/core/interfaces/analysis-engine.interface.js +100 -0
  35. package/core/multi-rule-runner.js +0 -221
  36. package/core/output-service.js +1 -1
  37. package/core/rule-mapping-service.js +1 -1
  38. package/core/rule-selection-service.js +10 -2
  39. package/core/smart-installer.js +164 -0
  40. package/docs/AI.md +163 -0
  41. package/docs/ARCHITECTURE.md +78 -0
  42. package/docs/CI-CD-GUIDE.md +315 -0
  43. package/docs/COMMAND-EXAMPLES.md +256 -0
  44. package/docs/CONFIGURATION.md +414 -0
  45. package/docs/DEBUG.md +86 -0
  46. package/docs/DEPENDENCIES.md +90 -0
  47. package/docs/DEPLOYMENT-STRATEGIES.md +270 -0
  48. package/docs/DISTRIBUTION.md +153 -0
  49. package/docs/ESLINT-INTEGRATION-STRATEGY.md +392 -0
  50. package/docs/ESLINT_INTEGRATION.md +238 -0
  51. package/docs/FOLDER_STRUCTURE.md +59 -0
  52. package/docs/FUTURE_PACKAGES.md +83 -0
  53. package/docs/HEURISTIC_VS_AI.md +113 -0
  54. package/docs/PRODUCTION_DEPLOYMENT_ANALYSIS.md +112 -0
  55. package/docs/PRODUCTION_SIZE_IMPACT.md +183 -0
  56. package/docs/README.md +32 -0
  57. package/docs/RELEASE_GUIDE.md +230 -0
  58. package/engines/eslint-engine.js +610 -0
  59. package/engines/heuristic-engine.js +864 -0
  60. package/engines/openai-engine.js +374 -0
  61. package/engines/tree-sitter-parser.js +0 -0
  62. package/engines/universal-ast-engine.js +0 -0
  63. package/integrations/eslint/README.md +99 -0
  64. package/integrations/eslint/configs/.eslintrc.js +98 -0
  65. package/integrations/eslint/configs/eslint.config.js +133 -0
  66. package/integrations/eslint/configs/eslint.config.simple.js +24 -0
  67. package/integrations/eslint/package.json +23 -0
  68. package/integrations/eslint/plugin/index.js +164 -0
  69. package/integrations/eslint/plugin/package.json +13 -0
  70. package/integrations/eslint/plugin/rules/common/c002-no-duplicate-code.js +204 -0
  71. package/integrations/eslint/plugin/rules/common/c003-no-vague-abbreviations.js +246 -0
  72. package/integrations/eslint/plugin/rules/common/c006-function-name-verb-noun.js +216 -0
  73. package/integrations/eslint/plugin/rules/common/c010-limit-block-nesting.js +90 -0
  74. package/integrations/eslint/plugin/rules/common/c013-no-dead-code.js +78 -0
  75. package/integrations/eslint/plugin/rules/common/c014-abstract-dependency-preferred.js +38 -0
  76. package/integrations/eslint/plugin/rules/common/c017-limit-constructor-logic.js +146 -0
  77. package/integrations/eslint/plugin/rules/common/c018-no-generic-throw.js +335 -0
  78. package/integrations/eslint/plugin/rules/common/c023-no-duplicate-variable-name-in-scope.js +142 -0
  79. package/integrations/eslint/plugin/rules/common/c029-catch-block-logging.js +115 -0
  80. package/integrations/eslint/plugin/rules/common/c030-use-custom-error-classes.js +294 -0
  81. package/integrations/eslint/plugin/rules/common/c035-no-empty-catch.js +162 -0
  82. package/integrations/eslint/plugin/rules/common/c041-no-config-inline.js +122 -0
  83. package/integrations/eslint/plugin/rules/common/c042-boolean-name-prefix.js +406 -0
  84. package/integrations/eslint/plugin/rules/common/c043-no-console-or-print.js +300 -0
  85. package/integrations/eslint/plugin/rules/common/c047-no-duplicate-retry-logic.js +239 -0
  86. package/integrations/eslint/plugin/rules/common/c072-one-assert-per-test.js +184 -0
  87. package/integrations/eslint/plugin/rules/common/c075-explicit-function-return-types.js +168 -0
  88. package/integrations/eslint/plugin/rules/common/c076-single-behavior-per-test.js +254 -0
  89. package/integrations/eslint/plugin/rules/security/s001-fail-securely.js +381 -0
  90. package/integrations/eslint/plugin/rules/security/s002-idor-check.js +945 -0
  91. package/integrations/eslint/plugin/rules/security/s003-no-unvalidated-redirect.js +86 -0
  92. package/integrations/eslint/plugin/rules/security/s007-no-plaintext-otp.js +74 -0
  93. package/integrations/eslint/plugin/rules/security/s013-verify-tls-connection.js +47 -0
  94. package/integrations/eslint/plugin/rules/security/s047-secure-random-passwords.js +108 -0
  95. package/integrations/eslint/plugin/rules/security/s055-verification-rest-check-the-incoming-content-type.js +143 -0
  96. package/integrations/eslint/plugin/rules/typescript/t002-interface-prefix-i.js +42 -0
  97. package/integrations/eslint/plugin/rules/typescript/t003-ts-ignore-reason.js +48 -0
  98. package/integrations/eslint/plugin/rules/typescript/t004-no-empty-type.js +95 -0
  99. package/integrations/eslint/plugin/rules/typescript/t007-no-fn-in-constructor.js +52 -0
  100. package/integrations/eslint/plugin/rules/typescript/t010-no-nested-union-tuple.js +48 -0
  101. package/integrations/eslint/plugin/rules/typescript/t019-no-this-assign.js +81 -0
  102. package/integrations/eslint/plugin/rules/typescript/t020-no-default-multi-export.js +127 -0
  103. package/integrations/eslint/plugin/rules/typescript/t021-limit-nested-generics.js +150 -0
  104. package/integrations/eslint/tsconfig.json +27 -0
  105. package/package.json +61 -21
  106. package/rules/README.md +252 -0
  107. package/rules/common/C002_no_duplicate_code/analyzer.js +65 -0
  108. package/rules/common/C002_no_duplicate_code/config.json +23 -0
  109. package/rules/common/C003_no_vague_abbreviations/analyzer.js +418 -0
  110. package/rules/common/C003_no_vague_abbreviations/config.json +35 -0
  111. package/rules/{C006_function_naming → common/C006_function_naming}/analyzer.js +13 -2
  112. package/rules/common/C010_limit_block_nesting/analyzer.js +389 -0
  113. package/rules/common/C013_no_dead_code/analyzer.js +206 -0
  114. package/rules/common/C014_dependency_injection/analyzer.js +338 -0
  115. package/rules/common/C017_constructor_logic/analyzer.js +314 -0
  116. package/rules/{C019_log_level_usage → common/C019_log_level_usage}/analyzer.js +5 -2
  117. package/rules/{C029_catch_block_logging → common/C029_catch_block_logging}/analyzer.js +49 -15
  118. package/rules/common/C041_no_sensitive_hardcode/analyzer.js +292 -0
  119. package/rules/common/C042_boolean_name_prefix/analyzer.js +300 -0
  120. package/rules/common/C043_no_console_or_print/analyzer.js +304 -0
  121. package/rules/common/C047_no_duplicate_retry_logic/analyzer.js +351 -0
  122. package/rules/common/C075_explicit_return_types/analyzer.js +103 -0
  123. package/rules/common/C076_single_test_behavior/analyzer.js +121 -0
  124. package/rules/docs/C002_no_duplicate_code.md +57 -0
  125. package/rules/index.js +149 -0
  126. package/rules/migration/converter.js +385 -0
  127. package/rules/migration/mapping.json +164 -0
  128. package/rules/security/S026_json_schema_validation/analyzer.js +251 -0
  129. package/rules/security/S026_json_schema_validation/config.json +27 -0
  130. package/rules/security/S027_no_hardcoded_secrets/analyzer.js +263 -0
  131. package/rules/security/S027_no_hardcoded_secrets/config.json +29 -0
  132. package/rules/security/S029_csrf_protection/analyzer.js +264 -0
  133. package/rules/tests/C002_no_duplicate_code.test.js +50 -0
  134. package/rules/universal/C010/generic.js +0 -0
  135. package/rules/universal/C010/tree-sitter-analyzer.js +0 -0
  136. package/rules/utils/ast-utils.js +191 -0
  137. package/rules/utils/base-analyzer.js +98 -0
  138. package/rules/utils/pattern-matchers.js +239 -0
  139. package/rules/utils/rule-helpers.js +264 -0
  140. package/rules/utils/severity-constants.js +93 -0
  141. package/scripts/build-release.sh +117 -0
  142. package/scripts/ci-report.js +179 -0
  143. package/scripts/install.sh +196 -0
  144. package/scripts/manual-release.sh +338 -0
  145. package/scripts/merge-reports.js +424 -0
  146. package/scripts/pre-release-test.sh +175 -0
  147. package/scripts/prepare-release.sh +202 -0
  148. package/scripts/setup-github-registry.sh +42 -0
  149. package/scripts/test-scripts/README.md +22 -0
  150. package/scripts/test-scripts/test-c041-comparison.js +114 -0
  151. package/scripts/test-scripts/test-c041-eslint.js +67 -0
  152. package/scripts/test-scripts/test-eslint-rules.js +146 -0
  153. package/scripts/test-scripts/test-real-world.js +44 -0
  154. package/scripts/test-scripts/test-rules-on-real-projects.js +86 -0
  155. package/scripts/trigger-release.sh +285 -0
  156. package/scripts/validate-rule-structure.js +148 -0
  157. package/scripts/verify-install.sh +82 -0
  158. package/config/sunlint-schema.json +0 -159
  159. package/config/typescript/custom-rules.js +0 -9
  160. package/config/typescript/package-lock.json +0 -1585
  161. package/config/typescript/package.json +0 -13
  162. package/config/typescript/security-rules/index.js +0 -90
  163. package/config/typescript/tsconfig.json +0 -29
  164. package/core/ai-analyzer.js +0 -169
  165. package/core/eslint-engine-service.js +0 -312
  166. package/core/eslint-instance-manager.js +0 -104
  167. package/core/eslint-integration-service.js +0 -363
  168. package/core/sunlint-engine-service.js +0 -23
  169. package/core/typescript-analyzer.js +0 -262
  170. package/core/typescript-engine.js +0 -313
  171. /package/config/{default.json → defaults/default.json} +0 -0
  172. /package/config/{typescript/eslint.config.js → integrations/eslint/typescript.config.js} +0 -0
  173. /package/config/{typescript/custom-rules-new.js → schemas/sunlint-schema.json} +0 -0
  174. /package/config/{typescript → testing}/test-s005-working.ts +0 -0
  175. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s005-no-origin-auth.js +0 -0
  176. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s006-activation-recovery-secret-not-plaintext.js +0 -0
  177. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s008-crypto-agility.js +0 -0
  178. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s009-no-insecure-crypto.js +0 -0
  179. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s010-no-insecure-random-in-sensitive-context.js +0 -0
  180. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s011-no-insecure-uuid.js +0 -0
  181. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s012-hardcode-secret.js +0 -0
  182. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s014-insecure-tls-version.js +0 -0
  183. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s015-insecure-tls-certificate.js +0 -0
  184. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s016-sensitive-query-parameter.js +0 -0
  185. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s017-no-sql-injection.js +0 -0
  186. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s018-positive-input-validation.js +0 -0
  187. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s019-no-raw-user-input-in-email.js +0 -0
  188. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s020-no-eval-dynamic-execution.js +0 -0
  189. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s022-output-encoding.js +0 -0
  190. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s023-no-json-injection.js +0 -0
  191. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s025-server-side-input-validation.js +0 -0
  192. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s026-json-schema-validation.js +0 -0
  193. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s027-no-hardcoded-secrets.js +0 -0
  194. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s029-require-csrf-protection.js +0 -0
  195. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s030-no-directory-browsing.js +0 -0
  196. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s033-require-samesite-cookie.js +0 -0
  197. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s034-require-host-cookie-prefix.js +0 -0
  198. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s035-cookie-specific-path.js +0 -0
  199. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s036-no-unsafe-file-include.js +0 -0
  200. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s037-require-anti-cache-headers.js +0 -0
  201. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s038-no-version-disclosure.js +0 -0
  202. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s039-no-session-token-in-url.js +0 -0
  203. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s041-require-session-invalidate-on-logout.js +0 -0
  204. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s042-require-periodic-reauthentication.js +0 -0
  205. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s043-terminate-sessions-on-password-change.js +0 -0
  206. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s044-require-full-session-for-sensitive-operations.js +0 -0
  207. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s045-anti-automation-controls.js +0 -0
  208. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s046-secure-notification-on-auth-change.js +0 -0
  209. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s048-password-credential-recovery.js +0 -0
  210. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s050-session-token-weak-hash.js +0 -0
  211. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s052-secure-random-authentication-code.js +0 -0
  212. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s054-verification-default-account.js +0 -0
  213. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s057-utc-logging.js +0 -0
  214. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s058-no-ssrf.js +0 -0
  215. /package/rules/{C006_function_naming → common/C006_function_naming}/config.json +0 -0
  216. /package/rules/{C019_log_level_usage → common/C019_log_level_usage}/config.json +0 -0
  217. /package/rules/{C029_catch_block_logging → common/C029_catch_block_logging}/config.json +0 -0
  218. /package/rules/{C031_validation_separation → common/C031_validation_separation}/analyzer.js +0 -0
  219. /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