@sun-asterisk/sunlint
Version:
☀️ SunLint - Multi-language static analysis tool for code quality and security | Sun* Engineering Standards
410 lines (315 loc) • 10.9 kB
Markdown
# Quality Scoring & Summary Report Guide
## Overview
SunLint includes a comprehensive quality scoring system and summary report generation feature designed for CI/CD integration and management dashboards.
## Features
### 1. Quality Scoring System
The quality score is calculated based on multiple factors:
```javascript
Score Formula: 100 - (errorCount × 5 + warningCount × 1) × (1000 / LOC) + (rulesChecked × 0.5)
```
**Scoring Components:**
- **Base Score**: Starts at 100 (perfect quality)
- **Error Penalty**: -5 points per error
- **Warning Penalty**: -1 point per warning
- **LOC Normalization**: Violations are normalized per 1000 lines of code
- **Rule Bonus**: +0.5 points per rule checked (max 10 points)
- **Final Range**: 0-100
**Grade Scale:**
- **A+**: 95-100
- **A**: 90-94
- **B+**: 85-89
- **B**: 80-84
- **C+**: 75-79
- **C**: 70-74
- **D**: 60-69
- **F**: Below 60
### 2. Summary Report Format
The summary report is generated in JSON format, designed for easy integration with CI/CD pipelines and management dashboards.
**Example Output:**
```json
{
"metadata": {
"generated_at": "2025-10-07T03:48:00.636Z",
"tool": "SunLint",
"version": "1.3.9",
"analysis_duration_ms": 390
},
"repository": {
"repository_url": "https://github.com/org/repo",
"branch": "main",
"commit_hash": "abc123"
},
"quality": {
"score": 98.9,
"grade": "A+",
"metrics": {
"errors": 0,
"warnings": 520,
"rulesChecked": 1,
"linesOfCode": 319709,
"violationsPerKLOC": 1.6
}
},
"violations": {
"total": 520,
"by_severity": {
"errors": 0,
"warnings": 520
},
"by_rule": [
{
"rule_code": "C065",
"count": 520,
"severity": "warning"
}
]
},
"analysis": {
"files_analyzed": 1000,
"rules_checked": 1,
"lines_of_code": 319709
}
}
```
## Usage
### Basic Usage
```bash
# Generate summary report only
node cli.js --input=src --rule=C065 --output-summary=summary.json
# Generate both detailed report and summary report
node cli.js --input=src --rule=C065 --output=report.txt --output-summary=summary.json
```
### CI/CD Integration
#### GitHub Actions Example
```yaml
name: Code Quality Check
on:
pull_request:
branches: [ main ]
push:
branches: [ main ]
jobs:
quality-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: npm install
- name: Run SunLint Analysis
run: |
node cli.js \
--input=src \
--rule=C001,C005,C015,C065 \
--output-summary=quality-report.json
env:
GITHUB_REPOSITORY: ${{ github.repository }}
GITHUB_REF_NAME: ${{ github.ref_name }}
GITHUB_SHA: ${{ github.sha }}
- name: Upload Quality Report
uses: actions/upload-artifact@v3
with:
name: quality-report
path: quality-report.json
- name: Post to Dashboard
run: |
curl -X POST https://your-dashboard.com/api/quality \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${{ secrets.DASHBOARD_TOKEN }}" \
-d @quality-report.json
```
### Environment Variables
The summary report automatically detects and uses Git information from environment variables (commonly available in CI/CD):
| Variable | Description | Source | Fallback |
|----------|-------------|--------|----------|
| `GITHUB_REPOSITORY` | Repository name (e.g., `owner/repo`) | GitHub Actions | Git remote URL |
| `GITHUB_REF_NAME` | Branch or tag name | GitHub Actions | `git rev-parse --abbrev-ref HEAD` |
| `GITHUB_SHA` | Commit hash | GitHub Actions | `git rev-parse HEAD` |
| `GITHUB_EVENT_PATH` | Path to event payload JSON | GitHub Actions | - |
| `GITHUB_EVENT_HEAD_COMMIT_MESSAGE` | Commit message | GitHub Actions | `git log -1 --pretty=%B` |
| `GITHUB_EVENT_HEAD_COMMIT_AUTHOR_EMAIL` | Author email | GitHub Actions | `git log -1 --pretty=%ae` |
| `GITHUB_EVENT_HEAD_COMMIT_AUTHOR_NAME` | Author name | GitHub Actions | `git log -1 --pretty=%an` |
**Additional Fields Auto-Detected:**
- **`repository_name`**: Extracted from repository URL
- **`project_path`**: Relative path from repo root (for mono-repo support)
- **`commit_message`**: From git log or GitHub event
- **`author_email`**: From git log or GitHub event
- **`author_name`**: From git log or GitHub event
- **`pr_number`**: Extracted from commit message (e.g., "#123") or branch name (e.g., "pr-123")
If environment variables are not available, the tool will automatically detect all Git information from the local repository.
## CLI Options
### `--output-summary <file>`
Generate a summary report in JSON format suitable for CI/CD and management dashboards.
**Differences from `--output`:**
| Feature | `--output` | `--output-summary` |
|---------|-----------|-------------------|
| Format | Text/JSON (ESLint-compatible) | JSON (Custom format) |
| Detail Level | Full violation details | Summary only |
| File Size | Large (includes all details) | Small (summary only) |
| Purpose | Detailed debugging | CI/CD integration |
| Includes Score | ❌ No | ✅ Yes |
| Includes LOC | ❌ No | ✅ Yes |
| Git Info | ❌ No | ✅ Yes |
| Violation Count by Rule | ❌ No | ✅ Yes |
**Example:**
```bash
# Detailed report: Shows every violation with line numbers and messages
node cli.js --input=src --rule=C065 --output=detailed-report.txt
# Summary report: Shows total count per rule, score, and metrics
node cli.js --input=src --rule=C065 --output-summary=summary.json
# Both: Get detailed report for debugging + summary for dashboard
node cli.js --input=src --rule=C065 \
--output=detailed-report.txt \
--output-summary=summary.json
```
## Integration Examples
### 1. Send to Management Dashboard
```javascript
const fs = require('fs');
const axios = require('axios');
const report = JSON.parse(fs.readFileSync('summary.json', 'utf8'));
await axios.post('https://dashboard.company.com/api/quality', {
project: 'my-project',
...report
}, {
headers: {
'Authorization': `Bearer ${process.env.DASHBOARD_TOKEN}`
}
});
```
### 2. Slack Notification
```javascript
const fs = require('fs');
const axios = require('axios');
const report = JSON.parse(fs.readFileSync('summary.json', 'utf8'));
const { quality, violations, analysis } = report;
const message = {
text: `Code Quality Report: ${quality.grade} (${quality.score})`,
blocks: [
{
type: "section",
text: {
type: "mrkdwn",
text: `*Code Quality Analysis*\n` +
`Score: *${quality.score}* (${quality.grade})\n` +
`Violations: ${violations.total} (${violations.by_severity.errors} errors, ${violations.by_severity.warnings} warnings)\n` +
`Files: ${analysis.files_analyzed} | LOC: ${analysis.lines_of_code.toLocaleString()}`
}
}
]
};
await axios.post(process.env.SLACK_WEBHOOK_URL, message);
```
### 3. Quality Gate in CI/CD
```bash
#!/bin/bash
# Run analysis
node cli.js --input=src --rule=C001,C005,C015,C065 --output-summary=quality.json
# Extract score
SCORE=$(jq -r '.quality.score' quality.json)
# Set minimum score threshold
MIN_SCORE=80
# Check if score meets threshold
if (( $(echo "$SCORE < $MIN_SCORE" | bc -l) )); then
echo "❌ Quality score $SCORE is below threshold $MIN_SCORE"
exit 1
else
echo "✅ Quality score $SCORE meets threshold"
exit 0
fi
```
## Best Practices
### 1. Rule Selection
Choose rules appropriate for your quality goals:
```bash
# Security focus
node cli.js --input=src --rule=S001,S004,S010 --output-summary=security.json
# Code organization focus
node cli.js --input=src --rule=C001,C005,C006,C015 --output-summary=organization.json
# Testing focus
node cli.js --input=src --rule=C065,C066 --output-summary=testing.json
# Comprehensive check (slower)
node cli.js --input=src --rule=security,cleancode --output-summary=full.json
```
### 2. Performance Optimization
For large projects:
```bash
# Analyze only changed files (PR mode)
node cli.js --input=src --rule=C001,C005 --changed-files --output-summary=pr-quality.json
# Set file limits for faster analysis
node cli.js --input=src --rule=C001,C005 --max-files=500 --output-summary=quick-check.json
```
### 3. Trending Analysis
Track quality over time:
```javascript
const fs = require('fs');
// Save with timestamp
const report = JSON.parse(fs.readFileSync('summary.json', 'utf8'));
const timestamp = new Date().toISOString();
// Store in database or time-series storage
await db.collection('quality_reports').insertOne({
...report,
timestamp
});
// Query trends
const last30Days = await db.collection('quality_reports')
.find({
timestamp: { $gte: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000) }
})
.sort({ timestamp: 1 })
.toArray();
// Calculate trend
const scores = last30Days.map(r => r.quality.score);
const trend = scores[scores.length - 1] - scores[0];
console.log(`Quality trend (30 days): ${trend > 0 ? '+' : ''}${trend.toFixed(1)}`);
```
## Scoring Interpretation
### Score Ranges
- **95-100 (A+)**: Excellent code quality with minimal violations
- **90-94 (A)**: Very good quality, minor improvements possible
- **85-89 (B+)**: Good quality with some areas for improvement
- **80-84 (B)**: Acceptable quality, several improvements recommended
- **75-79 (C+)**: Below average, significant improvements needed
- **70-74 (C)**: Poor quality, requires immediate attention
- **60-69 (D)**: Very poor quality, major refactoring needed
- **0-59 (F)**: Critical quality issues
### Metrics Understanding
**Violations per KLOC (Violations per 1000 Lines of Code)**
This metric normalizes violations by code size:
- **< 1**: Excellent
- **1-3**: Good
- **3-5**: Fair
- **5-10**: Poor
- **> 10**: Critical
## Troubleshooting
### LOC Calculation Issues
If LOC is 0 or incorrect:
```bash
# Ensure input path is correct
node cli.js --input=./src --rule=C065 --output-summary=summary.json
# For multiple paths
node cli.js --input=./src,./lib --rule=C065 --output-summary=summary.json
```
### Git Information Not Detected
In CI/CD, ensure environment variables are set:
```yaml
env:
GITHUB_REPOSITORY: ${{ github.repository }}
GITHUB_REF_NAME: ${{ github.ref_name }}
GITHUB_SHA: ${{ github.sha }}
```
For local development:
```bash
# Check if git is available
git rev-parse --git-dir
# Run from repository root
cd /path/to/repo
node /path/to/sunlint/cli.js --input=src --output-summary=summary.json
```
## See Also
- [Configuration Guide](CONFIGURATION.md)
- [CI/CD Integration Guide](CI-CD-GUIDE.md)
- [Command Examples](COMMAND-EXAMPLES.md)