ios 持續(xù)集成踩坑

剛開始打算直接用jenkins去走完整一條持續(xù)集成的踩坑之路。
然后發(fā)現(xiàn)jenkins上面坑比較多,網(wǎng)上的對(duì)于某一個(gè)問題解決方案也各式各樣,同樣遇到的問題有人提問,沒人回答,有的回答的然后去試了,感覺越踩越深,可能官方的坑吧。感覺Jenkins配置比較麻煩,學(xué)習(xí)成本比較高。所以后面采取的是jenkins + fastlane進(jìn)行持續(xù)集成操作。后面又涉及到批量打包,所以就采用了xconfig這種模式。

Jenkins主要用于拉取遠(yuǎn)程代碼,然后提供了一個(gè)可視化的界面
fastlane主要用于構(gòu)建工程,上傳的appstore 或者蒲公英等第三方托管平臺(tái)。
Jenkins在這里的操作就是操作fastlane去打包

一些比較好的文獻(xiàn):建議踩坑之前先看
http://www.itdecent.cn/p/5cad74906159 Jenkins For iOS安裝
https://whlsxl.github.io/#to_app_store [小團(tuán)隊(duì)的自動(dòng)化發(fā)布-Fastlane帶來的全自動(dòng)化發(fā)布]
http://www.itdecent.cn/p/c69deb29720d 一步一步構(gòu)建iOS持續(xù)集成:Jenkins+GitLab+蒲公英+FTP

Jenkins 一些簡(jiǎn)單的介紹:
Jenkins是一個(gè)開源軟件項(xiàng)目,是基于Java開發(fā)的一種[持續(xù)集成]工具,用于監(jiān)控持續(xù)重復(fù)的工作,旨在提供一個(gè)開放易用的軟件平臺(tái),使軟件的持續(xù)集成變成可能。
Jenkins 安裝方式總結(jié)下我碰到的有三種:
一種是直接去官網(wǎng)下載Jenkins的pkg安裝包進(jìn)行安裝
一種是下載java.war方式,這個(gè)和第一種其實(shí)一樣的
還有一種就是通過Homebrew進(jìn)行安裝,這些網(wǎng)上都有比較詳細(xì)的教程的。
他們安裝的路徑時(shí)不一樣的。

pkg安裝我遇到一個(gè)問題就是本地處于offline的狀態(tài),安裝不了插件,我跳過安裝插件,直接完成平臺(tái)的初始化配置,當(dāng)我登錄Jenkins平臺(tái),進(jìn)入 系統(tǒng)管理——管理插件,點(diǎn)擊可選插件時(shí)出現(xiàn)這樣一個(gè)錯(cuò)誤



網(wǎng)上翻了一圈,什么方法都嘗試了一下,感覺是java CA證書受信的問題。耽擱了很長(zhǎng)時(shí)間,于是我嘗試了brew安裝的方式,在用brew安裝的時(shí)候需要注意下,brew安裝的和pkg安裝的其實(shí)是可以共存的,pkg安裝默認(rèn)占用了8080端口,并且開機(jī)會(huì)自動(dòng)啟動(dòng)Jenkins服務(wù),你想運(yùn)行brew安裝的版本時(shí)可以找到brew 安裝的Jenkins的jenkins.war路徑,然后給他換個(gè)端口啟動(dòng):(mac如果用brew安裝的話應(yīng)該路徑一樣)

使用如下命令 9999為端口號(hào),當(dāng)某個(gè)端口被占用時(shí)也可以這樣切換
java -jar /usr/local/Cellar/jenkins/2.79/libexec/jenkins.war --httpPort=9999

brew安裝的時(shí)候也出現(xiàn)了offline的提示,看了插件庫(kù)也是一樣的報(bào)錯(cuò),然后找到了一個(gè)解決方案:
在安裝插件時(shí)出現(xiàn)這個(gè)問題(原因和解決方案看下面地址)
Jenkins PKIX path building failed
http://www.cnblogs.com/cuiliqiang/p/4039395.html

brew 安裝的方式,首先需要你本地裝了Homebrew
brew install jenkins  
終端命令啟動(dòng)
jenkins  
開機(jī)自動(dòng)啟動(dòng):
ln -sfv /usr/local/opt/jenkins/*.plist ~/Library/LaunchAgents  
卸載
brew uninstall jenkins  

jenkins 啟動(dòng)需要雙擊jenkins.war文件(如果使用Homebrew安裝只需要在終端 使用命令 jenkins)
在本地瀏覽器輸入localhost:8080 如果沒出現(xiàn)jenkins頁面應(yīng)該是服務(wù)沒起來。
如果終端機(jī)使用jenkins命令報(bào)以下錯(cuò)誤則是端口沖突

jenkins端口沖突報(bào)

可以手動(dòng)修改jenkins端口號(hào)
終端使用該命令:java -jar jenkins.war(該文件絕對(duì)路徑) --httpPort=9999
brew安裝的路徑應(yīng)該是這個(gè)/usr/local/Cellar/jenkins/2.79/libexec/jenkins.war
然后瀏覽器localhost:9999 應(yīng)該就會(huì)出現(xiàn)jenkins界面
java -jar /usr/local/Cellar/jenkins/2.79/libexec/jenkins.war --httpPort=9999

  1. 首先要得到StartCom的證書文件(xxx.cer)。從哪里獲得呢?既然瀏覽器能夠正常訪問,說明系統(tǒng)中是信任StartCom的證書的,所以先打開系統(tǒng)的證書管理界面。在Mac中是Keychain,打開之后找到StartCom的證書,然后右鍵導(dǎo)出成一個(gè).cer文件,命名為startcom.cer。
  2. 然后使用下面的命令把上面那個(gè)cer文件導(dǎo)入到Java的運(yùn)行時(shí)系統(tǒng)中:
    keytool -import -alias startcom -keystore %JRE_HOME/lib/security/cacerts -file startcom.cer
      運(yùn)行該命令時(shí)會(huì)提示輸入密碼,如果你沒有改過的話密碼是’changeit’
    但當(dāng)我運(yùn)行pkg安裝方式的Jenkins時(shí),發(fā)現(xiàn)上面那個(gè)問題還存在,腦袋疼。。。不知道為什么,如果有大神知道的話可以評(píng)論里告知一下。
    后面的操作都是在brew方式安裝的Jenkins配置的
    開始先安裝了一些插件:像Xcode git svn這些都是有必要裝一下的
    我們公司時(shí)gitLab 所以也安裝了這些插件,可以直接在插件庫(kù)里面過濾,或者網(wǎng)上找一下。
    然后就是配置一些證書(用于獲取用戶權(quán)限的證書,比如從gitLab拉取代碼權(quán)限這些)
    如果通過SSH這種方式去獲取用戶權(quán)限需要配置SSH,簡(jiǎn)單講一下:
    拉取代碼的時(shí)候GitLab可以通過git和http方式去獲取密碼,git這種方式需要配置SSH key。
    在使用SSH key時(shí)候還是遇到比較多的問題的,好像都是GitLab服務(wù)器的問題。
    使用http這種去拉取代碼還是比較順利的
配置SSH Key
在Jenkins管理頁面,選擇“Credentials”,然后選擇“Global credentials (unrestricted)”,點(diǎn)擊“Add Credentials” 具體配置如下圖:
ID會(huì)自動(dòng)生成
Passphrase 是生成SSH Key第二步那個(gè)加密私鑰的密碼 
——————————順便扯一下ssh公鑰和私鑰的生成——————————
本機(jī)生成SSH:ssh-keygen -t rsa -C “Your email” , 生成過程中需設(shè)置密碼,最終生成id_rsa和id_rsa.pub(公鑰)
Gitlab上添加公鑰:復(fù)制id_rsa.pub里面的公鑰添加到Gitlab
Jenkins上配置密鑰到SSH:復(fù)制id_rsa.pub里面的公鑰添加到Jenkins(private key選項(xiàng))
生成SSH 時(shí)會(huì)有一步讓你輸Passphrase,建議不要設(shè)密碼,我踩坑的時(shí)候設(shè)置了這個(gè)在我構(gòu)建項(xiàng)目的時(shí)候每次都讓我輸入,驗(yàn)證身份,會(huì)比較麻煩
Jenkins添加SSH Key

如果在項(xiàng)目配置中采用xcode 這種方式去構(gòu)建版本的話需要去這里配置下Keychains and Provisioning Profiles
Keychains and Provisioning Profiles Management

后面就是配置項(xiàng)目了,網(wǎng)上還是有比較多教程的,跟著配就行了,我這邊在構(gòu)建環(huán)節(jié)沒有用Xcode的方式,開始嘗試了,但是失敗了。這個(gè)坑周末填了兩天都沒走出來,網(wǎng)上說這是xcode 9 的一個(gè)bug,找不到描述文件。

Error Domain=IDEProvisioningErrorDomain Code=9 ""********.app" requires a provisioning profile." UserInfo={NSLocalizedDescription="********.app" requires a provisioning profile., NSLocalizedRecoverySuggestion=Add a profile to the "provisioningProfiles" dictionary in your Export Options property list.}

https://issues.jenkins-ci.org/browse/JENKINS-45509

嘗試了各種小道方法,還是不行,所以最后打算在構(gòu)建環(huán)節(jié) 使用Execute shell的方式配合fastlane 腳本進(jìn)行構(gòu)建項(xiàng)目。

Fastlane是用Ruby語言編寫的一套自動(dòng)化工具集和框架,每一個(gè)工具實(shí)際都對(duì)應(yīng)一個(gè)Ruby腳本,用來執(zhí)行某一個(gè)特定的任務(wù),而Fastlane核心框架則允許使用者通過類似配置文件的形式,將不同的工具有機(jī)而靈活的結(jié)合在一起,從而形成一個(gè)個(gè)完整的自動(dòng)化流程。
感覺網(wǎng)上Fastlane比Jenkins的資料多一點(diǎn),F(xiàn)astlane不能遠(yuǎn)程操作,拉取代碼等,所以采用了這兩者的結(jié)合方式,感覺還是比較好用的。

下面講一下 fastlane
首先,安裝 安裝方式網(wǎng)上很多,隨便搜一下就有了,我在安裝過程中沒遇到什么問題。
就遇到一個(gè)xcpretty 找不到,但是這個(gè)應(yīng)該是fastlane會(huì)配套安裝的,不知道是不是版本問題,還有fastlane更新比較快,一周升級(jí)了三個(gè)小版本。
安裝好之后 cd到工程目錄下,然后

fastlane init

這里肯定會(huì)被創(chuàng)建的是Appfile和Fastfile。如果Deliverfile,screenshots和metadata目錄沒被創(chuàng)建,可以運(yùn)行deliver init來創(chuàng)建。(這里備注下,我在使用299賬號(hào)進(jìn)行init操作時(shí)候只生成了Appfile和Fastfile文件,fastlane應(yīng)該做了能不能提交市場(chǎng)的區(qū)分吧,在使用99賬號(hào)進(jìn)行init 操作時(shí)則都生成了)
Fastfile => 用來定義所有的lane任務(wù)
Appfile => 是用來存儲(chǔ)一些公共信息的,比如app_identifier,apple_id,team_id,itc_team_id等。
Deliverfile => deliver的配置文件

PS:
這里有個(gè)小問題,iTC和ADC中的Team ID是不一樣的,在fastlane init中只會(huì)自動(dòng)在Appfile里寫入ADC的team_id,所以在這個(gè)過程中會(huì)不停的問你iTC的Team ID,所以在創(chuàng)建完Appfile后,手動(dòng)在里面添加itc_team_id。

這個(gè)注意下,在Jenkins運(yùn)行Fastfile腳本時(shí)候需要在Appfile中先指定團(tuán)隊(duì)名以及團(tuán)隊(duì)id,不然會(huì)打包不成功,因?yàn)槟悴恢付ㄗC書,F(xiàn)astfile會(huì)詢問你,Jenkins中你沒辦法操作,不像終端

Fastfile是進(jìn)行任務(wù)操作的一個(gè)文件
里面會(huì)有一些 before_all do after_all do這些操作,這個(gè)看看名字就知道了吧,before_all do一般做一些環(huán)境以及路徑的配置,cocoapods 的一些操作,當(dāng)然你也可以直接也在命令主體里面寫

這樣就可以看成一個(gè)方法,可以進(jìn)入到你要操作的項(xiàng)目的目錄下 在終端使用 fastlane upload ,下面的方法就會(huì)執(zhí)行了,注意fastlane在寫腳本的時(shí)候記得 configuration 設(shè)置成你要打包時(shí)候的設(shè)置成你要打包的那個(gè)configuration。
  desc "Deploy a new version to the App Store"
  lane :upload do
    # match(type: "appstore")
    # snapshot
    gym(
    scheme: "******************", # Build your app - more options available
    clean:true, # 在構(gòu)建前先clean
    configuration:"Release",  # 配置為Release版本
    codesigning_identity: "iPhone Distribution: ****************** Co. Ltd. (JQ******************)”,
    export_method:"enterprise",
    ) 
    pgyer(api_key: "15a8******************78245", user_key: "faf7******************9edf2ff1")
    # frameit
  end
這個(gè)是打包上傳蒲公英的方法,但是記得在fastlane init操作的時(shí)候填299的賬號(hào),同樣,上傳appstore時(shí)fastlane init操作時(shí)記得填99的賬號(hào)

Fastlane是一套工具集,包括:
測(cè)試
scan => 自動(dòng)運(yùn)行測(cè)試工具,并且可以生成漂亮的HTML報(bào)告
證書,配置文件
cert => 自動(dòng)創(chuàng)建管理iOS代碼簽名證書
sigh=> 一聲嘆息啊,這么多年和Provisioning Profile戰(zhàn)斗過無數(shù)次??偸怯羞@樣那樣的問題導(dǎo)致配置文件過期或者失效。sigh是用來創(chuàng)建、更新、下載、修復(fù)Provisioning Profile的工具。
pem=> 自動(dòng)生成、更新推送配置文件
match => 一個(gè)新的證書和配置文件管理工具。
截圖
snapshot => 用Xcode7推出的UI test功能實(shí)現(xiàn)自動(dòng)化截圖
frameit=> 可以把截的圖片自動(dòng)套上一層外邊框
編譯
shenzhen => 當(dāng)年大名鼎鼎的自動(dòng)編譯工具,現(xiàn)在已經(jīng)被棄用
gym=> Fastlane家族的自動(dòng)化編譯工具,和其他工具配合的非常默契
發(fā)布
produce => 如果你的產(chǎn)品還沒在iTunes Connect(iTC)或者Apple Developer Center(ADC)建立,produce可以自動(dòng)幫你完成這些工作
deliver => 自動(dòng)上傳截圖,APP的元數(shù)據(jù),二進(jìn)制(ipa)文件到iTunes Connect
TestFlight管理
pilot=> 管理TestFlight的測(cè)試用戶,上傳二進(jìn)制文件
boarding => 建立一個(gè)添加測(cè)試用戶界面,發(fā)給測(cè)試者,可自行添加郵件地址,并同步到iTC
輔助工具spaceship=> 為pilot,boarding和deliver等工具提供和 iTC 和 ADC 的交互API。spaceship本來是個(gè)獨(dú)立的項(xiàng)目,后來被Fastlane收編進(jìn)來
WatchBuild=> 是一個(gè)獨(dú)立的iTC監(jiān)控工具,開啟WatchBuild可以監(jiān)控iTC上的文件狀態(tài),彈出MacOS自帶的Notification
Android
supply => 自動(dòng)上傳到Google Play工具(如果有時(shí)間,我想把國(guó)內(nèi)提供API的Android Store都寫個(gè)插件自動(dòng)上傳,這個(gè)問題從10年我剛開始工作就覺得是個(gè)痛點(diǎn))
screengrab => Android的自動(dòng)截圖工具
Fastlane功能強(qiáng)大,只嘗試了比較少的功能,時(shí)時(shí)更新。
——————————fastlane一些腳本————————————

提交到蘋果市場(chǎng)
lane :upload do
    # match(type: "appstore")
    # snapshot
    gym(
    scheme: "******", # Build your app - more options available
    clean:true, # 在構(gòu)建前先clean
    configuration:"Release",  # 配置為Release版本
    export_method:"app-store",
    ) 
    deliver(force: true)
  end
走testflight進(jìn)行內(nèi)測(cè)
  lane :uploadTotest do
    # match(type: "appstore")
    # snapshot
    gym(
    scheme: "*******", # Build your app - more options available
    clean:true, # 在構(gòu)建前先clean
    configuration:"Release",  # 配置為Release版本
    export_method:"app-store",
    ) 
    pilot
    # frameit
  end

這個(gè)會(huì)等地比較久的時(shí)間,因?yàn)閕pa到蘋果市場(chǎng)要


上傳蘋果市場(chǎng)
上傳到蒲公英
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容