使用SonarQube 8.1静态检查OC代码质量
前言
SonarQube是一个开源的代码质量管理系统,它支持包括ObjectiveC、Java、C/C++、C#、PHP在内的超过25种编程语言。它能够提供包括重复代码、编码标准、单元测试、代码覆盖率、代码复杂度、潜在Bug、注释的报告。它还可以与持续集成工具配合使用实现完全自动化的分析。
之前在网上搜索学习SonarQube在Mac上的集成和使用教程,发现教程都比较老,使用的都是较老版本的SonarQube,在集成最新的8.1版本时踩了不少坑。本文就是对在Mac系统上安装和使用新版SonarQube的总结。后续会继续更新使用SonarQube静态分析Swift代码及结合Jenkins进行自动化分析。
注意:SonarQube需要Java 11及以上的运行环境,在终端输入java --version
即可查看系统的Java版本,如果不满足,请先自行下载和安装。
SonarQube平台架构
SonarQube平台主要由四大要件构成:
- 数据库:存放配置数据和检测数据(7.9及以后的版本不再支持MySQL,本文使用的是PostgreSQL)
- Web服务:在本地网页上查看配置数据和代码质量检测结果
- 分析器:对项目代码进行分析(OCLint)
- 插件:支持各种语言的插件
安装配置PostgreSQL数据库
SonarQube运行和储存数据需要数据库,而网上大多数教程使用的MySQL数据库已经不被7.9以后版本的SonarQube支持了,所以我选择了同样开源的关系数据库PostgreSQL。这个数据库和MySQL语法略有不同,但使用上基本大同小异。
我们先来安装和配置PostgreSQL数据库。
安装数据库
安装PostgreSQL数据库有两种方式,一种是Homebrew,一种是直接上官网下载安装程序安装,后一种有可视化界面使用上比较简单。
使用Homebrew安装
安装Homebrew(电脑上已经安装了的可以跳过这步)。
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
安装数据库
brew install postgresql
安装完成后,进行初始化
initdb /usr/local/var/postgres
启动服务
pg_ctl -D /usr/local/var/postgres -l /usr/local/var/postgres/server.log start
设置开机启动
ln -sfv /usr/local/opt/postgresql/*.plist ~/Library/LaunchAgents
launchctl load ~/Library/LaunchAgents/homebrew.mxcl.postgresql.plist
软件方式安装
进入官网按照提示进行下载和安装,安装完之后直接双击运行即可。
使用软件方式安装会自动创建两个用户,一个是postgres,一个是与电脑当前登录用户同名的用户,并且分别为两个用户创建了默认的数据库。后面我们添加用户和数据库时可以登录postgres这个用户进行创建。(注:PostgreSQL数据库可以使用pgAdmin在本地网页图形化界面上进行管理,具体安装和使用请自行搜索)
软件方式安装需要配置一下环境路径,这样我们就可以在命令行直接使用psql
命令。
在 ~/.bash_profile中添加以下内容(具体路径可以查看从图形界面进入psql命令行时显示的路径)
export PATH=$PATH:/Applications/Postgres.app/Contents/Versions/12/bin
保存之后退出,在终端输入source ~/.bash_profile
使设置生效。然后就可以直接在终端中键入psql --version
,显示如下则表示设置成功。
psql (PostgreSQL) 12.2
默认情况下本地用户登录都是受信任的,不需要输入密码,如果想要使用密码登录,可以修改/Users/本地用户名/Library/Application Support/Postgres/var-12/pg_hba.conf
文件,将以下内容中的trust改为md5
# TYPE DATABASE USER ADDRESS METHOD
# "local" is for Unix domain socket connections only
local all all trust
# IPv4 local connections:
host all all 127.0.0.1/32 trust
# IPv6 local connections:
host all all ::1/128 trust
# Allow replication connections from localhost, by a user with the
# replication privilege.
local replication all trust
host replication all 127.0.0.1/32 trust
host replication all ::1/128 trust
修改后
# TYPE DATABASE USER ADDRESS METHOD
# "local" is for Unix domain socket connections only
local all all md5
# IPv4 local connections:
host all all 127.0.0.1/32 md5
# IPv6 local connections:
host all all ::1/128 md5
# Allow replication connections from localhost, by a user with the
# replication privilege.
local replication all md5
host replication all 127.0.0.1/32 md5
host replication all ::1/128 md5
重启PostgreSQL之后使用psql -U 用户名
登录就需要输入密码了。
注:PostgreSQL常用指令如下:
psql -U [user] -d [database] -h [host] -p [post] //登录
\password:设置当前登录用户的密码
\h:查看SQL命令的解释,比如\h select。
\?:查看psql命令列表。
\l:列出所有数据库。
\c [database_name]:连接其他数据库。
\d:列出当前数据库的所有表格。
\d [table_name]:列出某一张表格的结构。
\du:列出所有用户。
\e:打开文本编辑器。
\conninfo:列出当前数据库和连接的信息。
\password [user]: 修改用户密码
\q:退出
配置数据库
首先使用postgres用户登录数据库
psql postgres
然后创建用户sonar并设置密码,这里的密码你可以填写自己的密码
CREATE USER sonar WITH PASSWORD 'sonar';
创建属于用户sonar的数据库sonar
CREATE DATABASE sonar OWNER sonar;
给sonar用户加上添加数据库的权限
ALTER ROLE sonar CREATEDB;
这样,数据库配置就完成了,接下来正式安装SonarQube。
安装和配置SonarQube
安装SonarQube主要分为三步:
- 安装配置SonarQube本地服务器
- 安装配置sonar-scanner
- 安装配置xcpretty、OCLint、slather等工具和插件
安装配置本地服务器
SonarQube的服务可以运行在本地服务器或者远程服务器上,本文主要讲解本地服务器的配置方式。
首先上SonarQube官网上下载SonarQube源文件并解压。
然后配置conf/sonar.properties文件
设置数据库url
sonar.jdbc.url=jdbc:postgresql://localhost/sonar
设置数据库账号密码
sonar.jdbc.username=sonar
sonar.jdbc.password=sonar
进入bin/macosx-universal-64文件夹,给sonar.sh设置权限
chmod 777 sonar.sh
使用./sonar.sh console来启动服务器,在浏览器输入http://localhost:9000
来测试服务器是否启动成功。页面正常显示就表示启动成功。
如果启动失败,可以根据SonarQube项目目录的logs文件夹中的日志查找原因。大部分启动不成功的情况都是数据库原因,这个在web.log文件中有记录。
注:SonarQube常用命令如下:
./sonar.sh console #Debug信息
./sonar.sh start #启动服务
./sonar.sh stop #停止服务
./sonar.sh restart #重启服务
安装和配置sonar-scanner
直接使用HomeBrew
安装sonar-scanner
brew install sonar-scanner
安装完成后输入sonar-scanner -v
或者sonar-scanner --version
可以看到如下配置文件地址和版本信息
INFO: Scanner configuration file: /usr/local/Cellar/sonar-scanner/4.2.0.1873/libexec/conf/sonar-scanner.properties
INFO: Project root configuration file: NONE
INFO: SonarQube Scanner 4.2.0.1873
INFO: Java 11.0.5 Oracle Corporation (64-bit)
INFO: Mac OS X 10.15.2 x86_64
根据上面显示的配置文件地址打开配置文件,即/usr/local/Cellar/sonar-runner/2.5/libexec/conf/sonar-runner.properties
,修改或添加以下内容
sonar.host.url=http://localhost:9000
sonar.jdbc.username=sonar
sonar.jdbc.password=sonar
sonar.jdbc.url=jdbc:postgresql://localhost/sonar
修改完后保存,sonar-scanner这部分就完成了。
安装其他工具和插件
首先安装环境工具。
安装xcpretty
git clone https://github.com/Backelite/xcpretty.git
cd xcpretty
git checkout fix/duration_of_failed_tests_workaround
gem build xcpretty.gemspec
sudo gem install --both xcpretty-0.2.2.gem
安装oclint
brew tap oclint/formulae
brew install oclint
或者
brew cask install oclint
如果使用Homebrew安装失败,可以直接下载安装包oclint-0.13.1-x86_64-darwin-17.4.0.tar.gz安装,下载后目录结构如下:
oclint.png然后把oclint路径加入到环境变量,我是把oclint文件夹放在用户根目录/Users/用户名/oclint-0.13.1
。使用命令vi ~/.bash_profile
进入编辑页面,在末尾加上
export PATH="/Users/用户名/oclint-0.13.1/bin:$PATH"
然后使用:wq
保存退出即可
安装slather
gem install slather
安装lizard
sudo pip install lizard
安装OC代码静态分析插件
由于官方插件SonarCFamily比较贵,使用开源的就好。
在这里下载相应版本的jar文件即可(也可以下载源文件自行编译,这个比较费时间,不推荐)。将下载好的jar文件放到SonarQube安装目录下的extensions/plugins文件夹中,插件安装就完成了。
使用SonarQube静态扫描代码
终端路径切换到待扫描项目的根目录下,输入touch run-sonar.sh
命令生成run-sonar.sh,然后输入vi run-sonar.sh
编辑文件,在里面添加以下内容(注意把里面的xxx
更改为你的项目名称的Scheme名称):
xcodebuild -workspace xxx.xcworkspace -scheme xxx clean build | tee xcodebuild.log | xcpretty --report json-compilation-database
mv build/reports/compilation_db.json compile_commands.json
oclint-json-compilation-database -exclude Pods -- -report-type pmd -o oclint.xml -max-priority-1 99999 -max-priority-2 99999 -max-priority-3 99999 -rc LONG_LINE=140 -rc LONG_METHOD=80 -rc NCSS_METHOD=50 -rc SHORT_VARIABLE_NAME=1 -rc CYCLOMATIC_COMPLEXITY=13 -rc MINIMUM_CASES_IN_SWITCH=2 -rc NPATH_COMPLEXITY=1500
rm -rf sonar-reports
mkdir sonar-reports
cat oclint.xml | sed "s#Switch Statements Should Have Default Rule#switch statements should have default#g" | sed "s#missing hash method#must override hash with isEqual#g" | sed "s#prefer early exits and continue#use early exits and continue#g" | sed "s#use boxed expression#replace with boxed expression#g" | sed "s#use container literal#replace with container literal#g" | sed "s#use number literal#replace with number literal#g" | sed "s#use object subscripting#replace with object subscripting#g" | sed "s#missing default in switch statements#switch statements should have default#g" | sed "s#unnecessary default statement in covered switch statement#switch statements don't need default when fully covered#g" | sed "s#covered switch statements dont need default#switch statements don't need default when fully covered#g" > sonar-reports/oclint.xml
/bin/sh sonar-scanner -X
以同样的方式新建sonar-project.properties文件,使用vi命令添加以下内容(同样注意替换项目的相关内容):
##########################
# Required configuration #
##########################
sonar.projectKey=你的项目Key
sonar.projectName=项目名
sonar.projectVersion=版本号
sonar.language=objc
# Project description
sonar.projectDescription=Text sonarquebe
# Path to source directories
sonar.sources=项目源码文件夹名称
# Path to test directories (comment if no test)
# sonar.tests=testSrcDir
# Xcode project configuration (.xcodeproj or .xcworkspace)
# -> If you have a project: configure only sonar.objectivec.project
# -> If you have a workspace: configure sonar.objectivec.workspace and sonar.objectivec.project
# and use the later to specify which project(s) to include in the analysis (comma separated list)
sonar.objectivec.project=项目名.xcodeproj
# sonar.objectivec.workspace=myApplication.xcworkspace
# Scheme to build your application
sonar.objectivec.appScheme=需要编译的Scheme名
# Scheme to build and run your tests (comment following line of you don't have any tests)
# sonar.objectivec.testScheme=myApplicationTests
##########################
# Optional configuration #
##########################
# Encoding of the source code
sonar.sourceEncoding=UTF-8
# JUnit report generated by run-sonar.sh is stored in sonar-reports/TEST-report.xml
# Change it only if you generate the file on your own
# The XML files have to be prefixed by TEST- otherwise they are not processed
# sonar.junit.reportsPath=sonar-reports/
# Cobertura report generated by run-sonar.sh is stored in sonar-reports/coverage.xml
# Change it only if you generate the file on your own
sonar.objectivec.coverage.reportPattern=sonar-reports/coverage*.xml
# OCLint report generated by run-sonar.sh is stored in sonar-reports/oclint.xml
# Change it only if you generate the file on your own
sonar.objectivec.oclint.report=oclint.xml
sonar.objectivec.oclint.reportPath=sonar-reports/oclint.xml
# Paths to exclude from coverage report (tests, 3rd party libraries etc.)
# sonar.objectivec.excludedPathsFromCoverage=pattern1,pattern2
sonar.objectivec.excludedPathsFromCoverage=.*Tests.*
# Project SCM settings
# sonar.scm.enabled=true
# sonar.scm.url=scm:git:https://...
输入wq
命令保存并退出。
为避免编译的时候出现oclint: error: one compiler command contains multiple jobs:
的报错,需要使用XCode打开工程文件并且在Build Settings中将COMPILER_INDEX_STORE_ENABLE设置为NO。
进入到SonarQube项目文件夹,进入到bin/macosx-universal-64,使用命令./sonar.sh restart
来重启服务器。
如果重启服务器失败,可以先看看PostgreSQL有没有正常启动,如果没有,按照前面PostgreSQL配置步骤启动。
上面的步骤全部完成后,就可以在工程目录下使用./run-sonar.sh
或sh run-sonar.sh
命令来执行脚本。
命令执行行完毕并且没有报错,就可以在浏览器中输入http://localhost:9000查看检测结果。
sonarqube_snap.png