本篇文章講述了如何使用Jenkins搭建iOS的自動(dòng)化構(gòu)建環(huán)境卷玉。
iOS自動(dòng)化構(gòu)建官方有篇文章介紹Xcode持續(xù)集成, 是基于Xcode Server以及Xcode Bots去實(shí)現(xiàn), 但是系統(tǒng)依賴(lài)和版本依賴(lài)過(guò)于嚴(yán)重, 并且需要在Xcode中配置Target的Shared屬性, 耦合性太強(qiáng), 因此不建議使用肆饶。
為什么客戶(hù)端需要自動(dòng)化構(gòu)建
個(gè)人覺(jué)得最主要的原因是需要提高編碼效率, 其次是方便測(cè)試與集成
<font size=4>場(chǎng)景: 開(kāi)發(fā)過(guò)程中, 不斷的有產(chǎn)品或者測(cè)試介入, 需要你不定時(shí)的打包給他們提供體驗(yàn)與測(cè)試如暖。</font>
對(duì)于小工程來(lái)說(shuō), build一下可能就是幾秒鐘的事情, 但是對(duì)于大工程來(lái)說(shuō), 一次打包可能耗費(fèi)5分鐘乃至10分鐘的開(kāi)發(fā)時(shí)間。開(kāi)發(fā)者一天中的有效開(kāi)發(fā)時(shí)間是有限的, 在不斷被打斷的情況下, 開(kāi)發(fā)者的產(chǎn)能實(shí)際上十分低效的缀匕。<font size=4>場(chǎng)景: 聯(lián)調(diào)過(guò)程中, 需要有第三方的SDK接入聯(lián)調(diào), 需要不斷的為對(duì)方更改SDK, 然后重新編譯打包蔫缸。</font>
這種場(chǎng)景一般發(fā)生在多個(gè)公司協(xié)作的時(shí)候, 本人在開(kāi)發(fā)某二手車(chē)批發(fā)軟件的時(shí)候, 就曾遇到與第三方支付平臺(tái)接入聯(lián)調(diào)的問(wèn)題, 一天中80%時(shí)間為對(duì)方提供打包服務(wù), 生產(chǎn)效能過(guò)低。<font size=4>場(chǎng)景: 用戶(hù)預(yù)覽&客戶(hù)演示杂穷。</font>
這個(gè)場(chǎng)景比較類(lèi)似第一個(gè)場(chǎng)景, 不過(guò)是面向不專(zhuān)業(yè)的人事或者客戶(hù), 需要不定時(shí)更新版本然后提供企業(yè)證書(shū)打包的預(yù)覽版給老板和客戶(hù)。嚴(yán)格意義上來(lái)說(shuō), 與第一個(gè)場(chǎng)景是同樣一個(gè)場(chǎng)景卦绣。<font size=4>場(chǎng)景: 測(cè)試集成耐量。</font>
自動(dòng)化構(gòu)建和持續(xù)集成本來(lái)就是一碼事, 如果你是個(gè)喜歡寫(xiě)集成測(cè)試的開(kāi)發(fā)者, 那么在每一次打包編譯的時(shí)候都要運(yùn)行一次集成測(cè)試是很浪費(fèi)時(shí)間的(PS: 集成測(cè)試不通過(guò)這個(gè)場(chǎng)景除外哦`)。將測(cè)試集成在構(gòu)建步驟里面, 可以讓自動(dòng)化集成的所有行為在另外一臺(tái)機(jī)器上工作, 工程師該干嘛還是干嘛去滤港。
還有其他很多應(yīng)用場(chǎng)景, 不過(guò)我個(gè)人暫時(shí)為了上述目的而搭建CI環(huán)境廊蜒。最主要的目的是解放打包時(shí)間, 防止開(kāi)發(fā)工作被打斷。
準(zhǔn)備工作
硬件環(huán)境
- <font size=4>搭載Macintosh系統(tǒng)的一臺(tái)硬件設(shè)備或虛擬機(jī)蜗搔。</font>
既然是編譯iOS應(yīng)用, 那自然少不了蘋(píng)果一系列的機(jī)器啦, 一臺(tái)搭載Macintosh OS操作系統(tǒng)的電腦還是必須的, 目前本人采用的硬件方案是Mac mini劲藐。
需要Macintosh是因?yàn)閄code運(yùn)行環(huán)境在該系統(tǒng)上, 因此如果你想利用腳本編譯iOS應(yīng)用, 你就需要Xcode, 如果你需要Xcode, 那你又必須處于Macintosh OS環(huán)境(哎~ 蘋(píng)果的生態(tài)鏈)。
鑒于目前國(guó)內(nèi)的云服務(wù)器均為windows或者Linux, 您如果想用Geek的方式去搭建iOS的自動(dòng)化構(gòu)建方式, 可以嘗試在云服務(wù)器上安裝虛擬機(jī)然后運(yùn)行Mac OS環(huán)境的方案樟凄。 - 在準(zhǔn)備做CI的機(jī)器上安裝Java SDK環(huán)境 & Xcode聘芜。
Xcode可以用過(guò)App Store直接安裝, Xcode體積非常大, 但是因?yàn)閕OS編譯腳本xcodebuile命令依賴(lài)于Xcode,因此Xcode是必須安裝的。
Java運(yùn)行環(huán)境是Jenkins需要, 因?yàn)镴enkins是基于Java實(shí)現(xiàn)的一套構(gòu)建系統(tǒng), Java SDK可以通過(guò)Oracle的官網(wǎng)去下載最新的適用版本, 在本文書(shū)寫(xiě)的時(shí)候, 最新的Java SDK是JDK8, 下載地址為 http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
安裝Jenkins
- 在Mac OS環(huán)境下, 建議采用Homebrew來(lái)安裝, 獲取Homebrew建議采用官網(wǎng)的方式缝龄。通過(guò)Homebrew官網(wǎng)獲取homebrew后執(zhí)行如下命令:
$ brew install jenkins
- 利用homebrew安裝完畢后, 可以在終端執(zhí)行
which jenkins
查看是否已經(jīng)安裝成功汰现。 - 在終端執(zhí)行
jenkins
命令啟動(dòng)Jenkins(PS: 默認(rèn)占用8080端口會(huì)導(dǎo)致啟動(dòng)失敗), 此處有可能會(huì)出現(xiàn)Jenkins ssl證書(shū)過(guò)期的問(wèn)題, 可以通過(guò)修改os系統(tǒng)時(shí)間, 調(diào)整為ssl支持的時(shí)間來(lái)解決, 否則安裝Jenkins插件可能會(huì)失敗挂谍。(jenkins命令依賴(lài)Java開(kāi)發(fā)環(huán)境, 舊版本的Jenkins需要自己去配置bash alias) - 打開(kāi)瀏覽器, 訪(fǎng)問(wèn)http://localhost:8080, 查看Jenkins是否正常啟動(dòng)(默認(rèn)端口8080)。
配置工作
Jenkins插件配置
Jenkins是個(gè)生態(tài)比較完善的自動(dòng)化構(gòu)建系統(tǒng), 提供了各種的可擴(kuò)展插件給用戶(hù)下載, 同時(shí)又開(kāi)放接口, 讓大家自主開(kāi)發(fā)對(duì)應(yīng)的插件瞎饲。插件管理路徑是系統(tǒng)管理
->管理插件
插件索引默認(rèn)并不是最新的, 需要大家手動(dòng)更新, 在管理插件
->可選插件
的右下角有個(gè)立即獲取
按鈕, 點(diǎn)擊即可獲取最新的插件索引口叙。
PS: <font color='red'>有時(shí)候官方索引的地址ssl證書(shū)過(guò)期導(dǎo)致索引會(huì)更新失敗, 大家可以通過(guò)瀏覽器調(diào)試獲取證書(shū)到期時(shí)間, 然后將本機(jī)時(shí)間調(diào)整為過(guò)期以前的時(shí)間即可解決該問(wèn)題。</font>(apache有時(shí)候也不靠譜啊嗅战。妄田。)
每個(gè)開(kāi)發(fā)者根據(jù)不同的業(yè)務(wù)場(chǎng)景需要用到不同的插件, 本文就不在這里贅述, 大家自由發(fā)揮吧。
Jenkins賬戶(hù)權(quán)限配置
Jenkins用戶(hù)權(quán)限配置和本文主題無(wú)關(guān), 主要是方便大家對(duì)Jenkins用戶(hù)進(jìn)行訪(fǎng)問(wèn)控制驮捍∨蹦牛可以參考文章"Jenkins安全配置/訪(fǎng)問(wèn)控制/審計(jì)"或文章"Jenkins使用經(jīng)驗(yàn)談5(用戶(hù)的登錄與權(quán)限設(shè)定等)"進(jìn)行配置。
我個(gè)人是比較喜歡采用安全域里的Jenkins專(zhuān)有用戶(hù)數(shù)據(jù)庫(kù)
進(jìn)行配置, 因?yàn)樽詭У谋容^方便, 而且在不復(fù)雜的企業(yè)環(huán)境里面已經(jīng)夠用, 負(fù)責(zé)的企業(yè)環(huán)境就另當(dāng)別論了东且。大致流程如下:
- 在Jenkins頁(yè)面上注冊(cè)一個(gè)新用戶(hù)(當(dāng)然可以導(dǎo)入)
- 在
系統(tǒng)管理
->Configure Global Security
里的授權(quán)策略進(jìn)行定向配置, 個(gè)人偏好采用項(xiàng)目矩陣授權(quán)策略
進(jìn)行管理启具。
項(xiàng)目&腳本配置
本文重點(diǎn)是如何自動(dòng)化編譯iOS項(xiàng)目, 這個(gè)其實(shí)大家應(yīng)該很熟悉了, 就是利用xcodebuild
命令和xcrun
組合進(jìn)行腳本編譯和簽名。編譯腳本的編寫(xiě)本質(zhì)上不缺分環(huán)境(Jenkins服務(wù)器環(huán)境or本機(jī)環(huán)境), 因此我們需要確保本機(jī)環(huán)境的腳本能夠正常的工作, 個(gè)人偏好使用bash環(huán)境(因?yàn)椴挥冒惭b其它的依賴(lài)), 然后使用下述的模板進(jìn)行填空珊泳。
#!/bin/bash
projAbbr='iOS_Bash_Build_Demo'
function autoBuild()
{
prepareBuildEnv
updatePodsDeps
clearProjs
buildProjs
signProjs
uploadAppFile
echo ${projAbbr} '- ALL Action Completed!'
}
function prepareBuildEnv()
{
# TODO - 執(zhí)行編譯器準(zhǔn)備工作, 可以調(diào)整項(xiàng)目配置等執(zhí)行任務(wù)
# eg: mkdir xxx
}
function updatePodsDeps()
{
# TODO - 更新Pod依賴(lài)
# eg: pod install
}
function clearProjs()
{
# TODO - clean項(xiàng)目
# eg: xcodebuild -workspace "demo.xcworkspace" -scheme "targetName" -configuration 'Release Adhoc' clean
}
function buildProjs()
{
# TODO - 編譯項(xiàng)目, 生產(chǎn)帶證書(shū)簽名的App文件
# eg: xcodebuild -workspace "demo.xcworkspace" -sdk iphoneos -scheme "targetName" -configuration 'Release Adhoc' SYMROOT='$(PWD)'
# eg: xcodebuild -workspace "demo.xcworkspace" -sdk iphoneos -scheme "targetName" -configuration 'Release Adhoc' CODE_SIGN_IDENTITY="keychain中證書(shū)代號(hào)名稱(chēng)" SYMROOT='$(PWD)'
}
function signProjs()
{
# TODO - 填充簽名腳本, 用于簽名編譯到的App, 打包成ipa文件
# eg: xcrun -sdk iphoneos PackageApplication -v "demo.app" -o "demo.ipa" > $logPath
}
function uploadAppFile()
{
# TODO - 上傳App文件到發(fā)布平臺(tái)
# 蒲公英鲁冯、Fir.im都是不錯(cuò)的選擇哦
}
# 如果使用第三方平臺(tái), 一般不需要createPlist, 因?yàn)榈谌狡脚_(tái)都已經(jīng)集成
function createPlist()
{
# TODO - 創(chuàng)建Plist文件, 用于企業(yè)證書(shū)下載
}
autoBuild
上述腳本將編譯步驟拆分為準(zhǔn)備環(huán)境
、更新Cocoapods
色查、clean項(xiàng)目
薯演、build項(xiàng)目
、簽名項(xiàng)目
和上傳ipa文件
六大步驟秧了。腳本的每一個(gè)步驟其實(shí)都可以在Jenkins需找對(duì)應(yīng)的插件進(jìn)行圖形化控制, 但是我本人喜歡編寫(xiě)腳本來(lái)輕量化Jenkins的依賴(lài), 除非需要本地上傳一些依賴(lài)配置的文件涣仿。
上述腳本的執(zhí)行任務(wù)也可以通過(guò)組合CocoaPods Jenkins Integration
插件、Xcode integration
插件以及其他上傳插件進(jìn)行組合示惊。但是我并不太喜歡過(guò)渡依賴(lài)Jenkins的圖形界面, 因此并沒(méi)有深度整合這兩個(gè)插件。
<font style='bold' color='black'>腳本的核心代碼注釋在代碼里的eg, xcodebuild命令進(jìn)行clean以及build, 然后通過(guò)xcrun進(jìn)行簽名app生成ipa文件</font>
clean清理腳本示例:
xcodebuild -workspace "demo.xcworkspace" -scheme "targetName" -configuration 'Release Adhoc' clean
build編譯腳本示例:
xcodebuild -workspace "demo.xcworkspace" -sdk iphoneos -scheme "targetName" -configuration 'Release Adhoc' CODE_SIGN_IDENTITY="keychain中證書(shū)代號(hào)名稱(chēng)" SYMROOT='$(PWD)
xcodebuild是Xcode Command Tool工具集里的一個(gè)命令, 可以通過(guò)-workspace
指定固定的xcode工作空間或者通過(guò)-project
指定固定的xcode項(xiàng)目愉镰。詳細(xì)的參數(shù)可以參考官方文檔米罚。
sign簽名腳本示例:
xcrun -sdk iphoneos PackageApplication -v "demo.app" -o "demo.ipa"
xcrun命令可以將app文件打包成ipa文件, 主要依賴(lài)xcodebuild命令中指定的證書(shū), 如果沒(méi)有有效證書(shū)的話(huà), 只能在越獄的環(huán)境中安裝ipa。
大家可以嘗試填充這個(gè)腳本, 來(lái)進(jìn)行本地編譯, 如果本地編譯不通過(guò), 那放在Jenkins上是肯定通過(guò)不了的丈探。
具體的腳本內(nèi)容每個(gè)人各不相同, Github上有個(gè)叫BashShell的項(xiàng)目里包含一個(gè)腳本示例build_install.sh, 該項(xiàng)目作者編寫(xiě)的腳本非常詳細(xì), 大家可以參考編寫(xiě)录择。
- xcodebuild命令可以指定對(duì)應(yīng)的簽名文件, 可以通過(guò)預(yù)先上傳簽名文件到編譯服務(wù)器的keychains中或者將證書(shū)存放于代碼托管庫(kù)中方便指定。
- 通過(guò)Jenkins執(zhí)行的腳本會(huì)默認(rèn)注入一些全局環(huán)境變量, 例如
${PWD}
碗降、${CHANGES}
等等隘竭。通過(guò)這些全局參數(shù)可以在執(zhí)行腳本或者郵件等任務(wù)中打印動(dòng)態(tài)數(shù)據(jù)。 - Jenkins默認(rèn)將返回值-1作為失敗條件, 因此如果需要主動(dòng)在腳本終止任務(wù),
return -1
就可以觸發(fā)Jenkins任務(wù)失敗了讼渊。
好了, 準(zhǔn)備工作已經(jīng)差不多了, 可以先將自己的腳本本地測(cè)試下了哦~ 編譯通過(guò)了就可以開(kāi)始配置Jenkins任務(wù)啦~
開(kāi)始自動(dòng)化之旅
新建任務(wù)
編譯腳本动看、編譯環(huán)境都準(zhǔn)備好, Jenkins也正常運(yùn)行了, 接下來(lái)就是創(chuàng)建Jenkins任務(wù)了。
通過(guò)
新建
構(gòu)建一個(gè)自由風(fēng)格的軟件項(xiàng)目爪幻。(同一個(gè)分支不同的任務(wù)也需要建立多個(gè)不同的Job, 每一個(gè)Job在服務(wù)器Home目錄下的.jenkins文件夾下面會(huì)創(chuàng)建一個(gè)獨(dú)立的job和workspace)在配置界面配置對(duì)應(yīng)的
源碼管理
, 現(xiàn)在國(guó)內(nèi)大部分開(kāi)發(fā)者的開(kāi)發(fā)項(xiàng)目應(yīng)該依托于gitlab
的吧菱皆。(gitlab需要制定對(duì)應(yīng)的版本號(hào))-
設(shè)定自動(dòng)執(zhí)行循環(huán)時(shí)間: 在
構(gòu)建觸發(fā)器
勾選Poll SCM
, 可以通過(guò)特定的表達(dá)式進(jìn)行觸發(fā)設(shè)定须误。點(diǎn)擊輸入框后方問(wèn)號(hào)會(huì)提示觸發(fā)表達(dá)式的規(guī)則與書(shū)寫(xiě)方式。- 例如12小時(shí)檢查一次源碼庫(kù)更新可以表達(dá)如下:
H H/12 * * *
- 例如30分鐘檢查一次源碼庫(kù)更新可以表達(dá)如下:
H/30 * * * *
-
在
構(gòu)建
欄點(diǎn)擊增加構(gòu)建步驟
, 選擇Execute Shell
, 在Command欄里面執(zhí)行預(yù)先保存的腳本文件仇轻。假如默認(rèn)保存在項(xiàng)目根目錄下的腳本文件名為jenkins.sh, 則輸入如下代碼:sh jenkins.sh
- PS: 此處如果使用圖形插件的同學(xué)們, 可以在這里添加對(duì)應(yīng)的插件京痢。
構(gòu)建后任務(wù)可以添加郵件提醒以及上傳FTP等執(zhí)行動(dòng)作。
自動(dòng)發(fā)送郵件
- Jenkins默認(rèn)提供了編譯錯(cuò)誤時(shí)候的自動(dòng)郵件發(fā)送功能篷店。 簡(jiǎn)易郵件功能需要在
系統(tǒng)管理
中的系統(tǒng)設(shè)置
中的郵件通知
欄進(jìn)行設(shè)置祭椰。設(shè)置了郵件通知全局配置后, 在Jenkins Job配置的增加構(gòu)建后步驟
中可以配置簡(jiǎn)易的郵件通知, 簡(jiǎn)易版本的郵件通知僅僅支持在系統(tǒng)不穩(wěn)定的時(shí)候通知相關(guān)的責(zé)任人與固定的郵件接收者。 - Email Extension Plugin: Jenkins一個(gè)很強(qiáng)大的郵件系統(tǒng), 可以配置各種各樣的郵件內(nèi)容, 也可以定制不同的觸發(fā)條件以及接受者疲陕。配置使用可以參考其他博文, 例如這篇《Jenkins中配置ESB構(gòu)建后自動(dòng)發(fā)郵件》
自動(dòng)化測(cè)試
自動(dòng)化測(cè)試可以參考構(gòu)建腳本的使用方式, 單獨(dú)書(shū)寫(xiě)shell任務(wù)去執(zhí)行對(duì)應(yīng)的測(cè)試任務(wù), 也可以在構(gòu)建腳本中提前穿插測(cè)試任務(wù)方淤。本文中自動(dòng)化測(cè)試并不是重點(diǎn), 再這里不討論, 后期更新相關(guān)內(nèi)容。
自動(dòng)上傳
自動(dòng)化的最后一步就是提供方便的下載地址給需要安裝App的測(cè)試體驗(yàn)人員鸭轮。需要一個(gè)平臺(tái)提供一個(gè)方便蘋(píng)果app下載的平臺(tái), 目前市面上以fir.im以及蒲公英使用率最廣臣淤。
第三方平臺(tái): 以
fir.im
為例子, fir.im平臺(tái)集成了ipa文件下載所需要plist文件以及一張優(yōu)美的下載頁(yè)。ipa文件第一次需要自己上傳產(chǎn)生一個(gè)對(duì)應(yīng)url地址窃爷。因?yàn)樵撈脚_(tái)本身依賴(lài)于七牛云存儲(chǔ), 因此使用該平臺(tái)的上傳腳本可以使用七牛的qrsync
腳本實(shí)現(xiàn), 具體怎么上傳請(qǐng)參考fir.im的官方指南文檔邑蒋。自建平臺(tái): 自建平臺(tái)比較麻煩, 需要產(chǎn)生對(duì)應(yīng)的plist文件以及下載頁(yè)面, 但是在很多高保密的企業(yè)下是不允許使用第三方平臺(tái)的, 個(gè)人建議為公司搭建一個(gè)簡(jiǎn)易版本的fir.im, 方便以后使用。
- 構(gòu)建平臺(tái)主要是承擔(dān)的工作是企業(yè)證書(shū)下載環(huán)境的搭建以及歷史版本的維護(hù)按厘。企業(yè)證書(shū)下載環(huán)境最關(guān)鍵的部分是plist描述文件的生產(chǎn)以及https服務(wù)的支持(iOS7以后的items-service服務(wù)需要ssl且不接受偽造證書(shū))医吊。
- Bryce Zhange的博文里面有一篇教大家使用Apache和PHP搭建一個(gè)服務(wù)器的博文《iOS自動(dòng)化編譯》, 大家可以參考。該博文包含了如何使用Bruce(heyuan110)的編譯腳本以及如何采用
cat
&EOF
&>>
去動(dòng)態(tài)生成plist文件逮京。
PS: 個(gè)人不建議采用Apache搭建服務(wù)器, 可以試試Ngnix~ 其實(shí)最好是不要自己搭建了~
總結(jié)
本文主要是總結(jié)了我個(gè)人喜愛(ài)的方式, 使用Jenkins+Bash腳本在Mac OS X環(huán)境下搭建一個(gè)自動(dòng)化構(gòu)建環(huán)境卿堂。通過(guò)自動(dòng)化構(gòu)建環(huán)境來(lái)將自己從體驗(yàn)人員和測(cè)試人員不斷要求安裝包的麻煩中解放出來(lái)專(zhuān)心編寫(xiě)工程代碼。Bash主要在于xcodebuild
和xcrun
命令的使用, 以及提供了本人比較愛(ài)好的一套模板方便大家快速編寫(xiě)懒棉。Jenkins主要用于定時(shí)輪詢(xún)代碼和郵件通知草描。
文章的作用是給我本人備忘用的哈~ 水平有限, 有錯(cuò)誤之處請(qǐng)大家及時(shí)指出哈~