# SonarQube Analysis Analyze SonarCloud quality issues for a specific PR. Generates comprehensive report with metrics, top violators, and action plan. **Core principle:** Analysis-only = no code changes, pure insight. ## Process 1. **Verify Token**: Check `$SONARQUBE_TOKEN` environment variable 2. **Fetch Issues**: Call SonarCloud API for PR issues 3. **Parse Data**: Group by severity, type, file, rule 4. **Generate Report**: Structured output with action plan 5. **Cleanup**: Remove temporary files ## Prerequisites ### Environment Variable ```bash # Set SonarQube token (add to ~/.bashrc or ~/.zshrc) export SONARQUBE_TOKEN="your_token_here" # Verify token is set echo $SONARQUBE_TOKEN ``` **To get token:** 1. Go to SonarCloud โ†’ My Account โ†’ Security 2. Generate new token 3. Copy and export as environment variable ### Project Configuration Configure your SonarCloud project details: ```bash # Add to project's CLAUDE.md or as environment variables SONAR_ORGANIZATION="your-org-name" SONAR_PROJECT_KEY="your-org_your-project" SONAR_BASE_URL="https://sonarcloud.io/api" ``` **If not set:** Ask user to provide organization and project key. ## Fetch Issues **Important:** Direct curl with `-u "$SONARQUBE_TOKEN:"` fails in zsh due to authentication parsing. Use bash script wrapper: ```bash # Create temporary bash script to handle authentication cat > /tmp/fetch_sonar.sh << 'SCRIPT' #!/bin/bash curl -s -u "${SONARQUBE_TOKEN}:" \ "https://sonarcloud.io/api/issues/search?componentKeys=${SONAR_PROJECT_KEY}&pullRequest=$1&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true&ps=500" SCRIPT chmod +x /tmp/fetch_sonar.sh /tmp/fetch_sonar.sh $PR_NUMBER > /tmp/sonar_pr_$PR_NUMBER.json ``` **API Parameters:** - `componentKeys`: Your project key - `pullRequest`: PR number - `issueStatuses`: OPEN,CONFIRMED (exclude resolved) - `sinceLeakPeriod`: Only new issues in this PR - `ps`: Page size (max 500) ## Analysis Script Create Node.js analysis script at `/tmp/sonar_analyze.js`: ```javascript const fs = require('fs'); const prNumber = process.argv[2]; const data = JSON.parse(fs.readFileSync(`/tmp/sonar_pr_${prNumber}.json`, 'utf8')); const issues = data.issues || []; // Group by severity const bySeverity = issues.reduce((acc, i) => { acc[i.severity] = (acc[i.severity] || 0) + 1; return acc; }, {}); // Group by type const byType = issues.reduce((acc, i) => { acc[i.type] = (acc[i.type] || 0) + 1; return acc; }, {}); // Group by file const byFile = issues.reduce((acc, i) => { const file = i.component.split(':')[1] || i.component; acc[file] = (acc[file] || 0) + 1; return acc; }, {}); // Group by rule const byRule = issues.reduce((acc, i) => { if (!acc[i.rule]) { acc[i.rule] = { count: 0, severity: i.severity, message: i.message }; } acc[i.rule].count++; return acc; }, {}); // Output structured data console.log(JSON.stringify({ total: data.total, bySeverity, byType, topFiles: Object.entries(byFile) .sort((a, b) => b[1] - a[1]) .slice(0, 10), topRules: Object.entries(byRule) .map(([rule, d]) => ({ rule, ...d })) .sort((a, b) => b.count - a.count) .slice(0, 5) }, null, 2)); ``` **Run analysis:** ```bash node /tmp/sonar_analyze.js $PR_NUMBER > /tmp/sonar_analysis_$PR_NUMBER.json ``` ## Report Format Generate formatted report from analysis: ``` ๐Ÿ“Š SonarCloud Analysis - PR #XXX โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” ๐Ÿ“ˆ EXECUTIVE SUMMARY โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Total Issues: {TOTAL} By Severity: ๐Ÿ”ด Blocker/Critical: {COUNT} ({PERCENTAGE}%) ๐ŸŸก Major: {COUNT} ({PERCENTAGE}%) ๐Ÿ”ต Minor/Info: {COUNT} ({PERCENTAGE}%) By Type: ๐Ÿ› Bugs: {COUNT} ๐Ÿ›ก๏ธ Vulnerabilities: {COUNT} ๐Ÿงน Code Smells: {COUNT} โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” ๐Ÿ“‚ TOP 10 FILES WITH ISSUES โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” 1. src/components/UserProfile.tsx - 8 issues 2. src/services/auth.service.ts - 5 issues 3. src/utils/validation.ts - 4 issues ... โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” โš ๏ธ TOP 5 VIOLATED RULES โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” 1. typescript:S1854 (MAJOR) - 12 occurrences "Dead stores should be removed" 2. typescript:S3776 (CRITICAL) - 8 occurrences "Cognitive Complexity of functions should not be too high" 3. typescript:S1186 (MINOR) - 6 occurrences "Functions should not be empty" ... โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” โœ… ACTION PLAN โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” Priority 1 - CRITICAL/BLOCKER ({COUNT} issues): โ€ข Fix immediately before merge โ€ข Focus on: {TOP_FILES} Priority 2 - MAJOR ({COUNT} issues): โ€ข Address in this PR if possible โ€ข Consider technical debt ticket if extensive Priority 3 - MINOR/INFO ({COUNT} issues): โ€ข Can be addressed in follow-up PR โ€ข Add to backlog for refactoring sprint โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” ๐Ÿ”— LINKS โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” View in SonarCloud: https://sonarcloud.io/project/pull_requests_list?id={PROJECT_KEY}&pullRequest={PR_NUMBER} ``` ## Severity Mapping | SonarCloud | Symbol | Priority | Action | |------------|--------|----------|--------| | BLOCKER | ๐Ÿ”ด | P0 | Fix immediately | | CRITICAL | ๐Ÿ”ด | P0 | Fix immediately | | MAJOR | ๐ŸŸก | P1 | Fix in this PR | | MINOR | ๐Ÿ”ต | P2 | Consider for follow-up | | INFO | ๐Ÿ”ต | P3 | Optional improvement | ## Issue Types | Type | Symbol | Description | |------|--------|-------------| | BUG | ๐Ÿ› | Code that is demonstrably wrong | | VULNERABILITY | ๐Ÿ›ก๏ธ | Security issues | | CODE_SMELL | ๐Ÿงน | Maintainability issue | | SECURITY_HOTSPOT | ๐Ÿ”’ | Security-sensitive code to review | ## Cleanup Always clean up temporary files after execution: ```bash rm -f /tmp/fetch_sonar.sh rm -f /tmp/sonar_pr_$PR_NUMBER.json rm -f /tmp/sonar_analyze.js rm -f /tmp/sonar_analysis_$PR_NUMBER.json ``` ## Error Handling | Error | Cause | Action | |-------|-------|--------| | Token not set | `$SONARQUBE_TOKEN` missing | Ask user to export token | | 401 Unauthorized | Invalid or expired token | Request new token from SonarCloud | | 404 Not Found | PR doesn't exist in SonarCloud | Verify PR number and project key | | Empty response | No issues found | Report clean PR, congratulate team | | >500 issues | Pagination limit reached | Warn about incomplete data, suggest filtering | | Network error | API unreachable | Check internet connection, retry | ## Configuration Options ### Project-Level Configuration Create `.sonarcloud.properties` or add to `CLAUDE.md`: ```properties # SonarCloud Configuration SONAR_ORGANIZATION=your-org SONAR_PROJECT_KEY=your-org_your-project SONAR_EXCLUSIONS=**/*.test.ts,**/*.spec.ts,**/migrations/** SONAR_COVERAGE_EXCLUSIONS=**/*.test.ts,src/test/** ``` ### API Rate Limits SonarCloud API limits: - Free tier: 10,000 requests/day - Paid tier: Unlimited **Tip:** Cache results for repeated queries to same PR. ## Integration Examples ### GitHub Actions ```yaml - name: SonarQube Analysis run: | export SONARQUBE_TOKEN=${{ secrets.SONAR_TOKEN }} export SONAR_PROJECT_KEY="${{ secrets.SONAR_PROJECT }}" claude -p "/sonarqube ${{ github.event.pull_request.number }}" ``` ### Pre-merge Hook Add to `.claude/hooks/pre-merge.sh`: ```bash #!/bin/bash PR_NUMBER=$(gh pr view --json number -q .number) claude -p "/sonarqube $PR_NUMBER" ``` ## Red Flags - NEVER Do **Never:** - โŒ Modify code or auto-fix issues (analysis-only command) - โŒ Skip token verification (security risk) - โŒ Leave temp files in `/tmp` (cleanup required) - โŒ Commit SonarQube token to repository (use env vars) - โŒ Run without checking token expiration **Always:** - โœ… Generate structured, actionable report - โœ… Clean up after execution - โœ… Handle API errors gracefully - โœ… Verify token is valid before API calls - โœ… Parse and present data clearly ## Advanced Usage ### Custom Filters ```bash # Only show critical/blocker issues /sonarqube 123 --severity BLOCKER,CRITICAL # Only show bugs and vulnerabilities /sonarqube 123 --types BUG,VULNERABILITY # Specific file pattern /sonarqube 123 --files "src/services/**" ``` ### Multiple PRs ```bash # Compare issues across PRs /sonarqube 123,124,125 --compare ``` ## Troubleshooting ### Issue: "curl: (22) The requested URL returned error: 401" **Cause:** Invalid or missing token **Fix:** ```bash # Regenerate token in SonarCloud # Export new token export SONARQUBE_TOKEN="new_token_here" ``` ### Issue: "Empty response or no issues" **Cause:** Analysis not yet complete or PR not analyzed **Fix:** Wait for SonarCloud analysis to complete (~2-5 minutes after PR creation) ### Issue: "componentKeys not found" **Cause:** Wrong project key **Fix:** Verify project key in SonarCloud URL: ``` https://sonarcloud.io/project/overview?id=YOUR_PROJECT_KEY ``` ## Usage Examples ```bash # Basic usage /sonarqube 170 # With PR prefix /sonarqube PR #234 # Using PR URL /sonarqube https://github.com/org/repo/pull/170 # Custom severity filter (if implemented) /sonarqube 170 --critical-only ``` PR Number: $ARGUMENTS