關於持續整合打包平臺的Jenkins配置和構建指令碼實現細節

發表於2016-07-29

在《用 Jenkins 搭建 iOS/Android 持續整合打包平臺》一文中,我對如何使用Jenkins搭建iOS/Android持續整合打包平臺的基礎概念和實施流程進行了介紹。本文作為配套,對搭建持續整合打包平臺中涉及到的執行命令、構建指令碼(build.py),以及Jenkins的配置進行詳細的補充說明。

當然,如果你不關心技術實現細節,也可以完全不用理會,直接參照【開箱即用】部分按照步驟進行操作即可。

關於iOS的構建

對iOS原始碼進行構建,目標是要生成.ipa檔案,即iOS應用安裝包。

當前,構建方式主要包括兩種:

  • 原始碼 -> .archive檔案 -> .ipa檔案
  • 原始碼 -> .app檔案 -> .ipa檔案

這兩種方式的主要差異是生成的中間產物不同,對應的,兩種構建方式採用的命令也不同。

原始碼 -> .archive -> .ipa

archive:打包命令,會生成一個.xcarchive的檔案;archive命令需要接一個引數-archivePath,即存放Archive檔案的目錄

原始碼 -> .app -> .ipa

引數說明

xcodebuild/xctool引數

  • -workspace:需要打包的workspace,後面接的檔案一定要是.xcworkspace結尾的;
  • -scheme:需要打包的Scheme,一般與$project_name相同;
  • -sdk:區分iphone device和Simulator;
  • -configuration:需要打包的配置檔案,我們一般在專案中新增多個配置,適合不同的環境,Release/Debug;
  • -derivedDataPath:指定編譯結果檔案的儲存路徑;例如,指定-derivedDataPath build時,將在專案根目錄下建立一個build資料夾,生成的.app檔案將位於build/Build/Products/Release-iphoneos中。

除了採用官方的xcodebuild命令,還可以使用由Facebook開發維護的xctoolxctool命令的使用方法基本與xcodebuild一致,但是輸出的日誌會清晰很多,而且還有許多其它優化,詳情請參考xctool的官方文件。

xcrun引數

  • -v:指定.app檔案的路徑
  • -o:指定生成.ipa檔案的路徑

補充說明

1、獲取Targets、Schemes、Configurations引數

在填寫target/workspace/scheme/configuration等引數時,如果不知道該怎麼填寫,可以在專案根目錄下執行xcodebuild -list命令,它會列出當前專案的所有可選引數。

2、清除快取檔案

在每次build之後,工程目錄下會遺留一些快取檔案,以便下次build時減少編譯時間。然而,若因為工程配置錯誤等問題造成編譯失敗後,下次再編譯時就可能會受到快取的影響。

因此,在持續整合構建指令碼中,比較好的做法是在每次build之前都清理一下上一次編譯遺留的快取檔案。

clean:清除編譯產生的問題,下次編譯就是全新的編譯了

3、處理Cocoapod依賴庫

另外一個需要注意的是,若專案是採用Cocoapod管理專案依賴,每次拉取最新程式碼後直接編譯可能會報錯。這往往是因為其他同事更新了依賴庫(新增了第三方庫或升級了某些庫),而本地還採用之前的第三方庫進行編譯,從而會出現依賴庫缺失或版本不匹配等問題。

應對的做法是,在每次build之前都更新一下Cocoapod。

4、修改編譯包的版本號

通過持續整合打包,我們會得到大量的安裝包。為了便於區分,比較好的做法是在App中顯示版本號,並將版本號與Jenkins的BUILD_NUMBER關聯起來。

例如,當前專案的主版本號為2.6.0,本次構建的BUILD_NUMBER為130,那麼我們就可以將本次構建的App版本號設定為2.6.0.130。通過這種方式,我們可以通過App中顯示的版本號快速定位到具體到構建歷史,從而對應到具體的程式碼提交記錄。

要實現對App版本號的設定,只需要在打包前對Info.plist檔案中的CFBundleVersionCFBundleShortVersionString進行修改即可。在Python中,利用plistlib庫可以很方便地實現對Info.plist檔案的讀寫。

5、模擬器執行

如果持續整合測試是要執行在iOS模擬器上,那麼就需要構建生成.app檔案。

在前面講解的兩種構建方式中,中間產物都包含了.app檔案。對於以.xcarchive為中間產物的方式,生成的.app檔案位於output_dir/StoreCI_Release.xcarchive/Products/Applications/目錄中。

不過,這個.app檔案在模擬器中還無法直接執行,還需要在Xcode中修改Supported Platforms,例如,將iphoneos更改為iOS。詳細原因請參考《從0到1搭建移動App功能自動化測試平臺(1):模擬器中執行iOS應用》

關於Android的構建

待續

關於構建指令碼

對於構建指令碼(build.py)本身,原始碼應該是最好的說明文件。

build.py指令碼中,主要實現的功能就四點:

  • 執行構建命令,編譯生成.ipa檔案,這部分包含了關於iOS的構建部分的全部內容;
  • 構建時動態修改Info.plist,將編譯包的版本號與Jenkins的BuildNumber關聯起來;
  • 上傳.ipa檔案至pyger/fir.im平臺,並且做了失敗重試機制;
  • 解析pyger/fir.im平臺頁面中的二維碼,將二維碼圖片儲存到本地。

需要說明的是,對於構建任務中常用的可配置引數,例如BRANCH/SCHEME/CONFIGURATION/OUTPUT_FOLDER等,需要在構建指令碼中通過OptionParser的方式實現可傳引數機制。這樣我們不僅可以命令列中通過傳參的方式靈活地呼叫構建指令碼,也可以在Jenkins中實現引數傳遞。

之所以強調常用的可配置引數,這是為了儘可能減少引數數目,降低指令碼呼叫的複雜度。像PROVISIONING_PROFILEpgyer/fir.im賬號這種比較固定的配置引數,就可以寫死在指令碼中。因此,在使用構建指令碼(build.py)之前,需要先在指令碼中配置下PROVISIONING_PROFILEpgyer/fir.im賬號。

另外還想多說一句,pyger/fir.im這類第三方平臺在為我們提供便利的同時,穩定性不可控也是一個不得不考慮的問題。在我使用pgyer平臺期間,就遇到了平臺服務變動、介面時而不穩定出現502等問題。因此,最好的方式還是自行搭建一套類似的服務,反正我是打算這麼做了。

Jenkins的詳細配置

對於Jenkins的詳細配置,需要補充說明的有四點。

1、引數的傳遞

在構建指令碼中,我們已經對常用的可配置引數實現了可傳參機制。例如,在Terminal中可以通過如下形式呼叫構建指令碼。

那麼我們在Jenkins中要怎樣才能指定引數呢?

實際上,Jenkins針對專案具有引數化的功能。在專案的配置選項中,勾選This project is parameterized後,就可以為當前project新增多種型別的引數,包括:

  • Boolean Parameter
  • Choice Parameter
  • Credentials Parameter
  • File Parameter
  • Multi-line String Parameter
  • Password Parameter
  • Run Parameter
  • String Parameter

通常,我們可以選擇使用String Parameter來定義自定義引數,並可對每個引數設定預設值。

當我們配置了BRANCHSCHEMECONFIGURATIONOUTPUT_FOLDERBUILD_VERSION這幾個引數後,我們就可以在Build配置區域的Execute shell通過如下形式來進行引數傳遞。

可以看出,引數的傳遞方式很簡單,只需要預先定義好了自定義引數,然後就可以通過${Param}的形式來進行呼叫了。

不過你也許會問,WORKSPACEBUILD_NUMBER這兩個引數我們並未進行定義,為什麼也能進行呼叫呢?這是因為Jenkins自帶部分與專案相關的環境變數,例如BRANCH_NAMEJOB_NAME等,這部分引數可以在shell指令碼中直接進行呼叫。完整的環境變數可在Jenkins_Url/env-vars.html/中檢視。

配置完成後,就可以在Build with Parameters中通過如下形式手動觸發構建。

2、修改build名稱

Build History列表中,構建任務的名稱預設顯示為按照build次數遞增的BUILD_NUMBER。有時候我們可能想在build名稱中包含更多的資訊,例如包含當次構建的SCHEMECONFIGURATION,這時我們就可以通過修改BuildName實現。

Jenkins預設不支援BuildName設定,但可通過安裝build-name-setter外掛進行實現。安裝build-name-setter外掛後,在配置頁面的Build Environment欄目下會出現Set Build Name配置項,然後在Build Name中就可以通過環境變數引數來設定build名稱。

例如,要將build名稱設定為上面截圖中的StoreCI_Release_#130樣式,就可以在Build Name中配置為${SCHEME}_${CONFIGURATION}_#${BUILD_NUMBER}

除了在Build Name中傳遞環境變數引數,build-name-setter還可以實現許多更加強大的自定義功能,大家可自行探索。

3、展示二維碼圖片

然後再說下如何在Build History列表中展示每次構建對應的二維碼圖片。

需要說明的是,在上圖中,綠色框對應的內容是BuildName,我們可以通過build-name-setter外掛來實現自定義配置;但是紅色框已經不在BuildName的範圍之內,而是對應的BuildDescription

同樣地,Jenkins預設不支援在構建過程中自動修改BuildDescription,需要通過安裝description setter plugin外掛來輔助實現。安裝description setter plugin外掛後,在配置頁面的Build欄目下,Add build step中會出現Set build description配置項,新增該配置項後就會出現如下配置框。

該功能的強大之處在於,它可以在構建日誌中通過正規表示式來匹配內容,並將匹配到的內容新增到BuildDescription中去。

例如,我們想要展示的二維碼圖片是在每次構建過程中生成的,因此我們首先要獲取到二維碼圖片檔案。

我的做法是,在build.py中將蒲公英平臺返回的應用下載頁面地址和二維碼圖片地址列印到log中。

然後,在Set build description配置項的Regular expression就可以按照如下正規表示式進行匹配:

接下來,就可以在Description中對匹配到的結果進行引用。

在這裡,我們用到了HTML的標籤,而Jenkins的Markup Formatter預設是採用Plain text模式,因此還需要對Jenkins對系統配置進行修改,在《用 Jenkins 搭建 iOS/Android 持續整合打包平臺》中已進行了詳細說明,在此就不再重複。

通過以上方式,就可以實現前面圖片中的效果。

4、收集編譯成果物

在上面講解的展示二維碼圖片一節中,用到了${BUILD_URL}artifact/build_outputs/QRCode.png一項,這裡的URL就是用到了編譯成果物收集後儲存的路徑。

Archives build artifacts是Jenkins預設自帶的功能,無需安裝外掛。該功能在配置頁面的Post-build Actions欄目下,在Add post-build action的列表中選擇新增Archives build artifacts

新增後的配置頁面如下圖所示:

通常,我們只需要配置Files to archive即可。定位檔案時,可以通過正規表示式進行匹配,也可以呼叫專案的環境變數;多個檔案通過逗號進行分隔。

例如,假如我們想收集QRCode.pngStoreCI_Release.ipaInfo.plist這三個檔案,那麼我們就可以通過如下表示式來進行指定。

當然,目標檔案的具體位置是我們在構建指令碼(build.py)中預先進行處理的。

通過這種方式,我們就可以實現在每次完成構建後將需要的檔案收集起來進行存檔,以便後續在Jenkins的任務頁面中進行下載。

也可以直接通過歸檔檔案的URL進行訪問。例如,上圖中QRCode.png的URL為Jenkins_Url/job/JenkinsJobName/131/artifact/build_outputs/QRCode.png,而Jenkins_Url/job/JenkinsJobName/131/即是${BUILD_URL},因此可以直接通過${BUILD_URL}artifact/build_outputs/QRCode.png引用。

總結

至此,《用 Jenkins 搭建 iOS/Android 持續整合打包平臺一文中涉及到的Jenkins配置和構建指令碼實現細節均已補充完畢了。相信大家結合這兩篇文章,應該會對如何使用Jenkins搭建iOS/Android持續整合打包平臺的基礎概念和實現細節都有一個比較清晰的認識。

對於還未完善的部分,我後續將在部落格中進行更新。

操作手冊請參考文章末尾的【開箱即用】部分,祝大家玩得愉快!

開箱即用

GitHub地址:https://github.com/debugtalk/JenkinsTemplateForApp

1、新增構建指令碼

  • 在構建指令碼中配置PROVISIONING_PROFILEpgyer/fir.im賬號;
  • 在目標構建程式碼庫的根目錄中,建立Build_scripts資料夾,並將build.py拷貝到Build_scripts中;
  • Build_scripts/build.py提交到專案中。

除了與Jenkins實現持續整合,構建指令碼還可單獨使用,使用方式如下:

2、執行jenkins,安裝必備外掛

3、建立Jenkins Job

  • 在Jenkins中建立一個Freestyle project型別的Job,先不進行任何配置;
  • 然後將config.xml檔案拷貝到~/.jenkins/jobs/YourProject/中覆蓋原有配置檔案,重啟Jenkins;
  • 完成配置檔案替換和重啟後,剛建立好的Job就已完成了大部分配置;
  • Job Configure中根據專案實際情況調整配置,其中Git Repositories是必須修改的,其它配置項可選擇性地進行調整。

4、done!

相關文章