Jenkins 實(shí)現(xiàn) iOS 項(xiàng)目自動(dòng)打包

Jenkins 概述

Jenkins 是一款流行的開源持續(xù)集成(Continuous Integration)工具,廣泛用于項(xiàng)目開發(fā)垦沉,具有自動(dòng)化構(gòu)建迫皱、測(cè)試和部署等功能。Jenkins用Java語(yǔ)言編寫沸版,可在Tomcat等流行的servlet容器中運(yùn)行,也可獨(dú)立運(yùn)行兴蒸。通常與版本管理工具(SCM)视粮、構(gòu)建工具結(jié)合使用。常用的版本控制工具有SVN橙凳、GIT蕾殴,構(gòu)建工具有Maven、Ant岛啸、Gradle钓觉。

安裝 Jenkins

由于Jenkins 依賴于Java,所以在安裝Jenkins前坚踩,需要先檢查是否已安裝Java環(huán)境荡灾。 在終端輸入命令進(jìn)行檢測(cè):

$ java -version

官網(wǎng)下載

image.png

點(diǎn)擊進(jìn)入安裝說明頁(yè)面,可以按照提示命令安裝

使用 Homebrew 軟件包管理器安裝Jenkins 瞬铸。

自制安裝程序 jenkins-lts 批幌。

安裝命令:

  • 安裝最新的LTS版本:brew install jenkins-lts
  • 安裝特定的LTS版本:brew install jenkins-lts@YOUR_VERSION
  • 啟動(dòng) Jenkins 服務(wù):brew services start jenkins-lts
  • 重新啟動(dòng) Jenkins 服務(wù):brew services restart jenkins-lts
  • 更新 Jenkins 版本:brew upgrade jenkins-lts

安裝步驟

  • 啟動(dòng) Jenkins 服務(wù)后,瀏覽 http://localhost:8080 嗓节,該頁(yè)面需要確認(rèn)是管理員安裝荧缘,讓我們輸入密碼,密碼存放在紅色的目錄下赦政,取出來填到輸入框里就行胜宇。
    image.png
  • 選擇安裝推薦的插件。


    image.png
  • 等待插件安裝完成恢着,有的插件可能會(huì)安裝失敗桐愉,建議重試,直到把建議安裝的都裝好掰派。


    image.png
  • 插件安裝完成后會(huì)自動(dòng)跳轉(zhuǎn)到配置完管理員賬戶


    image.png
  • 點(diǎn)擊保存并完成从诲,完成注冊(cè)

Jenkins 配置

打開瀏覽器,輸入localhost:8080靡羡,即可打開Jenkins系洛,輸入密碼,點(diǎn)擊繼續(xù)略步。

重啟Jenkins

因部分插件依賴可能出現(xiàn)錯(cuò)誤
圖片

待創(chuàng)建好用戶后描扯,可以重啟Jenkins,并用剛創(chuàng)建的賬戶或者admin賬戶登錄Jenkins趟薄。重啟Jenkins方法绽诚,命令行中輸入jenkins-lts,回車即可。

安裝iOS相關(guān)插件

iOS打包需要鑰匙串中訪問證書恩够、描述文件等卒落,所以我們要安裝鑰匙串和描述文件插件。進(jìn)入Jenkins->系統(tǒng)管理->插件管理安裝相關(guān)插件蜂桶,可通過右上角過濾搜索儡毕。然后選擇需要安裝的插件,進(jìn)行勾選扑媚,安裝腰湾。安裝成功后可以選擇是否重啟Jenkins。


圖片
圖片
圖片

等待安裝完成后重啟 jenkins


image.png

配置鑰匙串

成功之后钦购,我們可以在Jenkins首頁(yè)->系統(tǒng)管理中發(fā)現(xiàn)剛才我們安裝的Keychains and Provisioning Profiles Management檐盟,點(diǎn)擊進(jìn)入配置鑰匙串和描述文件。


圖片

上傳keychain和provisioning Profile文件押桃。
圖片

可以在鑰匙串中看到登錄的鑰匙串路徑葵萎,然后只需要按照路徑找到這個(gè)文件上傳(點(diǎn)擊upload)即可。
圖片

注意:login.keychain-db是上傳不了的唱凯,我們需要復(fù)制一份羡忘,改為login.keychain。另外上傳的時(shí)候磕昼,找不到路徑卷雕,是因?yàn)橘Y源庫(kù)被隱藏起來了,需要使用command+shift+.將其顯示出來票从,就可以了漫雕。
圖片

注意:Code Signing Identity是可以配置多個(gè)的,我們可以把通知證書峰鄙、發(fā)布證書都加入到里面浸间,方法就是點(diǎn)擊下面的Add Code Sign Identity。

配置描述文件

先上傳Provisioning Profiles文件吟榴,這些文件的路徑為/Users/[你的電腦用戶名]/Library/MobileDevice/Provisioning Profiles魁蒜,在此路徑下找到相應(yīng)的項(xiàng)目的profile文件上傳,拖入終端會(huì)顯示整個(gè)路徑吩翻,復(fù)制過來兜看,點(diǎn)擊保存就OK了,現(xiàn)在 Jenkins不需要一個(gè)一個(gè)上傳描述文件了??狭瞎。

圖片

到此為止整個(gè)插件配置完成细移。

創(chuàng)建一個(gè)工程

新建任務(wù)

選第一個(gè),輸入工程名稱熊锭,點(diǎn)擊確定葫哗。


image.png

構(gòu)建配置

General

image.png

源碼管理

我使用Git缔刹,credentials是登錄的賬號(hào)密碼球涛,打包分支可以根據(jù)需要設(shè)置


圖片

如果沒有添加一個(gè)劣针,如下圖


image.png

構(gòu)建環(huán)境

選擇剛才插件填寫的對(duì)應(yīng)證書。


圖片

構(gòu)建(關(guān)鍵)

點(diǎn)擊增加構(gòu)建步驟亿扁,選擇執(zhí)行shell捺典,輸入打包腳本


圖片

腳本說明

-exportArchive有一個(gè)文件adhoc_ExportOptions.plist。
圖片

不用自己創(chuàng)建从祝,可以使用xcode導(dǎo)出ipa后襟己,從導(dǎo)出的文件夾里獲取。名字為ExportOptions.plist牍陌,修改一下名字就行了 method:有四種渠道擎浴。我將他們做了區(qū)分,分成四個(gè)不同的plist文件毒涧。

分別為 app-store ad-hoc enterprise development
打包導(dǎo)出ipa后需要執(zhí)行上傳內(nèi)測(cè)或應(yīng)用平臺(tái)贮预,我是上傳的蒲公英, 使用cURL直接上傳到蒲公英契讲,具體命令蒲公英官方有提供 蒲公英API仿吞,獲取uKey 和 _api_key也是在這個(gè)頁(yè)面
到這里就配置完了,點(diǎn)擊保存捡偏,可以開始構(gòu)建了唤冈。

附打包腳本

#!/bin/sh
export LANG=en_US.UTF-8

# 1.設(shè)置配置標(biāo)識(shí),編譯環(huán)境(根據(jù)需要自行填寫 release |debug )
configuration="release"

# 工程名(根據(jù)項(xiàng)目自行填寫)
APP_NAME="TestDome"

# TARGET名稱(根據(jù)項(xiàng)目自行填寫)
TARGET_NAME="TestDome"

# ipa前綴(根據(jù)項(xiàng)目自行填寫)
IPA_NAME="測(cè)試"

# info.plist路徑
#project_infoplist_path="./${TARGET_NAME}/Info.plist"
# 取版本號(hào)
#bundleShortVersion=$(/usr/libexec/PlistBuddy -c "print CFBundleShortVersionString" "${project_infoplist_path}")

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

# 日期
DATE=$(date +%Y%m%d-%H-%M-%S)
# 工程文件路徑
ARCHIVE_NAME="${APP_NAME}_${DATE}.xcarchive"
# 存放ipa的文件夾名稱(根據(jù)自己的喜好自行修改)
IPANAME="${APP_NAME}_${DATE}_IPA"

# 工程根目錄#工程源碼目錄(這里的${WORKSPACE}是jenkins的內(nèi)置變量表示(jenkins job的路徑):/Users/plz/.jenkins/workspace/TestDome/)
# ${WORKSPACE}/TestDome/ 中的TestDome根據(jù)你的項(xiàng)目自行修改
CODE_PATH="${WORKSPACE}"

# 要上傳的ipa文件路徑 ${username} 需要換成自己的用戶名
ROOT_PATH="/Users/${username}/Desktop/Jenkins"
ARCHIVE_PATH="${ROOT_PATH}/Archive/${ARCHIVE_NAME}"
IPA_PATH="${ROOT_PATH}/Export/${IPANAME}"
echo "ARCHIVE_PATH: ${ARCHIVE_PATH}"
echo "IPA_PATH: ${IPA_PATH}"
echo "IPA_PATH:\n${IPA_PATH}">> export_history.txt

# 導(dǎo)包方式(這里需要根據(jù)需要手動(dòng)配置:AdHoc/AppStore/Enterprise/Development)
EXPORT_METHOD="AdHoc"
# 導(dǎo)包方式配置文件路徑(這里需要手動(dòng)創(chuàng)建對(duì)應(yīng)的XXXExportOptionsPlist.plist文件,并將文件復(fù)制到根目錄下[我這里在源項(xiàng)目的根目錄下又新建了ExportPlist文件夾專門放ExportPlist文件])
if test "$EXPORT_METHOD" = "AdHoc"; then
    EXPORT_METHOD_PLIST_PATH=${CODE_PATH}/ExportOptions/AdHocExportOptions.plist
elif test "$EXPORT_METHOD" = "AppStore"; then
    EXPORT_METHOD_PLIST_PATH=${CODE_PATH}/ExportOptions/AppStoreExportOptios.plist
elif test "$EXPORT_METHOD" = "Enterprise"; then
    EXPORT_METHOD_PLIST_PATH=${CODE_PATH}/ExportOptions/EnterpriseExportOptions.plist
else
    EXPORT_METHOD_PLIST_PATH=${CODE_PATH}/ExportOptions/DevelopmentExportOptions.plist
fi

# 指ipa定輸出文件夾,如果有刪除后再創(chuàng)建银伟,如果沒有就直接創(chuàng)建
if test -d ${IPA_PATH}; then
    rm -rf ${IPA_PATH}
    mkdir -pv ${IPA_PATH}
     echo ${IPA_PATH}
else
     mkdir -pv ${IPA_PATH}
fi

# 進(jìn)入工程源碼根目錄
cd "${CODE_PATH}"

# 執(zhí)行pod
pod install --verbose --no-repo-update

#mkdir -p build

# 清除工程
echo "++++++++++++++++clean++++++++++++++++"
xcodebuild clean -workspace ${APP_NAME}.xcworkspace -scheme ${APP_NAME} -configuration ${configuration}

# 將app打包成xcarchive格式文件
echo "+++++++++++++++++archive+++++++++++++++++"
xcodebuild archive -workspace ${APP_NAME}.xcworkspace -scheme ${APP_NAME} -configuration ${configuration} -archivePath ${ARCHIVE_PATH}

# 將xcarchive格式文件打包成ipa
echo "+++++++++++++++++ipa+++++++++++++++++"
xcodebuild -exportArchive -archivePath ${ARCHIVE_PATH} -exportPath "${IPA_PATH}" -exportOptionsPlist ${EXPORT_METHOD_PLIST_PATH} -allowProvisioningUpdates

# 刪除工程文件
# echo "+++++++++刪除工程文件+++++++++"
# rm -rf $ARCHIVE_PATH


# 蒲公英上傳結(jié)果日志文件路徑
PGYERLOG_PATH="${IPA_PATH}/upload_pgyer_log"
# 創(chuàng)建蒲公英上傳結(jié)果日志文件夾
mkdir -p ${PGYERLOG_PATH}
# 創(chuàng)建蒲公英上傳結(jié)果日志文
touch "${PGYERLOG_PATH}/log.txt"

# 上傳IPA到蒲公英 根據(jù)蒲公英官方文檔編寫
file_path="${IPA_PATH}/${IPA_NAME}.ipa"
echo "正在上傳文件"
echo $file_path
curl -F "file=@${file_path}" -F "uKey=0ea4142136d51cbe5aaf94cdbf6aaeb1" -F "_api_key=16d3ff684c5576f9d9f6c958cf0a7300" https://upload.pgyer.com/apiv1/app/upload

構(gòu)建 (打包上傳)

立即構(gòu)建

點(diǎn)擊立即構(gòu)建開始構(gòu)建
圖片

點(diǎn)擊構(gòu)建版本可以查看狀態(tài)和控制臺(tái)輸出信息


image.png

Jenkins 打包 ipa 常見錯(cuò)誤匯總

問題1. pod時(shí)候會(huì)出現(xiàn) command not found

當(dāng)你jenkins服務(wù)在非OS X系統(tǒng)運(yùn)行時(shí)你虹,使用Mac節(jié)點(diǎn)的配置稍微不一樣。

解決方案

  • 系統(tǒng)管理-系統(tǒng)配置-全局屬性


    image.png

值:在終端中輸入echo $PATH將輸出內(nèi)容復(fù)制填寫彤避。

問題2:ipa包導(dǎo)出失敗傅物,導(dǎo)致報(bào)錯(cuò):curl: (26) Failed to open/read local data from file/application

  1. 先去文件路徑下查看打包是否成功,路徑下包含已經(jīng)IPA文件忠藤,確定路徑?jīng)]有問題挟伙;
  2. 查看腳本文件中的路徑,腳本中的ipa名稱與打包出來的IPA文件的名稱不一致模孩。

解決方案

將腳本中的ipa名稱改為應(yīng)用的顯示名稱

問題3. 打包時(shí)報(bào)錯(cuò):error: exportArchive: The data couldn’t be read because it isn’t in the correct format.

解決方案 1

xcode archive 導(dǎo)出 ipa 時(shí)不要勾選 Rebuild from Bitcode 尖阔,導(dǎo)出的 ExportOptions.plist 替換項(xiàng)目目錄下的 AdHocExportOptions.plist

圖片
解決方案 2

需要把xcode上的BitCode關(guān)閉,設(shè)置成No即可,project和targets里面對(duì)應(yīng)的BitCode都需要關(guān)閉

圖片

問題4. 打包時(shí)報(bào)錯(cuò):xcodebuild: error: 'APP.xcworkspace' does not exist

解決方案
Choose Product > Scheme > Manage Schemes.
Share your scheme:
圖片

也可能是Xcode Workspace File 路徑錯(cuò)誤

問題5. 編輯報(bào)錯(cuò) error: /Users/plz/.jenkins/workspace/target_name/Pods/Target Support Files/Pods-HIGO/Pods-HIGO.release.xcconfig: unable to open file (in target "target_name" in project "target_name") (in target 'target_name' from project 'target_name')

解決方案

shell腳本中添加如下命令
1. sudo gem install cocoapods --pre
2. pod install
如果不行 加上 3. pod update        

問題6. 編輯報(bào)錯(cuò) This project contains no schemes

解決方案
圖片

這里我們不能去Jenkins項(xiàng)目目錄下修改Xcode項(xiàng)目的shared勾選榨咐,我們應(yīng)該在本地的開發(fā)源碼上修改介却,然后提交到git遠(yuǎn)程倉(cāng)庫(kù),再次構(gòu)建?樽隆齿坷!

問題7. 編輯報(bào)錯(cuò) `xcodebuild -exportArchive -archivePath /xxx.xcarchive -exportOptionsPlist /Users/xxx/ExportOptions.plist -allowProvisioningUpdates -exportPath ./

error: archive not found at path '/xxx.xcarchive' Build step 'Execute shell' marked build as failure`

解決方案

用腳本構(gòu)建時(shí)桂肌,腳本輸寫錯(cuò)誤

問題8. 編輯報(bào)錯(cuò) error: archive not found at path '/Users/plz/Desktop/Jenkins/HIGO/Archive/HIGO_20210122-15-43-31.xcarchive'

查看日志發(fā)現(xiàn)在執(zhí)行 pod install 時(shí)中斷了,引入的三方庫(kù)沒有拉下來

圖片
解決方案

按照日志提示 shell 腳本 pod install 前執(zhí)行 pod update PLPlayerKit --no-repo-update

參考文章

Jenkins+github+fir持續(xù)集成iOS項(xiàng)目

iOS: Jenkins + xcodebuild打包ipa + 上傳蒲公英

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末永淌,一起剝皮案震驚了整個(gè)濱河市崎场,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌遂蛀,老刑警劉巖谭跨,帶你破解...
    沈念sama閱讀 216,470評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異李滴,居然都是意外死亡螃宙,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門所坯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來谆扎,“玉大人,你說我怎么就攤上這事芹助√煤” “怎么了?”我有些...
    開封第一講書人閱讀 162,577評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵周瞎,是天一觀的道長(zhǎng)苗缩。 經(jīng)常有香客問我,道長(zhǎng)声诸,這世上最難降的妖魔是什么酱讶? 我笑而不...
    開封第一講書人閱讀 58,176評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮彼乌,結(jié)果婚禮上泻肯,老公的妹妹穿的比我還像新娘。我一直安慰自己慰照,他們只是感情好灶挟,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著毒租,像睡著了一般稚铣。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上墅垮,一...
    開封第一講書人閱讀 51,155評(píng)論 1 299
  • 那天惕医,我揣著相機(jī)與錄音,去河邊找鬼算色。 笑死抬伺,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的灾梦。 我是一名探鬼主播峡钓,決...
    沈念sama閱讀 40,041評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼妓笙,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了能岩?” 一聲冷哼從身側(cè)響起寞宫,我...
    開封第一講書人閱讀 38,903評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎捧灰,沒想到半個(gè)月后淆九,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,319評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡毛俏,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了饲窿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片煌寇。...
    茶點(diǎn)故事閱讀 39,703評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖逾雄,靈堂內(nèi)的尸體忽然破棺而出阀溶,到底是詐尸還是另有隱情,我是刑警寧澤鸦泳,帶...
    沈念sama閱讀 35,417評(píng)論 5 343
  • 正文 年R本政府宣布银锻,位于F島的核電站,受9級(jí)特大地震影響做鹰,放射性物質(zhì)發(fā)生泄漏击纬。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評(píng)論 3 325
  • 文/蒙蒙 一钾麸、第九天 我趴在偏房一處隱蔽的房頂上張望更振。 院中可真熱鬧,春花似錦饭尝、人聲如沸肯腕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)实撒。三九已至,卻和暖如春涉瘾,著一層夾襖步出監(jiān)牢的瞬間知态,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工睡汹, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留肴甸,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,711評(píng)論 2 368
  • 正文 我出身青樓囚巴,卻偏偏與公主長(zhǎng)得像原在,于是被迫代替她去往敵國(guó)和親友扰。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評(píng)論 2 353

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