搭建iOS代碼質量監控平臺 - SonarQube

背景

近期團隊內進行了一次項目代碼警告清理工作,對項目里各種觸發警告的代碼進行優化。人工改費時費力,效率低,同時也沒有合適的清理警告的自動化工具,因此只是清理了一部分便告一段落。事后對這次工作進行總結,提出下面三個問題:

  1. 代碼警告對我們有什么影響?
  2. 為什么會有這么多的警告代碼?
  3. 如何避免后續開發過程的代碼質量問題?

第一個問題,喵神有句話這里引用一下

一個有節操的程序員會在乎自己的代碼的警告,就像在乎飯碗邊上有只死蟑螂那樣。 ——@onevcat

代碼警告實際帶來的風險具體有:代碼可讀性差、難以維護、Crash、邏輯錯誤等,同時也是一個團隊開發人員技術水平的體現。

代碼警告意味著編譯器發現某段代碼有風險,雖然可能對實際邏輯功能不會產生影響,但是對嚴謹的程序員來說,始終有這樣一個、甚至上萬個警告提示在那里不去管,或者簡單的關閉警告,是不應該的。

第二個問題,歸其原因,可以分為兩個方面:一方面是之前項目將警告關閉了,我們看不到大部分的代碼警告;另一方面是我們缺少代碼質量分析的機制,僅僅通過人工CodeReview的方式進行代碼審查,能發現的問題是很有限的,缺少一些工具的幫助。

第三個問題,重點是需要建立起代碼質量監控的機制,通過一些自動化的工具,完成代碼質量的分析、匯總。同時要把提升代碼質量作為一個開發團隊的日常工作任務,定期的根據分析結果,解決相關的問題,清理飯碗邊上的蟑螂。

鑒于上述總結,調研了一些工具后,發現業內常用的的比較完善的代碼質量監控平臺是SonarQube。同時我們的測試團隊也已經在使用SonarQube對公司內的項目代碼進行檢測,由于iOS的工程支持需要一些配置,還沒有跑通,所以我們配合測試團隊完成iOS項目支持SonarQube掃描,下面進行相關工作的介紹。

工具介紹

SonarQube

SonarQube是一個代碼質量監控平臺,能夠匯總各類代碼分析工具的檢測報告,從Bug、問題代碼重復代碼、單測覆蓋度、技術債等維度展示項目代碼的健康程度,綜合各個維度的評價,為代碼質量進行評級。

SonarQube有社區版和多種付費版本,主要差別是對語言種類的支持有差異。SonarQube同時也支持插件開發,通過插件的方式可以擴展對語言的支持,所以可以使用社區版+插件的方式支持ObjC、Swift的質量檢測,也是下面介紹的Sonar-Swift的實現方式。

Sonar-Swift

Sonar-Swift是一個面向ObjCSwift的開源靜態代碼分析工具集,通過SonarScannerSwiftLintOCLint、Tailor、Lizard等代碼分析工具的結果提交給SonarQube,完成iOS項目的代碼質量監控。對于ObjC的分析,由于OCLint存在很多問題,國內有團隊在Sonar-Swift的基礎上進行二次開發,引入了Infer掃描工具,來替代OCLint

SwiftLint

SwiftLint是用于進行Swift靜態代碼分析的工具,通過HookClang獲取代碼的AST數據,進行分析后,輸出報告,同時使用SourceKit,將提示信息展示在Xcode編輯器內。SwiftLint支持自定義檢測規則,這一點為制定適用于自己團隊的開發規則比較友好。

OCLint

OCLint是用于進行ObjC靜態代碼分析的工具,也是基于Clang提供的工具,獲取AST數據進行分析,輸出報告。主要工作流程如下:

  1. xcodebuild或者xcrun生成構建日志
  2. 結合xcpretty,輸出一個符合JSONCompilationDatabase標準的json文件,文件包含的主要是此次構建的每個源碼文件、編譯命令和文件路徑文件路徑。
  3. OCLint根據該文件進行二次編譯,在二次編譯過程中,獲取AST數據進行分析。

OCLint也支持自定義檢測規則,但是在大型項目的實際接入過程中,問題較多,個別文件編譯失敗時導致整體工作流程失敗,使用不夠友好。

Infer

Infer也是可以用于進行ObjC靜態代碼分析的工具,由FaceBook發布,開源。工作流程與OCLint類似,也是根據構建日志進行二次編譯,輸出分析報告。比較好的一點是即使個別文件編譯失敗,Infer仍然可以繼續執行,不會打斷整體工作流程失敗,也是我們選擇Infer的一個主要原因。

SonarScanner

SonarScannerSonarQube提供的一個工具,能夠根據配置文件將指定工程及掃描報告上傳到SonarQube平臺中??梢岳斫鉃槭且粋€數據收集器,收集、上報代碼分析的數據。

工作流程

Sonar-Swift
Sonar-Swift的工作流程如上圖所示,分為以下幾個步驟:

  • xcodebuild構建工程,輸出xcodebuild.log
  • xcpretty處理xcodebuild.log,輸出compile_commands.json
  • infer處理compile_commands.json,輸出report.json
  • swiftlint處理swift文件,輸出swiftlint.txt
  • lizard處理ObjC文件,輸出lizard-report.xml
  • Sonar-Scanner收集report.json、swiftlint.txt、lizard-report.xml上報到SonarQube

搭建過程

上面介紹了相關工具及整體的工作流程,接下來具體記錄下在搭建平臺的步驟及相關配置。

SonarQube服務

首先我們需要搭建起SonarQube服務,官網提供多種搭建方式,我們選擇使用Docker一鍵安裝,省心省力。兼容性上需要注意兩點:

  • SonarQube目前不支持M1的芯片設備,Docker部署失敗
  • SonarQube 9.x版本不支持Sonar-Swift插件,服務啟動失敗

鑒于上述兩個問題,我們使用的是基于Intel芯片的Mac設備,SonarQube的版本是8.9.2-communitydocker鏡像傳送門。

docker pull sonarqube:8.9.2-community

部署成功后,需要安裝Sonar-Swift插件,下載插件jar包,復制到docker上sonarqube的服務目錄下:

docker cp tal-sonar-swift-plugin-1.5.0.jar sonarqube:/opt/sonarqube/extensions/plugins/

啟動sonarqube服務,默認的端口是9000,本地打開localhost:9000即可看到SonarQube的頁面,默認賬號密碼都是admin,首次登錄后會提示更新密碼。

服務搭建好后,在平臺上創建一個工程,支持通過GitLab等方式,我們選擇通過手工的方式創建,完成提示步驟后即可創建工程。工程創建好后,可以進行一些自定義的設置,根據項目的實際需要,過濾不在監控范圍內的目錄、選擇Quality Profiles,在Quality Profiles里,可以看到infer的選擇,設置為默認選項即可。

參考配置

配置路徑時有兩個地方需要注意下:

  • 使用正則表達式來過濾,如果實際使用過程中有一些文件被忽略掉了,可以驗證下正則表達式是否正確。
  • 在確認正則沒問題的情況下,還是有文件沒有上報上來,可以再確認下想要上報分析的文件是不是在項目的.gitignore列表里,SonarScanner在掃描時會將.gitignore忽略的文件一起忽略掉。

對于.gitignore忽略的文件,可以通過設置sonar.scm.exclusions.disabled=true來關閉,具體設置的地方可以在SonarQube的后臺,也可以在Sonar-Swift提供的sonar-project.properties文件中配置。

SonarScanner安裝

下載SonarScanner,在全局環境變量中設置執行路徑,以zsh為例,在~/.zshrc中增加以下代碼:

export SONAR_SCANNER_PATH=your scanner bin path
export PATH=$SONAR_SCANNER_PATH:$PATH

執行source ~/.zshrc后,命令行輸入sonar-scanner確認執行路徑是否配置成功。

sonar-scanner支持通過sonar-project.properties文件的方式配置相關屬性,該文件內可以配置sonarqube服務地址、工程名稱(SonarQube上對應的工程信息)、登錄名、密碼、登錄token等。Sonar-Swift也提供了一個默認的模版,我們可以將其放到工程目錄里,執行sonar-scanner命令時,會讀取該配置,根據配置內容上報數據。

SwiftLint安裝配置

SwiftLint的安裝可以參考其Github指導進行安裝即可。需要指出的一點是SwiftLint支持自定義規則,自定義的規則通過.swiftlin.yml文件來設置,所以在后面使用Sonar-Swift提供的腳本時,可以在腳本內進行修改,使用自己提供的配置文件目錄進行檢查。

Infer安裝配置

Infer的安裝也可以參考其官網進行安裝即可。Infer執行時的一些命令行選項配置可以通過在執行目錄下設置.inferconfig文件來配置。Infer并沒有在Sonar-Swift提供的腳本中設置,所以在執行Sonar-Swiftrun-sonar-swift.sh腳本中,需要增加調用infer的相關命令。

if [ "$infer" = "on" ]; then
        runCommand /dev/stdout infer run --keep-going
fi

同時在sonar-project.properties文件中,需要指定infer的報告路徑

sonar.swift.infer.report=infer-out/report.json
Sonar-Swift配置&腳本

Sonar-Swift除了提供了一個jar包插件外,還提供了一個sonar-project.properties配置模版、一個run-sonar-swift.sh腳本。在具體接入時,可以根據自己項目的實際需要,對這兩個文件進行修改。其中run-sonar-swift.sh的腳本主要是將工作流程圖中介紹的過程整合起來,方便執行。

run-sonar-swift.sh

總結

本次著重介紹了Sonar-Swift的整體搭建過程,一些細節問題沒有完全列出,還需要在實踐過程中,具體項目具體分析。建立起質量監控平臺不是最終目的,保證代碼質量才是我們的目標。所以后續還需要將這個平臺真正的使用起來,在項目的迭代過程中,將平臺的分析數據作為監控指標,根據分析結果不斷的修復相關問題,以此提升我們的代碼質量,同時在解決問題的過程中,也能獲得技術上的成長。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,837評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,196評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 175,688評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,654評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,456評論 6 406
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,955評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,044評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,195評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,725評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,608評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,802評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,318評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,048評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,422評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,673評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,424評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,762評論 2 372

推薦閱讀更多精彩內容