使用SonarQube静态检查OC代码质量

SonarQube是一个开源的代码质量管理系统,它支持包括ObjectiveC、Java、C/C++、C#、PHP在内的超过25种编程语言。它能够提供包括重复代码、编码标准、单元测试、代码覆盖率、代码复杂度、潜在Bug、注释的报告。它还可以与持续集成工具配合使用实现完全自动化的分析。

之前在网上搜索学习 SonarQube 在Mac上的集成和使用教程,发现教程都比较老,使用的都是较老版本的 SonarQube ,在集成最新的8.1版本时踩了不少坑。本文就是对在Mac系统上安装和使用新版SonarQube的总结。后续会继续更新使用 SonarQube 静态分析Swift代码及使用 Jenkins 进行自动化分析。

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

软件方式安装

进入 官网 按照提示进行下载和安装,安装完之后直接双击运行即可。

使用软件方式安装会自动创建两个用户,一个是postgres,一个是与电脑当前登录用户同名的用户,并且分别为两个用户创建了默认的数据库。后面我们添加用户和数据库时可以登录postgres这个用户进行创建。(注: PostgreSQL 数据库可以使用 pgAdmin 在本地网页图形化界面上进行管理,具体安装和使用请自行搜索)

软件方式安装需要配置一下环境路径,这样我们就可以在命令行直接使用 psql 命令。

在 ~/.bash_profile中添加以下内容(具体路径可以查看从图形界面进入 psql 命令行时显示的路径)

export PATH=$PATH:/Applications/Postgres.app/Contents/Versions/12/bin

保存之后退出,在终端输入 source ~/.bash_profile 使设置生效。然后就可以直接在终端中键入 psql ,显示如下则表示设置成功。

psql (12.1)
Type "help" for help.

默认情况下本地用户登录都是受信任的,不需要输入密码,如果想要使用密码登录,可以修改 /Users/本地用户名/Library/Application Support/Postgres/var-12/pg_hba.conf 文件,将以下内容

# 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 用户名 登录就需要输入密码了。

配置数据库

首先使用 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
  • 安装配置 xcprettyOCLintslather 等工具和插件

安装配置本地服务器

SonarQube的服务可以运行在本地服务器或者远程服务器上,本文主要讲解本地服务器的配置方式。

首先上 SonarQube官网 上下载SonarQube源文件并解压。

然后配置conf/sonar.properties文件

设置数据库版本

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 需要Java版本需要升级到 Java 11 及以上,否则会报错。

注: 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 cask install oclint

安装slather

gem install slather

安装lizard

sudo pip install lizard

然后是安装静态分析插件,由于官方插件 SonarCFamily 比较贵,使用开源的就好。

这里 下载最新版本的源文件压缩包,解压后终端切换到源文件根目录。

在执行编译前要确保系统安装了maven,否则需要先进行安装

brew install maven

接下来就可以对源文件进行编译了

mvn package

编译完成后 backelite-sonar-objective-c-plugin-0.6.2.jar 文件在 sonar-objective-c-plugin/target 中可以找到,将jar文件复制到 SonarQube 安装目录下的 extensions/plugins 文件夹中。

使用SonarQube静态扫描代码

终端路径切换到待扫描项目的根目录下,输入 touch run-sonar.sh 命令生成 run-sonar.sh ,然后输入 vi run-sonar.sh 编辑文件,在里面添加以下内容:

cd /Users/你的用户名/你的项目根目录路径

xcodebuild -workspace 项目名.xcworkspace -scheme scheme名 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 命令保存并退出。

进入到 SonarQube 项目文件夹,进入到bin/macosx-universal-64,使用命令 ./sonar.sh restart 来重启服务器。

上面的步骤全部完成后,就可以在工程目录下使用 ./run-sonar.shsh run-sonar.sh 命令来执行脚本。

命令招行完毕并且没有报错,就可以在浏览器中输入””

我来评几句
登录后评论

已发表评论数()

相关站点

热门文章