遠(yuǎn)端GitLab+Jenkins(CentOS)+本地Mac 做CI自動打包iOS上傳到蒲公英

前言

Jenkins是個(gè)啥?Jenkins是個(gè)非常強(qiáng)大,用于”自動化”編譯、打包、分發(fā)部署的持續(xù)構(gòu)建的可視化web工具。Jenkins支持各種語言的項(xiàng)目,一般情況下,公司的整個(gè)產(chǎn)品線下的各端,我們都可以用Jenkins來創(chuàng)建各個(gè)任務(wù)并完成自動部署并發(fā)布,很好很強(qiáng)大。

構(gòu)建iOS?一般情況下,為了統(tǒng)一管理整個(gè)產(chǎn)品不同端代碼的構(gòu)建,我們會將代碼的構(gòu)建以任務(wù)形式放到同一個(gè)Jenkins下方便管理,那么問題就來了,我們的服務(wù)器大多數(shù)情況下都是Linux,然而iOS的打包并不能在Linux下執(zhí)行,只能在OSX系統(tǒng)下進(jìn)行,所以引出了我今天的內(nèi)容。

Jenkins在Linux上的安裝過程我就省了,這個(gè)在網(wǎng)上到處都有,下面直接進(jìn)入正題。

一、在Jenkins上創(chuàng)建MacOSX節(jié)點(diǎn)

注意:Mac系統(tǒng)上不用安裝Jenkins,因?yàn)樗挥脠?zhí)行遠(yuǎn)程Jenkins給他的命令,所以只需要安裝jdk用來識別遠(yuǎn)程命令即可,后面講到的Jenkins均為遠(yuǎn)程Linux上的,這一點(diǎn)大家先要搞清楚。
首先進(jìn)入節(jié)點(diǎn)管理

image.png

點(diǎn)擊新建節(jié)點(diǎn),輸入名稱,并勾選Permanent Agent

image.png

配置如下圖(鏈接端口在高級按鈕里面填):

image.png

下面是你需要填寫用來存放遠(yuǎn)端Linux服務(wù)器傳給本地Mac用來存證書和keychain的文件的目錄,如下圖:

image.png

這里解釋下每一項(xiàng)的意義:
Name:你節(jié)點(diǎn)取個(gè)名字,隨便填
描述:給予節(jié)點(diǎn)的描述,隨便填
# of executors:并發(fā)任務(wù)數(shù)(不要超過5)
遠(yuǎn)程工作目錄:是你目標(biāo)Mac的工作目錄,在Mac創(chuàng)建一個(gè)目錄用于遠(yuǎn)程Jenkins使用,這里注意這個(gè)目錄的權(quán)限,需要在Mac設(shè)為可讀寫
標(biāo)簽:節(jié)點(diǎn)類型,用于后面分組管理
用法:沒什么說的,照著選就行了
啟動方法:
1.選擇Launch slave agents via SSH;
2.Host填Mac的IP或者域名;
注意了,因?yàn)槲覀兪沁h(yuǎn)程的Linux連接本地的Mac,那么就涉及到一個(gè)內(nèi)網(wǎng)穿透的問題,那么很多同學(xué)會想到“花生殼”,可是Mac上目前是不能用花生殼的,給大家推薦一個(gè)Mac上簡單好用的內(nèi)網(wǎng)穿透工具
https://ngrok.cc/ 使用簡單,速度還行,最重要的是他是免費(fèi)的,大家可以注冊一個(gè)號后根據(jù)他的說明文檔創(chuàng)建一個(gè)基于TCP的隧道,映射到本地SSH端扣(22),這樣一來遠(yuǎn)端的Jenkins就能通過SSH隧道連接到你的Mac了,我配置好后的截圖如下(本地Mac還需要用ngrok客戶端通過命令行來創(chuàng)建隧道,具體參看ngrok文檔說明):

image.png

3.Credentials創(chuàng)建一個(gè)以用戶名密碼登錄的方式,并填入用戶名和密碼,如下圖:

image.png

4.Host Key Verification Strategy:在SSH Slave Plugin插件1.16版本后加入了此選項(xiàng),這里一定注意要選擇"Non verifying Verification Strategy",否則SSH鏈接會報(bào)以下錯(cuò)誤:

[09/23/17 11:40:34] [SSH] Opening SSH connection to xxx.xxx.xxx.xxx:22
[09/23/17 11:40:34] [SSH] WARNING: No entry currently exists in the Known Hosts file for this host.      Connections will be denied until this new host and its associated key is added to the Known Hosts file.
     Key exchange was not finished, connection is closed.
     java.io.IOException: There was a problem while connecting to xxx.xxx.xxx.xxx:22

此時(shí)還需要本地的Mac打開遠(yuǎn)程訪問的權(quán)限,在偏好設(shè)置-》共享中,配置好如下圖:

image.png

配置成功后點(diǎn)擊保存,他將會自動開始連接,連接成功后如圖所示:

image.png

二、創(chuàng)建任務(wù)并配置Mac節(jié)點(diǎn)到任務(wù)中

節(jié)點(diǎn)我們創(chuàng)建好了,接下來需要?jiǎng)?chuàng)建一個(gè)任務(wù),在這里我就簡單介紹一下(不太熟悉的同學(xué)可以完全照著我的配置做),在首頁點(diǎn)擊新建,填入任務(wù)名稱,?選擇第一個(gè)選項(xiàng),如圖:

image.png

因?yàn)槲疫@里使用的是GitLab,所以需要添加兩個(gè)插件“GitLab Plugin”和“Gitlab Hook Plugin”,然后Git需要在全局配置中配置一下:

image.png

點(diǎn)了Add過后選擇GitLab API Token,如下圖:

image.png

去GitLab把Token拿到,并填在Token欄里,在Setting->Account里面,如圖:

image.png

拿到過后就可以ADD再保存,那么在這里就可以看到剛剛添加的Git項(xiàng)了:

image.png

這里勾選“Restrict where this project can be run”,然后填寫MacOSX,他會識別為我們剛才創(chuàng)建的Mac節(jié)點(diǎn):

image.png

源碼管理選擇Git,因?yàn)槲覀兪荊itLab的環(huán)境,這里我填寫的是http的Git鏈接,這樣就用不去配置SSH KEY,省去一些麻煩,當(dāng)然在Credentials選項(xiàng)中對應(yīng)填寫的就是UserName和Password,這個(gè)用戶名和密碼最好是GitLab上的管理員用戶,我在下圖中標(biāo)注了一些Tip:

image.png

構(gòu)建觸發(fā)器照著勾,身份驗(yàn)證令牌需要用命令行創(chuàng)建創(chuàng)建Token

openssl rand -hex 12
e8924xxxxxxxxxx740790531

創(chuàng)建好后先填在這里,然后把下面“GitHub hook trigger for GITScm polling”打上勾,如下圖:

image.png
注意:這里有一個(gè)天坑,必須要安裝"Build Authorization Token Root Plugin"這個(gè)插件,不然我們在做WebHook的時(shí)候GitLab會報(bào)各種403。

Jenkins的WebHook就設(shè)置好了,接下來就來設(shè)置GitLab上的WebHook,
首先選擇需要被Hook的項(xiàng)目,然后Setting->Edit->Integrations,填入Hook的URL,可以看看這個(gè)插件的官方說明https://wiki.jenkins.io/display/JENKINS/Build+Token+Root+Plugin,我總結(jié)的具體格式如下(token就是上面我們生成的”身份驗(yàn)證令牌“):

http://Jenkins服務(wù)器地址:端口/buildByToken/build?job=job名稱&token=token

填寫如下圖,填寫完了直接保存就OK了,保存后點(diǎn)擊TEST,如果之前按照我的配置設(shè)置的,那應(yīng)該就可以成功了(任務(wù)要先保存才能Test成功):

image.png

接下來構(gòu)建環(huán)境需要先配置證書等相關(guān)文件所以必須先配置Keychain和Code Signing Identity具體步驟如下:
1.點(diǎn)擊系統(tǒng)管理-》Keychains and Provisioning Profiles Management(如果沒有,先裝同名插件)

image.png

2.來到這個(gè)插件主頁面,先把Login.keychain和證書傳上去,具體看我的標(biāo)圖:

image.png

3.下方的“Provisioning Profiles Directory Path”需要填寫一個(gè)遠(yuǎn)端Linux服務(wù)器上有的目錄,并且把Login.keychain和證書文件都放到這個(gè)目錄下,證書文件必須是以下圖UUID命名,不然會報(bào)錯(cuò),參看下圖:

image.png

好了到此,證書和keychain都配好了,有同學(xué)可能會問,P12怎么沒地方傳,因?yàn)長ogin.keychain里面包含你所有的證書,你只需要提供登錄密碼個(gè)Jenkins,他會自動解鎖,獲取里面的證書信息,所以上面一張圖里會填寫證書的常用名稱,因?yàn)樗峭ㄟ^常用名稱來找到對應(yīng)證書的。
證書相關(guān)的做完了,那么下圖的配置也就可以做了,ps:Variables是自動生成的:

image.png

下面的配置也一樣,選擇對應(yīng)證書就OK了:

image.png

三、項(xiàng)目構(gòu)建及相關(guān)腳本

下面就是構(gòu)建了,選擇“Execute Shell”,為什么用腳本不用"Xcode"選項(xiàng),明細(xì)腳本會方便很多,省了去看很多沒用的配置。
我這里直講使用直接使用xcodebuild的方式,網(wǎng)上以前版本有人寫過用“xcodebuild + xcrun命令”,但是如今xcrun已經(jīng)不能將.app轉(zhuǎn)為.ipa了,所以有些同學(xué)用以前網(wǎng)上的腳本編譯會出現(xiàn)xcrun命令中“PackageApplication”的錯(cuò)誤:

image.png

這個(gè)錯(cuò)誤是因?yàn)樾掳妫?.3以后)的Xcode已經(jīng)徹底廢棄了PackageApplication,所以報(bào)錯(cuò)是肯定的,所以.app轉(zhuǎn).ipa就得用其他方法了,這里廢話不多說,我把我最新寫出來的打包腳本貼出來,大家自己看看就明白了:

#打包目錄
DEBUG_PATH_NAME="Debug-iphoneos"
# 工程名
APP_NAME="yourAppName"
# 證書,上面配置中填寫的證書常用名
CODE_SIGN_DISTRIBUTION="iPhone Developer: xxxxxx"
# info.plist路徑
project_infoplist_path="./${APP_NAME}/Info.plist"

#取版本號
bundleShortVersion=$(/usr/libexec/PlistBuddy -c "print CFBundleShortVersionString" "${project_infoplist_path}")

#取build值
bundleVersion=$(/usr/libexec/PlistBuddy -c "print CFBundleVersion" "${project_infoplist_path}")

DATE="$(date +%Y%m%d)"
IPANAME="${APP_NAME}_V${bundleShortVersion}_${DATE}.ipa"

#解鎖
security unlock-keychain -p 你的開機(jī)密碼

//下面2行是沒有Cocopods的用法
echo "=================clean================="
xcodebuild -target "${APP_NAME}"  -configuration 'Debug' clean

echo "+++++++++++++++++build+++++++++++++++++"
xcodebuild -target "${APP_NAME}" -sdk iphoneos -configuration 'Debug' CODE_SIGN_IDENTITY="${CODE_SIGN_DISTRIBUTION}" SYMROOT='$(PWD)'

#下面2行xcodebuild命令是集成有Cocopods的用法
echo "=================clean================="
xcodebuild -workspace "${APP_NAME}.xcworkspace" -scheme "${APP_NAME}"  -configuration ‘Debug’ clean

echo "+++++++++++++++++build+++++++++++++++++"
xcodebuild -workspace "${APP_NAME}.xcworkspace" -scheme "${APP_NAME}" -sdk iphoneos -configuration 'Debug' CODE_SIGN_IDENTITY="${CODE_SIGN_DISTRIBUTION}" SYMROOT='$(PWD)'

#將.app文件轉(zhuǎn)為.ipa文件,并放到
rm -rf ./${DEBUG_PATH_NAME}/ipaFolder
mkdir ./${DEBUG_PATH_NAME}/ipaFolder
mkdir ./${DEBUG_PATH_NAME}/ipaFolder/Payload
cp -r ./${DEBUG_PATH_NAME}/${APP_NAME}.app ./${DEBUG_PATH_NAME}/ipaFolder/Payload/${APP_NAME}.app
cd ${DEBUG_PATH_NAME}/ipaFolder
zip -r ${IPANAME} Payload iTunesArtwork
rm -rf ./Payload

#上傳到蒲公英的API
curl -F "file=@${IPANAME}" -F "uKey=yourKey" -F "_api_key=yourKey" https://qiniu-storage.pgyer.com/apiv1/app/upload

1.上面腳本需要修改為你的工程名字
2.證書要改為上面配置中填寫的證書常用名
3.解鎖需要把“你的開機(jī)密碼”替換為你的Mac開機(jī)密碼,否則會報(bào)如下錯(cuò)誤:

unknown error -1=ffffffffffffffff Command /usr/bin/codesign failed with exit code 1

如圖:

image.png

關(guān)于簽名最好把證書的權(quán)限放開,免得又報(bào)簽名的錯(cuò)誤,具體設(shè)置如下:
打開鑰匙串訪問-》找到對應(yīng)的描述-》雙擊-》改為允許所有訪問,如圖:

image.png

4.有沒有CocoaPods是用不同的命令進(jìn)行編譯的,需要二選一
5.蒲公英的上傳需要注冊一個(gè)號,實(shí)名認(rèn)證,然后后臺拿取兩個(gè)對應(yīng)KEY,填入腳本即可在打包完成后上傳

至此任務(wù)創(chuàng)建好后,可以手動點(diǎn)擊開始任務(wù),任務(wù)開始后就如下圖:

image.png

總結(jié)

因?yàn)楣疽话銜信_xx云服務(wù)器,適合用于做CI的總控,然而目前還沒有哪個(gè)廠商有Mac服務(wù)器的鏡像,那么如果需統(tǒng)一自動化打包那么iOS就掉鏈子了,所以我們完全可以用一臺公司內(nèi)網(wǎng)的Mac專門用來自動化打包iOS應(yīng)用,也可以多創(chuàng)建幾個(gè)節(jié)點(diǎn)靈活使用,反正各種場景就完全看你的需求了。

今天整個(gè)實(shí)踐之路非??部?,基本記錄下了主要的坑,還有一些坑可能忘記記錄了,遇到坑的同學(xué)可以給我留言,反正我是各種坑踩了一堆,最后終于算是成功了,經(jīng)歷了43次的失敗,最后曬曬成績單:

image.png

希望我的經(jīng)歷可以給正在路上的你,清空障礙,歡迎各位評論點(diǎn)贊,如果大家喜歡,后面我會陸續(xù)上Android、Maven+SpringMVC、Maven+SpringBoot等CI自動化發(fā)布的文章,謝謝

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容