官网:

SonarQube 是一个开源的代码质量管理系统。可以对代码进行自动审查,检测代码中的错误、漏洞和代码味道。它可以与您现有的工作流程集成,以实现跨项目分支和拉取请求的持续代码检查。使所有开发人员能够编写更清洁、更安全的代码。

5.png

开发人员在 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.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 安装插件

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:

中文插件:

scanner 下载:

多分支插件:

关联提交:

2.3 强制登陆

默认所有项目都可以公开的查看,在企业内肯定要配置成私有的。只有登录后才能查看。sonarqube 8.9.5 默认已经开启了,低于该版本的可以手动开启(配置 — 权限 — Force user authentication)。


3.1 安装配置

scanner 的类型有很多,可以通过官网: 获取支持的列表。  

变更项目代码:可以使用构建工具进行扫描。例如 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

项目参数可以参考:

# 指定配置文件扫描
sonar-scanner -Dproject.settings=myproject.properties

# 命令行传参扫描
sonar-scanner -Dsonar.projectKey=myproject -Dsonar.sources=./src

各种语言扫描示例:

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