根據項目需求,現要在團隊內部搭建一個統一的打包平臺,實現對iOS和Android項目的打包。並且爲了方便團隊內部的測試包分發,但願在打包完成後能生成一個二維碼,體驗用戶(產品、運營、測試等人員)經過手機掃描二維碼後就能直接安裝測試包。html
該需求具備必定的廣泛性,基本上全部開發APP的團隊均可能會用到,所以我將整個需求實現的過程整理後造成此文,而且真正地作到了零基礎上手,到手即飛、開箱即用
,但願能對你們有所幫助。java
首先,先給你們展現下平臺建設完成後的總體效果:正則表達式
該平臺主要實現的功能有3點:docker
.ipa
、.app
、.apk
、info.plist
等文件),供有須要的用戶進行下載。接下來,本文就開始對平臺建設的完整實現過程進行詳細介紹。shell
Jenkins依賴於Java運行環境,所以須要首先安裝Java。安全
安裝Jenkins的方式有多種,能夠運行對應系統類型的安裝包,能夠經過docker獲取鏡像,也能夠直接運行war
包。服務器
我我的傾向於直接運行war
包的形式,只需下載jenkins.war
後,運行以下命令便可啓動Jenkins。markdown
$ nohup java -jar jenkins_located_path/jenkins.war --httpPort=88 &
若是不指定httpPort
,Jenkins的默認端口爲8080。網絡
Jenkins有很是多的插件,能夠實現各類功能的擴展。oracle
針對搭建的iOS/Android持續集成打包平臺,我使用到了以下幾個插件。
安裝方式也比較簡單,直接在Jenkins的插件管理頁面搜索上述插件,點擊安裝便可。
在Jenkins中,構建項目以Job的形式存在,所以須要針對每一個項目建立一個Job。有時候,一個項目中可能有多個分支同時在進行開發,爲了分別進行構建,也能夠針對每一個分支建立一個Job。
建立Job的方式有多種,本次只須要建立Freestyle project
類型的便可。
Main page
->New Item
->Freestyle project
對於一個持續集成打包平臺,每次打包都由4步組成:觸發構建、拉取代碼、執行構建、構建後處理。對應的,在每一個Job中也對應了這幾項的配置。
要對項目進行構建,配置項目的代碼倉庫是必不可少的。因爲當前咱們的項目託管在GitHub私有倉庫中,所以在此須要對Git
進行配置。
在【Source Code Management】
配置欄目下,若是以前GIT plugin
安裝成功,則會出現Git
選項。
配置Git代碼倉庫時,有三項是必須配置的:倉庫URL地址(Repository URL
)、倉庫權限校驗方式(Credentials
),以及當前Job須要構建的代碼分支(Branches to build
)。
在配置Repository URL
時,選擇HTTPS URL
或SSH URL
都可。不過須要注意的是,Credentials
要和Repository URL
對應,也就是說:
Repository URL
是HTTPS URL
形式的,那麼Credentials
就要採用GitHub用戶名密碼的校驗方式;並且,若是在GitHub中開啓了2FA(two-factor authentication)
,那麼還須要在GitHub中建立一個Personal access token
,輸入密碼時將這個Personal access token
做爲密碼進行輸入。Repository URL
是SSH URL
形式的,那麼就須要先在Jenkins所在的服務器上建立一個SSH
祕鑰對,並將公鑰添加到GitHub的SSH keys
中,而後在填寫Credentials
時,選擇SSH Username with private key
的校驗方式,填入GitHub Username、SSH私鑰、以及建立SSH
祕鑰對時設置的Passphrase
。若是對Git權限校驗的概念還比較模糊,能夠參考《深刻淺出Git權限校驗》。
在配置Branches to build
時,能夠採用多種形式,包括分支名稱(branchName
)、tagName
、commitId
等。其中分支名稱的形式用的最多,例如,如果構建master
分支,則填寫refs/heads/master
,如果構建develop
分支,則填寫refs/heads/develop
。
除了以上關於Git的必填配置項,有時根據項目的實際狀況,可能還須要對Jenkins的默認配置項進行修改。
比較常見的一種狀況就是對clone
的配置進行修改。
在Jenkins的默認配置中,clone
代碼時會拉取全部歷史版本的代碼,並且默認的超時時限只有10分鐘。這就形成在某些項目中,因爲代碼量自己就比較大,歷史版本也比較多,再加上網絡環境不是特別好,Jenkins根本無法在10分鐘以內拉取完全部代碼,超時後任務就會被自動終止了(錯誤狀態碼143)。
這種問題的解決方式也很簡單,無非就是兩種思路,要麼少拉取點代碼(不獲取歷史版本),要麼提升超時時限。對應的配置在Advanced clone behaviours
中:
Shallow clone
:勾選後不獲取歷史版本;Timeout (in minutes) for clone and fetch operation
:配置後覆蓋默認的超時時限。代碼倉庫配置好了,意味着Jenkins具備了訪問GitHub代碼倉庫的權限,能夠成功地拉取代碼。
那Jenkins何時執行構建呢?
這就須要配置構建觸發策略,即構建觸發器,配置項位於【Build Triggers】
欄目。
觸發器支持多種類型,經常使用的有:
構建觸發器的選擇爲複合選項,若選擇多種類型,則任一類型知足構建條件時就會執行構建工做。若是全部類型都不選擇,則該Jenkins Job
不執行自動構建,但可經過手動點擊【Build Now】
觸發構建。
關於定時器(Schedule)的格式,簡述以下:
MINUTE HOUR DOM MONTH DOW
一般狀況下須要指定多個值,這時能夠採用以下operator(優先級從上到下):
*
適配全部有效的值,若不指定某一項,則以*
佔位;M-N
適配值域範圍,例如7-9表明7/8/9均知足;M-N/X
或*/X
:以X做爲間隔;A,B,C
:枚舉多個值。另外,爲了不多個任務在同一時刻同時觸發構建,在指定時間段時能夠配合使用H
字符。添加H
字符後,Jenkins會在指定時間段內隨機選擇一個時間點做爲起始時刻,而後加上設定的時間間隔,計算獲得後續的時間點。直到下一個週期時,Jenkins又會從新隨機選擇一個時間點做爲起始時刻,依次類推。
爲了便於理解,列舉幾個示例:
H/15 * * * *
:表明每隔15分鐘,而且開始時間不肯定,這個小時多是:07,:22,:37,:52
,下一個小時就多是:03,:18,:33,:48
;H(0-29)/10 * * * *
:表明前半小時內每隔10分鐘,而且開始時間不肯定,這個小時多是:04,:14,:24
,下一個小時就多是:09,:19,:29
;H 23 * * 1-5
:工做日每晚23:00至23:59之間的某一時刻;觸發策略配置好以後,Jenkins就會按照設定的策略自動執行構建。但如何執行構建操做,這還須要咱們經過配置構建方式來進行設定。
經常使用的構建方式是根據構建對象的具體類型,安裝對應的插件,而後採用相應的構建方式。例如,如果構建Android
應用,安裝Gradle plugin
以後,就能夠選擇Invoke Gradle script
,而後採用Gradle
進行構建;如果構建iOS
應用,安裝Xcode integration
插件以後,就能夠選擇Xcode
,而後選擇Xcode
進行構建。
該種方式的優點是操做簡單,UI可視化,在場景不復雜的狀況下能夠快速知足需求。不過缺點就是依賴於插件已有的功能,若是場景較複雜時可能單個插件還沒法知足需求,須要再安裝其它插件。並且,有些插件可能還存在一些問題,例如對某些操做系統版本或XCode版本兼容不佳,出現問題時咱們就會比較被動。
我我的更傾向於另一種方式,就是本身編寫打包腳本,在腳本中自定義實現全部的構建功能,而後在Execute Shell
中執行。這種方式的靈活度更高,各類場景的構建需求都能知足,出現問題後也能自行快速修復。
另外,對於iOS應用的構建,還有一個須要額外關注的點,就是開發者證書的配置。
若是是採用Xcode integration
插件進行構建,配置會比較複雜,須要在Jenkins中導入開發證書,並填寫多個配置項。不過,若是是採用打包腳本進行構建的話,狀況就會簡單許多。只要在Jenkins所運行的計算機中安裝好開發者證書,打包命令在Shell中能正常工做,那麼在Jenkins中執行打包腳本也不會有什麼問題。
完成構建後,生成的編譯成果物(ipa/apk)會位於指定的目錄中。可是,若是要直接在手機中安裝ipa/apk
文件還比較麻煩,不只在分發測試包時須要將好幾十兆的安裝包進行傳送,體驗用戶在安裝時也還須要經過數據線將手機與計算機進行鏈接,而後再使用PP助手或豌豆莢等工具進行安裝。
當前比較優雅的一種方式是藉助蒲公英(pgyer)
或fir.im
等平臺,將ipa/apk
文件上傳至平臺後由平臺生成二維碼,而後只須要對二維碼連接進行分發,體驗用戶經過手機掃描二維碼後便可實現快速安裝,效率獲得了極大的提高。
無論是蒲公英
仍是fir.im
,都有對應的Jenkins插件,安裝插件後能夠在Post-build
中實現對安裝包的上傳。
除了使用Jenkins插件,fir.im
還支持命令上傳的方式,蒲公英
還支持HTTP Post
接口上傳的方式。
我我的推薦採用命令或接口上傳的方法,並在構建腳本中進行調用。靈活是一方面,更大的好處是若是上傳失敗後還能進行重試,這在網絡環境不是很穩定的狀況下極其必要。
Jenkins成功完成安裝包上傳後,pgyer/fir.im
平臺會生成一個二維碼圖片,並在響應中將圖片的URL連接地址進行返回。
二維碼圖片的URL連接有了,那要怎樣才能將二維碼圖片展現在Jenkins項目的歷史構建列表中呢?
這裏須要用到另一個插件,description setter plugin
。安裝該插件後,在【Post-build Actions】
欄目中會多出description setter
功能,能夠實現構建完成後設置當次build的描述信息。這個描述信息不只會顯示在build頁面中,同時也會顯示在歷史構建列表中。
有了這個前提,要將二維碼圖片展現在歷史構建列表中貌似就能夠實現了,能直觀想到的方式就是採用HTML
的img
標籤,將<img src='qr_code_url'>
寫入到build描述信息中。
這個方法的思路是正確的,不過這麼作之後並不會實現咱們預期的效果。
這是由於Jenkins出於安全的考慮,全部描述信息的Markup Formatter
默認都是採用Plain text
模式,在這種模式下是不會對build描述信息中的HTML編碼進行解析的。
要改變也很容易,Manage Jenkins
-> Configure Global Security
,將Markup Formatter
的設置更改成Safe HTML
便可。
更改配置後,咱們就能夠在build描述信息中採用HTML
的img
標籤插入圖片了。
另外還須要補充一個點。若是是使用蒲公英(pyger)
平臺,會發現每次上傳安裝包後返回的二維碼圖片是一個短連接,神奇的是這個短鏈接竟然是固定的(對同一個帳號而言)。這個短鏈接老是指向最近生成的二維碼圖片,可是對於二維碼圖片的惟一URL地址,平臺並無在響應中進行返回。在這種狀況下,咱們每次構建完成後保存二維碼圖片的URL連接就沒有意義了。
應對的作法是,每次上傳完安裝包後,經過返回的二維碼圖片短連接將二維碼圖片下載並保存到本地,而後在build描述信息中引用該圖片的Jenkins地址便可。
每次完成構建後,編譯生成的文件較多,可是並非全部的文件都是咱們須要的。
一般狀況下,咱們可能只須要其中的部分文件,例如.ipa/.app/.plist/.apk
等,這時咱們能夠將這部分文件單獨收集起來,並在構建頁面中展現出來,以便在須要時進行下載。
要實現這樣一個功能,須要在【Post-build Actions】
欄目中新增Archive the artifacts
,而後在Files to archive
中經過正則表達式指定成果物文件的路徑。
設置完畢後,每次構建完成後,Jenkins會在Console Output
中採用設定的正則表達式進行搜索匹配,若是能成功匹配到文件,則會將文件收集起來。
本文主要是對如何使用Jenkins搭建iOS/Android持續集成打包平臺的基礎概念和實施流程進行了介紹。對於其中涉及到的執行命令、構建腳本(build.py),以及Jenkins的詳細配置,出於篇幅長度和閱讀體驗的考慮,並無在文中進行詳細展開。
爲了實現真正的開箱即用
,我將Jenkins的配置文件和構建腳本抽離出來造成一套模板,只須要導入到Jenkins中,而後針對具體的項目修改少許配置信息,便可將這一套持續集成打包平臺運行起來,實現和文章開頭插圖中徹底相同的功能效果。