@sun-asterisk/sunlint 1.0.7 → 1.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) 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 +73 -52
  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} +22 -0
  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 +147 -0
  23. package/core/ast-modules/parsers/eslint-ts-parser.js +106 -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/enhanced-rules-registry.js +331 -0
  32. package/core/file-targeting-service.js +92 -23
  33. package/core/interfaces/analysis-engine.interface.js +100 -0
  34. package/core/multi-rule-runner.js +0 -221
  35. package/core/output-service.js +1 -1
  36. package/core/rule-mapping-service.js +1 -1
  37. package/core/rule-selection-service.js +10 -2
  38. package/docs/AI.md +163 -0
  39. package/docs/ARCHITECTURE.md +78 -0
  40. package/docs/CI-CD-GUIDE.md +315 -0
  41. package/docs/COMMAND-EXAMPLES.md +256 -0
  42. package/docs/CONFIGURATION.md +414 -0
  43. package/docs/DEBUG.md +86 -0
  44. package/docs/DEPLOYMENT-STRATEGIES.md +270 -0
  45. package/docs/DISTRIBUTION.md +153 -0
  46. package/docs/ESLINT-INTEGRATION-STRATEGY.md +392 -0
  47. package/docs/ESLINT_INTEGRATION.md +238 -0
  48. package/docs/FOLDER_STRUCTURE.md +59 -0
  49. package/docs/HEURISTIC_VS_AI.md +113 -0
  50. package/docs/README.md +32 -0
  51. package/docs/RELEASE_GUIDE.md +230 -0
  52. package/engines/eslint-engine.js +601 -0
  53. package/engines/heuristic-engine.js +860 -0
  54. package/engines/openai-engine.js +374 -0
  55. package/engines/tree-sitter-parser.js +0 -0
  56. package/engines/universal-ast-engine.js +0 -0
  57. package/integrations/eslint/README.md +99 -0
  58. package/integrations/eslint/configs/.eslintrc.js +98 -0
  59. package/integrations/eslint/configs/eslint.config.js +133 -0
  60. package/integrations/eslint/configs/eslint.config.simple.js +24 -0
  61. package/integrations/eslint/package.json +23 -0
  62. package/integrations/eslint/plugin/index.js +164 -0
  63. package/integrations/eslint/plugin/package.json +13 -0
  64. package/integrations/eslint/plugin/rules/common/c002-no-duplicate-code.js +204 -0
  65. package/integrations/eslint/plugin/rules/common/c003-no-vague-abbreviations.js +246 -0
  66. package/integrations/eslint/plugin/rules/common/c006-function-name-verb-noun.js +216 -0
  67. package/integrations/eslint/plugin/rules/common/c010-limit-block-nesting.js +90 -0
  68. package/integrations/eslint/plugin/rules/common/c013-no-dead-code.js +78 -0
  69. package/integrations/eslint/plugin/rules/common/c014-abstract-dependency-preferred.js +38 -0
  70. package/integrations/eslint/plugin/rules/common/c017-limit-constructor-logic.js +146 -0
  71. package/integrations/eslint/plugin/rules/common/c018-no-generic-throw.js +335 -0
  72. package/integrations/eslint/plugin/rules/common/c023-no-duplicate-variable-name-in-scope.js +142 -0
  73. package/integrations/eslint/plugin/rules/common/c029-catch-block-logging.js +115 -0
  74. package/integrations/eslint/plugin/rules/common/c030-use-custom-error-classes.js +294 -0
  75. package/integrations/eslint/plugin/rules/common/c035-no-empty-catch.js +162 -0
  76. package/integrations/eslint/plugin/rules/common/c041-no-config-inline.js +122 -0
  77. package/integrations/eslint/plugin/rules/common/c042-boolean-name-prefix.js +406 -0
  78. package/integrations/eslint/plugin/rules/common/c043-no-console-or-print.js +300 -0
  79. package/integrations/eslint/plugin/rules/common/c047-no-duplicate-retry-logic.js +239 -0
  80. package/integrations/eslint/plugin/rules/common/c072-one-assert-per-test.js +184 -0
  81. package/integrations/eslint/plugin/rules/common/c075-explicit-function-return-types.js +168 -0
  82. package/integrations/eslint/plugin/rules/common/c076-single-behavior-per-test.js +254 -0
  83. package/integrations/eslint/plugin/rules/security/s001-fail-securely.js +381 -0
  84. package/integrations/eslint/plugin/rules/security/s002-idor-check.js +945 -0
  85. package/integrations/eslint/plugin/rules/security/s003-no-unvalidated-redirect.js +86 -0
  86. package/integrations/eslint/plugin/rules/security/s007-no-plaintext-otp.js +74 -0
  87. package/integrations/eslint/plugin/rules/security/s013-verify-tls-connection.js +47 -0
  88. package/integrations/eslint/plugin/rules/security/s047-secure-random-passwords.js +108 -0
  89. package/integrations/eslint/plugin/rules/security/s055-verification-rest-check-the-incoming-content-type.js +143 -0
  90. package/integrations/eslint/plugin/rules/typescript/t002-interface-prefix-i.js +42 -0
  91. package/integrations/eslint/plugin/rules/typescript/t003-ts-ignore-reason.js +48 -0
  92. package/integrations/eslint/plugin/rules/typescript/t004-no-empty-type.js +95 -0
  93. package/integrations/eslint/plugin/rules/typescript/t007-no-fn-in-constructor.js +52 -0
  94. package/integrations/eslint/plugin/rules/typescript/t010-no-nested-union-tuple.js +48 -0
  95. package/integrations/eslint/plugin/rules/typescript/t019-no-this-assign.js +81 -0
  96. package/integrations/eslint/plugin/rules/typescript/t020-no-default-multi-export.js +127 -0
  97. package/integrations/eslint/plugin/rules/typescript/t021-limit-nested-generics.js +150 -0
  98. package/integrations/eslint/test-c041-rule.js +87 -0
  99. package/integrations/eslint/tsconfig.json +27 -0
  100. package/package.json +29 -16
  101. package/rules/README.md +252 -0
  102. package/rules/common/C002_no_duplicate_code/analyzer.js +65 -0
  103. package/rules/common/C002_no_duplicate_code/config.json +23 -0
  104. package/rules/common/C003_no_vague_abbreviations/analyzer.js +418 -0
  105. package/rules/common/C003_no_vague_abbreviations/config.json +35 -0
  106. package/rules/{C006_function_naming → common/C006_function_naming}/analyzer.js +13 -2
  107. package/rules/common/C010_limit_block_nesting/analyzer.js +389 -0
  108. package/rules/common/C013_no_dead_code/analyzer.js +206 -0
  109. package/rules/common/C014_dependency_injection/analyzer.js +338 -0
  110. package/rules/common/C017_constructor_logic/analyzer.js +314 -0
  111. package/rules/{C019_log_level_usage → common/C019_log_level_usage}/analyzer.js +5 -2
  112. package/rules/{C029_catch_block_logging → common/C029_catch_block_logging}/analyzer.js +49 -15
  113. package/rules/common/C041_no_sensitive_hardcode/analyzer.js +292 -0
  114. package/rules/common/C042_boolean_name_prefix/analyzer.js +300 -0
  115. package/rules/common/C043_no_console_or_print/analyzer.js +304 -0
  116. package/rules/common/C047_no_duplicate_retry_logic/analyzer.js +351 -0
  117. package/rules/common/C075_explicit_return_types/analyzer.js +103 -0
  118. package/rules/common/C076_single_test_behavior/analyzer.js +121 -0
  119. package/rules/docs/C002_no_duplicate_code.md +57 -0
  120. package/rules/index.js +149 -0
  121. package/rules/migration/converter.js +385 -0
  122. package/rules/migration/mapping.json +164 -0
  123. package/rules/security/S026_json_schema_validation/analyzer.js +251 -0
  124. package/rules/security/S026_json_schema_validation/config.json +27 -0
  125. package/rules/security/S027_no_hardcoded_secrets/analyzer.js +263 -0
  126. package/rules/security/S027_no_hardcoded_secrets/config.json +29 -0
  127. package/rules/security/S029_csrf_protection/analyzer.js +264 -0
  128. package/rules/tests/C002_no_duplicate_code.test.js +50 -0
  129. package/rules/universal/C010/generic.js +0 -0
  130. package/rules/universal/C010/tree-sitter-analyzer.js +0 -0
  131. package/rules/utils/ast-utils.js +191 -0
  132. package/rules/utils/base-analyzer.js +98 -0
  133. package/rules/utils/pattern-matchers.js +239 -0
  134. package/rules/utils/rule-helpers.js +264 -0
  135. package/rules/utils/severity-constants.js +93 -0
  136. package/scripts/build-release.sh +117 -0
  137. package/scripts/ci-report.js +179 -0
  138. package/scripts/install.sh +196 -0
  139. package/scripts/manual-release.sh +338 -0
  140. package/scripts/merge-reports.js +424 -0
  141. package/scripts/pre-release-test.sh +175 -0
  142. package/scripts/prepare-release.sh +202 -0
  143. package/scripts/setup-github-registry.sh +42 -0
  144. package/scripts/test-scripts/README.md +22 -0
  145. package/scripts/test-scripts/test-c041-comparison.js +114 -0
  146. package/scripts/test-scripts/test-c041-eslint.js +67 -0
  147. package/scripts/test-scripts/test-eslint-rules.js +146 -0
  148. package/scripts/test-scripts/test-real-world.js +44 -0
  149. package/scripts/test-scripts/test-rules-on-real-projects.js +86 -0
  150. package/scripts/trigger-release.sh +285 -0
  151. package/scripts/validate-rule-structure.js +148 -0
  152. package/scripts/verify-install.sh +82 -0
  153. package/config/sunlint-schema.json +0 -159
  154. package/config/typescript/custom-rules.js +0 -9
  155. package/config/typescript/package-lock.json +0 -1585
  156. package/config/typescript/package.json +0 -13
  157. package/config/typescript/security-rules/index.js +0 -90
  158. package/config/typescript/tsconfig.json +0 -29
  159. package/core/ai-analyzer.js +0 -169
  160. package/core/eslint-engine-service.js +0 -312
  161. package/core/eslint-instance-manager.js +0 -104
  162. package/core/eslint-integration-service.js +0 -363
  163. package/core/sunlint-engine-service.js +0 -23
  164. package/core/typescript-analyzer.js +0 -262
  165. package/core/typescript-engine.js +0 -313
  166. /package/config/{default.json → defaults/default.json} +0 -0
  167. /package/config/{typescript/eslint.config.js → integrations/eslint/typescript.config.js} +0 -0
  168. /package/config/{typescript/custom-rules-new.js → schemas/sunlint-schema.json} +0 -0
  169. /package/config/{typescript → testing}/test-s005-working.ts +0 -0
  170. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s005-no-origin-auth.js +0 -0
  171. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s006-activation-recovery-secret-not-plaintext.js +0 -0
  172. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s008-crypto-agility.js +0 -0
  173. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s009-no-insecure-crypto.js +0 -0
  174. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s010-no-insecure-random-in-sensitive-context.js +0 -0
  175. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s011-no-insecure-uuid.js +0 -0
  176. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s012-hardcode-secret.js +0 -0
  177. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s014-insecure-tls-version.js +0 -0
  178. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s015-insecure-tls-certificate.js +0 -0
  179. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s016-sensitive-query-parameter.js +0 -0
  180. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s017-no-sql-injection.js +0 -0
  181. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s018-positive-input-validation.js +0 -0
  182. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s019-no-raw-user-input-in-email.js +0 -0
  183. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s020-no-eval-dynamic-execution.js +0 -0
  184. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s022-output-encoding.js +0 -0
  185. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s023-no-json-injection.js +0 -0
  186. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s025-server-side-input-validation.js +0 -0
  187. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s026-json-schema-validation.js +0 -0
  188. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s027-no-hardcoded-secrets.js +0 -0
  189. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s029-require-csrf-protection.js +0 -0
  190. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s030-no-directory-browsing.js +0 -0
  191. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s033-require-samesite-cookie.js +0 -0
  192. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s034-require-host-cookie-prefix.js +0 -0
  193. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s035-cookie-specific-path.js +0 -0
  194. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s036-no-unsafe-file-include.js +0 -0
  195. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s037-require-anti-cache-headers.js +0 -0
  196. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s038-no-version-disclosure.js +0 -0
  197. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s039-no-session-token-in-url.js +0 -0
  198. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s041-require-session-invalidate-on-logout.js +0 -0
  199. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s042-require-periodic-reauthentication.js +0 -0
  200. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s043-terminate-sessions-on-password-change.js +0 -0
  201. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s044-require-full-session-for-sensitive-operations.js +0 -0
  202. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s045-anti-automation-controls.js +0 -0
  203. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s046-secure-notification-on-auth-change.js +0 -0
  204. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s048-password-credential-recovery.js +0 -0
  205. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s050-session-token-weak-hash.js +0 -0
  206. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s052-secure-random-authentication-code.js +0 -0
  207. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s054-verification-default-account.js +0 -0
  208. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s057-utc-logging.js +0 -0
  209. /package/{config/typescript/security-rules → integrations/eslint/plugin/rules/security}/s058-no-ssrf.js +0 -0
  210. /package/rules/{C006_function_naming → common/C006_function_naming}/config.json +0 -0
  211. /package/rules/{C019_log_level_usage → common/C019_log_level_usage}/config.json +0 -0
  212. /package/rules/{C029_catch_block_logging → common/C029_catch_block_logging}/config.json +0 -0
  213. /package/rules/{C031_validation_separation → common/C031_validation_separation}/analyzer.js +0 -0
  214. /package/rules/{C031_validation_separation/README.md → docs/C031_validation_separation.md} +0 -0
@@ -0,0 +1,86 @@
1
+ const HeuristicEngine = require('./engines/heuristic-engine.js');
2
+
3
+ async function testRuleOnRealProjects(ruleId, ruleName) {
4
+ console.log(`\n🔍 Testing ${ruleId} - ${ruleName}`);
5
+ console.log('=' .repeat(50));
6
+
7
+ const engine = new HeuristicEngine();
8
+ await engine.initialize({ verbose: false });
9
+
10
+ // Test files from both BE and FE projects
11
+ const testFiles = [
12
+ // Backend files
13
+ 'examples/project-samples/replace-be/lambda/refpl-dev-cognito-custom-message-lambda/app.ts',
14
+ 'examples/project-samples/replace-be/lambda/refpl-dev-cognito-custom-message-lambda/common/utils.ts',
15
+ 'examples/project-samples/replace-be/lambda/refpl-dev-cognito-custom-message-lambda/common/mailTemplates.ts',
16
+
17
+ // Frontend files
18
+ 'examples/project-samples/replace-fe/.storybook/preview.tsx',
19
+ 'examples/project-samples/replace-fe/s055-simple.ts'
20
+ ];
21
+
22
+ let totalViolations = 0;
23
+
24
+ for (const file of testFiles) {
25
+ try {
26
+ const result = await engine.analyze([file], [{ id: ruleId }], { verbose: false });
27
+ const violations = result.results[0]?.violations || [];
28
+
29
+ if (violations.length > 0) {
30
+ console.log(`\n📁 ${file}:`);
31
+ console.log(` ${violations.length} violation(s) found`);
32
+ violations.forEach(v => {
33
+ console.log(` ⚠️ Line ${v.line}: ${v.message}`);
34
+ if (v.code) console.log(` Code: ${v.code.trim()}`);
35
+ });
36
+ } else {
37
+ console.log(`✅ ${file}: No violations`);
38
+ }
39
+
40
+ totalViolations += violations.length;
41
+ } catch (error) {
42
+ console.log(`❌ ${file}: Error - ${error.message}`);
43
+ }
44
+ }
45
+
46
+ console.log(`\n📊 Total violations for ${ruleId}: ${totalViolations}`);
47
+ return totalViolations;
48
+ }
49
+
50
+ async function main() {
51
+ console.log('🚀 Testing recently improved rules on real projects\n');
52
+
53
+ const rulesToTest = [
54
+ { id: 'S027', name: 'No Hardcoded Secrets' },
55
+ { id: 'S026', name: 'JSON Schema Validation' },
56
+ { id: 'C047', name: 'No Duplicate Retry Logic' },
57
+ { id: 'C013', name: 'No Dead Code' },
58
+ { id: 'C042', name: 'Boolean Name Prefix' }
59
+ ];
60
+
61
+ const results = {};
62
+
63
+ for (const rule of rulesToTest) {
64
+ try {
65
+ const violations = await testRuleOnRealProjects(rule.id, rule.name);
66
+ results[rule.id] = violations;
67
+ } catch (error) {
68
+ console.log(`❌ Failed to test ${rule.id}: ${error.message}`);
69
+ results[rule.id] = 'ERROR';
70
+ }
71
+ }
72
+
73
+ console.log('\n🎯 SUMMARY');
74
+ console.log('=' .repeat(50));
75
+ Object.entries(results).forEach(([ruleId, violations]) => {
76
+ if (violations === 'ERROR') {
77
+ console.log(`❌ ${ruleId}: Test failed`);
78
+ } else if (violations === 0) {
79
+ console.log(`✅ ${ruleId}: No violations (Good!)`);;
80
+ } else {
81
+ console.log(`⚠️ ${ruleId}: ${violations} violations (Review needed)`);
82
+ }
83
+ });
84
+ }
85
+
86
+ main().catch(console.error);
@@ -0,0 +1,285 @@
1
+ #!/bin/bash
2
+
3
+ # SunLint v1.0.5 Release Trigger Script
4
+ # This script helps trigger and monitor the GitHub Actions release workflow
5
+
6
+ set -e
7
+
8
+ echo "🚀 =========================================="
9
+ echo "☀️ SunLint v1.0.5 Release Trigger"
10
+ echo "🚀 =========================================="
11
+ echo ""
12
+
13
+ # Colors
14
+ RED='\033[0;31m'
15
+ GREEN='\033[0;32m'
16
+ YELLOW='\033[1;33m'
17
+ BLUE='\033[0;34m'
18
+ NC='\033[0m' # No Color
19
+
20
+ # Configuration
21
+ REPO="sun-asterisk/engineer-excellence"
22
+ WORKFLOW_FILE="release-sunlint.yml"
23
+ VERSION="1.0.5"
24
+ RELEASE_TYPE="both" # both, github-package, global-tarball
25
+
26
+ # Check if GitHub CLI is installed
27
+ if ! command -v gh &> /dev/null; then
28
+ echo -e "${RED}❌ GitHub CLI (gh) is required but not installed.${NC}"
29
+ echo "Install it from: https://cli.github.com/"
30
+ echo ""
31
+ echo "macOS: brew install gh"
32
+ echo "Ubuntu: sudo apt install gh"
33
+ exit 1
34
+ fi
35
+
36
+ # Check if user is authenticated
37
+ if ! gh auth status &> /dev/null; then
38
+ echo -e "${RED}❌ Not authenticated with GitHub CLI.${NC}"
39
+ echo "Please run: gh auth login"
40
+ exit 1
41
+ fi
42
+
43
+ echo -e "${GREEN}✅ GitHub CLI authenticated${NC}"
44
+ echo ""
45
+
46
+ # Function to run pre-release tests
47
+ run_pre_release_tests() {
48
+ echo -e "${BLUE}🧪 Running pre-release tests...${NC}"
49
+
50
+ if [ -f "scripts/pre-release-test.sh" ]; then
51
+ ./scripts/pre-release-test.sh
52
+ if [ $? -eq 0 ]; then
53
+ echo -e "${GREEN}✅ Pre-release tests passed!${NC}"
54
+ echo ""
55
+ return 0
56
+ else
57
+ echo -e "${RED}❌ Pre-release tests failed!${NC}"
58
+ echo ""
59
+ return 1
60
+ fi
61
+ else
62
+ echo -e "${YELLOW}⚠️ Pre-release test script not found, skipping...${NC}"
63
+ echo ""
64
+ return 0
65
+ fi
66
+ }
67
+
68
+ # Function to trigger GitHub Actions workflow
69
+ trigger_release_workflow() {
70
+ echo -e "${BLUE}🚀 Triggering GitHub Actions release workflow...${NC}"
71
+ echo ""
72
+ echo "Parameters:"
73
+ echo " Repository: $REPO"
74
+ echo " Workflow: $WORKFLOW_FILE"
75
+ echo " Version: $VERSION"
76
+ echo " Release Type: $RELEASE_TYPE"
77
+ echo ""
78
+
79
+ # Trigger the workflow
80
+ if gh workflow run "$WORKFLOW_FILE" \
81
+ --repo "$REPO" \
82
+ --field version="$VERSION" \
83
+ --field release_type="$RELEASE_TYPE"; then
84
+
85
+ echo -e "${GREEN}✅ Workflow triggered successfully!${NC}"
86
+ echo ""
87
+
88
+ # Wait a moment for the workflow to start
89
+ echo "⏳ Waiting for workflow to start..."
90
+ sleep 5
91
+
92
+ # Get the latest workflow run
93
+ echo -e "${BLUE}📋 Latest workflow runs:${NC}"
94
+ gh run list --repo "$REPO" --workflow="$WORKFLOW_FILE" --limit=3
95
+
96
+ echo ""
97
+ echo -e "${BLUE}🔗 Workflow monitoring links:${NC}"
98
+ echo "• Actions: https://github.com/$REPO/actions/workflows/release-sunlint.yml"
99
+ echo "• Releases: https://github.com/$REPO/releases"
100
+ echo "• Packages: https://github.com/$REPO/packages"
101
+
102
+ return 0
103
+ else
104
+ echo -e "${RED}❌ Failed to trigger workflow!${NC}"
105
+ return 1
106
+ fi
107
+ }
108
+
109
+ # Function to monitor workflow progress
110
+ monitor_workflow() {
111
+ echo ""
112
+ echo -e "${BLUE}👀 Monitoring workflow progress...${NC}"
113
+
114
+ # Get the latest run ID
115
+ RUN_ID=$(gh run list --repo "$REPO" --workflow="$WORKFLOW_FILE" --limit=1 --json databaseId --jq '.[0].databaseId')
116
+
117
+ if [ -n "$RUN_ID" ]; then
118
+ echo "Workflow Run ID: $RUN_ID"
119
+ echo ""
120
+
121
+ # Watch the workflow
122
+ echo "📺 Watching workflow (Ctrl+C to stop monitoring)..."
123
+ gh run watch "$RUN_ID" --repo "$REPO" --exit-status
124
+
125
+ # Check final status
126
+ STATUS=$(gh run view "$RUN_ID" --repo "$REPO" --json conclusion --jq '.conclusion')
127
+
128
+ if [ "$STATUS" = "success" ]; then
129
+ echo -e "${GREEN}🎉 Release workflow completed successfully!${NC}"
130
+ show_release_summary
131
+ else
132
+ echo -e "${RED}💥 Release workflow failed with status: $STATUS${NC}"
133
+ echo ""
134
+ echo "🔍 Check logs: gh run view $RUN_ID --repo $REPO --log"
135
+ fi
136
+ else
137
+ echo -e "${YELLOW}⚠️ Could not find workflow run to monitor${NC}"
138
+ fi
139
+ }
140
+
141
+ # Function to show release summary
142
+ show_release_summary() {
143
+ echo ""
144
+ echo "🎊 =========================================="
145
+ echo "🎉 SunLint v$VERSION Released Successfully!"
146
+ echo "🎊 =========================================="
147
+ echo ""
148
+
149
+ echo -e "${GREEN}📦 Installation Methods:${NC}"
150
+ echo ""
151
+ echo "1. GitHub Package Registry:"
152
+ echo " npm install -g @sun-asterisk/sunlint"
153
+ echo ""
154
+ echo "2. Direct GitHub Release:"
155
+ echo " npm install -g https://github.com/$REPO/releases/download/sunlint-v$VERSION/sunlint-$VERSION.tgz"
156
+ echo ""
157
+
158
+ echo -e "${BLUE}🔗 Release Links:${NC}"
159
+ echo "• Release Page: https://github.com/$REPO/releases/tag/sunlint-v$VERSION"
160
+ echo "• GitHub Package: https://github.com/$REPO/packages"
161
+ echo "• Documentation: https://github.com/$REPO/tree/main/coding-quality/extensions/sunlint"
162
+ echo ""
163
+
164
+ echo -e "${YELLOW}🧪 Test Installation:${NC}"
165
+ echo "npm install -g @sun-asterisk/sunlint && sunlint --version"
166
+ echo ""
167
+
168
+ echo -e "${GREEN}✨ Next Steps:${NC}"
169
+ echo "1. Test installation from both sources"
170
+ echo "2. Update internal documentation"
171
+ echo "3. Announce to development teams"
172
+ echo "4. Monitor adoption metrics"
173
+ }
174
+
175
+ # Main execution flow
176
+ main() {
177
+ echo -e "${YELLOW}🔍 Pre-flight checks...${NC}"
178
+ echo ""
179
+
180
+ # Check if we're in the right directory
181
+ if [ ! -f "cli.js" ] || [ ! -f "package.json" ]; then
182
+ echo -e "${RED}❌ Not in SunLint directory!${NC}"
183
+ echo "Please run this script from: coding-quality/extensions/sunlint/"
184
+ exit 1
185
+ fi
186
+
187
+ # Check current version in package.json
188
+ CURRENT_VERSION=$(node -e "console.log(require('./package.json').version)")
189
+ echo "Current package.json version: $CURRENT_VERSION"
190
+
191
+ if [ "$CURRENT_VERSION" != "$VERSION" ]; then
192
+ echo -e "${YELLOW}⚠️ Version mismatch! Updating package.json...${NC}"
193
+ npm version "$VERSION" --no-git-tag-version
194
+ echo -e "${GREEN}✅ Version updated to $VERSION${NC}"
195
+ fi
196
+ echo ""
197
+
198
+ # Run pre-release tests
199
+ if ! run_pre_release_tests; then
200
+ echo -e "${RED}💥 Pre-release tests failed! Aborting release.${NC}"
201
+ exit 1
202
+ fi
203
+
204
+ # Confirm release
205
+ echo -e "${YELLOW}⚠️ About to trigger release workflow for SunLint v$VERSION${NC}"
206
+ echo "This will:"
207
+ echo "• Run tests"
208
+ echo "• Build package"
209
+ echo "• Publish to GitHub Package Registry"
210
+ echo "• Create GitHub Release with tarball"
211
+ echo ""
212
+
213
+ read -p "🚀 Proceed with release? (y/N): " -n 1 -r
214
+ echo ""
215
+
216
+ if [[ $REPLY =~ ^[Yy]$ ]]; then
217
+ # Trigger the workflow
218
+ if trigger_release_workflow; then
219
+ # Ask if user wants to monitor
220
+ echo ""
221
+ read -p "👀 Monitor workflow progress? (Y/n): " -n 1 -r
222
+ echo ""
223
+
224
+ if [[ ! $REPLY =~ ^[Nn]$ ]]; then
225
+ monitor_workflow
226
+ else
227
+ echo -e "${BLUE}🔗 Monitor manually at:${NC}"
228
+ echo "https://github.com/$REPO/actions/workflows/release-sunlint.yml"
229
+ fi
230
+ else
231
+ echo -e "${RED}💥 Failed to trigger release!${NC}"
232
+ exit 1
233
+ fi
234
+ else
235
+ echo -e "${YELLOW}🛑 Release cancelled by user${NC}"
236
+ exit 0
237
+ fi
238
+ }
239
+
240
+ # Parse command line arguments
241
+ while [[ $# -gt 0 ]]; do
242
+ case $1 in
243
+ --version)
244
+ VERSION="$2"
245
+ shift 2
246
+ ;;
247
+ --type)
248
+ RELEASE_TYPE="$2"
249
+ shift 2
250
+ ;;
251
+ --skip-tests)
252
+ SKIP_TESTS=true
253
+ shift
254
+ ;;
255
+ --monitor-only)
256
+ monitor_workflow
257
+ exit 0
258
+ ;;
259
+ --help)
260
+ echo "Usage: $0 [options]"
261
+ echo ""
262
+ echo "Options:"
263
+ echo " --version VERSION Release version (default: $VERSION)"
264
+ echo " --type TYPE Release type: both|github-package|global-tarball (default: $RELEASE_TYPE)"
265
+ echo " --skip-tests Skip pre-release tests"
266
+ echo " --monitor-only Only monitor existing workflow"
267
+ echo " --help Show this help"
268
+ echo ""
269
+ echo "Examples:"
270
+ echo " $0 # Release v1.0.5 with all checks"
271
+ echo " $0 --version 1.0.6 # Release specific version"
272
+ echo " $0 --type github-package # Only GitHub Package Registry"
273
+ echo " $0 --monitor-only # Monitor existing workflow"
274
+ exit 0
275
+ ;;
276
+ *)
277
+ echo "Unknown option: $1"
278
+ echo "Use --help for usage information"
279
+ exit 1
280
+ ;;
281
+ esac
282
+ done
283
+
284
+ # Run main function
285
+ main
@@ -0,0 +1,148 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Validation script to ensure all rule test fixtures follow standardized structure
5
+ */
6
+
7
+ const fs = require('fs');
8
+ const path = require('path');
9
+
10
+ const RULES_DIR = 'examples/rule-test-fixtures/rules';
11
+
12
+ function validateRuleStructure() {
13
+ console.log('🔍 Validating Rule Test Fixtures Structure\n');
14
+
15
+ const rulesPath = path.resolve(__dirname, '..', RULES_DIR);
16
+ const ruleDirs = fs.readdirSync(rulesPath, { withFileTypes: true })
17
+ .filter(dirent => dirent.isDirectory())
18
+ .map(dirent => dirent.name)
19
+ .filter(name => !name.startsWith('.') && name !== 'README.md');
20
+
21
+ let allValid = true;
22
+ const results = [];
23
+
24
+ for (const ruleDir of ruleDirs) {
25
+ const rulePath = path.join(rulesPath, ruleDir);
26
+ const result = {
27
+ rule: ruleDir,
28
+ hasClean: false,
29
+ hasViolations: false,
30
+ cleanFiles: [],
31
+ violationFiles: [],
32
+ issues: []
33
+ };
34
+
35
+ // Check for clean directory
36
+ const cleanPath = path.join(rulePath, 'clean');
37
+ if (fs.existsSync(cleanPath)) {
38
+ result.hasClean = true;
39
+ result.cleanFiles = fs.readdirSync(cleanPath).filter(f => !f.startsWith('.'));
40
+ } else {
41
+ result.issues.push('Missing clean/ directory');
42
+ allValid = false;
43
+ }
44
+
45
+ // Check for violations directory
46
+ const violationsPath = path.join(rulePath, 'violations');
47
+ if (fs.existsSync(violationsPath)) {
48
+ result.hasViolations = true;
49
+ result.violationFiles = fs.readdirSync(violationsPath).filter(f => !f.startsWith('.'));
50
+ } else {
51
+ result.issues.push('Missing violations/ directory');
52
+ allValid = false;
53
+ }
54
+
55
+ // Check for loose files (should be moved to clean/violations)
56
+ const allFiles = fs.readdirSync(rulePath, { withFileTypes: true });
57
+ const looseFiles = allFiles
58
+ .filter(dirent => dirent.isFile() && !dirent.name.startsWith('.') && dirent.name !== 'README.md')
59
+ .map(dirent => dirent.name);
60
+
61
+ if (looseFiles.length > 0) {
62
+ result.issues.push(`Loose files found: ${looseFiles.join(', ')}`);
63
+ allValid = false;
64
+ }
65
+
66
+ results.push(result);
67
+ }
68
+
69
+ // Display results
70
+ console.log(`📊 Validation Results for ${results.length} rules:\n`);
71
+
72
+ for (const result of results) {
73
+ const status = result.issues.length === 0 ? '✅' : '❌';
74
+ console.log(`${status} ${result.rule}`);
75
+
76
+ if (result.hasClean) {
77
+ console.log(` ✅ clean/ (${result.cleanFiles.length} files)`);
78
+ } else {
79
+ console.log(` ❌ clean/ directory missing`);
80
+ }
81
+
82
+ if (result.hasViolations) {
83
+ console.log(` ✅ violations/ (${result.violationFiles.length} files)`);
84
+ } else {
85
+ console.log(` ❌ violations/ directory missing`);
86
+ }
87
+
88
+ if (result.issues.length > 0) {
89
+ result.issues.forEach(issue => console.log(` ⚠️ ${issue}`));
90
+ }
91
+
92
+ console.log('');
93
+ }
94
+
95
+ // Summary
96
+ const validRules = results.filter(r => r.issues.length === 0).length;
97
+ const invalidRules = results.length - validRules;
98
+
99
+ console.log('📈 Summary:');
100
+ console.log(` ✅ Valid rules: ${validRules}`);
101
+ console.log(` ❌ Invalid rules: ${invalidRules}`);
102
+ console.log(` 📁 Total rules: ${results.length}`);
103
+
104
+ if (allValid) {
105
+ console.log('\n🎉 All rules follow standardized structure!');
106
+ } else {
107
+ console.log('\n⚠️ Some rules need structure fixes.');
108
+ }
109
+
110
+ return allValid;
111
+ }
112
+
113
+ // Create missing clean folders for empty rules
114
+ function createMissingFolders() {
115
+ console.log('\n🛠️ Creating missing folders...\n');
116
+
117
+ const rulesPath = path.resolve(__dirname, '..', RULES_DIR);
118
+ const ruleDirs = fs.readdirSync(rulesPath, { withFileTypes: true })
119
+ .filter(dirent => dirent.isDirectory())
120
+ .map(dirent => dirent.name)
121
+ .filter(name => !name.startsWith('.') && name !== 'README.md');
122
+
123
+ for (const ruleDir of ruleDirs) {
124
+ const rulePath = path.join(rulesPath, ruleDir);
125
+
126
+ // Create clean folder if missing
127
+ const cleanPath = path.join(rulePath, 'clean');
128
+ if (!fs.existsSync(cleanPath)) {
129
+ fs.mkdirSync(cleanPath, { recursive: true });
130
+ console.log(`✅ Created: ${ruleDir}/clean/`);
131
+ }
132
+
133
+ // Create violations folder if missing
134
+ const violationsPath = path.join(rulePath, 'violations');
135
+ if (!fs.existsSync(violationsPath)) {
136
+ fs.mkdirSync(violationsPath, { recursive: true });
137
+ console.log(`✅ Created: ${ruleDir}/violations/`);
138
+ }
139
+ }
140
+ }
141
+
142
+ if (require.main === module) {
143
+ createMissingFolders();
144
+ const isValid = validateRuleStructure();
145
+ process.exit(isValid ? 0 : 1);
146
+ }
147
+
148
+ module.exports = { validateRuleStructure, createMissingFolders };
@@ -0,0 +1,82 @@
1
+ #!/bin/bash
2
+
3
+ # SunLint v1.0.4 Quick Verification Script
4
+ # Following Rule C005: Single responsibility - verify installation only
5
+
6
+ echo "🧪 SunLint v1.0.4 Quick Verification"
7
+ echo "=================================="
8
+
9
+ # Check if sunlint is installed
10
+ if ! command -v sunlint &> /dev/null; then
11
+ echo "❌ SunLint not found in PATH"
12
+ echo "💡 Install with: npm install -g ./sun-sunlint-1.0.4.tgz"
13
+ exit 1
14
+ fi
15
+
16
+ # Check version
17
+ echo "📋 Checking version..."
18
+ VERSION=$(sunlint --version 2>/dev/null | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "unknown")
19
+ if [ "$VERSION" = "1.0.4" ]; then
20
+ echo "✅ Version: $VERSION"
21
+ else
22
+ echo "❌ Expected version 1.0.4, got: $VERSION"
23
+ exit 1
24
+ fi
25
+
26
+ # Create test file
27
+ echo "📁 Creating test file..."
28
+ TEST_FILE="/tmp/sunlint-test-security.ts"
29
+ cat > "$TEST_FILE" << 'EOF'
30
+ function doAdminTask() {}
31
+ function isAuthenticated(req: any): boolean { return true; }
32
+
33
+ function doPost(request: any, response: any) {
34
+ const origin = request.getHeader("Origin");
35
+ if (origin === "https://admin.example.com") {
36
+ doAdminTask();
37
+ }
38
+ }
39
+ EOF
40
+
41
+ # Test security rules
42
+ echo "🔒 Testing security rules..."
43
+ SECURITY_OUTPUT=$(sunlint --security --typescript --input="$TEST_FILE" 2>&1)
44
+ if echo "$SECURITY_OUTPUT" | grep -q "S005"; then
45
+ echo "✅ Security rules working (S005 detected)"
46
+ else
47
+ echo "❌ Security rules not working"
48
+ echo "Output: $SECURITY_OUTPUT"
49
+ rm -f "$TEST_FILE"
50
+ exit 1
51
+ fi
52
+
53
+ # Test quality rules
54
+ echo "✨ Testing quality rules..."
55
+ QUALITY_OUTPUT=$(sunlint --quality --typescript --input="$TEST_FILE" 2>&1)
56
+ if echo "$QUALITY_OUTPUT" | grep -q "No violations found"; then
57
+ echo "✅ Quality rules working"
58
+ else
59
+ echo "⚠️ Quality rules output: $QUALITY_OUTPUT"
60
+ fi
61
+
62
+ # Test all rules
63
+ echo "🎯 Testing all rules..."
64
+ ALL_OUTPUT=$(sunlint --all --typescript --input="$TEST_FILE" 2>&1)
65
+ if echo "$ALL_OUTPUT" | grep -q "44 rules"; then
66
+ echo "✅ All rules loaded (44 total)"
67
+ else
68
+ echo "⚠️ All rules output: $ALL_OUTPUT"
69
+ fi
70
+
71
+ # Cleanup
72
+ rm -f "$TEST_FILE"
73
+
74
+ echo ""
75
+ echo "🎉 SunLint v1.0.4 verification completed!"
76
+ echo ""
77
+ echo "📖 Usage examples:"
78
+ echo " sunlint --security --typescript --input=src/"
79
+ echo " sunlint --quality --typescript --input=src/"
80
+ echo " sunlint --all --typescript --input=src/"
81
+ echo ""
82
+ echo "✅ Ready to secure your codebase!"