前言
Jenkins是個(gè)啥底循?Jenkins是個(gè)非常強(qiáng)大巢株,用于”自動(dòng)化”編譯、打包熙涤、分發(fā)部署的持續(xù)構(gòu)建的可視化web工具阁苞。Jenkins支持各種語(yǔ)言的項(xiàng)目困檩,一般情況下,公司的整個(gè)產(chǎn)品線下的各端那槽,我們都可以用Jenkins來創(chuàng)建各個(gè)任務(wù)并完成自動(dòng)部署并發(fā)布悼沿,很好很強(qiáng)大。
構(gòu)建iOS?一般情況下骚灸,為了統(tǒng)一管理整個(gè)產(chǎn)品不同端代碼的構(gòu)建糟趾,我們會(huì)將代碼的構(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用來識(shí)別遠(yuǎn)程命令即可,后面講到的Jenkins均為遠(yuǎn)程Linux上的俏橘,這一點(diǎn)大家先要搞清楚允华。
首先進(jìn)入節(jié)點(diǎn)管理
點(diǎn)擊新建節(jié)點(diǎn),輸入名稱敷矫,并勾選Permanent Agent
配置如下圖(鏈接端口在高級(jí)按鈕里面填):
下面是你需要填寫用來存放遠(yuǎn)端Linux服務(wù)器傳給本地Mac用來存證書和keychain的文件的目錄例获,如下圖:
這里解釋下每一項(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)類型收壕,用于后面分組管理
用法:沒什么說的,照著選就行了
啟動(dòng)方法:
1.選擇Launch slave agents via SSH轨蛤;
2.Host填Mac的IP或者域名蜜宪;
注意了,因?yàn)槲覀兪沁h(yuǎn)程的Linux連接本地的Mac祥山,那么就涉及到一個(gè)內(nèi)網(wǎng)穿透的問題圃验,那么很多同學(xué)會(huì)想到“花生殼”,可是Mac上目前是不能用花生殼的缝呕,給大家推薦一個(gè)Mac上簡(jiǎn)單好用的內(nèi)網(wǎng)穿透工具
https://ngrok.cc/ 使用簡(jiǎn)單澳窑,速度還行斧散,最重要的是他是免費(fèi)的,大家可以注冊(cè)一個(gè)號(hào)后根據(jù)他的說明文檔創(chuàng)建一個(gè)基于TCP的隧道摊聋,映射到本地SSH端扣(22)鸡捐,這樣一來遠(yuǎn)端的Jenkins就能通過SSH隧道連接到你的Mac了,我配置好后的截圖如下(本地Mac還需要用ngrok客戶端通過命令行來創(chuàng)建隧道麻裁,具體參看ngrok文檔說明):
3.Credentials創(chuàng)建一個(gè)以用戶名密碼登錄的方式箍镜,并填入用戶名和密碼,如下圖:
4.Host Key Verification Strategy:在SSH Slave Plugin插件1.16版本后加入了此選項(xiàng)煎源,這里一定注意要選擇"Non verifying Verification Strategy"色迂,否則SSH鏈接會(huì)報(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è)置-》共享中手销,配置好如下圖:
配置成功后點(diǎn)擊保存脚草,他將會(huì)自動(dòng)開始連接,連接成功后如圖所示:
二原献、創(chuàng)建任務(wù)并配置Mac節(jié)點(diǎn)到任務(wù)中
節(jié)點(diǎn)我們創(chuàng)建好了,接下來需要?jiǎng)?chuàng)建一個(gè)任務(wù)埂淮,在這里我就簡(jiǎn)單介紹一下(不太熟悉的同學(xué)可以完全照著我的配置做)姑隅,在首頁(yè)點(diǎn)擊新建,填入任務(wù)名稱倔撞,?選擇第一個(gè)選項(xiàng)讲仰,如圖:
因?yàn)槲疫@里使用的是GitLab,所以需要添加兩個(gè)插件“GitLab Plugin”和“Gitlab Hook Plugin”痪蝇,然后Git需要在全局配置中配置一下:
點(diǎn)了Add過后選擇GitLab API Token鄙陡,如下圖:
去GitLab把Token拿到,并填在Token欄里躏啰,在Setting->Account里面趁矾,如圖:
拿到過后就可以ADD再保存,那么在這里就可以看到剛剛添加的Git項(xiàng)了:
這里勾選“Restrict where this project can be run”给僵,然后填寫MacOSX毫捣,他會(huì)識(shí)別為我們剛才創(chuàng)建的Mac節(jié)點(diǎn):
源碼管理選擇Git,因?yàn)槲覀兪荊itLab的環(huán)境帝际,這里我填寫的是http的Git鏈接蔓同,這樣就用不去配置SSH KEY,省去一些麻煩蹲诀,當(dāng)然在Credentials選項(xiàng)中對(duì)應(yīng)填寫的就是UserName和Password斑粱,這個(gè)用戶名和密碼最好是GitLab上的管理員用戶,我在下圖中標(biāo)注了一些Tip:
構(gòu)建觸發(fā)器照著勾脯爪,身份驗(yàn)證令牌需要用命令行創(chuàng)建創(chuàng)建Token
openssl rand -hex 12
e8924xxxxxxxxxx740790531
創(chuàng)建好后先填在這里则北,然后把下面“GitHub hook trigger for GITScm polling”打上勾矿微,如下圖:
注意:這里有一個(gè)天坑,必須要安裝"Build Authorization Token Root Plugin"這個(gè)插件咒锻,不然我們?cè)谧鯳ebHook的時(shí)候GitLab會(huì)報(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成功):
接下來構(gòu)建環(huán)境需要先配置證書等相關(guān)文件所以必須先配置Keychain和Code Signing Identity具體步驟如下:
1.點(diǎn)擊系統(tǒng)管理-》Keychains and Provisioning Profiles Management(如果沒有蜈垮,先裝同名插件)
2.來到這個(gè)插件主頁(yè)面耗跛,先把Login.keychain和證書傳上去,具體看我的標(biāo)圖:
3.下方的“Provisioning Profiles Directory Path”需要填寫一個(gè)遠(yuǎn)端Linux服務(wù)器上有的目錄攒发,并且把Login.keychain和證書文件都放到這個(gè)目錄下调塌,證書文件必須是以下圖UUID命名,不然會(huì)報(bào)錯(cuò)惠猿,參看下圖:
好了到此羔砾,證書和keychain都配好了,有同學(xué)可能會(huì)問偶妖,P12怎么沒地方傳姜凄,因?yàn)長(zhǎng)ogin.keychain里面包含你所有的證書,你只需要提供登錄密碼個(gè)Jenkins趾访,他會(huì)自動(dòng)解鎖态秧,獲取里面的證書信息,所以上面一張圖里會(huì)填寫證書的常用名稱腹缩,因?yàn)樗峭ㄟ^常用名稱來找到對(duì)應(yīng)證書的屿聋。
證書相關(guān)的做完了,那么下圖的配置也就可以做了藏鹊,ps:Variables是自動(dòng)生成的:
下面的配置也一樣润讥,選擇對(duì)應(yīng)證書就OK了:
三、項(xiàng)目構(gòu)建及相關(guān)腳本
下面就是構(gòu)建了盘寡,選擇“Execute Shell”楚殿,為什么用腳本不用"Xcode"選項(xiàng),明細(xì)腳本會(huì)方便很多,省了去看很多沒用的配置脆粥。
我這里直講使用直接使用xcodebuild的方式砌溺,網(wǎng)上以前版本有人寫過用“xcodebuild + xcrun命令”,但是如今xcrun已經(jīng)不能將.app轉(zhuǎn)為.ipa了变隔,所以有些同學(xué)用以前網(wǎng)上的腳本編譯會(huì)出現(xiàn)xcrun命令中“PackageApplication”的錯(cuò)誤:
這個(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"
#取版本號(hào)
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ī)密碼,否則會(huì)報(bào)如下錯(cuò)誤:
unknown error -1=ffffffffffffffff Command /usr/bin/codesign failed with exit code 1
如圖:
關(guān)于簽名最好把證書的權(quán)限放開柑爸,免得又報(bào)簽名的錯(cuò)誤吵护,具體設(shè)置如下:
打開鑰匙串訪問-》找到對(duì)應(yīng)的描述-》雙擊-》改為允許所有訪問,如圖:
4.有沒有CocoaPods是用不同的命令進(jìn)行編譯的表鳍,需要二選一
5.蒲公英的上傳需要注冊(cè)一個(gè)號(hào)馅而,實(shí)名認(rèn)證,然后后臺(tái)拿取兩個(gè)對(duì)應(yīng)KEY譬圣,填入腳本即可在打包完成后上傳
至此任務(wù)創(chuàng)建好后用爪,可以手動(dòng)點(diǎn)擊開始任務(wù),任務(wù)開始后就如下圖:
總結(jié)
因?yàn)楣疽话銜?huì)有臺(tái)xx云服務(wù)器胁镐,適合用于做CI的總控,然而目前還沒有哪個(gè)廠商有Mac服務(wù)器的鏡像诸衔,那么如果需統(tǒng)一自動(dòng)化打包那么iOS就掉鏈子了盯漂,所以我們完全可以用一臺(tái)公司內(nèi)網(wǎng)的Mac專門用來自動(dòng)化打包iOS應(yīng)用,也可以多創(chuàng)建幾個(gè)節(jié)點(diǎn)靈活使用笨农,反正各種場(chǎng)景就完全看你的需求了就缆。
今天整個(gè)實(shí)踐之路非常坎坷谒亦,基本記錄下了主要的坑竭宰,還有一些坑可能忘記記錄了,遇到坑的同學(xué)可以給我留言份招,反正我是各種坑踩了一堆切揭,最后終于算是成功了,經(jīng)歷了43次的失敗锁摔,最后曬曬成績(jī)單:
希望我的經(jīng)歷可以給正在路上的你廓旬,清空障礙,歡迎各位評(píng)論點(diǎn)贊谐腰,如果大家喜歡孕豹,后面我會(huì)陸續(xù)上Android涩盾、Maven+SpringMVC、Maven+SpringBoot等CI自動(dòng)化發(fā)布的文章励背,謝謝