OCLint + Infer +Jenkins + SonarQube 搭建iOS代碼靜態(tài)分析系統(tǒng)

背景

隨著代碼量的日益增加,以及團隊的擴大,我們往往因為需求需要盡快上線以及快速迭代,導(dǎo)致代碼并不是很規(guī)范,時間長了就留下了一堆技術(shù)債,代碼的質(zhì)量也沒有了保證。所以開始嘗試一些代碼質(zhì)量相關(guān)建設(shè),希望能夠通過代碼靜態(tài)掃描的方式,幫助我們掃描出一些代碼漏洞,然后嘗試去修復(fù)漏洞和bug,以此來保證代碼質(zhì)量。

工具與平臺

本文涉及的工具及平臺:

開源方案介紹及配置

大部分iOS平臺代碼靜態(tài)分析基本是基于開源的oclint或者infer進行的,本文雖然使用sonarqube,但免費的分析方案核心仍然是oclintinfer

sonarqube是一個開源的靜態(tài)代碼分析平臺,提供免費的社區(qū)版,免費的社區(qū)版不支持Objective-C,但github有提供開源的插件,Objective-C,付費的社區(qū)版plus有支持Objective-C的分析插件SonarCFamily for C

無論免費方案還是付費方案,首先都是基于xcodebuid過程中的日志來進行的,我們這次主要針對開源方案來講相關(guān)配置流程。

對于使用開源方案來說,本質(zhì)流程如下:


image

xcodebuild

iOS核心工具,安裝好Xcode就會自帶此工具,因為oclint分析的核心是xcodebuild在編譯app過程中的log,所以需要xcodebuild(build失敗也會對已經(jīng)build的日志進行分析,但盡量保證可以build成功)

如果項目是在workspace中需要指定-workspace和對應(yīng)的scheme,可以通過xcodebuild -list查看

//執(zhí)行
$ xcodebuild -list
image
//執(zhí)行
$ xcodebuild -workspace CsdnPlus.xcworkspace -scheme CsdnPlus
image

我們并不需要打出的IPA包可以安裝到手機上,只是需要build過程中的日志而已,所以我們只需要打出模擬器下Debug包就可以了。

//執(zhí)行
$ xcodebuild -showsdks
image

因為xcodebuild會有緩存,所以我們每次執(zhí)行前需要clean

$ xcodebuild -workspace CsdnPlus.xcworkspace -scheme CsdnPlus clean
image

執(zhí)行build編譯

$ xcodebuild -scheme CsdnPlus -workspace CsdnPlus.xcworkspace -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 12 Pro Max' -configuration Debug
image

image

能編譯成功的話就可以進入下一步了

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
image

-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文件:

首先需要用xcodebuild cleanbuild項目,并且添加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,驗證是否安裝成功。

image

在終端輸入oclint --help 查看命令介紹
image

其中我們主要使用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

InferFacebook開源的一款代碼掃描軟件,可以分析Objective-C,Java或者C代碼,報告潛在的問題。任何人都可以使用Infer檢測應(yīng)用,這可以將那些嚴(yán)重的 bug 扼殺在發(fā)布之前,同時防止應(yīng)用崩潰和性能低下。

  • 命令安裝
$ brew install infer

在終端輸入 infer --version,驗證是否安裝成功。

在這里插入圖片描述

InferOCLint一樣,都是分析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é)合jenkinsgitlab等平臺來進行代碼分析。sonarqube分社區(qū)版本和商業(yè)化版本,能掃描多種語言并且開源。官網(wǎng)地址。
因為其底層源碼為java開發(fā)的,所以對java代碼支持比較完善,但是免費的社區(qū)版并不支持OC,所以我們?nèi)绻柚似脚_的話,有以下兩種方式:

  • 開源插件sonar-swift
    ,支持Objective-CSwift / Java,支持導(dǎo)入 SwiftLint、Infer、OCLint、LizardFauxpas 工具的掃描分析結(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
image

控制臺輸出Started SonarQube說明啟動成功。

在瀏覽器訪問http://localhost:9000/,能打開頁面說明啟動成功。
默認(rèn)賬號為admin,密碼為admin。

image

注意:如果啟動失敗可以去sonarqube/logs下查看日志。

image

安裝時,發(fā)現(xiàn)sonarqube 8.9.7版本需要Java 11環(huán)境。所以需要先安裝Java 11環(huán)境。
安裝Java 11:
image

image

啟動成功后我們在最下面會看到warning

image

警告建議我們自己配置數(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 //安裝
image

安裝完數(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
image

然后我們?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)消除了。

image

至此我們的sonarqube的前端服務(wù)已經(jīng)配置完成了。

漢化包安裝

通過Github 下載對應(yīng)版本漢化包jar包插件。

image

下載插件放到/extensions/plugins 目錄下。重啟sonarqube服務(wù),就可以看到漢化后的界面。
image

sonar-swift

通過GitHub 下載對應(yīng)插件

image

下載插件放到/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.jsonInfer生成的infer-out目錄下。

image

在這里插入圖片描述

命令執(zhí)行成功后,便可在sonarQube的前端頁面看到對應(yīng)的檢測效果了。


image

在這里插入圖片描述

在這里插入圖片描述

檢測效果圖:


image

image

集成進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

image
  • 企業(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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容