使用Jenkins搭建iOS/Android持續集成打包平臺

背景描述
  根據項目需求,現要在團隊內部搭建一個統一的打包平臺,實現對iOS和 Android項目的打包。並且爲了方便團隊內部的 測試包分發,但願在打包完成後能生成一個二維碼,體驗用戶(產品、運營、測試等人員)經過 手機掃描二維碼後就能直接安裝測試包。
  該需求具備必定的廣泛性,基本上全部開發APP的團隊均可能會用到,所以我將整個需求實現的過程整理後造成此文,而且真正地作到了零基礎上手,到手即飛、開箱即用,但願能對你們有所幫助。
  首先,先給你們展現下平臺建設完成後的總體效果:
   該平臺主要實現的功能有3點:
  · 按期對GitHub倉庫進行檢測,如有更新則自動執行構建打包;
  · 構建成功後根據ipa/apk生成二維碼,並可在歷史構建列表中展現各個版本的二維碼,經過手機掃描二維碼可直接安裝對應版本;
  · 在構建結果頁面中展現當次構建的成果物(Artifact,如.ipa、.app、.apk、info.plist等文件),供有須要的用戶進行下載。
  接下來,本文就開始對平臺建設的完整實現過程進行詳細介紹。
   安裝Jenkins
  Jenkins依賴於 Java運行環境,所以須要首先安裝Java。
  安裝Jenkins的方式有多種,能夠運行對應系統類型的安裝包,能夠經過docker獲取鏡像,也能夠直接運行war包。
  我我的傾向於直接運行war包的形式,只需下載jenkins.war後,運行以下命令便可啓動Jenkins。
  $ nohup java -jar jenkins_located_path/jenkins.war --httpPort=88 &
  若是不指定httpPort,Jenkins的默認端口爲8080。
Jenkins插件
  Jenkins有很是多的插件,能夠實現各類功能的擴展。
  針對搭建的iOS/Android持續集成打包平臺,我使用到了以下幾個插件。
  · GIT plugin
  · SSH Credentials Plugin
  · Git Changelog Plugin: 獲取倉庫提交的commit log
  · build-name-setter:用於修改Build名稱
  · description setter plugin:用於在修改Build描述信息,在描述信息中增長顯示QRCode(二維碼)
  · Post-Build Script Plug-in:在編譯完成後經過執行腳本實現一些額外功能
  · Xcode integration: iOS專用(可選)
  · Gradle plugin: Android專用(可選)
  安裝方式也比較簡單,直接在Jenkins的插件管理頁面搜索上述插件,點擊安裝便可。
   建立項目(Job)
  在Jenkins中,構建項目以Job的形式存在,所以須要針對每一個項目建立一個Job。有時候,一個項目中可能有多個分支同時在進行開發,爲了分別進行構建,也能夠針對每一個分支建立一個Job。
  建立Job的方式有多種,本次只須要建立Freestyle project類型的便可。
  Main page -> New Item -> Freestyle project
  對於一個持續集成打包平臺,每次打包都由4步組成:觸發構建、拉取代碼、執行構建、構建後處理。對應的,在每一個Job中也對應了這幾項的配置。
   配置Git代碼倉庫
  要對項目進行構建,配置項目的代碼倉庫是必不可少的。因爲當前咱們的項目託管在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】欄目。
  觸發器支持多種類型,經常使用的有:
  · 按期進行構建(Build periodically)
  · 根據提交進行構建(Build when a change is pushed to GitHub)
  · 按期檢測代碼更新,若有更新則進行構建(Poll SCM)
  構建觸發器的選擇爲複合選項,若選擇多種類型,則任一類型知足構建條件時就會執行構建工做。若是全部類型都不選擇,則該Jenkins Job不執行自動構建,但可經過手動點擊【Build Now】觸發構建。
  關於定時器(Schedule)的格式,簡述以下:
  MINUTE HOUR DOM MONTH DOW
  · MINUTE: Minutes within the hour (0-59)
  · HOUR: The hour of the day (0-23)
  · DOM: The day of the month (1-31)
  · MONTH: The month (1-12)
  · DOW: The day of the week (0-7) where 0 and 7 are Sunday.
  一般狀況下須要指定多個值,這時能夠採用以下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 url='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地址便可。
   收集編譯成果物(Artifacts)
  每次完成構建後,編譯生成的文件較多,可是並非全部的文件都是咱們須要的。
  一般狀況下,咱們可能只須要其中的部分文件,例如.ipa/.app/.plist/.apk等,這時咱們能夠將這部分文件單獨收集起來,並在構建頁面中展現出來,以便在須要時進行下載。
  要實現這樣一個功能,須要在【Post-build Actions】欄目中新增Archive the artifacts,而後在Files to archive中經過正則表達式指定成果物文件的路徑。
  設置完畢後,每次構建完成後,Jenkins會在Console Output中採用設定的正則表達式進行搜索匹配,若是能成功匹配到文件,則會將文件收集起來。
   總結
  本文主要是對如何使用Jenkins搭建iOS/Android持續集成打包平臺的基礎概念和實施流程進行了介紹。對於其中涉及到的執行命令、構建腳本(build.py),以及Jenkins的詳細配置,出於篇幅長度和閱讀體驗的考慮,並無在文中進行詳細展開。
  爲了實現真正的開箱即用,我將Jenkins的配置文件和構建腳本抽離出來造成一套模板,只須要導入到Jenkins中,而後針對具體的項目修改少許配置信息,便可將這一套持續集成打包平臺運行起來,實現和文章開頭插圖中徹底相同的功能效果。
相關文章
相關標籤/搜索