iOS自动化代码检查及持续集成(xcode+oclint+xcpretty+Jenkins)

OCLint是什么?

OCLint是一个静态代码分析工具,通过检查C,C ++和Objective-C代码并寻找潜在问题来提高质量和减少缺陷:

  • 如果/ else / try / catch / finally语句为空
  • 未使用的局部变量和参数
  • 高圈复杂度,NPath复杂度和高NCSS
  • 冗余if语句和无用的括号
  • 长方法和长参数列表
  • 倒置逻辑和参数重新分配
    ...
    总结:OCLint实现自动化审查代码规范,提升代码质量,帮助广大开发者节省CodeReview的人力~
安装OClint工具
1、Homebrew Tap

重点讲述下Homebrew安装OCLint,不为什么,因为这个方法最快速简单~
安装OCLint方法:

$ brew tap oclint/formulae
$ brew install oclint

更新OClint方法:

$ brew update
$ brew upgrade oclint

验证OClint成功安装

$ oclint
oclint: Not enough positional command line arguments specified!
Must specify at least 1 positional arguments: See: oclint -help
2、安装包安装
  • 进入oclint release下载页,下载最新版本安装包Source code(tar.gz)
  • 解压下载文件得到oclint-0.14文件,将文件放在某个目录下,如/User/XXX/OCLint
  • 打开终端编辑.bash_profile文件(先输入cd~,然后输入open -e .bash_profile,这时./bash_profile就会打开),将oclint添加到环境变量中,如下:
OCLint_HOME=/User/XXX/OCLint/oclint-0.14
export PATH=$OCLINT_HOME/bin:$PATH
  • 保存文件,关闭.bash_profile文件
  • 更新刚配置的环境变量:输入source .bash_profile,重启终端就可以执行oclint命令啦~
3、编译源码安装

这个就不详细多说了,大家可以看oclint官网说明

xcobuild的安装

这个只要下载Xcode工具,即可安装~

xcpretty 的安装
sudo gem install -n /usr/local/bin  xcpretty

这里说下我遇到的Error问题:

 gem install xcpretty
 ERROR:  While executing gem ... (Gem::FilePermissionError)
    You don't have write permissions for the /Library/Ruby/Gems/2.3.0 directory.

所以我换了sudo gem install -n /usr/local/bin xcpretty命令行,就解决了~

OCLint + Xcode结合使用

1、在工程中,创建一个新的Target,命令为OCLintTest~


0CDCE218EA7B7376C50AD9DE9B826E31.png

2、在OCLintTest上添加Run Script,如图:


D5AB956BD47F4BB5D641674D06874332.png

Xcode上Shell脚本,没有Pods的脚本编写代码:
source ~/.bash_profile
cd ${SRCROOT}
xcodebuild clean
xcodebuild build | tee xcodebuild.log | xcpretty -r json-compilation-database -o compile_commands.json
oclint-json-compilation-database -- -report-type Xcode

编译后的Xcode警告截图:


DFB37F40C41B35476D75CA27E5AA6BDE.png
OCLint+shell脚本结合使用
#!/bin/bash

# 指定编码
export LANG="zh_CN.UTF-8"
export LC_COLLATE="zh_CN.UTF-8"
export LC_CTYPE="zh_CN.UTF-8"
export LC_MESSAGES="zh_CN.UTF-8"
export LC_MONETARY="zh_CN.UTF-8"
export LC_NUMERIC="zh_CN.UTF-8"
export LC_TIME="zh_CN.UTF-8"


function checkDepend () {
command -v xcpretty >/dev/null 2>&1 || {
echo >&2 "I require xcpretty but it's not installed.  Install:gem install xcpretty";
exit
}
command -v oclint-json-compilation-database >/dev/null 2>&1 || {
echo >&2 "I require oclint-json-compilation-database but it's not installed.  Install:brew install oclint";
exit
}
}

function oclintForProject () {

# 检测依赖
checkDepend

projectName=$1
scheme=$2
reportType=$3

REPORT_PMD="pmd"
REPORT_XCODE="Xcode"

myworkspace=${projectName}
myscheme=${scheme}
echo "myworkspace是:${myworkspace}"
echo "myscheme是:${myscheme}"
echo "reportType为:${reportType}"

# 清除上次编译数据
if [ -d ./build/derivedData ]; then
echo '-----清除上次编译数据derivedData-----'
rm -rf ./build/derivedData
fi

# xcodebuild -workspace $myworkspace -scheme $myscheme clean
xcodebuild clean

echo '-----开始编译-----'

# 生成编译数据
xcodebuild -workspace ${myworkspace} -scheme ${myscheme} -UseModernBuildSystem=NO -derivedDataPath ./build/derivedData -configuration Debug COMPILER_INDEX_STORE_ENABLE=NO | xcpretty -r json-compilation-database -o compile_commands.json


if [ -f ./compile_commands.json ]
then
echo '-----编译数据生成完毕-----'
else
echo "-----生成编译数据失败-----"
return -1
fi

echo '-----分析中-----'

# 自定义排除警告的目录,将目录字符串加到数组里面
# 转化为:-e Debug.m -e Port.m -e Test
exclude_files=("Pods")

exclude=""
for i in ${exclude_files[@]}; do
exclude=${exclude}"-e "${i}" "
done
echo "排除目录:${exclude}"

# 分析reportType =~判断子字符串包含关系
if [[ ${reportType} =~ ${REPORT_PMD} ]]
then
nowReportType="-report-type html -o pmd.html"
else
nowReportType="-report-type Xcode"
fi
# 自定义report 如:
# nowReportType="-report-type html -o oclint_result.html"

echo "**************${nowReportType}"

# 生成报表
oclint-json-compilation-database ${exclude} -- \
${nowReportType} \
-rc=LONG_CLASS=1500 \
-rc=NESTED_BLOCK_DEPTH=5 \
-rc=LONG_VARIABLE_NAME=80 \
-rc=LONG_METHOD=200 \
-rc=LONG_LINE=300 \
-disable-rule ShortVariableName \
-disable-rule ObjCAssignIvarOutsideAccessors \
-disable-rule AssignIvarOutsideAccessors \
-max-priority-1=100000 \
-max-priority-2=100000 \
-max-priority-3=100000

#rm compile_commands.json
if [[ ${reportType} =~ ${REPORT_PMD} ]] && [ ! -f ./pmd.html ]
then
echo "-----分析失败-----"
return -1
else
echo '-----分析完毕-----'
return 0
fi
}

# 替换workspace的名字
myworkspace="OCLint.xcworkspace"
# 替换scheme的名字
myscheme="OCLint"
# 输出方式 Xcode/pmd
reportType="pmd"

oclintForProject ${myworkspace} ${myscheme} ${reportType}

以上就是完整的shell脚本,oclint.sh下载地址,用法:下载oclint.sh文件,拖到Xcode工程目录下,如图:

5965A58FB5EE8844DF72D7333C01048D.png

终端进入工程目录,执行命令行,就可以自动审查代码规范啦~

./oclint.sh

执行后生成的html文件,打开界面如图:


oclint report.png
OCLint + Jenkins实现自动化审查代码规范

一、在Jenkins的插件管理里面,下载PMD插件并安装
二、Jenkins新建自由任务,如图:


F80B7C4D8AD60FA74CCF68F6D0691A3F.png

三、工程相关配置

1、General

这里我选的是github上我的一个项目,参数化构建过程我添加了Git Parameter的分支参数,用于选择构建的一个分支,如图:


屏幕快照 2019-07-11 下午4.46.47.png
2、源码管理

这里我设置了git仓库地址以及自己的用户账号和密码,还有分支参数,如图所示:


FDA6444B-6A5A-40E3-BD39-70CD27252243.png
3、构建触发器

我选的是定时构建~

4、构建

选择执行shell,shell里面代码与oclint.sh不同的地方就是:

#这里是将xcpretty的安装路径导入到jenkins,为了解决xcpretty命令找不到的错误
export PATH=$PATH:/usr/local/bin
#拉取git工程
git clean -df
git fetch
git reset --hard $GIT_BRANCH
#代码修改为pmd格式的,因为展示在pmd插件上
nowReportType="-report-type pmd -o pmd.html"
#还有修改,查找文件路径地方也要做相应的修改
project_path=$(pwd)
cd "${project_path}/BaSiBuDeJie"
echo "pwd === $(pwd)"
# 替换workspace的名字
myworkspace="BaSiBuDeJie.xcworkspace"
# 替换scheme的名字
myscheme="BaSiBuDeJie"
# 输出方式 Xcode/pmd
reportType="pmd"

完整Jenkins-OCLint代码下载

5、构建后操作

构建后操作需要选上PMD的插件了,如图所示:


6B0A4D8841569B2BB8410F11E96AA297.png
6、Jenkins + OCLint结合操作后的效果图
PMD Warning.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容