SonarQube
DevOps Tool
SonarQube
Overview
SonarQube is a continuous code quality management platform that uses static analysis to detect bugs, vulnerabilities, and code smells, providing technical debt visualization and automated quality checks through quality gates. Supporting 30+ programming languages with AI-generated code quality assurance capabilities, it's an industry-standard tool that integrates with DevOps pipelines to achieve enterprise-level code quality management and security enhancement.
Details
SonarQube is an enterprise code quality management platform developed by SonarSource, established as the industry standard for static code analysis since its release in 2007. The 2025 version of SonarQube Server 2025.3 introduces AI Code Assurance functionality, enabling automated review and quality checking of AI-generated code.
Key Features
- Comprehensive Static Analysis: Support for 30+ languages, frameworks, and IaC platforms
- AI Code Assurance: Automated quality assurance and security checking for AI-generated code
- Security Enhancement: Comprehensive secret detection and security vulnerability analysis
- Quality Gates: Prevention of production deployment for code that doesn't meet quality standards
- Technical Debt Management: Visualization of code debt and improvement prioritization
- CI/CD Integration: Integration with GitHub Actions, GitLab CI/CD, Azure Pipelines, etc.
- IDE Integration: Real-time code review through development-time quality checks
- Compliance Support: Adherence to standards like NIST SSDF, OWASP, CWE, STIG, CASA
- Multi-Deployment: Support for on-premises, cloud, Docker, and Kubernetes
Provides integrated management of code quality metrics (bugs, vulnerabilities, code smells, duplication, coverage, complexity) to support continuous quality improvement.
Pros and Cons
Pros
- Centralized enterprise-level comprehensive code quality management
- AI-generated code quality assurance addresses modern development environments
- 30+ language support enables unified quality management for multilingual projects
- Automatic quality standard enforcement through quality gates ensures production quality
- Technical debt visualization enables planned refactoring
- Automated quality checks in DevOps pipelines through CI/CD integration
- Security enhancement through vulnerability and secret detection
- Compliance-ready quality management meeting regulatory requirements
- Real-time quality feedback during development through IDE integration
- Rich metrics and reporting provide numerical basis for quality improvement
Cons
- Commercial license costs for enterprise features (expensive for large organizations)
- Complex initial setup and high learning curve
- Long analysis times for large projects
- High server resource requirements (CPU, memory, storage)
- Feature limitations in Community Edition (branch analysis, security features, etc.)
- Complexity of rule adjustment and customization
- Operational burden from massive warnings when applying to legacy code
- Time required for quality culture adoption within development teams
- Risk of reduced development speed due to excessive quality enforcement
Reference Links
- SonarQube Official Site
- SonarQube Official Documentation
- SonarQube GitHub Repository
- SonarQube Community
- SonarLint IDE Extension
- SonarCloud (Cloud Version)
Code Examples
Installation and Setup
Docker Compose Configuration
# docker-compose.yml
version: "3.8"
services:
sonarqube:
image: sonarqube:10.8.1-community
container_name: sonarqube
depends_on:
- sonarqube-db
environment:
SONAR_JDBC_URL: jdbc:postgresql://sonarqube-db:5432/sonar
SONAR_JDBC_USERNAME: sonar
SONAR_JDBC_PASSWORD: sonar
volumes:
- sonarqube_data:/opt/sonarqube/data
- sonarqube_extensions:/opt/sonarqube/extensions
- sonarqube_logs:/opt/sonarqube/logs
ports:
- "9000:9000"
ulimits:
nofile:
soft: 65536
hard: 65536
nproc: 4096
sonarqube-db:
image: postgres:16-alpine
container_name: sonarqube-db
environment:
POSTGRES_USER: sonar
POSTGRES_PASSWORD: sonar
POSTGRES_DB: sonar
volumes:
- postgresql_data:/var/lib/postgresql/data
volumes:
sonarqube_data:
sonarqube_extensions:
sonarqube_logs:
postgresql_data:
Startup and Access
# Start with Docker Compose
docker-compose up -d
# Check logs
docker-compose logs -f sonarqube
# Verify access
curl http://localhost:9000/api/system/health
# Initial access
# URL: http://localhost:9000
# Initial login: admin / admin
# Password change required on first login
Project Analysis Configuration
sonar-project.properties Configuration
# sonar-project.properties - Basic configuration
sonar.projectKey=my-project
sonar.projectName=My Project
sonar.projectVersion=1.0
sonar.sourceEncoding=UTF-8
# Source code configuration
sonar.sources=src
sonar.tests=tests
sonar.exclusions=**/node_modules/**,**/dist/**,**/*.min.js
sonar.test.exclusions=**/node_modules/**
# JavaScript/TypeScript configuration
sonar.javascript.lcov.reportPaths=coverage/lcov.info
sonar.typescript.lcov.reportPaths=coverage/lcov.info
# Java configuration
sonar.java.source=17
sonar.java.target=17
sonar.java.binaries=target/classes
sonar.java.test.binaries=target/test-classes
sonar.junit.reportPaths=target/surefire-reports
# Python configuration
sonar.python.coverage.reportPaths=coverage.xml
sonar.python.xunit.reportPaths=test-results.xml
# C# configuration
sonar.cs.nunit.reportsPaths=TestResults/*.xml
sonar.cs.opencover.reportsPaths=TestResults/coverage.opencover.xml
# Coverage thresholds
sonar.coverage.exclusions=**/*test*/**,**/migrations/**
Analysis Execution with SonarScanner
JavaScript/TypeScript Project
# Install SonarScanner
npm install -g sonar-scanner
# package.json configuration
npm pkg set scripts.sonar="sonar-scanner"
# Run analysis
sonar-scanner \
-Dsonar.projectKey=my-js-project \
-Dsonar.sources=src \
-Dsonar.host.url=http://localhost:9000 \
-Dsonar.token=your_token_here
# Analysis with coverage
npm run test -- --coverage
sonar-scanner \
-Dsonar.projectKey=my-js-project \
-Dsonar.sources=src \
-Dsonar.tests=src \
-Dsonar.test.inclusions=**/*.test.ts,**/*.spec.ts \
-Dsonar.javascript.lcov.reportPaths=coverage/lcov.info \
-Dsonar.host.url=http://localhost:9000 \
-Dsonar.token=your_token_here
Maven (Java) Project
<!-- pom.xml -->
<properties>
<sonar.host.url>http://localhost:9000</sonar.host.url>
<sonar.token>your_token_here</sonar.token>
<sonar.coverage.exclusions>
**/test/**,
**/target/**
</sonar.coverage.exclusions>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>4.0.0.4121</version>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.12</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
# Run Maven analysis
mvn clean compile test jacoco:report sonar:sonar
# Check specific quality gate
mvn sonar:sonar -Dsonar.qualitygate.wait=true
.NET Project
# Install .NET SonarScanner
dotnet tool install --global dotnet-sonarscanner
# Begin analysis
dotnet sonarscanner begin \
/k:"my-dotnet-project" \
/d:sonar.host.url="http://localhost:9000" \
/d:sonar.token="your_token_here" \
/d:sonar.cs.opencover.reportsPaths="TestResults/coverage.opencover.xml"
# Build and test
dotnet build
dotnet test --collect:"XPlat Code Coverage" -- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=opencover
# End analysis
dotnet sonarscanner end /d:sonar.token="your_token_here"
CI/CD Integration Examples
GitHub Actions
# .github/workflows/sonarqube.yml
name: SonarQube Analysis
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
sonarqube:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0 # Shallow clones should be disabled
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests with coverage
run: npm run test -- --coverage --watchAll=false
- name: SonarQube Scan
uses: sonarqube-quality-gate-action@master
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
with:
projectBaseDir: .
args: >
-Dsonar.projectKey=${{ github.repository }}
-Dsonar.sources=src
-Dsonar.tests=src
-Dsonar.test.inclusions=**/*.test.ts,**/*.spec.ts
-Dsonar.javascript.lcov.reportPaths=coverage/lcov.info
- name: Quality Gate Check
uses: sonarqube-quality-gate-action@master
timeout-minutes: 5
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
GitLab CI/CD
# .gitlab-ci.yml
variables:
SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar"
GIT_DEPTH: "0"
cache:
key: "${CI_JOB_NAME}"
paths:
- .sonar/cache
stages:
- test
- quality
test:
stage: test
image: node:20-alpine
before_script:
- npm ci
script:
- npm run test -- --coverage --watchAll=false
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: coverage/cobertura-coverage.xml
paths:
- coverage/
expire_in: 1 day
sonarqube-check:
stage: quality
image:
name: sonarsource/sonar-scanner-cli:latest
entrypoint: [""]
dependencies:
- test
script:
- sonar-scanner
-Dsonar.projectKey=${CI_PROJECT_NAME}
-Dsonar.sources=src
-Dsonar.tests=src
-Dsonar.test.inclusions=**/*.test.ts,**/*.spec.ts
-Dsonar.javascript.lcov.reportPaths=coverage/lcov.info
-Dsonar.host.url=${SONAR_HOST_URL}
-Dsonar.token=${SONAR_TOKEN}
-Dsonar.qualitygate.wait=true
only:
- main
- develop
- merge_requests
Quality Gate Configuration
Custom Quality Gate Configuration Example
{
"name": "Strict Quality Gate",
"conditions": [
{
"metric": "new_coverage",
"operation": "LT",
"threshold": "80",
"periodIndex": "1"
},
{
"metric": "new_duplicated_lines_density",
"operation": "GT",
"threshold": "3",
"periodIndex": "1"
},
{
"metric": "new_maintainability_rating",
"operation": "GT",
"threshold": "1",
"periodIndex": "1"
},
{
"metric": "new_reliability_rating",
"operation": "GT",
"threshold": "1",
"periodIndex": "1"
},
{
"metric": "new_security_rating",
"operation": "GT",
"threshold": "1",
"periodIndex": "1"
},
{
"metric": "new_security_hotspots_reviewed",
"operation": "LT",
"threshold": "100",
"periodIndex": "1"
}
]
}
Project-Specific Configuration and Rule Customization
Quality Profile Creation
# SonarQube Web API for Quality Profile operations
# Create new Quality Profile
curl -X POST \
"${SONAR_HOST_URL}/api/qualityprofiles/create" \
-H "Authorization: Bearer ${SONAR_TOKEN}" \
-d "language=js" \
-d "name=MyCompany TypeScript Rules"
# Add rule
curl -X POST \
"${SONAR_HOST_URL}/api/qualityprofiles/activate_rule" \
-H "Authorization: Bearer ${SONAR_TOKEN}" \
-d "key=MyCompany_TypeScript_Rules" \
-d "rule=typescript:S1066" \
-d "severity=MAJOR"
# Change rule configuration
curl -X POST \
"${SONAR_HOST_URL}/api/qualityprofiles/activate_rule" \
-H "Authorization: Bearer ${SONAR_TOKEN}" \
-d "key=MyCompany_TypeScript_Rules" \
-d "rule=typescript:S3776" \
-d "severity=CRITICAL" \
-d "params=threshold=15"
Reports and Metrics Utilization
SonarQube Web API Utilization
# Get project quality metrics
curl -H "Authorization: Bearer ${SONAR_TOKEN}" \
"${SONAR_HOST_URL}/api/measures/component?component=${PROJECT_KEY}&metricKeys=coverage,duplicated_lines_density,bugs,vulnerabilities,code_smells,sqale_rating,reliability_rating,security_rating"
# Check quality gate status
curl -H "Authorization: Bearer ${SONAR_TOKEN}" \
"${SONAR_HOST_URL}/api/qualitygates/project_status?projectKey=${PROJECT_KEY}"
# Get issues list
curl -H "Authorization: Bearer ${SONAR_TOKEN}" \
"${SONAR_HOST_URL}/api/issues/search?componentKeys=${PROJECT_KEY}&types=BUG,VULNERABILITY,CODE_SMELL"
Custom Dashboard Data Collection
# Python example: SonarQube metrics collector
import requests
import json
class SonarQubeCollector:
def __init__(self, host_url, token):
self.host_url = host_url
self.headers = {"Authorization": f"Bearer {token}"}
def get_project_metrics(self, project_key):
"""Get project metrics"""
metrics = [
'coverage', 'duplicated_lines_density', 'bugs',
'vulnerabilities', 'code_smells', 'sqale_rating',
'reliability_rating', 'security_rating', 'sqale_index'
]
url = f"{self.host_url}/api/measures/component"
params = {
'component': project_key,
'metricKeys': ','.join(metrics)
}
response = requests.get(url, headers=self.headers, params=params)
return response.json()
def get_quality_gate_status(self, project_key):
"""Get quality gate status"""
url = f"{self.host_url}/api/qualitygates/project_status"
params = {'projectKey': project_key}
response = requests.get(url, headers=self.headers, params=params)
return response.json()
def get_issues_summary(self, project_key):
"""Get issues summary"""
url = f"{self.host_url}/api/issues/search"
params = {
'componentKeys': project_key,
'facets': 'types,severities,rules',
'ps': 1 # Count not needed
}
response = requests.get(url, headers=self.headers, params=params)
return response.json()
# Usage example
collector = SonarQubeCollector('http://localhost:9000', 'your_token')
metrics = collector.get_project_metrics('my-project')
quality_gate = collector.get_quality_gate_status('my-project')
Security and Compliance Configuration
Security Hotspot Management
# Get security hotspots list
curl -H "Authorization: Bearer ${SONAR_TOKEN}" \
"${SONAR_HOST_URL}/api/hotspots/search?projectKey=${PROJECT_KEY}"
# Get hotspot details
curl -H "Authorization: Bearer ${SONAR_TOKEN}" \
"${SONAR_HOST_URL}/api/hotspots/show?hotspot=${HOTSPOT_KEY}"
# Update hotspot status (reviewed)
curl -X POST \
-H "Authorization: Bearer ${SONAR_TOKEN}" \
"${SONAR_HOST_URL}/api/hotspots/change_status" \
-d "hotspot=${HOTSPOT_KEY}" \
-d "status=REVIEWED" \
-d "resolution=SAFE"
Compliance Report Configuration
# compliance-check.yml - Compliance check automation
name: Compliance Check
on:
schedule:
- cron: '0 2 * * 1' # Every Monday at 2 AM
workflow_dispatch:
jobs:
compliance:
runs-on: ubuntu-latest
steps:
- name: Generate Compliance Report
run: |
# OWASP Top 10 check
curl -H "Authorization: Bearer ${{ secrets.SONAR_TOKEN }}" \
"${{ secrets.SONAR_HOST_URL }}/api/measures/component?component=${{ github.repository }}&metricKeys=security_rating,security_hotspots,vulnerabilities" \
> security-report.json
# CWE category vulnerability aggregation
curl -H "Authorization: Bearer ${{ secrets.SONAR_TOKEN }}" \
"${{ secrets.SONAR_HOST_URL }}/api/issues/search?componentKeys=${{ github.repository }}&types=VULNERABILITY&facets=cwe" \
> cwe-report.json
# Generate report (Python script, etc.)
python generate-compliance-report.py
- name: Upload Compliance Report
uses: actions/upload-artifact@v4
with:
name: compliance-report
path: compliance-report.pdf