SonarQube 代码质量平台
开发人员在 IDE 开发代码,可以安装 SonarLint 插件进行提交前代码扫描,当开发人员提交代码到版本控制系统中,自动触发 Jenkins 进行代码扫描。
1、特性
持续检查:
项目整体的健康程度
项目的主页面会给出,项目整体的 Bugs、Vulnerabilities、Code Smells
专注于漏洞
water-leak-paradigm (代码管理方法) 可以有效的管理代码质量:新特性,增加的,改变的
在项目监测报告中,需要密切关注:New Bugs、New Vulnerabilities
实施质量阈值
在团队项目中,可以设置质量阈值(Quality Gate),用于监管质量
分支分析
确保干净的代码才会被合并到主分支中
支持多语言:
适用于 C/C++, C#, CSS, Go, HTML, Java, JavaScript, PHP, Python, Ruby 等 29 种编程语言。
七个维度检测代码质量:
复杂度分布(complexity):代码复杂度过高将难以理解
重复代码(duplications):程序中包含大量复制、粘贴的代码而导致代码臃肿,sonar 可以展示源码中重复严重的地方
单元测试统计(unit tests):统计并展示单元测试覆盖率,开发或测试可以清楚测试代码的覆盖情况
代码规则检查(coding rules):通过 Findbugs, PMD, CheckStyle 等检查代码是否符合规范
注释率(comments):若代码注释过少,特别是人员变动后,其他人接手比较难接手;若过多,又不利于阅读
潜在的 Bug(potential bugs):通过 Findbugs, PMD, CheckStyle 等检测潜在的 bug
结构与设计(architecture & design):找出循环,展示包与包、类与类之间的依赖、检查程序之间耦合度
2、SonarQube 安装
2.1 组件组成
SonarQube Server 启动 3 个主要进程:
Web 服务器,供开发人员,管理人员浏览高质量的快照并配置 SonarQube 实例
基于 Elasticsearch 的 Search Server 从 UI 进行搜索服务
Compute Engine 服务器,负责处理代码分析报告并将其保存在 SonarQube 数据库中
SonarQube 数据库:存储 SonarQube 实例的配置(安全,插件设置等)项目,视图质量快照。
服务器上安装了多个 SonarQube 插件,可能包括语言,SCM,集成,身份验证和管理插件。
在持续集成服务器上运行一个或多个 SonarScanner,以分析项目。
2.2 安装配置
前提:SonarQube 服务器需要 Java 版本 11(Oracle JRE 11 or OpenJDK 11)
部署:本次基于 Docker 的方式安装部署 SonaQube
# 创建数据目录
mkdir -p /srv/sonarqube/{conf,extensions,logs,data}
chmod 777 -R /srv/sonarqube/
# 运行
docker pull sonarqube:8.9.5-community
docker run -itd --name sonarqube \
-p 9000:9000 \
-v /srv/sonarqube/conf:/opt/sonarqube/conf \
-v /srv/sonarqube/extensions:/opt/sonarqube/extensions \
-v /srv/sonarqube/logs:/opt/sonarqube/logs \
-v /srv/sonarqube/data:/opt/sonarqube/data \
sonarqube:8.9.5-community
# 验证
docker logs -f sonarqube
2.2.1 安装插件
在线安装
Administration — Marketplace — Plugins(chinese)
手动安装
插件源:https://update.sonarsource.org/
cd /srv/sonarqube/extensions/downloads
wget https://github.com/xuhuisheng/sonar-l10n-zh/releases/download/sonar-l10n-zh-plugin-8.9/sonar-l10n-zh-plugin-8.9.jar
chmod +x sonar-l10n-zh-plugin-8.9.jar
docker restart sonarqube
Tips:
中文插件:https://github.com/xuhuisheng/sonar-l10n-zh/tree/master
scanner 下载:https://docs.sonarqube.org/8.9/analysis/overview/
多分支插件:https://github.com/mc1arke/sonarqube-community-branch-plugin/releases
关联提交:https://github.com/gabrie-allaigre/sonar-gitlab-plugin/tree/4.1.0-SNAPSHOT
2.3 强制登陆
默认所有项目都可以公开的查看,在企业内肯定要配置成私有的。只有登录后才能查看。sonarqube 8.9.5 默认已经开启了,低于该版本的可以手动开启(配置 — 权限 — Force user authentication)。
3、SonarScanner 使用
3.1 安装配置
scanner 的类型有很多,可以通过官网:https://docs.sonarqube.org/8.9/analysis/overview/ 获取支持的列表。
Gradle -
.NET -
Maven - use the
Jenkins - (Jenkins 集成插件)
Azure DevOps - (devops 平台扩展插件)
Ant -
anything else (CLI) - (更加通用的扫描命令行)
变更项目代码:可以使用构建工具进行扫描。例如 maven、ant、gradle 可以在配置文件中引入对应的配置。
不变更项目代码配置:可以使用 Jenkins 或其他平台的扩展插件,以及使用命令行进行扫描。
部署:
# 下载
$ sudo wget https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.6.2.2472-linux.zip
# 解压(JDK)
$ sudo unzip sonar-scanner-cli-4.6.2.2472-linux.zip -d /usr/local/src/
# 设置环境变量
$ sudo vim /etc/profile
export SONAR_SCANNER_HOME=/usr/local/src/sonar-scanner-cli-4.6.2.2472-linux
export PATH=$SONAR_SCANNER_HOME/bin:$PATH
$ sudo source /etc/profile
# 测试生效
$ sonar-scanner -v
INFO: Scanner configuration file: /usr/local/src/sonar-scanner-4.6.2.2472-linux/conf/sonar-scanner.properties
INFO: Project root configuration file: NONE
INFO: SonarScanner 4.6.2.2472
INFO: Java 11.0.14.1 Eclipse Adoptium (64-bit)
INFO: Linux 3.10.0-1127.el7.x86_64 amd64
默认安装的 sonarscanner 是使用自带的 jdk。通过上面的显示可以发现是 jdk1.11 版本, 如果想使用系统默认的 jdk 版本,可以修改 scanner 可执行程序的配置:
$ sudo vim /usr/local/src/sonar-scanner-4.6.2.2472-linux/bin/sonar-scanner
use_embedded_jre=false
$ sonar-scanner -v
INFO: Scanner configuration file: /usr/local/src/sonar-scanner-4.6.2.2472-linux/conf/sonar-scanner.properties
INFO: Project root configuration file: NONE
INFO: SonarScanner 4.6.2.2472
INFO: Java 1.8.0_332 Temurin (64-bit)
INFO: Linux 3.10.0-1127.el7.x86_64 amd64
扩展:Docker 运行 sonarscanner
docker run \
--rm \
-e SONAR_HOST_URL="http://${SONARQUBE_URL}" \
-e SONAR_LOGIN="myAuthenticationToken" \
-v "${YOUR_REPO}:/usr/src" \
sonarsource/sonar-scanner-cli
3.2 代码扫描
代码扫描过程:本地(构建节点)安装配置 SonarScanner 环境,然后通过设置 sonar 的一系列参数进行扫描分析:
配置文件方式读取扫描参数
文件方式存放可以将扫描参数放到项目的根目录或者 sonar-scanner 的配置文件目录等自定义的目录中
命令行方式读取扫描参数
命令行传参则可以直接将变量传递给 sonarsacnner cli(-Dsonar.projectKey=xxx)
一个基本的 sonar-project.properties 配置文件的参数:
# 定义唯一关键字
sonar.projectKey=pro-demo-maven
# 定义项目的名称
sonar.projectName=pro-demo-maven
# 定义项目的版本
sonar.projectVersion=1.0
# 指定扫描代码的目录位置(多个逗号分隔)
sonar.sources=./src
# 执行项目的编码
sonar.sourceEncoding=UTF-8
# sonar server
sonar.host.url=http://172.16.107.104:9000
# sonar server certificate
sonar.login=admin
sonar.password=Admin@123
# JAVA(JAVA项目需要指定)
sonar.java.binaries=./target/classes
项目参数可以参考: https://docs.sonarqube.org/latest/analysis/analysis-parameters/
# 指定配置文件扫描
sonar-scanner -Dproject.settings=myproject.properties
# 命令行传参扫描
sonar-scanner -Dsonar.projectKey=myproject -Dsonar.sources=./src
各种语言扫描示例: https://docs.sonarqube.org/latest/analysis/languages/
SonarQube 中各种语言的扫描规则都是以 jar 包的方式。在 SonarQube8.9.1 之前版本,默认没有安装语言规则插件,需要手动安装。服务端安装 Java Code Quality and Security, SonarJS, SonarGO 插件,并重启服务器。
Tips: SonarScanner 生成 Token(凭证)
账号 — 安全 — 生成令牌(jenkinsci):c6cff069662339b3522bf90665f52f36a0ef80f2
3.2.1 Java 项目扫描
sonar-scanner -Dsonar.host.url=http://172.16.107.104:9000 \
-Dsonar.projectKey=demo-maven \
-Dsonar.projectName=demo-maven \
-Dsonar.projectVersion=1.0 \
-Dsonar.login=admin \
-Dsonar.password=Admin@123 \
-Dsonar.ws.timeout=30 \
-Dsonar.projectDescription="demo maven project scanner!" \
-Dsonar.links.homepage=http://172.16.107.104:3000/demo/demo-maven \
-Dsonar.links.ci=http://172.16.104.21:8080/job/demo/job/demo-maven/ \
-Dsonar.sources=src \
-Dsonar.sourceEncoding=UTF-8 \
-Dsonar.java.binaries=target/classes \
-Dsonar.java.test.binaries=target/test-classes \
-Dsonar.java.surefire.report=target/surefire-reports
sonar.projectKey,指定项目的关键字
sonar.host.url,指定服务器地址
projectName,指定项目的名称
projectVersion,指定项目的版本(可以用构建时间和构建 ID 定义)
login,指定登录用户名
password,指定登录用户密码
projectDescription,指定项目的描述信息
links.homepage,指定项目的主页(超链接)
sources,指定扫描的目录
sourceEncoding,指定扫描时的编码
java.binaries,指定编译后的类文件目录(必填)
java.test.binaries,指定编译后的测试类目录
java.surefire.report,指定测试报告目录
3.2.2 Web 项目扫描
sonar-scanner \
-Dsonar.projectKey=demo-devops-ui \
-Dsonar.projectName=demo-devops-ui \
-Dsonar.sources=src \
-Dsonar.host.url=http://192.168.1.200:9000 \
-Dsonar.login=0809881d71f2b06b64786ae3f81a9acf22078e8b \
-Dsonar.projectVersion=2.0 \
-Dsonar.ws.timeout=30 \
-Dsonar.projectDescription="my first project!" \
-Dsonar.links.homepage=http://192.168.1.200/devops/devops-maven-service \
-Dsonar.links.ci=http://192.168.1.200:8080/job/demo-pipeline-service/ \
-Dsonar.sourceEncoding=UTF-8
3.2.3 Go 项目扫描
sonar-scanner -Dsonar.projectKey=devops-golang-service \
-Dsonar.projectName=devops-golang-service \
-Dsonar.sources=src \
-Dsonar.login=admin \
-Dsonar.password=admin \
-Dsonar.host.url=http://192.168.1.200:9000
# 有测试用例的情况
sonar.exclusions=**/*_test.go
sonar.tests=.
sonar.test.inclusions=**/*_test.go