你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> iOS 持續集成系列

iOS 持續集成系列

編輯:IOS開發基礎

318764-130HPZ33685.jpg

本文為投稿文章,作者:PPPan


  • iOS 持續集成 - 開篇

  • iOS 持續集成 - 自動化 Code Review

  • [iOS 持續集成 - 自動化單元測試]

  • [iOS 持續集成 - 自動化打包與分發]

為了保證代碼質量,Code Review 是非常重要的一環。細到*的位置是否正確,大到代碼的結構是否符合了軟件開發的一些基本原則,都在這項工作的范圍內。

受限於現實情況,大多數團隊沒有足夠的時間進行 Code Review,那麼只能把一部分 CR 工作交給計算機去完成了。我們只需要定下合理的流程,用代碼告訴計算機需要做什麼,剩下的就交給我們可靠的伙伴吧。

應用了自動化 Code Review 後,如果你的代碼寫得不好,Xcode 會表示不開心。

36.png

如果你忽略 Xcode 的心情,那麼質量管理平台會默默地記錄這一切。

37.png

這套東西既幫助開發們寫出更高質量的的代碼,也給經理們對工程質量的評估提供了一個切面的支持,同時只需要花費較少的人力維護,聽起來是不是躍躍欲試了呢 : )

流程

整體的工作流程非常簡單,如圖:

38.png

自動化 Code Review 總體流程

關鍵點在於本地 Review和遠端 Review這兩步。前者是提供給開發者一個即時的代碼質量反饋,以便開發者修改,從而避免在接下來的遠端 Review 中得到一個較低的得分。後者則是為了生成相關報表,為項目管理人員跟蹤項目質量提供依據。在很多大公司裡,這也是開發者們績效的參考之一。

剩下的就是一些膠水步驟了,如何讓過程更自動化,就是膠水步驟要做的事。例如利用 WebHook 自動觸發遠端 Review,利用 Git 的鉤子進行增量校驗而不是全量校驗等。這些我們放在後面聊,先來看看本地校驗的流程。

本地 Review

39.png

本地自動化 Code Review

在本地 Review 環節,開發者只需要像往常一樣按下 CMD + B,然後只要靜靜地等待進度條讀完,滿屏的??就會精確地指示出某一行的代碼違反了哪條規則。此時開發者就可以根據代碼規范進行對應修改。

從按下按鍵到產生警告主要發生了這麼幾件事情:

  • 生成 compile_commands.json 文件

  • OCLint 讀取相關的 Rules,逐個掃描 compile_commands.json 中的 .m 文件

  • OCLint 將生成的報告展示在 Xcode 上

實現本地 Review 的核心就是 OCLint 和 compile_commands.json文件

OCLint

工欲善其事,必先利其器

OCLint 是一個開源的,基於 Clang 用 C++ 編寫而成的,可以用於 C、C++ 和 Objective-C 的靜態代碼分析器。它可以在掃描的過程中動態加載規則文件(Rules),因此可以實現非常靈活的,高度可自定義的代碼分析方案。它幾乎可以和大多數系統無縫集成,例如 Cmake、Bear、xcodebuild、xctool、Xcode、xcpretty、Jenkins CI、Travis CI 等。你可以在這裡找到如何將其和 Xcode 配合使用。

最新版本的 OCLint 已經自帶了 71 條 Rules,基本上都是先人寶貴的經驗,比如這條禁用 goto 語句的 Rule,就是來源於 Edsger W. Dijkstra 1968 年的一篇手稿。

這 71 條 Rules 已經可以幫助我們避免一部分因書寫習慣和語言誤區而導致的問題,但是對於有完整編碼規范的公司來說顯然是不夠的。我們必須要自己開發 Rules。

幸運的是,OCLint 已經為我們准備好了一切。

OCLint 提供了 Clang 和 AST (Abstract Syntax Tree) 的一層封裝,使我們不必對抽象語法樹進行解析,只需要專注規則相關的邏輯開發即可。從其提供的接口中我們可以很明顯地看出這一點。

// 遇到一元操作符
bool VisitUnaryOperator(UnaryOperator *node)

// 遇到二元操作符
bool VisitBinaryOperator(BinaryOperator *node)

// 遇到 Objective-C 的函數聲明
bool VisitObjCMethodDecl(ObjCMethodDecl *node)

在開發好相關的規則後,打包成 dylib,就可以在分析的時候加載我們自己的 Rule 了。

compile_commands.json

compile_commands.json 是 Clang 定義的一個規范,裡面存放了一組工作目錄、目標文件、需要被執行的命令,幫助相關工具可以獨立於編譯系統來將源代碼文件轉換為 AST 並做對應的事。

看文件內容會更直觀一些:

[
{
  "directory": "/path/to/project/", 
  "command": "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -x ...", 
  "file": "/path/to/project/XXXViewController.m"},
...
]

OCLint 可以根據 compile_commands.json 中的內容,批量檢查源代碼文件。

xcpretty

還有一個點需要關注的是,如何生成 compile_commands.json 文件?

最便捷的方式是使用 oclint-xcodebuild 來生成。首先,利用xcodebuild 生成 xcodebuild.log 文件。

xcodebuild | tee xcodebuild.log

然後利用 oclint-xcodebuild 生成 compile_commands.json

oclint-xcodebuild

截至 Xcode 8.1,這種做法可以正確生成 json 文件。由於 OCLint 團隊已經聲稱不再維護 oclint-xcodebuild , 因此可能在未來的某個 Xcode 版本中這個方法將不再適用。

另一個推薦的方法是利用 xcpretty 。

xcpretty 可以一句話生成 json 文件。

xcodebuild | xcpretty -r json-compilation-database --output /path/to/compile_commands.json

使用本地 Review

了解了這些工具後就很容易明白本地自動化 Code Review 是如何工作的,使用方式也非常容易理解了:

1.首先在電腦本地安裝好 OCLint 並拿到公司自定義的 Rules 文件

2.在 Xcode 上配置好工程

3.build 工程,等待結果顯示在 Xcode 上。

附一個我們團隊的配置腳本供參考:

source ~/.bash_profile
cd ${SRCROOT}
xcodebuild clean
xcodebuild | tee xcodebuild.log
oclint-xcodebuild
oclint-json-compilation-database \
-e Vendor \
-e Pods \
-- \
-max-priority-1 100000 \
-max-priority-2 100000 \
-max-priority-3 100000 \
-report-type xcode \
-R /path/to/rules

遠端 Review

44.png

遠端自動化 Code Review

遠端 Review 和 本地 Review 大體相似,區別在與引用構建的腳本的對象從 Xcode 變成了 Jenkins CI ,報告的展示者從 Xcode 變成了 SonarQube 。其流程是這樣的:

工程師通過 git push 提交代碼
→ Web Hook 觸發 Jenkins 構建
→ OCLint 掃描代碼生成PMD格式報告
→ Sonar-runner 讀取報告並展現到 SonarQube。

CI 環境

為了實現遠端 Review ,服務端必須首先有一套 CI 環境。鑒於 iOS 的特殊性,服務器必須是 macOS 系統。CI 我們直接選擇開源的 Jenkins,質量管理平台則選用開源的 SonarQube。Jenkins 大名鼎鼎大家都非常熟悉了,SonarQube 則相對少的人了解。

SonarQube 是一個質量管理平台,在 SonarQube 上,你可以看到一個項目的代碼行數、文件數量、代碼重復率、違反的代碼規范、技術債時間等等指標。SonarQube 對 Java 的支持極度友好,提供了 SonarScanner 可以直接對 Java 源代碼進行掃描。Objective-C 就沒有這麼幸運了。雖然 SonarQube 也提供了 Objective-C 的報告展示的支持,但靜態分析還是得依靠 OCLint 。

Sonnar-Runner

我們在 Jenkins 上運行 OCLint 生成了報告。需要一個中間人將報告解析成 SonarQube 可以理解的格式並傳輸到 SonarQube 平台。這個中間人就是 Sonnar-Runner。Sonnar-Runner 在我們的系統中也僅僅扮演這個搬運工的角色。你可以從這裡了解到如何在 Jenkins 上安裝和使用 Sonnar-Runner。

Sonnar-Runner 只能解析 PMD 格式的報告,因此我們在使用 OCLint 分析代碼後,需要將報告格式輸出為 PMD 格式。

oclint -report-type pmd -o ./report.xml

Rules in Sonar

SonarQube 有一套規則,將代碼問題按照嚴重程度分為 5 個等級,不同等級的問題會以不同權重影響到項目質量評分。這套規則和 OCLint 生成的報告中的 Rule name 必須要一一對應,SonarQube 才能正確將報告中的問題歸類並評分。

如果你使用 OCLint 原生的 Rules 來檢查代碼,只需要在 SonarQube 上安裝 SonarQube Plugin for Objective C 插件,相關的報告就會被正確識別了。

如果是使用了自行開發的 Rules ,只需要 Clone 上述插件,並在profile-oclint.xml 和 rules.txt 中添加相關的 rule name ,然後打包並將這個插件安裝到 SonarQube 上即可。

舉個例子:

當我們用自行開發的 Rule 檢查完代碼後,生成了report.xml,內容如下:

33.png

其中 binary operator space (HT_iOS_Coding_style 2.8) 是我們定義的錯誤rule name。在 SonarQube 上,也必須對應有這麼一條 rule 的 name,才能正確識別這個錯誤。

此時我們只需要在上述插件的 rules.txt 中添加一段

35.png

在上述插件的 profile-oclint.xml 中添加另外一段代碼

36.png

然後將這個插件打包並安裝到 SonarQube 上,SonarQube 就可以正確識別我們的問題並分類了。

使用遠端 Review

在使用前,一定要確保你的 macOS 服務器已經安裝好了最新版的 Xocde、OCLint、Jenkins、sonnar-runner,安裝好 Jenkins 的相關插件,並將自定義的 Rule 放置在服務器上(如果有的話)。

檢查並生成報告

在 Jenkins 上新建工程並配置好Git、構建觸發器等其他內容。在構建步驟中添加一步 Execute Shell ,填入下述腳本

cd YourProjectDir
xcodebuild clean
xcodebuild -workspace MyProject.xcworkspace -scheme HTMarket -sdk iphonesimulator | tee xcodebuild.log | xcpretty
oclint-xcodebuild
oclint-json-compilation-database -e Pods \
-v \
-- \
-max-priority-1 100000 \
-max-priority-2 100000 \
-max-priority-3 100000 \
-report-type pmd \
-R /path/to/diy-rules \
-o /path/to/report.xml

腳本大致和本地 Review 一致,有三個地方需要注意一下。

1.xcodebuild 命令添加了 -sdk iphonesimulator參數,以避免 build 需要 Code Sign 的問題。

2.-report-type pmd 輸出格式必須為 pmd 格式

3.-o /path/to/report.xml 注意輸出報告的路徑,下一步sonnar-runner 讀取時會用到。

讀取到 SonarQube

在上一步的下方再添加一步 Invoke Standalone SonarQube Analysis,選擇好你的 sonnar-runner。並在 Analysis Properties 中添加如下配置:(如果沒有這一項,你可能需要安裝 SonarQube 相關的插件。)

sonar.projectKey=YOUR_PROJECT_NAME
sonar.projectName=YOUR_PROJECT_NAME
sonar.projectVersion=1.0
sonar.language=objc
sonar.projectDescription=YOUR_PROJECT_DESCRIPTION

# Path to source directories 
sonar.sources=/path/to/source/directories

# 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=YOUR_PROJECT_NAME.xcodeproj 
sonar.objectivec.workspace= YOUR_PROJECT_NAME.xcworkspace

# Scheme to build your application
sonar.objectivec.appScheme=YOUR_PROJECT_NAME

sonar.sourceEncoding=UTF-8

# 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=YOUR_REPORT_FILE_PATH

注意看注釋並修改 YOUR_PROJECT_NAME 、YOUR_PROJECT_DESCRIPTION、和 YOUR_REPORT_FILE_PATH為你項目的值。

一切順利的話,在 Jenkins 上立即構建,你就可以在你的 Sonar 平台上看到代碼質量報告了。

配合好構建觸發器 和 Git 平台的 WebHook 功能,就可以在開發提交代碼或者合並分支等關鍵點自動觸發構建了。

Troubleshooting

為什麼生成的 compile_commands.json 為空

檢查 log 是否為空,如果 log 為空則代表 build 失敗。排除失敗原因後即可正常生成。

Jenkins 構建遇到了如下問題

Code signing is required for product type 'Application' in SDK 'iOS 10.0'

遇到這樣的情況,是因為構建了 Release 版本,且項目在 Xcode8+ 上開啟了 Automatic Code Sign。解決方法如下:

1.如果只需要檢查代碼規范,則在 xcodebuild 命令後添加 -sdk iphonesimulator 參數指明以 Debug 方式構建即可。

2.如果希望構建 Release 版本,那麼關閉自動簽名,在 CI 系統上手動配置證書和Proversion Profile。或者保留自動簽名,參考這個回答用 sed 命令在構建前修改相關配置。

參考鏈接

  • OCLint

  • Jenkins

  • SonarQube

  • Edsger W. Dijkstra

  • AST (Abstract Syntax Tree)

  • json compilation database format specification

  • xcpretty

  • PMD

  • xcode8 和 ios10 升級之後的問題集中討論帖 -- TesterHome

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved