@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.
- package/.sunlint.json +35 -0
- package/CHANGELOG.md +30 -3
- package/CONTRIBUTING.md +235 -0
- package/PROJECT_STRUCTURE.md +60 -0
- package/README.md +73 -52
- 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} +22 -0
- 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 +147 -0
- package/core/ast-modules/parsers/eslint-ts-parser.js +106 -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/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/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/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/HEURISTIC_VS_AI.md +113 -0
- package/docs/README.md +32 -0
- package/docs/RELEASE_GUIDE.md +230 -0
- package/engines/eslint-engine.js +601 -0
- package/engines/heuristic-engine.js +860 -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/test-c041-rule.js +87 -0
- package/integrations/eslint/tsconfig.json +27 -0
- package/package.json +29 -16
- 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,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!"
|