背景
隨著代碼量的日益增加,以及團隊的擴大,我們往往因為需求需要盡快上線以及快速迭代,導(dǎo)致代碼并不是很規(guī)范,時間長了就留下了一堆技術(shù)債,代碼的質(zhì)量也沒有了保證。所以開始嘗試一些代碼質(zhì)量相關(guān)建設(shè),希望能夠通過代碼靜態(tài)掃描的方式,幫助我們掃描出一些代碼漏洞,然后嘗試去修復(fù)漏洞和bug,以此來保證代碼質(zhì)量。
工具與平臺
本文涉及的工具及平臺:
開源方案介紹及配置
大部分iOS平臺代碼靜態(tài)分析基本是基于開源的oclint或者infer進行的,本文雖然使用sonarqube,但免費的分析方案核心仍然是oclint與infer
sonarqube是一個開源的靜態(tài)代碼分析平臺,提供免費的社區(qū)版,免費的社區(qū)版不支持Objective-C,但github有提供開源的插件,Objective-C,付費的社區(qū)版plus有支持Objective-C的分析插件SonarCFamily for C
無論免費方案還是付費方案,首先都是基于xcodebuid過程中的日志來進行的,我們這次主要針對開源方案來講相關(guān)配置流程。
對于使用開源方案來說,本質(zhì)流程如下:
xcodebuild
iOS核心工具,安裝好Xcode就會自帶此工具,因為oclint分析的核心是xcodebuild在編譯app過程中的log,所以需要xcodebuild(build失敗也會對已經(jīng)build的日志進行分析,但盡量保證可以build成功)
如果項目是在workspace中需要指定-workspace和對應(yīng)的scheme,可以通過xcodebuild -list查看
//執(zhí)行
$ xcodebuild -list
//執(zhí)行
$ xcodebuild -workspace CsdnPlus.xcworkspace -scheme CsdnPlus
我們并不需要打出的IPA包可以安裝到手機上,只是需要build過程中的日志而已,所以我們只需要打出模擬器下Debug包就可以了。
//執(zhí)行
$ xcodebuild -showsdks
因為xcodebuild會有緩存,所以我們每次執(zhí)行前需要clean
$ xcodebuild -workspace CsdnPlus.xcworkspace -scheme CsdnPlus clean
執(zhí)行build編譯
$ xcodebuild -scheme CsdnPlus -workspace CsdnPlus.xcworkspace -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 12 Pro Max' -configuration Debug
能編譯成功的話就可以進入下一步了
xcpretty
xcpretty is a fast and flexible formatter for xcodebuild.
It does one thing, and it should do it well.
xcpretty是一個格式化xcodebuild輸出的工具。安裝:
$ gem install xcpretty
-r, --report指定生成的報告格式可選為junit, html, json-compilation-database。
-o, --output指定生成的文件名稱。
這里我們使用json-compilation-database格式,輸出文件名為compile_commands.json
(注意輸出名稱不能更改,否則后面oclint會報錯,因為oclint源碼中內(nèi)置了校驗名稱,具體可查看源碼)
用法:
緊跟在xcodebuild相關(guān)語句后面,比如:
$ xcodebuild [flags] | xcpretty
可以結(jié)合tee進行日志收集
$ xcodebuild [flags] | tee xcodebuild.log | xcpretty
執(zhí)行完整命令生成編譯數(shù)據(jù)compile_commands.json文件:
首先需要用
xcodebuildclean和build項目,并且添加COMPILER_INDEX_STORE_ENABLE=NO參數(shù),不然可能會出現(xiàn)報錯:oclint: error: one compiler command contains multiple jobs報錯
$ xcodebuild -scheme CsdnPlus -workspace CsdnPlus.xcworkspace -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 12 Pro Max' -configuration Debug GCC_PRECOMPILE_PREFIX_HEADER=YES CLANG_ENABLE_MODULE_DEBUGGING=NO COMPILER_INDEX_STORE_ENABLE=NO OTHER_CFLAGS="-DNS_FORMAT_ARGUMENT(A)= -D_Nullable_result=_Nullable" | tee xcodebuild.log | xcpretty -r json-compilation-database -o compile_commands.json
OCLint
OCLint is a static code analysis tool for improving quality and reducing defects by inspecting C, C++ and Objective-C code
OCLint 是基于 Clang Tooling 開發(fā)的靜態(tài)分析工具,主要用來發(fā)現(xiàn)編譯器檢查不到的那些潛在的關(guān)鍵技術(shù)問題。是進行OC代碼分析的核心工具,主要對上一步生成的compile_commands.json進行分析,生成報告
命令安裝:
$ brew tap oclint/formulae
$ brew install oclint
我建議使用安裝包來安裝
OCLint,Homebrew安裝只能安裝到20.11版本,最新Xcode版本對應(yīng)的是22.02。如果安裝版本不符合,OClint分析出來只有一堆compiler error。
image
下載安裝包安裝:
https://github.com/oclint/oclint/releases
配置環(huán)境變量:
export PATH="/Users/csdn/oclint-22.02/bin:$PATH"
source ~/.zshrc
在終端輸入 oclint --version,驗證是否安裝成功。

在終端輸入
oclint --help 查看命令介紹其中我們主要使用oclint-json-compilation-database命令,Github源碼
oclint-json-compilation-database命令支持指定校驗文件夾和過濾指定文件夾,本質(zhì)上最終執(zhí)行oclint -p命令,可以通過附加-v查看,同時還支持使用--后面跟上oclint執(zhí)行參數(shù)。
例如:
// 此處--符號后的參數(shù)是傳遞給oclint的
$ oclint-json-compilation-database -v -e Pods -e xxxx -- -report-type html -o report.html
oclint的-rc選項可以自定義校驗的參數(shù)值,例如:
$ oclint-json-compilation-database -v -e Pods -e xxxx -- -rc LONG_METHOD=60 -rc LONG_LINE=100
另外當(dāng)我們需要自定義多個
oclint參數(shù)時,我們可以將配置寫在.oclint文件中
disable-rules: // 不使用的規(guī)則
- LongLine
rulePaths: // oclint校驗規(guī)則所在的路徑,Mac端默認(rèn)在/usr/local/lib/oclint/rules,如果不需要自定義規(guī)則的話可以不配置此項
- /etc/rules
rule-configurations: // 自定義配置參數(shù)
- key: CYCLOMATIC_COMPLEXITY
value: 15
- key: NPATH_COMPLEXITY
value: 300
output: oclint.xml // 生成的報告
report-type: xml // 生成的報告格式支持html、xml、json等
max-priority-1: 20 // 級別1的問題最大個數(shù),如果檢測出的問題超過這個個數(shù)就會自動終止
max-priority-2: 40 // 級別2的問題最大個數(shù)
max-priority-3: 60 // 級別3的問題最大個數(shù)
enable-clang-static-analyzer: false //
以下是OCLint內(nèi)置支持的72條Rule,可以通過 --list-enabled-rules x查看
$ oclint --list-enabled-rules x
enabled rules:
- TooManyMethods
- DestructorOfVirtualClass
- DeadCode
- EmptyForStatement
- AvoidDefaultArgumentsOnVirtualMethods
- ProblematicBaseClassDestructor
- MisplacedDefaultLabel
- EmptyFinallyStatement
- CallingProhibitedMethod
- RedundantIfStatement
- CollapsibleIfStatements
- UnnecessaryElseStatement
- ConstantConditionalOperator
- DeepNestedBlock
- AssignIvarOutsideAccessors
- UnnecessaryNullCheckForDealloc
- RedundantNilCheck
- RedundantLocalVariable
- EmptyDoWhileStatement
- UnusedMethodParameter
- BitwiseOperatorInConditional
- ReturnFromFinallyBlock
- MultipleUnaryOperator
- DoubleNegative
- MissingCallToBaseMethod
- EmptyWhileStatement
- ShortVariableName
- ParameterReassignment
- UselessParentheses
- ThrowExceptionFromFinallyBlock
- UnnecessaryDefaultStatement
- HighNcssMethod
- PreferEarlyExit
- MissingBreakInSwitchStatement
- TooManyParameters
- CallingProtectedMethod
- AvoidBranchingStatementAsLastInLoop
- MissingAbstractMethodImplementation
- MissingHashMethod
- MisplacedNullCheck
- MisplacedNilCheck
- UseContainerLiteral
- LongLine
- ForLoopShouldBeWhileLoop
- HighNPathComplexity
- LongMethod
- EmptySwitchStatement
- RedundantConditionalOperator
- EmptyTryStatement
- EmptyCatchStatement
- UseObjectSubscripting
- AvoidPrivateStaticMembers
- EmptyElseBlock
- InvertedLogic
- LongClass
- LongVariableName
- GotoStatement
- BrokenOddnessCheck
- UseNumberLiteral
- TooFewBranchesInSwitchStatement
- UseBoxedExpression
- JumbledIncrementer
- EmptyIfStatement
- BranchDivergence
- MissingDefaultStatement
- HighCyclomaticComplexity
- NonCaseLabelInSwitchStatement
- ConstantIfExpression
- BrokenNullCheck
- BrokenNilCheck
- TooManyFields
- UnusedLocalVariable
如果我們使用.oclint最終我們將.oclint放在與compile_commands.json相同的路徑下,并在該路徑下執(zhí)行命令:
$ oclint-json-compilation-database -v -e Pods
或者直接執(zhí)行命令:
$ oclint-json-compilation-database -e Pods -- -report-type pmd \
-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 \
-allow-duplicated-violations=false\
-max-priority-1=100000 \
-max-priority-2=100000 \
-max-priority-3=100000 >> oclint.xml
最終會生成oclint.xml(也可以自己生成html格式,直接查看效果)
Infer
Infer是Facebook開源的一款代碼掃描軟件,可以分析Objective-C,Java或者C代碼,報告潛在的問題。任何人都可以使用Infer檢測應(yīng)用,這可以將那些嚴(yán)重的 bug 扼殺在發(fā)布之前,同時防止應(yīng)用崩潰和性能低下。
- 命令安裝
$ brew install infer
在終端輸入 infer --version,驗證是否安裝成功。

Infer與OCLint一樣,都是分析compile_commands.json文件。在compile_commands.json文件相同路徑下執(zhí)行命令:
# --skip-analysis-in-path 是忽略掃描目錄
$ infer run --skip-analysis-in-path Pods --keep-going --compilation-database compile_commands.json
注意:命令中一定要有
--keep-going不然會有錯誤導(dǎo)致無法進行分析。
另外需要在xcodebuild命令中添加OTHER_CFLAGS="-DNS_FORMAT_ARGUMENT(A)= -D_Nullable_result=_Nullable"。


掃描出的結(jié)果會在工程目錄下的
infer-out 文件中,其中具體的代碼會以 csv,txt,json 的格式分別存在對應(yīng)的文件中。
總結(jié):
OCLint基本上分析都是一些代碼規(guī)范的問題,Infer可以檢查出空指針訪問、資源泄露以及內(nèi)存泄露。
sonarqube
sonarqube是一個提供代碼靜態(tài)分析的平臺,提供了一套完整的靜態(tài)分析方案,包括后端及前端頁面,可以結(jié)合jenkins、gitlab等平臺來進行代碼分析。sonarqube分社區(qū)版本和商業(yè)化版本,能掃描多種語言并且開源。官網(wǎng)地址。
因為其底層源碼為java開發(fā)的,所以對java代碼支持比較完善,但是免費的社區(qū)版并不支持OC,所以我們?nèi)绻柚似脚_的話,有以下兩種方式:
- 開源插件sonar-swift
,支持Objective-C和Swift/Java,支持導(dǎo)入SwiftLint、Infer、OCLint、Lizard、Fauxpas工具的掃描分析結(jié)果。最新v1.6版本,兼容SonarQube 8.9LTS版本。該插件是好未來研發(fā)團隊研發(fā)并且開源。 - 付費使用社區(qū)版plus,提供了SonarCFamily for C插件
有官方提供技術(shù)支持,250+的rules可供選擇,不可自定義規(guī)則。
我們將使用開源插件方案。
sonar-services(sonarqube)安裝
sonarqube 安裝有兩種方式
- docker 安裝
$ docker pull sonarqube:8.9.7-community
- 下載二進制安裝包
選中 8.9.7LTS 社區(qū)版本,下載
image
下載完安裝包后,進入bin/macosx-universal-64 目錄。執(zhí)行命令:
$ sh sonar.sh start

控制臺輸出Started SonarQube說明啟動成功。
在瀏覽器訪問http://localhost:9000/,能打開頁面說明啟動成功。
默認(rèn)賬號為admin,密碼為admin。
注意:如果啟動失敗可以去
sonarqube/logs下查看日志。
image
安裝時,發(fā)現(xiàn)sonarqube 8.9.7版本需要Java 11環(huán)境。所以需要先安裝Java 11環(huán)境。
安裝Java 11:
image
image
啟動成功后我們在最下面會看到warning

警告建議我們自己配置數(shù)據(jù)庫,需要說明的是SonarQube如果想持久化保存數(shù)據(jù),是需要依賴數(shù)據(jù)庫的。
SonarQube默認(rèn)提供H2存儲,只能暫時存儲一些小項目結(jié)果,僅為了演示使用。
在conf/sonar.properties下配置數(shù)據(jù)庫地址即可??蛇x MySQL、Oracle、PostgreSQL。
下面我們就來配置數(shù)據(jù)庫(mysql后續(xù)將不再支持):這里我們使用的是PostgreSQL,配置參考
PostgreSQL
用Homebrew 執(zhí)行命令安裝PostgreSQL:
$ brew install postgresql //安裝
安裝完數(shù)據(jù)庫后,啟動數(shù)據(jù)庫,執(zhí)行命令:
$ pg_ctl -D /usr/local/var/postgres start //啟動
$ createdb //創(chuàng)建數(shù)據(jù)庫
$ psql //登錄控制臺
數(shù)據(jù)庫安裝創(chuàng)建好后,我們需要提供一個數(shù)據(jù)庫和賬號sonarqube使用。執(zhí)行命令:
CREATE USER sonarqube WITH PASSWORD 'sonarqube';//創(chuàng)建用戶
CREATE DATABASE sonar OWNER sonarqube;//創(chuàng)建屬于該用戶的數(shù)據(jù)庫
創(chuàng)建完成后執(zhí)行命令退出:
\q
然后我們?nèi)?code>sonarqube/conf目錄下編輯sonar.properties,將數(shù)據(jù)庫相應(yīng)配置配置完成
sonar.jdbc.username=sonarqube
sonar.jdbc.password=sonarqube
sonar.jdbc.url=jdbc:postgresql://localhost/sonar
編輯完成后在sonarqube/bin/macosx-universal-64/目錄下執(zhí)行: sh sonar.sh restart,此時警告已經(jīng)消除了。
至此我們的sonarqube的前端服務(wù)已經(jīng)配置完成了。
漢化包安裝
通過Github 下載對應(yīng)版本漢化包jar包插件。
下載插件放到
/extensions/plugins 目錄下。重啟sonarqube服務(wù),就可以看到漢化后的界面。sonar-swift
通過GitHub 下載對應(yīng)插件
下載插件放到
/extensions/plugins 目錄下。重啟sonarqube服務(wù),就可以了。
sonar-scanner
sonar-scanner 用來掃描本地代碼,并且上傳到SonarQube平臺中。
-
下載安裝地址;按照不同的操作系統(tǒng)選擇不同安裝包即可。
image - 配置環(huán)境變量:
$ vim ~/.bash_profile
#sonar-scanner for cli
export PATH=$PATH:/Users/csdn/scanner/bin:$PATH
$ source ~/.bash_profile
sonar-scanner分為兩種使用方式:
- 配置文件方式:
在需要掃描項目根目錄下新建sonar-project.properties 文件,內(nèi)容如下:
sonar.projectKey=CsdnPlus
sonar.projectName=CsdnPlus
sonar.language=objc
sonar.sources=/Users/csdn/.jenkins/workspace/csdn_build_ios/
sonar.objectivec.workspace=CsdnPlus.xcworkspace
sonar.objectivec.appScheme=CsdnPlus
sonar.sourceEncoding=UTF-8
sonar.junit.reportsPath=sonar-reports/
sonar.objectivec.oclint.report=sonar-reports/oclint.xml
sonar.swift.infer.report=infer-out/report.json
進入項目根目錄下,然后輸入sonar-scanner命令,執(zhí)行代碼分析。
- 命令行方式:
在命令中設(shè)置了參數(shù):
sonar-scanner -Dsonar.projectKey=CsdnPlus -Dsonar.projectName=CsdnPlus -Dsonar.projectName=CsdnPlus -Dsonar.projectVersion=5.1.0
如果我們要SonarQube忽略一些指定目錄或者文件的掃描,可以在配置中添加sonar.exclusions 例如:
//忽略指定文件目錄或者文件
sonar.exclusions=**/Resource/**,**/*.py
或者可以在命令中設(shè)置參數(shù),例如:
sonar-scanner -Dsonar.exclusions=**/Resource/**,**/*.py -Dsonar.projectKey=CsdnPlus -Dsonar.projectName=CsdnPlus -Dsonar.projectName=CsdnPlus -Dsonar.projectVersion=5.1.0
這里的核心便是在上面步驟中由OCLint生成的oclint.xml文件與Infer生成的report.json,另外注意oclint.xml必須放至sonar-reports文件下。report.json在Infer生成的infer-out目錄下。
命令執(zhí)行成功后,便可在sonarQube的前端頁面看到對應(yīng)的檢測效果了。

檢測效果圖:
集成進Jenkins
我們項目本身已經(jīng)有自動化構(gòu)建服務(wù),所以比較方便。
-
Jenkins項目配置,選項中增加OCLint(可以自己命名)選項
image 構(gòu)建Shell命令中,增加OCLint相關(guān)命令
if [ "$MODE"x = "OCLint"x ]
then
sh /Users/csdn/.jenkins/workspace/csdn_build_ios/fastlane/oclint.sh "$GIT_BRANCH"
fi
- 企業(yè)微信通知, Shell中增加企業(yè)微信機器人URL
//獲取本機IP
local_ip=$(ifconfig | grep '\<inet\>'| grep -v '127.0.0.1' | awk '{ print $2}' | awk 'NR==1')
curl 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxxx' \
-H 'Content-Type: application/json' \
-d '
{
"msgtype":"news",
"news":{
"articles":[
{
"title":"SonarQube 靜態(tài)代碼掃描完成",
"url":"http://'${local_ip}':9000/",
"description":"APP名稱:CSDNAPP\n掃描代碼分支:'$1'",
"picurl":"https://img-bss.csdnimg.cn/202103251639445966.png"
}
]
}
}'
一些有用的
shell命令獲取APP名稱:
product_name=`sed -n '/PRODUCT_NAME/{s/PRODUCT_NAME = //;s/;//;s/^[[:space:]]*//;s/\"http://g;p;q;}' ./$myscheme.xcodeproj/project.pbxproj`獲取APP版本:
version_number=`sed -n '/MARKETING_VERSION/{s/MARKETING_VERSION = //;s/;//;s/^[[:space:]]*//;s/\"http://g;p;q;}' ./$myscheme.xcodeproj/project.pbxproj`獲取本機IP地址:
local_ip = $(ifconfig | grep '\<inet\>'| grep -v '127.0.0.1' | awk '{ print $2}' | awk 'NR==1')
- 附上完整
oclint.sh命令:
#!/bin/bash
COLOR_ERR="\033[1;31m" #出錯提示
COLOR_SUCC="\033[0;32m" #成功提示
COLOR_QS="\033[1;37m" #問題顏色
COLOR_AW="\033[0;37m" #答案提示
COLOR_END="\033[1;34m" #顏色結(jié)束符
# 尋找項目的 ProjectName
function searchProjectName () {
# maxdepth 查找文件夾的深度
find . -maxdepth 1 -name "*.xcodeproj"
}
function oclintForProject () {
# 預(yù)先檢測所需的安裝包是否存在
if which xcodebuild 2>/dev/null; then
echo 'xcodebuild exist'
else
echo 'xcodebuild 未安裝,請安裝Xcode'
fi
if which oclint 2>/dev/null; then
echo 'oclint exist'
else
echo 'oclint 未安裝,請安裝OCLint'
fi
if which xcpretty 2>/dev/null; then
echo 'xcpretty exist'
else
gem install xcpretty
fi
# 指定編碼
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"
export xcpretty=/usr/local/bin/xcpretty # xcpretty 的安裝位置可以在終端用 which xcpretty找到
searchFunctionName=`searchProjectName`
path=${searchFunctionName}
# 字符串替換函數(shù)。//表示全局替換 /表示匹配到的第一個結(jié)果替換。
path=${path//.\//} # ./BridgeLabiPhone.xcodeproj -> BridgeLabiPhone.xcodeproj
path=${path//.xcodeproj/} # BridgeLabiPhone.xcodeproj -> BridgeLabiPhone
myworkspace=$path".xcworkspace" # workspace名字
myscheme=$path # scheme名字
# 清除上次編譯數(shù)據(jù)
if [ -d ./derivedData ]; then
echo -e $COLOR_SUCC'-----清除上次編譯數(shù)據(jù)derivedData-----'$COLOR_SUCC
rm -rf ./derivedData
fi
# xcodebuild clean
xcodebuild -scheme $myscheme -workspace $myworkspace clean
# # 生成編譯數(shù)據(jù)
xcodebuild -scheme $myscheme -workspace $myworkspace -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 12 Pro Max' -configuration Debug GCC_PRECOMPILE_PREFIX_HEADER=YES CLANG_ENABLE_MODULE_DEBUGGING=NO COMPILER_INDEX_STORE_ENABLE=NO OTHER_CFLAGS="-DNS_FORMAT_ARGUMENT(A)= -D_Nullable_result=_Nullable" | tee xcodebuild.log | xcpretty -r json-compilation-database -o compile_commands.json
if [ -f ./compile_commands.json ]; then
echo -e $COLOR_SUCC'編譯數(shù)據(jù)生成完畢'$COLOR_SUCC
else
echo -e $COLOR_ERR'編譯數(shù)據(jù)生成失敗'$COLOR_ERR
return -1
fi
echo -e $COLOR_SUCC'OCLint代碼分析開始'$COLOR_SUCC
# 生成報表
oclint-json-compilation-database -e Pods -- -report-type pmd \
-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 \
-allow-duplicated-violations=false\
-max-priority-1=100000 \
-max-priority-2=100000 \
-max-priority-3=100000 >> oclint.xml
echo -e $COLOR_SUCC'Infer代碼分析開始'$COLOR_SUCC
# --skip-analysis-in-path 是忽略掃描目錄
infer run --skip-analysis-in-path Pods --keep-going --compilation-database compile_commands.json
product_name=`sed -n '/PRODUCT_NAME/{s/PRODUCT_NAME = //;s/;//;s/^[[:space:]]*//;s/\"http://g;p;q;}' ./$myscheme.xcodeproj/project.pbxproj`
version_number=`sed -n '/MARKETING_VERSION/{s/MARKETING_VERSION = //;s/;//;s/^[[:space:]]*//;s/\"http://g;p;q;}' ./$myscheme.xcodeproj/project.pbxproj`
if [ -f ./oclint.xml -a -f ./infer-out/report.json ]; then
rm compile_commands.json
echo -e $COLOR_SUCC'代碼分析完畢'$COLOR_SUCC
mv oclint.xml sonar-reports/
echo -e $COLOR_SUCC'移動至sonar-reports完畢'$COLOR_SUCC
echo -e $COLOR_SUCC'開始執(zhí)行sonar-scanner掃描文件'$COLOR_SUCC
echo -e $COLOR_SUCC'版本號:'${version_number}''$COLOR_SUCC
sonar-scanner -Dsonar.projectVersion=$version_number
else
echo -e $COLOR_ERR'分析失敗'$COLOR_ERR
curl 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxxxx' \
-H 'Content-Type: application/json' \
-d '
{
"msgtype": "text",
"text": {
"content": "APP名稱:'${product_name}'\nAPP版本:'${version_number}'\nOCLint分析失敗"
}
}'
return -1
fi
local_ip = $(ifconfig | grep '\<inet\>'| grep -v '127.0.0.1' | awk '{ print $2}' | awk 'NR==1')
curl 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxxx' \
-H 'Content-Type: application/json' \
-d '
{
"msgtype":"news",
"news":{
"articles":[
{
"title":"SonarQube 靜態(tài)代碼掃描完成",
"url":"http://'${local_ip}':9000/",
"description":"APP名稱:'${product_name}'\nAPP版本:'${version_number}'掃描代碼分支:'$1'",
"picurl":"https://csdn-app.csdn.net/1024store_1024pt.png"
}
]
}
}'
}
oclintForProject $1
-
Jenkins 配置PMD(當(dāng)然有了SonarQube,PMD就很雞肋了)
image
image
image