1 代码质量测试
官方网站:http://www.sonarqube.org/
SonarQube 是一个用于代码质量管理的开放平台,通过插件机制,SonarQube可以
集成不同的测试工具,代码分析工具,以及持续集成工具,例如 Hudson/Jenkins 等
下载地址:https://www.sonarqube.org/downloads/
七个维度检测代码质量:
复杂度分布:代码复杂度过高将难以理解
重复代码:程序中包含大量复制、粘贴的代码而导致代码臃肿,sonar 可以展示源码中重复严重的地方
单元测试统计:统计并展示单元测试覆盖率,开发或测试可以清楚测试代码的覆盖情况
代码规则检查:检查代码是否符合规范
注释率:若代码注释过少,特别是人员变动后,其他人接手比较难接手;若过多,又不利于阅读
潜在的 Bug:检测潜在的 bug
结构与设计:找出循环,展示包与包、类与类之间的依赖、检查程序之间耦合度
2 Sonarqube
2.1 Sonarqube架构
Sonarqube代码检测功能由Sonarqube服务器端提供
SonarScanner需要在执行代码扫描的服务器安装, 用于扫描代码, 并且上传到Sonarqube Server端
2.2 Sonarqube部署环境
10.0.0.139 Sonarqube Server 4G 2c v7.9.6
10.0.0.149 PGSQL 4G 2c
Jenkins master服务器负责代码扫描, 需要安装Sonar Scanner
2.3 Sonarqube Server安装
2.3.1 包下载
https://www.sonarqube.org/downloads/
root@sonarserver:~# ls
sonarqube-7.9.6.zip
2.3.2 配置环境依赖
- 内核参数要求
root@sonarserver:~# vim /etc/sysctl.conf
vm.max_map_count=262144
fs.file-max=65536
root@sonarserver:~# sysctl -p
vm.max_map_count = 262144
fs.file-max = 65536
- 文件描述符限制
root@sonarserver:~# vim /etc/security/limits.conf
sonarqube - nofile 65536
sonarqube - nproc 65536
2.3.3 创建sonarqube用户
Sonarqube Server不能用root账户启动
root@sonarserver:~# useradd -m -r -s /bin/bash sonarqube
2.3.4 安装jdk-11
Sonarqube Server只支持jdk-11, 而SonarScanner支持jdk8和jdk11
root@sonarserver:~# apt -y install openjdk-11-jdk
root@sonarserver:~# reboot
2.3.5 安装PGSQL
Sonarqube7.x开始支持PGSQL, 支持v10和v9.3-v9.6, 字符集必须是UTF-8
root@pgsql:~# apt-cache madison postgresql
postgresql | 10+190ubuntu0.1 | http://mirrors.aliyun.com/ubuntu bionic-security/main amd64 Packages
postgresql | 10+190ubuntu0.1 | http://mirrors.aliyun.com/ubuntu bionic-security/main i386 Packages
postgresql | 10+190ubuntu0.1 | http://mirrors.aliyun.com/ubuntu bionic-updates/main amd64 Packages
postgresql | 10+190ubuntu0.1 | http://mirrors.aliyun.com/ubuntu bionic-updates/main i386 Packages
postgresql | 10+190 | http://mirrors.aliyun.com/ubuntu bionic/main amd64 Packages
postgresql | 10+190 | http://mirrors.aliyun.com/ubuntu bionic/main i386 Packages
postgresql-common | 190 | http://mirrors.aliyun.com/ubuntu bionic/main Sources
postgresql-common | 190ubuntu0.1 | http://mirrors.aliyun.com/ubuntu bionic-security/main Sources
postgresql-common | 190ubuntu0.1 | http://mirrors.aliyun.com/ubuntu bionic-updates/main Sources
root@pgsql:~# apt install postgresql -y
切换到 postgres 操作,PostgresSQL 安装后会自动创建 postgres 用户且没有密码. 数据库的创建必须使用postgres账户操作
root@pgsql:~# su - postgres
postgres@pgsql:~$ psql -U postgres
psql (10.17 (Ubuntu 10.17-0ubuntu0.18.04.1))
Type "help" for help.
postgres=# CREATE DATABASE sonar;
CREATE DATABASE
postgres=# CREATE USER sonar WITH ENCRYPTED PASSWORD '123456';
CREATE ROLE
postgres=# GRANT ALL PRIVILEGES ON DATABASE sonar TO sonar;
GRANT
postgres=# ALTER DATABASE sonar OWNER TO sonar;
ALTER DATABASE
修改监听地址, 使用root账号配置
root@pgsql:~# vim /etc/postgresql/10/main/postgresql.conf
listen_addresses = '*' # 修改第59行
开启远程访问
root@pgsql:~# vim /etc/postgresql/10/main/pg_hba.conf
host all all 10.0.0.0/24 md5 # 修改第92行, 允许某个网段或者某台主机访问
重启服务
root@pgsql:~# systemctl restart postgresql
root@pgsql:~# ss -ntl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 0.0.0.0:5432 # 监听在0.0.0.0 0.0.0.0:*
LISTEN 0 128 127.0.0.53%lo:53 0.0.0.0:*
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 128 [::]:5432 [::]:*
LISTEN 0 128 [::]:22 [::]:*
2.3.6 安装Sonarqube Server
root@sonarserver:~# mkdir /apps
root@sonarserver:~# ls
sonarqube-7.9.6.zip
root@sonarserver:~# unzip sonarqube-7.9.6.zip -d /apps
root@sonarserver:~# cd /apps
root@sonarserver:/apps# ll
total 12
drwxr-xr-x 3 root root 4096 Jul 6 22:33 ./
drwxr-xr-x 25 root root 4096 Jul 6 22:32 ../
drwxr-xr-x 11 root root 4096 Mar 1 09:21 sonarqube-7.9.6/
root@sonarserver:/apps# ln -sv sonarqube-7.9.6/ sonarqube
'sonarqube' -> 'sonarqube-7.9.6/'
root@sonarserver:/apps# chown -R sonarqube.sonarqube /apps/sonarqube
root@sonarserver:/apps# chown -R sonarqube.sonarqube /apps/sonarqube/
root@sonarserver:/apps# ll /apps
total 12
drwxr-xr-x 3 root root 4096 Jul 6 22:34 ./
drwxr-xr-x 25 root root 4096 Jul 6 22:32 ../
lrwxrwxrwx 1 sonarqube sonarqube 16 Jul 6 22:34 sonarqube -> sonarqube-7.9.6//
drwxr-xr-x 11 sonarqube sonarqube 4096 Mar 1 09:21 sonarqube-7.9.6/
sonarqube@sonarserver:/apps/sonarqube$ vim conf/sonar.properties
sonarqube@sonarserver:/apps/sonarqube$ grep -E '^[a-zA-Z]' conf/sonar.properties
sonar.jdbc.username=sonar # 数据库账号
sonar.jdbc.password=123456 # 密码
sonar.jdbc.url=jdbc:postgresql://10.0.0.149/sonar # 数据库地址
2.3.7 启动服务
使用sonarqube普通账户启动, 如果用root账户启动, 那么ES服务无法启动, 间接造成Sonarqube无法启动
sonarqube@sonarserver:/apps/sonarqube$ ./bin/linux-x86-64/sonar.sh start
Starting SonarQube...
Started SonarQube.
sonarqube@sonarserver:/apps/sonarqube$ tail logs/*.log
2021.07.06 22:41:32 INFO app[][o.s.a.SchedulerImpl] Process[ce] is up
2021.07.06 22:41:32 INFO app[][o.s.a.SchedulerImpl] SonarQube is up
2.3.8 访问sonarqube
账号:admin
密码:admin
2.3.9 使用官方提供的Service文件启动sonarqube
- 先停止服务
sonarqube@sonarserver:~$ /apps/sonarqube/bin/linux-x86-64/sonar.sh stop
Gracefully stopping SonarQube...
Stopped SonarQube.
- 使用root账号, 创建Service文件
root@sonarserver:~# vim /etc/systemd/system/sonarqube.service
[Unit]
Description=SonarQube service
After=syslog.target network.target
[Service]
Type=simple
User=sonarqube
Group=sonarqube
PermissionsStartOnly=true
ExecStart=/usr/bin/nohup /usr/bin/java -Xms1024m -Xmx1024m -Djava.net.preferIPv4Stack=true -jar /apps/sonarqube/lib/sonar-application-7.9.6.jar
StandardOutput=syslog
LimitNOFILE=131072
LimitNPROC=8192
TimeoutStartSec=5
Restart=always
SuccessExitStatus=143
[Install]
WantedBy=multi-user.target
root@sonarserver:~# systemctl daemon-reload
root@sonarserver:~# systemctl restart sonarqube
root@sonarserver:~# systemctl enable --now sonarqube
Created symlink /etc/systemd/system/multi-user.target.wants/sonarqube.service → /etc/systemd/system/sonarqube.service.
root@sonarserver:/apps/sonarqube# ss -ntl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 127.0.0.53%lo:53 0.0.0.0:*
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 128 [::]:22 [::]:*
LISTEN 0 25 *:9000 *:*
LISTEN 0 128 [::ffff:127.0.0.1]:9001 *:*
2.3.10 安装中文插件
插件保存目录
root@sonarserver:~# ll /apps/sonarqube/extensions/plugins/
total 87836
drwxr-xr-x 2 sonarqube sonarqube 4096 Mar 1 09:10 ./
drwxr-xr-x 5 sonarqube sonarqube 4096 Jul 6 22:41 ../
-rw-r--r-- 1 sonarqube sonarqube 224 Mar 1 09:10 README.txt
-rw-r--r-- 1 sonarqube sonarqube 287504 Mar 1 09:10 sonar-auth-github-plugin-1.5.0.870.jar
-rw-r--r-- 1 sonarqube sonarqube 3312399 Mar 1 09:10 sonar-auth-saml-plugin-1.2.0.682.jar
-rw-r--r-- 1 sonarqube sonarqube 4094975 Mar 1 09:10 sonar-csharp-plugin-7.15.0.8572.jar
-rw-r--r-- 1 sonarqube sonarqube 7015434 Mar 1 09:10 sonar-css-plugin-1.1.1.1010.jar
-rw-r--r-- 1 sonarqube sonarqube 1544789 Mar 1 09:10 sonar-flex-plugin-2.5.1.1831.jar
-rw-r--r-- 1 sonarqube sonarqube 3903342 Mar 1 09:10 sonar-go-plugin-1.1.1.2000.jar
-rw-r--r-- 1 sonarqube sonarqube 1727846 Mar 1 09:10 sonar-html-plugin-3.1.0.1615.jar
-rw-r--r-- 1 sonarqube sonarqube 15098 Mar 1 09:10 sonar-jacoco-plugin-1.0.2.475.jar
-rw-r--r-- 1 sonarqube sonarqube 8302745 Mar 1 09:10 sonar-java-plugin-5.13.1.18282.jar
-rw-r--r-- 1 sonarqube sonarqube 6866969 Mar 1 09:10 sonar-javascript-plugin-5.2.1.7778.jar
-rw-r--r-- 1 sonarqube sonarqube 7595999 Mar 1 09:10 sonar-kotlin-plugin-1.5.0.315.jar
-rw-r--r-- 1 sonarqube sonarqube 300503 Mar 1 09:10 sonar-ldap-plugin-2.2.0.608.jar
-rw-r--r-- 1 sonarqube sonarqube 5105268 Mar 1 09:10 sonar-php-plugin-3.2.0.4868.jar
-rw-r--r-- 1 sonarqube sonarqube 2752167 Mar 1 09:10 sonar-python-plugin-1.14.1.3143.jar
-rw-r--r-- 1 sonarqube sonarqube 10036210 Mar 1 09:10 sonar-ruby-plugin-1.5.0.315.jar
-rw-r--r-- 1 sonarqube sonarqube 9202024 Mar 1 09:10 sonar-scala-plugin-1.5.0.315.jar
-rw-r--r-- 1 sonarqube sonarqube 2538373 Mar 1 09:10 sonar-scm-git-plugin-1.12.1.2064.jar
-rw-r--r-- 1 sonarqube sonarqube 7229293 Mar 1 09:10 sonar-scm-svn-plugin-1.9.0.1295.jar
-rw-r--r-- 1 sonarqube sonarqube 2239156 Mar 1 09:10 sonar-typescript-plugin-1.9.0.3766.jar
-rw-r--r-- 1 sonarqube sonarqube 3580236 Mar 1 09:10 sonar-vbnet-plugin-7.15.0.8572.jar
-rw-r--r-- 1 sonarqube sonarqube 2242738 Mar 1 09:10 sonar-xml-plugin-2.0.1.2020.jar
看到install pending后, 要点击重启服务器, 以便开始安装
2.4 Sonar-Scanner安装
Sonar-Scanner可以部署在单独的服务器, 也可以部署在Jenkins服务器, Jenkins把代码拉取到本地后, 直接通过Sonar-Scanner扫描
下载地址:https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/
官方文档:https://docs.sonarqube.org/latest/analysis/scan/sonarscanner/
root@jenkins:/opt# ls
sonar-scanner-cli-4.5.0.2216-linux.zip
root@jenkins:~# unzip sonar-scanner-cli-4.5.0.2216-linux.zip -d /apps/
root@jenkins:/apps# ln -sv sonar-scanner-4.5.0.2216-linux/ sonar-scanner
root@jenkins:/apps# cd sonar-scanner
root@jenkins:/apps/sonar-scanner# vim conf/sonar-scanner.properties
#----- Default SonarQube server
sonar.host.url=http://10.0.0.139:9000
#----- Default source code encoding
sonar.sourceEncoding=UTF-8
2.5 利用官方提供的bug代码进行扫描测试
https://github.com/SonarSource/sonar-scanning-examples
将示例代码传到Jenkins服务器
root@jenkins:~# cd /opt
root@jenkins:/opt# ls
sonar-scanning-examples-master.zip
root@jenkins:/opt# unzip sonar-scanning-examples-master.zip
root@jenkins:/opt/sonar-scanning-examples-master/sonarqube-scanner# cd src/ # 代码示例存放位置
root@jenkins:/opt/sonar-scanning-examples-master/sonarqube-scanner/src# ll
total 80
drwxr-xr-x 20 root root 4096 Jun 24 16:41 ./
drwxr-xr-x 5 root root 4096 Jun 24 16:41 ../
drwxr-xr-x 2 root root 4096 Jun 24 16:41 abap/
drwxr-xr-x 2 root root 4096 Jun 24 16:41 cobol/
drwxr-xr-x 2 root root 4096 Jun 24 16:41 directory/
drwxr-xr-x 2 root root 4096 Jun 24 16:41 erlang/
drwxr-xr-x 2 root root 4096 Jun 24 16:41 flex/
drwxr-xr-x 2 root root 4096 Jun 24 16:41 html/
drwxr-xr-x 2 root root 4096 Jun 24 16:41 javascript/
drwxr-xr-x 2 root root 4096 Jun 24 16:41 kotlin/
drwxr-xr-x 2 root root 4096 Jun 24 16:41 package/
drwxr-xr-x 2 root root 4096 Jun 24 16:41 php/
drwxr-xr-x 2 root root 4096 Jun 24 16:41 pli/
drwxr-xr-x 2 root root 4096 Jun 24 16:41 python/
drwxr-xr-x 2 root root 4096 Jun 24 16:41 rpg/
drwxr-xr-x 2 root root 4096 Jun 24 16:41 samples/
drwxr-xr-x 2 root root 4096 Jun 24 16:41 sql/
drwxr-xr-x 2 root root 4096 Jun 24 16:41 swift/
drwxr-xr-x 2 root root 4096 Jun 24 16:41 vb6/
drwxr-xr-x 2 root root 4096 Jun 24 16:41 xml/
扫描php代码, 每个代码目录都要有一个sonar-project.properties
文件, 来指定项目名称, 扫描代码后会在sonarqube显示
root@jenkins:/opt/sonar-scanning-examples-master/sonarqube-scanner/src/php# vim ../../sonar-project.properties
sonar.projectKey=org.sonarqube:sonarqube-scanner
sonar.projectName=Example of SonarQube Scanner Usage
sonar.projectVersion=1.0
sonar.sources=src,copybooks
sonar.sourceEncoding=UTF-8
## Cobol Specific Properties
# comma-separated paths to directories with copybooks
sonar.cobol.copy.directories=copybooks
# comma-separated list of suffixes
sonar.cobol.file.suffixes=cbl,cpy
sonar.cobol.copy.suffixes=cpy
## Flex Specific Properties
# retrieve code coverage data from the Cobertura report
sonar.flex.cobertura.reportPath=coverage-report/coverage-cobertua-flex.xml
# PL/I Specific Properties
sonar.pli.marginLeft=2
sonar.pli.marginRight=0
root@jenkins:/opt/sonar-scanning-examples-master/sonarqube-scanner/src/php# ll
total 16
drwxr-xr-x 2 root root 4096 Jun 24 16:41 ./
drwxr-xr-x 20 root root 4096 Jun 24 16:41 ../
-rw-r--r-- 1 root root 5559 Jun 24 16:41 Math.php
将sonar-project.properties
文件拷贝到php目录下, 做修改
root@jenkins:/opt/sonar-scanning-examples-master/sonarqube-scanner# cp sonar-project.properties src/php/
root@jenkins:/opt/sonar-scanning-examples-master/sonarqube-scanner# cd src/php
root@jenkins:/opt/sonar-scanning-examples-master/sonarqube-scanner/src/php# vim sonar-project.properties
sonar.projectKey=sonarqube-sample-php-projectKey
sonar.projectName=sonarqube-sample-php-projectName
sonar.projectVersion=1.0
sonar.sources=src # src目录相对于php目录, 因此, 在php目录下还要创建src目录, 存放php代码
sonar.language=php
sonar.sourceEncoding=UTF-8
root@jenkins:/opt/sonar-scanning-examples-master/sonarqube-scanner/src/php# mkdir src
root@jenkins:/opt/sonar-scanning-examples-master/sonarqube-scanner/src/php# mv Math.php src/
root@jenkins:/opt/sonar-scanning-examples-master/sonarqube-scanner/src/php# ll
total 16
drwxr-xr-x 3 root root 4096 Jul 6 23:47 ./
drwxr-xr-x 20 root root 4096 Jun 24 16:41 ../
-rw-r--r-- 1 root root 172 Jul 6 23:47 sonar-project.properties
drwxr-xr-x 2 root root 4096 Jul 6 23:47 src/
root@jenkins:/opt/sonar-scanning-examples-master/sonarqube-scanner/src/php# ll src/
total 16
drwxr-xr-x 2 root root 4096 Jul 6 23:47 ./
drwxr-xr-x 3 root root 4096 Jul 6 23:47 ../
-rw-r--r-- 1 root root 5559 Jun 24 16:41 Math.php
在php
目录下执行扫描命令
root@jenkins:/opt/sonar-scanning-examples-master/sonarqube-scanner/src/php# /apps/sonar-scanner/bin/sonar-scanner
...
INFO: ANALYSIS SUCCESSFUL, you can browse http://10.0.0.139:9000/dashboard?id=sonarqube-sample-php-projectKey
...
NFO: EXECUTION SUCCESS
INFO: ------------------------------------------------------------------------
INFO: Total time: 8.974s
INFO: Final Memory: 6M/24M
INFO:
- 查看结果
3 Gitlab+Jenkins+Sonarqube结合使用
让Jenkins到Gitlab拉取代码到本地, 之后使用SonarScanner进行代码扫描, 然后传到Sonarqube
3.1 通过Jenkins插件执行代码扫描
3.1.1 创建一个测试项目, 测试web-02项目克隆
3.1.2 Jenkins安装插件
root@jenkins:/tmp# systemctl restart jenkins
3.1.3 在Jenkins上, 配置Sonarqube Server地址
3.1.4 在Jenkins上, 配置Sonarscanner的路径
- 如果Jenkins服务器可以联网, 也可使用自动安装, 这样Jenkins会自动下载Scanner到本地, 如果不能上网, 就要通过离线安装包的方式
3.1.5 在Jenkins上, 配置项目构建
选择项目 --> 配置 --> 构建 --> Execute SonarQube Scanner --> 将Analysis properties里的内容填写为代码扫描的properties文件里的内容
jenkins@jenkins:/opt/sonar-scanning-examples-master/sonarqube-scanner/src/php$ vim sonar-project.properties
sonar.projectKey=sonarqube-sample-php-projectKey
sonar.projectName=sonarqube-sample-php-projectName
sonar.projectVersion=1.0
sonar.sources=src
sonar.language=php
sonar.sourceEncoding=UTF-8
本案例内容
sonar.projectKey=project-web-02
sonar.projectName=project-web-02
sonar.projectVersion=1.0
sonar.sources=./ # 这里写./表示当前目录, 也就是相对于/var/lib/jenkins/workspace/test-scanner目录, Scanner会扫描该目录下的所有文件. 如果代码放到了$WORKSPACE/src目录, 那么这里就写src
sonar.languagehtml # web-02里只有一个html文件
sonar.sourceEncoding=UTF-8
- 执行构建
- Sonarqube Server查看结果
3.2 通过脚本自定义代码扫描
配置项目构建时, 无需指定git仓库, 也无需使用Scanner插件, 而是统一把流程定义在构建的Shell脚本中.
先在Jenkins服务器上, 用Jenkins用户运行脚本测试, 如果没问题, 再把脚本保存的构建的Shell脚本中
先用root用户创建/data/jenkins/qq目录, 然后授权给jenkins用户
root@jenkins:~# mkdir -pv /data/jenkins/qq
root@jenkins:~# chown -R jenkins.jenkins /data/jenkins/
切换到jenkins用户下, 创建脚本
jenkins@jenkins:/opt$ vim sonar.sh
#!/bin/bash
cd /data/jenkins/qq # 进到项目目录
rm -rf * && git clone [email protected]:qq/web-02.git # 删除旧的项目内容, clone新的内容
cd web-02 # 进到项目里面
cat >> sonar-project.properties <
INFO: Analysis total time: 3.226 s
INFO: ------------------------------------------------------------------------
INFO: EXECUTION SUCCESS
INFO: ------------------------------------------------------------------------
INFO: Total time: 3.916s
INFO: Final Memory: 12M/44M
INFO: ------------------------------------------------------------------------
测试没问题, 保存到Jenkins配置