SonarQube 代码质量平台
概述
SonarQube 是一个开源的代码质量与安全检测平台,能够对 30 多种编程语言进行静态代码分析,检测代码中的 Bug、漏洞、代码异味、安全热点,并提供代码覆盖率、重复率、技术债等质量指标。通过集成到 CI/CD 流水线中,SonarQube 可以在每次代码提交时自动执行质量门禁检查,确保只有满足质量要求的代码才能合入主干。
核心功能
| 功能 | 说明 |
|---|---|
| 静态代码分析 | 检测代码中的 Bug、安全漏洞、代码异味 |
| 质量门禁 (Quality Gate) | 设定质量阈值,控制代码合入 |
| 安全热点 (Security Hotspot) | 识别潜在安全风险区域 |
| 技术债管理 | 量化代码维护成本 |
| 增量分析 | 仅扫描变更代码,提高扫描效率 |
| 历史趋势 | 追踪代码质量随时间的变化 |
| 多语言支持 | Java、JavaScript、Python、Go、C#、TypeScript 等 30+ 语言 |
SonarQube 架构
SonarQube 采用微服务架构,由以下几个核心组件构成:
┌─────────────────────────────┐
│ SonarQube │
│ Web Server │
│ (HTTP / 端口 9000) │
└──────┬──────────┬────────────┘
│ │
┌─────────────┘ └─────────────┐
│ │
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ Compute Engine │ │ ElasticSearch │
│ (分析任务执行) │ │ (搜索索引引擎) │
└──────────────────┘ └──────────────────┘
│ │
└─────────────┬────────────────────────┘
│
▼
┌──────────────────┐
│ 数据库 │
│ (PostgreSQL) │
└──────────────────┘Web Server
Web Server 是 SonarQube 的用户界面入口,提供以下功能:
- 管理控制台 — 项目管理、用户权限、质量门禁、规则配置
- 质量仪表盘 — 项目健康状态可视化、历史趋势图表
- API 接口 — 供外部工具和 CI/CD 系统调用的 REST API
- 身份认证 — 支持 LDAP、SAML、OAuth 集成
建议配置:至少 2GB 内存,生产环境建议 4GB+。
Compute Engine
Compute Engine 负责执行代码分析任务的后台处理,是 SonarQube 的"计算层":
- 任务队列 — 接收并管理来自扫描器的分析报告
- 异步处理 — 将分析结果写入数据库并更新 ElasticSearch 索引
- 资源消耗 — 分析任务消耗大量 CPU 和内存资源
- 并行度 — 可配置同时处理的任务数量(
sonar.ce.workerCount)
Scanner 提交报告 --> 任务队列排队 --> Compute Engine 处理 --> 写入数据库/索引建议参数配置(sonar.properties):
# Compute Engine 工作线程数,默认 1,建议不超过 CPU 核心数
sonar.ce.workerCount=2
# Compute Engine Java 进程内存
sonar.ce.javaOpts=-Xmx2048m -Xms1024mElasticSearch
ElasticSearch 为 SonarQube 提供搜索和索引能力:
- 代码搜索 — 支持快速搜索代码中的标识符、字符串
- 指标存储 — 存储度量指标的索引数据
- 故障影响 — ES 故障会导致 UI 搜索功能不可用,但不影响扫描
- 数据恢复 — 可从数据库重建 ES 索引
ES 相关配置:
# 数据存储路径
sonar.es.data=./data/es
# ES Java 堆内存
sonar.es.javaOpts=-Xmx2048m -Xms1024m数据库
SonarQube 使用关系型数据库持久化存储配置和数据:
| 数据类别 | 说明 |
|---|---|
| 项目配置 | 项目元数据、质量门禁、规则配置 |
| 分析结果 | Issue、指标值、快照 |
| 用户数据 | 用户信息、权限、组 |
| 插件数据 | 插件状态和配置 |
支持的数据库:
| 数据库 | 版本要求 |
|---|---|
| PostgreSQL | 13+(推荐) |
| Oracle | 21c+ |
| Microsoft SQL Server | 2019+ |
PostgreSQL 配置建议:
-- 创建专用用户和数据库
CREATE USER sonarqube WITH PASSWORD 'sonarqube_password';
CREATE DATABASE sonarqube OWNER sonarqube;
-- 调整连接数
ALTER SYSTEM SET max_connections = 50;
-- 建议:使用 SSD 存储提高性能组件通信流程
1. Scanner(CI 工具/Maven/Gradle)通过 Web API 提交分析报告
2. Web Server 将任务加入 Compute Engine 队列
3. Compute Engine 异步处理分析报告
4. 处理结果写入 PostgreSQL 数据库
5. ElasticSearch 索引更新(用于搜索)
6. 用户通过浏览器访问 Web Server 查看结果Docker Compose 部署
docker-compose.yml
version: "3.8"
services:
sonarqube-db:
image: postgres:15
container_name: sonarqube-db
restart: always
environment:
POSTGRES_USER: sonarqube
POSTGRES_PASSWORD: sonarqube_password
POSTGRES_DB: sonarqube
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
networks:
- sonarqube-net
healthcheck:
test: ["CMD-SHELL", "pg_isready -U sonarqube -d sonarqube"]
interval: 10s
timeout: 5s
retries: 5
sonarqube:
image: sonarqube:community-10.7
container_name: sonarqube
restart: always
depends_on:
sonarqube-db:
condition: service_healthy
environment:
SONAR_JDBC_URL: jdbc:postgresql://sonarqube-db:5432/sonarqube
SONAR_JDBC_USERNAME: sonarqube
SONAR_JDBC_PASSWORD: sonarqube_password
# 额外 Java 选项
SONAR_SEARCH_JAVA_OPTS: "-Xmx2048m -Xms1024m"
SONAR_CE_JAVA_OPTS: "-Xmx2048m -Xms1024m"
SONAR_WEB_JAVA_OPTS: "-Xmx2048m -Xms1024m"
# 基础配置
SONAR_ES_BOOTSTRAP_CHECKS_DISABLE: "true"
volumes:
- sonarqube_data:/opt/sonarqube/data
- sonarqube_logs:/opt/sonarqube/logs
- sonarqube_extensions:/opt/sonarqube/extensions
ports:
- "9000:9000"
networks:
- sonarqube-net
volumes:
postgres_data:
sonarqube_data:
sonarqube_logs:
sonarqube_extensions:
networks:
sonarqube-net:
driver: bridge系统调优
SonarQube 使用 ElasticSearch,需要调整 Linux 系统参数:
# /etc/sysctl.conf - ElasticSearch 需要调整 vm.max_map_count
vm.max_map_count = 262144
# 立即生效
sudo sysctl -w vm.max_map_count=262144启动与验证
# 启动服务
docker-compose up -d
# 查看日志
docker-compose logs -f sonarqube
# 等待初始化完成(约 1-3 分钟),访问
# http://localhost:9000
# 默认管理员账号:admin / admin生产环境部署注意事项
| 事项 | 建议 |
|---|---|
| 内存规划 | 最少 4GB,推荐 8GB+(含 ES) |
| 存储介质 | 使用 SSD 存储,尤其是数据库和 ES 数据目录 |
| 备份策略 | 定期备份 PostgreSQL 数据库 |
| 高可用 | 社区版仅支持单实例;Developer 版起支持多节点 |
| 安全配置 | 修改默认 admin 密码,配置 HTTPS(反向代理) |
质量门(Quality Gate)
质量门是 SonarQube 的核心机制之一,用于定义项目必须满足的最低质量标准。当扫描结果不满足质量门条件时,CI/CD 流水线可以据此阻断发布。
质量门工作原理
扫描报告 --> 质量门评估 --> 通过 / 失败 --> CI/CD 决策
│
┌───────┴───────┐
▼ ▼
PASSED FAILED
│ │
允许合入 阻断发布/告警默认质量门(Sonar Way)
SonarQube 内置的默认质量门 "Sonar way" 包含以下规则:
| 指标 | 阈值 | 说明 |
|---|---|---|
| 覆盖率 (Coverage) | < 80% | 新增代码的行覆盖率低于 80% 则告警 |
| 重复率 (Duplicated Lines) | > 3% | 新增代码的重复行占比超过 3% 则告警 |
| 可靠性评级 (Reliability Rating) | > A | 可靠性评级不为 A 则告警 |
| 安全评级 (Security Rating) | > A | 安全评级不为 A 则告警 |
| 可维护性评级 (Maintainability Rating) | > A | 可维护性评级不为 A 则告警 |
| 安全审查评级 (Security Review Rating) | > A | 安全审查评级不为 A 则告警 |
| 新增 Bug | > 0 | 新增代码引入 Bug 则失败 |
| 新增漏洞 (New Vulnerabilities) | > 0 | 新增漏洞则失败 |
| 新增安全热点 (New Security Hotspots) | > 0 | 新增安全热点则失败 |
| 新增代码异味 (New Technical Debt) | > 0 | 新增技术债则告警 |
注意:SonarQube 10.x 版本中,对于新增代码的覆盖率和重复率通常配置为 WARN(告警) 而非 ERROR(失败),只有新增 Bug 和漏洞会直接导致失败。
评级体系
SonarQube 使用 A 到 E 的评级体系:
| 评级 | 说明 | Bug/漏洞/异味密度范围 |
|---|---|---|
| A | 优秀 | 0 - 0.05 |
| B | 良好 | 0.06 - 0.10 |
| C | 一般 | 0.11 - 0.20 |
| D | 较差 | 0.21 - 0.50 |
| E | 很差 | > 0.50 |
自定义质量门
通过 SonarQube UI(Quality Gates > Create)或 REST API 创建自定义质量门:
# 通过 API 创建质量门
POST /api/qualitygates/create
{
"name": "My Team Quality Gate"
}
# 添加条件:新增代码覆盖率 >= 85%
POST /api/qualitygates/create_condition
{
"gateName": "My Team Quality Gate",
"metric": "new_coverage",
"op": "LT",
"warning": "80",
"error": "85"
}
# 添加条件:新增代码行重复率 <= 3%
POST /api/qualitygates/create_condition
{
"gateName": "My Team Quality Gate",
"metric": "new_duplicated_lines_density",
"op": "GT",
"warning": "3",
"error": "5"
}
# 添加条件:新增代码异味 <= 0
POST /api/qualitygates/create_condition
{
"gateName": "My Team Quality Gate",
"metric": "new_code_smells",
"op": "GT",
"error": "0"
}质量门常用指标
| 指标 Key | 名称 | 适用场景 |
|---|---|---|
new_coverage | 新增代码覆盖率 | 要求新增代码有足够测试覆盖 |
new_duplicated_lines_density | 新增代码重复率 | 防止引入重复代码 |
new_bugs | 新增 Bug 数量 | 不允许新增缺陷 |
new_vulnerabilities | 新增漏洞数量 | 不允许新增安全漏洞 |
new_code_smells | 新增代码异味数量 | 控制代码质量 |
new_security_hotspots | 新增安全热点数量 | 需要审查的安全区域 |
reliability_rating | 可靠性评级 | 整体项目可靠性要求 |
security_rating | 安全评级 | 整体项目安全性要求 |
coverage | 整体覆盖率 | 整体测试覆盖要求 |
duplicated_lines_density | 整体重复率 | 整体代码重复控制 |
在 sonar-project.properties 中指定质量门
# 指定使用自定义质量门
sonar.qualitygate=My Team Quality Gate规则配置
规则严重级别
SonarQube 定义了 5 个严重级别:
| 级别 | 标签 | 说明 | 示例 |
|---|---|---|---|
| BLOCKER | 阻断 | 极有可能导致生产事故的 Bug | 内存泄漏、SQL 注入、空指针解引用 |
| CRITICAL | 严重 | 有较高概率导致程序异常 | 未关闭的资源、未处理的异常 |
| MAJOR | 主要 | 明显影响代码质量的缺陷 | 复杂度过高、空 catch 块 |
| MINOR | 次要 | 轻微质量问题 | 未使用的变量、命名不规范 |
| INFO | 信息 | 提示信息,非缺陷 | 注释规范、TODO 标记 |
激活/停用规则
通过 UI 或 API 管理规则:
UI 路径:Administration > Quality Profiles > 选择语言 > Rules
通过 API 激活规则:
# 激活规则
POST /api/qualityprofiles/activate_rule
{
"rule": "java:S106", # 规则 ID(S106 对应 Printf-style format strings)
"profile": "AYu-xxx...", # 质量配置 Key
"severity": "MAJOR" # 覆盖默认严重级别
}
# 停用规则
POST /api/qualityprofiles/deactivate_rule
{
"rule": "java:S106",
"profile": "AYu-xxx..."
}批量管理:通过 UI 的 Bulk Change 功能可以一次性激活/停用多条规则,或修改规则的严重级别。
创建自定义规则
当内置规则不满足需求时,可以创建自定义规则:
自定义规则示例(Java):
// 自定义规则:禁止使用 System.out.println
// 通过 SonarSource 规则扩展机制实现
@Rule(key = "Custom_001")
public class AvoidSystemOutPrintln extends BaseTreeVisitor implements JavaFileScanner {
private static final String ISSUE_MSG = "请使用日志框架代替 System.out.println";
@Override
public void scanFile(JavaFileScannerContext context) {
// 扫描 AST 节点,检测 System.out.println 调用
}
}自定义规则步骤:
- 创建独立的 Java 项目,依赖
sonar-plugin-api - 实现
RulesDefinition和Check类 - 打包为 JAR 并部署至
extensions/plugins - 重启 SonarQube
- 在质量配置中激活自定义规则
通过 UI 创建自定义规则(SonarQube 10.x 开发者版+):
Administration > Rules > Custom Rules > Create需要填写:
- 引擎 — 选择规则引擎(内置/自定义插件)
- Key — 唯一标识符
- 名称 — 规则显示名称
- 严重级别 — BLOCKER / CRITICAL / MAJOR / MINOR / INFO
- 描述 — 规则说明和示例
- 正则表达式 — 对于某些规则类型,提供匹配模式
质量配置(Quality Profile)
质量配置是特定语言的规则集合,一个项目必须关联一个质量配置。
多配置策略建议:
推荐方案:
Java - Sonar way [Java](推荐覆盖默认)
JavaScript - Sonar way [JavaScript]
Python - Sonar way [Python]
团队可按需派生定制:
Java - My Team Java Rules(基于 Sonar way 派生并调整)多语言分析
通用配置
无论哪种语言,都需要在项目根目录创建 sonar-project.properties 文件:
# 项目基本信息
sonar.projectKey=my-project
sonar.projectName=My Project
sonar.projectVersion=1.0.0
# 源代码目录
sonar.sources=src
# 测试目录
sonar.tests=src/test
# 编译输出目录(用于排除)
sonar.inclusions=**
sonar.exclusions=**/generated/**, **/build/**, **/target/**, **/dist/**Java 分析
Java 分析需要指定字节码目录以支持精确的类型解析、流分析等高级特性:
# Java 专用配置
# 指定编译后的字节码目录(必须),SonarQube 需据此解析类型
sonar.java.binaries=target/classes
# 单元测试覆盖率工具(JaCoCo)
sonar.java.coveragePlugin=jacoco
# JaCoCo 报告路径
sonar.jacoco.reportPaths=target/jacoco.exec
# 指定 JDK 版本
sonar.java.source=17
# 测试类字节码目录(可选)
sonar.java.test.binaries=target/test-classes
# 依赖库(可选,提升分析精度)
sonar.java.libraries=**/*.jarMaven 集成:
<!-- pom.xml -->
<properties>
<sonar.java.source>17</sonar.java.source>
</properties>执行分析:
# Maven
mvn clean verify sonar:sonar \
-Dsonar.host.url=http://localhost:9000 \
-Dsonar.token=sqa_xxxx
# 手动方式(先编译后分析)
mvn clean package
sonar-scanner多模块 Maven 项目:
# 在根 pom.xml 中统一定义
sonar.coverage.jacoco.xmlReportPaths=**/target/site/jacoco/jacoco.xmlJavaScript/TypeScript 分析
# JavaScript 专用配置
sonar.javascript.lcov.reportPaths=coverage/lcov.info
# TypeScript 配置
sonar.typescript.lcov.reportPaths=coverage/lcov.info
# 排除 node_modules
sonar.exclusions=**/node_modules/**, **/dist/**, **/build/**
# ESLint 报告导入(可选)
sonar.eslint.reportPaths=eslint-report.json
# 指定 JavaScript 分析版本
sonar.javascript.node.maxspace=4096Python 分析
# Python 专用配置
# 覆盖率报告(coverage.py)
sonar.python.coverage.reportPaths=coverage.xml
# Pylint 报告导入(可选)
sonar.python.pylint.reportPath=pylint-report.txt
# 排除虚拟环境目录
sonar.exclusions=**/venv/**, **/.tox/**, **/__pycache__/**
# Flake8 报告导入(可选)
sonar.python.flake8.reportPaths=flake8-report.txtPython 覆盖率生成:
# 使用 coverage.py 生成 Coverage XML 报告
pip install coverage
coverage run -m pytest
coverage xml -o coverage.xmlGo 分析
# Go 专用配置
# Go 代码覆盖率(需使用 go test 生成)
sonar.go.coverage.reportPaths=coverage.out
# Go 测试文件排除
sonar.exclusions=**/vendor/**, **/*_test.go
# Go 报告导入(可选,使用 golangci-lint)
sonar.go.golangci-lint.reportPaths=golangci-lint-report.jsonGo 覆盖率生成:
# 生成覆盖率报告
go test -coverprofile=coverage.out ./...sonar-project.properties 完整示例
sonar.projectKey=my-application
sonar.projectName=My Application
sonar.projectVersion=1.0.0
sonar.sources=src
sonar.tests=src/test
sonar.exclusions=**/generated/**,**/node_modules/**,**/vendor/**,**/build/**
sonar.sourceEncoding=UTF-8
# Java
sonar.java.binaries=target/classes
sonar.java.source=17
# JavaScript
sonar.javascript.lcov.reportPaths=coverage/lcov.info
# Python
sonar.python.coverage.reportPaths=coverage.xml
# Go
sonar.go.coverage.reportPaths=coverage.out
# SonarQube 连接信息
sonar.host.url=http://localhost:9000
sonar.token=sqa_xxxxCI/CD 集成
Maven 插件配置
在 pom.xml 中添加 SonarQube Maven 插件:
<build>
<plugins>
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>4.0.0.4121</version>
</plugin>
</plugins>
</build>设置文件配置(~/.m2/settings.xml,避免在 pom.xml 中硬编码凭证):
<settings>
<pluginGroups>
<pluginGroup>org.sonarsource.scanner.maven</pluginGroup>
</pluginGroups>
<profiles>
<profile>
<id>sonar</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<sonar.host.url>http://localhost:9000</sonar.host.url>
<sonar.token>sqa_xxxx</sonar.token>
</properties>
</profile>
</profiles>
</settings>执行分析:
# 先编译,再执行 SonarQube 分析
mvn clean verify sonar:sonarGradle 插件配置
在 build.gradle 中配置:
plugins {
id "org.sonarqube" version "5.1.0.4882"
}
sonar {
properties {
property "sonar.host.url", "http://localhost:9000"
property "sonar.token", "sqa_xxxx"
property "sonar.sourceEncoding", "UTF-8"
property "sonar.exclusions", "**/generated/**, **/build/**"
}
}执行分析:
./gradlew clean test sonarGitLab CI 集成
# .gitlab-ci.yml
stages:
- test
- sonarqube
variables:
SONAR_HOST_URL: "http://sonarqube.example.com:9000"
SONAR_TOKEN: $SONAR_TOKEN # 在 GitLab CI/CD Variables 中设置
# Java Maven 项目示例
maven-build:
stage: test
script:
- mvn clean compile
artifacts:
paths:
- target/classes/
- target/surefire-reports/
expire_in: 1 hour
sonarqube-analysis:
stage: sonarqube
script:
- mvn verify sonar:sonar
-Dsonar.host.url=$SONAR_HOST_URL
-Dsonar.token=$SONAR_TOKEN
-Dsonar.qualitygate.wait=true
only:
- main
- merge_requests
# 非 Java 项目使用 sonar-scanner
sonarqube-scanner:
stage: sonarqube
image:
name: sonarsource/sonar-scanner-cli:11
entrypoint: [""]
script:
- sonar-scanner
-Dsonar.host.url=$SONAR_HOST_URL
-Dsonar.token=$SONAR_TOKEN
-Dsonar.qualitygate.wait=true
only:
- main
- merge_requestsMR 检测说明:sonar.qualitygate.wait=true 会让分析过程等待质量门结果,在 GitLab MR 中显示为 Pipeline 状态。
GitHub Actions 集成
# .github/workflows/sonarqube.yml
name: SonarQube Analysis
on:
push:
branches: [main]
pull_request:
branches: [main]
types: [opened, synchronize, reopened]
jobs:
sonarqube:
name: SonarQube Scan
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
# PR 检测需要完整的 git 历史
fetch-depth: 0
- name: Setup JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- name: Cache SonarQube packages
uses: actions/cache@v4
with:
path: ~/.sonar/cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar
- name: Build and analyze
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
run: |
mvn clean verify sonar:sonar \
-Dsonar.host.url=$SONAR_HOST_URL \
-Dsonar.token=$SONAR_TOKEN \
-Dsonar.qualitygate.wait=true
- name: Quality Gate check
run: |
echo "SonarQube analysis completed. Check results at $SONAR_HOST_URL"重要配置说明:
fetch-depth: 0— PR 检测需要完整 git 历史以计算新代码sonar.qualitygate.wait=true— 等待质量门结果,PR check 会等待此结果
Jenkins Pipeline 集成
// Jenkinsfile
pipeline {
agent any
environment {
SONAR_HOST_URL = 'http://sonarqube.example.com:9000'
SONAR_TOKEN = credentials('sonarqube-token')
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Build') {
steps {
sh 'mvn clean compile'
}
}
stage('Test') {
steps {
sh 'mvn test'
}
}
stage('SonarQube Analysis') {
steps {
// 方式一:使用 Maven 插件
sh """
mvn sonar:sonar \
-Dsonar.host.url=${SONAR_HOST_URL} \
-Dsonar.token=${SONAR_TOKEN} \
-Dsonar.qualitygate.wait=true
"""
// 方式二:使用 SonarScanner(需要安装 SonarScanner 工具)
// 在 Jenkins Global Tool Configuration 中配置 SonarScanner
// withSonarQubeEnv('SonarQube Server') {
// sh 'sonar-scanner'
// }
}
}
// 可选:单独的质量门检查步骤
stage('Quality Gate Check') {
steps {
script {
// 使用 SonarQube API 检查质量门结果
def qg = waitForQualityGate()
if (qg.status != 'OK') {
error "Pipeline aborted due to quality gate failure: ${qg.status}"
}
}
}
}
stage('Deploy') {
when {
branch 'main'
}
steps {
sh 'mvn deploy'
}
}
}
post {
failure {
emailext(
subject: "SonarQube Quality Gate Failed: ${env.JOB_NAME} - ${env.BUILD_NUMBER}",
body: "The SonarQube analysis failed. Check results at ${SONAR_HOST_URL}",
to: 'team@example.com'
)
}
}
}Jenkins 前置要求:
- 安装 SonarQube Scanner 插件
- 在 Manage Jenkins > Configure System > SonarQube servers 中配置 SonarQube 服务端
- 在 Manage Jenkins > Global Tool Configuration 中配置 SonarScanner
- 创建名为
sonarqube-token的凭据
非 Java 项目的通用方式:SonarScanner CLI
# Docker 运行 sonar-scanner
docker run \
--rm \
-v $(pwd):/usr/src \
sonarsource/sonar-scanner-cli:11 \
sonar-scanner \
-Dsonar.host.url=http://localhost:9000 \
-Dsonar.token=sqa_xxxx \
-Dsonar.projectKey=my-project \
-Dsonar.sources=. \
-Dsonar.exclusions=**/node_modules/**,**/vendor/**扫描指标详解
SonarQube 将代码质量分为几个核心维度,每个维度有对应的指标和评级。
可靠性(Reliability)
衡量代码中 Bug 的严重程度和数量。Bug 指可能导致程序行为异常或崩溃的缺陷。
| 指标 Key | 名称 | 说明 |
|---|---|---|
bugs | Bug 数量 | 当前代码中的 Bug 总数 |
new_bugs | 新增 Bug | 新增代码引入的 Bug 数量 |
reliability_rating | 可靠性评级 | 基于 Bug 密度计算(A-E) |
reliability_remediation_effort | 可靠性修复耗时 | 修复所有 Bug 的预估时间(人天) |
评级计算:
Bug 密度 = Bug 数 / 代码行数(千行)
A: 密度 = 0 (无 Bug)
B: 密度 <= 0.05 (低密度)
C: 密度 <= 0.10 (中密度)
D: 密度 <= 0.50 (高密度)
E: 密度 > 0.50 (极高密度)安全性(Security)
衡量代码中安全漏洞的数量和严重程度。
| 指标 Key | 名称 | 说明 |
|---|---|---|
vulnerabilities | 漏洞数量 | 当前代码中的安全漏洞总数 |
new_vulnerabilities | 新增漏洞 | 新增代码引入的安全漏洞 |
security_rating | 安全评级 | 基于漏洞密度计算(A-E) |
security_remediation_effort | 安全修复耗时 | 修复所有漏洞的预估时间 |
安全热点 (Security Hotspot):需要人工审查的安全敏感代码区域,不是确定的漏洞,但需要开发人员确认是否安全。
| 指标 Key | 名称 | 说明 |
|---|---|---|
security_hotspots | 安全热点数量 | 需要审查的安全区域 |
security_review_rating | 安全审查评级 | 基于已审查热点比例计算 |
可维护性(Maintainability)
衡量代码的易维护程度,基于代码异味(Code Smell)计算。
| 指标 Key | 名称 | 说明 |
|---|---|---|
code_smells | 代码异味数量 | 代码中需要清理的"坏味道" |
new_code_smells | 新增异味 | 新增代码引入的异味数量 |
maintainability_rating | 可维护性评级 | 基于异味密度计算(A-E) |
sqale_index | 技术债(分钟) | 修复所有异味所需的分钟数 |
sqale_rating | 技术债评级 | 基于技术债比例计算 |
覆盖率(Coverage)
衡量测试代码对业务代码的覆盖程度。
| 指标 Key | 名称 | 说明 |
|---|---|---|
coverage | 行覆盖率 | 被测试覆盖的代码行占比 |
line_coverage | 行覆盖率(精确) | 精确的行覆盖率值 |
branch_coverage | 分支覆盖率 | 条件分支的覆盖比例(如 if/else) |
new_coverage | 新增代码覆盖率 | 新增代码的覆盖率 |
uncovered_lines | 未覆盖行数 | 未命中测试的代码行 |
uncovered_conditions | 未覆盖分支数 | 未测试到的条件分支 |
覆盖率指标解读:
coverage = (覆盖的代码行 + 覆盖的分支) / (总代码行 + 总分支) * 100%
line_coverage = 覆盖的代码行 / 总代码行 * 100%
branch_coverage = 覆盖的分支数 / 总分支数 * 100%重复率(Duplications)
衡量代码中重复块的比例。
| 指标 Key | 名称 | 说明 |
|---|---|---|
duplicated_lines_density | 代码重复率 | 重复代码行占总行数比例 |
duplicated_lines | 重复行数 | 重复的代码行数 |
duplicated_blocks | 重复块数 | 重复代码块的数量 |
duplicated_files | 重复文件数 | 包含重复代码的文件数 |
new_duplicated_lines_density | 新增代码重复率 | 新增代码中的重复比例 |
技术债(Technical Debt)
技术债是修复代码中所有异味所需的预估工作量,以时间单位衡量。
| 指标 Key | 名称 | 说明 |
|---|---|---|
sqale_index | 技术债指数 | 修复所有异味所需的总分钟数 |
sqale_debt_ratio | 技术债比率 | 技术债与代码规模的比值 |
effort_to_reach_maintainability_rating_a | 达 A 级工作量 | 达到 A 级可维护性还需投入的工作量 |
技术债计算公式:
技术债比率 = 技术债(分钟)/ 代码行数 * 转换系数
通常:
技术债比率 < 5% → A 级
技术债比率 5-10% → B 级
技术债比率 10-20% → C 级
技术债比率 20-50% → D 级
技术债比率 > 50% → E 级指标总览表
| 维度 | 核心指标 | 评级依据 | 阈值(A 级) |
|---|---|---|---|
| 可靠性 | Bug 数量 | Bug 密度 | 密度 = 0 |
| 安全性 | 漏洞数量 | 漏洞密度 | 密度 = 0 |
| 可维护性 | 代码异味数、技术债 | 技术债比率 | 比率 < 5% |
| 覆盖率 | 行覆盖率、分支覆盖率 | 百分比 | >= 80% |
| 重复率 | 重复行占比 | 百分比 | <= 3% |
最佳实践
增量分析(New Code Period)
增量分析是 SonarQube 最有价值的特性之一,它仅检测新增或修改的代码,避免被存量代码问题淹没。
配置新代码周期:
UI 路径:Administration > General Settings > New Code Period
选项:
- Number of days:设为 30,表示只关注最近 30 天内的改动
- Previous version:基于版本变更分析(推荐在项目中设置版本号)
- Number of days after version:版本发布后 N 天的改动视为新代码
- Reference branch:指定参考分支(Git 场景推荐)推荐策略:
团队场景:
- 日常开发:Reference branch(main/master),只分析当前分支与主分支的差异
- 版本发布:Previous version,分析自上个版本以来的全部变更
- 新项目:Number of days(30),前 30 天逐步清理存量问题CI/CD 中的增量分析:
# GitLab CI: 只在 MR 时启用增量分析
sonarqube-analysis:
script:
- sonar-scanner
-Dsonar.pullrequest.key=$CI_MERGE_REQUEST_IID
-Dsonar.pullrequest.branch=$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
-Dsonar.pullrequest.base=$CI_MERGE_REQUEST_TARGET_BRANCH_NAME
only:
- merge_requests排除目录
将不需要分析的目录排除,可以减少扫描时间、避免误报。
# sonar-project.properties
# 基础排除
sonar.exclusions=**/generated/**,**/build/**,**/target/**,**/dist/**,**/node_modules/**
# 按文件模式排除
sonar.exclusions=**/*.min.js,**/*.generated.*,**/test-resources/**
# 按目录排除
sonar.exclusions=**/vendor/**,**/third-party/**,**/lib/**
# 排除文件的覆盖率统计(不参与覆盖率计算但不排除分析)
sonar.coverage.exclusions=**/test/**/*.java,**/model/**/*.java
# 排除文件的重复检测
sonar.cpd.exclusions=**/*DTO.java,**/*VO.java,**/generated/**规则阈值调整
根据团队实际情况调整默认阈值,避免过于严格或过于宽松。
调整建议:
# 方法复杂度阈值(默认 15,大型项目可适当放宽)
sonar.java.maximumLines=200
# 文件行数阈值
sonar.java.maximumLinesFile=1000
# 允许的重复行百分比(默认 3%,遗留项目初期可放宽到 10%)
# 此配置在 Quality Gate 条件中设置而非 properties
# 方法参数数量(默认 10)
sonar.java.maximumParameters=8分阶段收紧策略:
第一阶段(第 1-2 月):
- 覆盖率要求:60%
- 重复率允许:10%
- 目标:建立基本的质量意识
第二阶段(第 3-4 月):
- 覆盖率要求:70%
- 重复率允许:5%
- 目标:提升测试覆盖,减少重复代码
第三阶段(第 5 月后):
- 覆盖率要求:80%
- 重复率允许:3%
- 目标:达到 Sonar 推荐的优秀标准PR 检测(Pull Request 检测)
PR 检测是 SonarQube 与 Git 工作流结合的核心场景,在代码合入前自动执行质量检查。
GitLab MR 集成:
# .gitlab-ci.yml
sonarqube-pr:
stage: sonarqube
script:
- sonar-scanner
-Dsonar.pullrequest.key=$CI_MERGE_REQUEST_IID
-Dsonar.pullrequest.branch=$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
-Dsonar.pullrequest.base=$CI_MERGE_REQUEST_TARGET_BRANCH_NAME
-Dsonar.qualitygate.wait=true
only:
- merge_requestsGitHub PR 集成:
# .github/workflows/sonarqube-pr.yml
name: SonarQube PR Check
on:
pull_request:
types: [opened, synchronize, reopened]
jobs:
sonarqube-pr:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: SonarQube PR Analysis
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
run: |
sonar-scanner \
-Dsonar.host.url=$SONAR_HOST_URL \
-Dsonar.token=$SONAR_TOKEN \
-Dsonar.pullrequest.key=${{ github.event.pull_request.number }} \
-Dsonar.pullrequest.branch=${{ github.event.pull_request.head.ref }} \
-Dsonar.pullrequest.base=${{ github.event.pull_request.base.ref }} \
-Dsonar.qualitygate.wait=truePR 检测工作原理:
1. 开发者创建 MR/PR
2. CI 系统触发 SonarQube 分析,传入 PR 参数
3. SonarQube 将 PR 源码与目标分支(main)进行差异对比
4. 仅分析新增/修改的代码
5. 质量门仅针对新代码进行评估
6. 结果通过 CI 状态同步到 MR/PR 页面
7. 如果质量门失败,PR 被阻断(可在 Git 平台设置 Required Check)推荐的 PR 质量门设置:
| 条件 | 阈值 | 处理方式 |
|---|---|---|
| 新增 Bug | > 0 | ERROR(阻断) |
| 新增漏洞 | > 0 | ERROR(阻断) |
| 新增代码覆盖率 | < 80% | WARN(告警) |
| 新增代码重复率 | > 3% | WARN(告警) |
| 新增代码异味 | > 0 | WARN(告警) |
其他最佳实践
1. 统一的扫描配置
将 sonar-project.properties 纳入版本控制,确保所有开发者使用一致的配置。
2. 合理使用 @SuppressWarnings
在不可避免的场景(如自动生成代码、特殊情况下的安全警告)中,谨慎使用 @SuppressWarnings("squid:Sxxx") 抑制特定规则。应附带注释说明原因。
3. 定期审核 SonarQube 配置
- 每季度审核规则配置,淘汰过期或不适用的规则
- 定期更新 SonarQube 版本以获取新规则和修复
- 根据项目阶段调整质量门阈值
4. 代码审查联动
- 将 SonarQube 分析结果作为代码审查的输入
- 要求开发者在提交代码前本地运行 sonar-scanner
- 在 Code Review Checklist 中包含 SonarQube 问题处理
5. 性能优化
# 大型项目性能调优
# 增加扫描器内存
# 设置环境变量
SONAR_SCANNER_OPTS=-Xmx4096m
# 限制并行分析任务(服务端配置)
sonar.ce.workerCount=2
# 使用增量分析而非全量分析
# 配置 Reference branch
sonar.newCode.referenceBranch=main6. 安全配置
- 使用 Token 而非密码进行 API 认证
- 配置 HTTPS 访问 SonarQube 服务端
- 定期轮换 SONAR_TOKEN
- 最小权限原则分配用户角色
- 审计日志启用(开发者版+)