開篇
天生的程序猿都愛偷懶听隐,總想著機(jī)器能干的事情就不想手動。
有一定經(jīng)驗的iOS開發(fā)從業(yè)人員都知道漫長的揪荣、沒有技術(shù)含量的贮匕、反反復(fù)復(fù)的打包過程操作是多么無聊多么無聊多么無聊地寂寞啊勺良。
所以有了這么一個一鍵打包自動發(fā)布的想法,經(jīng)過一番探索與實踐骄噪,總尋得一條成神之路修煉尚困。
Bash與Shell簡介
Bash 是 Unix 系統(tǒng)和 Linux 系統(tǒng)的一種 Shell(命令行環(huán)境),是目前絕大多數(shù) Linux 發(fā)行版的默認(rèn) Shell。
首先坠狡,Shell 是一個程序募寨,提供一個與用戶對話的環(huán)境蒿柳。這個環(huán)境只有一個命令提示符崖蜜,讓用戶從鍵盤輸入命令乒疏,所以又稱為命令行環(huán)境(command line interface盖高,簡寫為 CLI)听想。Shell 接收到用戶輸入的命令邦马,將命令送入操作系統(tǒng)執(zhí)行贱鼻,并將結(jié)果返回給用戶。
其次滋将,Shell 是一個命令解釋器邻悬,解釋用戶輸入的命令。它支持變量随闽、條件判斷父丰、循環(huán)操作等語法,所以用戶可以用 Shell 命令寫出各種小程序掘宪,又稱為腳本(script)蛾扇。這些腳本都通過 Shell 的解釋執(zhí)行,而不通過編譯魏滚。
最后镀首,Shell 是一個工具箱,提供了各種小工具栏赴,供用戶方便地使用操作系統(tǒng)的功能蘑斧。
在iOS開發(fā)中,我們通常編寫一些自動化的腳本文件须眷,來提高我們的生產(chǎn)效率竖瘾,其本質(zhì)就是通過Shell腳本對一些xcodebuild,xcode-select,xcrun等指令的封裝,還可以通過Shell進(jìn)行第三方庫的導(dǎo)入如Pod管理工具花颗,自動上傳dSym文件到分析平臺以及生成模板代碼文件捕传。可以這么說:掌握Shell腳本編程作為iOS工程師封神必備技能扩劝。
Bash簡單學(xué)習(xí)
此腳本涉及的知識點并不多庸论,簡單學(xué)習(xí)bash基本命令語法即可掌握此腳本
echo命令
read命令
條件判斷
變量
字符串操作
cd? rm? mv? open? mkdir 等文件夾相關(guān)操作命令
想學(xué)習(xí)更多的命令請前往Bash學(xué)習(xí)資料
準(zhǔn)備工作
必須是MacOS系統(tǒng)【非蘋果電腦飄過太平洋再回來吧】
項目工程在Xcode11以上版本能夠正常編譯無報錯
開發(fā)者相關(guān)證書已存在電腦keychain中
證書配置選擇自動管理
項目工程配置確保準(zhǔn)確無誤,手動能正常打包棒呛,發(fā)布驗證正常下載安裝后聂示。此時說明你的項目工程各方面配置OK,可以使用腳本打包了簇秒,否則腳本同樣會顯示報錯信息鱼喉。
腳本重點知識
命令說明以及坑點說明,特別是上傳App Store的時候,老報錯
xcodebuild扛禽、xcrun altool
Xcode打包和上傳App Store用到命令锋边。
xcodebuild命令比較復(fù)雜,安裝Xcode就有编曼,清理clear工程和構(gòu)
建archive文件豆巨,exportArchive導(dǎo)出ipa文件都用到此命令。
清理工程命令xcodebuild clean -workspace ${workspace_name}.xcworkspace \? ? ? ? ? ? ? ? -scheme ${scheme_name} \? ? ? ? ? ? ? ? -configuration ${build_configuration}
構(gòu)建工程命令xcodebuild archive -workspace ${workspace_name}.xcworkspace \? ? ? ? ? ? ? ? ? -scheme ${scheme_name} \? ? ? ? ? ? ? ? ? -configuration ${build_configuration} \? ? ? ? ? ? ? ? ? -archivePath ${export_archive_path}
導(dǎo)出IPA命令xcodebuild? -exportArchive \? ? ? ? ? ? -archivePath ${export_archive_path} \? ? ? ? ? ? -exportPath ${export_ipa_path} \? ? ? ? ? ? -exportOptionsPlist ${export_options_plist_path} \? ? ? ? ? ? -allowProvisioningUpdates
Xcode11之后驗證應(yīng)用APP和上傳都是使用xcrun altool命令
驗證ipaxcrun altool --validate-app -f $export_ipa_path/$ipa_name.ipa -t ios --apiKey xxx --apiIssuer xxx? --verbose
上傳ipa文件? xcrun altool --upload-app -f $export_ipa_path/$ipa_name.ipa -t ios --apiKey xxx --apiIssuer xxx --verbose
坑位地方特別注意
使用xcrun altool命令之前掐场,先做好以下這兩步必要工作往扔,否則老報錯
開發(fā)者賬號【持有人】登錄appstoreconnect管理后臺,申請秘鑰刻肄。如圖1所示
圖1開發(fā)者秘鑰信息
命令中的xxx 就是指上圖紅色??的兩個ID
將申請得到的秘鑰下載下來【不要修改文件名--不要修改文件名--不要修改文件名】瓤球,放到/Users/xxx/private_keys文件夾中【xxx是你當(dāng)前電腦用戶;? 如果沒有private_keys此文件夾敏弃,就創(chuàng)建命名private_keys的文件夾卦羡。】麦到。如圖2所示
圖2文件目錄
命令后面的參數(shù)請看詳細(xì)的文檔說明
fir-cli? 上傳fir用到
沒有安裝此命令的請先安裝绿饵,安裝方法很簡單,在終端執(zhí)行命令
sudo gem install fir-cli即可
安裝好之后瓶颠,發(fā)布IPA文件到fir就兩行命令拟赊,是不是很簡單
fir login -T xxxxx? ? ? # xxxxx 是你 fir.im token? fir publish ffffff? ? ? # ffffffffff 是你上傳的ipa包路徑
蒲公英平臺上傳
發(fā)布到蒲公英平臺就簡單多了,據(jù)官方文檔提供的一行命令即可粹淋。 請根據(jù)開發(fā)者自己的賬號吸祟,將其中的 uKey 和 _api_key 的值替換為相應(yīng)的值。
curl-F"file=@xxxxxxx.ipa"-F"uKey=xxx"-F"_api_key=xxx"https://www.pgyer.com/apiv2/app/upload
完整腳本
附上完整的腳本代碼桃移,請詳細(xì)看注釋的內(nèi)容
YHAutoPackageScript.sh如下
#!/bin/sh# 使用方法:# step1: 將該腳本放在工程的根目錄下(跟.xcworkspace文件or .xcodeproj文件同目錄)# step2: 根據(jù)情況修改下面的參數(shù)# step3: 打開終端屋匕,執(zhí)行腳本。(輸入sh借杰,然后將腳本文件拉到終端过吻,會生成文件路徑,然后enter就可)# =============項目自定義部分(自定義好下列參數(shù)后再執(zhí)行該腳本)=================== ## 是否編譯工作空間 (例:若是用Cocopods管理的.xcworkspace項目,賦值true;用Xcode默認(rèn)創(chuàng)建的.xcodeproj,賦值false)is_workspace="true"# .xcworkspace的名字蔗衡,如果is_workspace為true纤虽,則必須填。否則可不填workspace_name="XXX"? ? #XXX 就是你.xcworkspace工程的名稱# .xcodeproj的名字绞惦,如果is_workspace為false逼纸,則必須填。否則可不填project_name="XXX"? ? ? ? ? #XXX 就是你.xcodeproj工程的名稱# 指定項目的scheme名稱(也就是工程的target名稱)济蝉,必填#scheme_name="xxx"? ? ? #xxx 就是你工程里面某個target的scheme名稱 echo "-------------------------輸入target的scheme名稱-----------------------------"echo "\033[36;1m請輸入您的項目target的scheme名稱(大小寫區(qū)分杰刽,務(wù)必和工程中的配置一致,按回車即可) \033[0m"# 讀取用戶輸入并存到變量里read targetNamesleep 0.5scheme_name="$targetName"echo "\033[33;1m您的項目target的scheme名稱為=${scheme_name} "# 指定要打包編譯的方式 : Release,Debug呻纹。一般用Release。必填build_configuration="Release"# method专缠,打包的方式。方式分別為 development, ad-hoc, app-store, enterprise 淑仆。必填#method="ad-hoc"echo "-------------------------選擇打包方式-----------------------------"echo "\033[36;1m請選擇打包方式(輸入序號,按回車即可) \033[0m"echo "\033[33;1m1. AdHoc? ? ? \033[0m"echo "\033[33;1m2. AppStore? ? \033[0m"echo "\033[33;1m3. Enterprise? \033[0m"echo "\033[33;1m4. Development \033[0m"# 讀取用戶輸入并存到變量里read parametersleep 0.5packMethod="$parameter"# 判讀用戶是否有輸入if [ -n "$packMethod" ]then? ? if [ "$packMethod" = "1" ] ; then? ? ? ? method="ad-hoc"? ? elif [ "$packMethod" = "2" ] ; then? ? ? ? method="app-store"? ? elif [ "$packMethod" = "3" ] ; then? ? ? ? method="enterprise"? ? elif [ "$packMethod" = "4" ] ; then? ? ? ? method="development"? ? else? ? ? ? echo "輸入的參數(shù)無效!!!"? ? ? ? exit 1? ? fifiecho "\033[33;1m打包方式method=${method} "#? 下面兩個參數(shù)只是在手動指定Pofile文件的時候用到涝婉,如果使用Xcode自動管理Profile,直接留空就好# (跟method對應(yīng)的)mobileprovision文件名,需要先雙擊安裝.mobileprovision文件.手動管理Profile時必填mobileprovision_name=""# 項目的bundleID蔗怠,手動管理Profile時必填bundle_identifier=""echo "--------------------腳本配置參數(shù)檢查--------------------"echo "\033[33;1mis_workspace=${is_workspace} "echo "workspace_name=${workspace_name}"echo "project_name=${project_name}"echo "scheme_name=${scheme_name}"echo "build_configuration=${build_configuration}"echo "bundle_identifier=${bundle_identifier}"echo "method=${method}"echo "mobileprovision_name=${mobileprovision_name} \033[0m"echo "-------------------------選擇發(fā)布平臺-----------------------------"echo "\033[36;1m請選擇發(fā)布平臺(輸入序號,按回車即可) \033[0m"echo "\033[33;1m1. AppStore? ? ? \033[0m"echo "\033[33;1m2. 蒲公英pgyer? ? \033[0m"echo "\033[33;1m3. fir平臺? \033[0m"echo "\033[33;1m4. 不發(fā)布 \033[0m"# 讀取用戶輸入并存到變量里read uploadTypeParametersleep 0.5uploadType="$uploadTypeParameter"# 是否上傳分發(fā)平臺(fir)is_uploadfir="true"# firTokenfir_token="xxxxxx"? ? # xxxxxx? 就是你fir平臺上tokenupload_token=$fir_token# 蒲公英上傳# 執(zhí)行 curl -F "file=@xxxxxxx.ipa" -F "uKey=xxx" -F "_api_key=xxx" https://www.pgyer.com/apiv2/app/upload? ? ? 請根據(jù)開發(fā)者自己的賬號墩弯,將其中的 uKey 和 _api_key 的值替換為相應(yīng)的值。# =======================腳本的一些固定參數(shù)定義(無特殊情況不用修改)====================== ## 獲取當(dāng)前腳本所在目錄script_dir="$( cd "$( dirname "$0"? )" && pwd? )"# 工程根目錄project_dir=$script_dir# 時間DATE=`date '+%Y%m%d_%H%M%S'`# 指定輸出導(dǎo)出文件夾路徑export_path="$project_dir/Package/$scheme_name-$DATE"# 指定輸出歸檔文件路徑export_archive_path="$export_path/$scheme_name.xcarchive"# 指定輸出ipa文件夾路徑export_ipa_path="$export_path"# 指定輸出ipa名稱ipa_name="${scheme_name}_${DATE}"# 指定導(dǎo)出ipa包需要用到的plist配置文件的路徑export_options_plist_path="$project_dir/ExportOptions.plist"echo "--------------------腳本固定參數(shù)檢查--------------------"echo "\033[33;1mproject_dir=${project_dir}"echo "DATE=${DATE}"echo "export_path=${export_path}"echo "export_archive_path=${export_archive_path}"echo "export_ipa_path=${export_ipa_path}"echo "export_options_plist_path=${export_options_plist_path}"echo "ipa_name=${ipa_name} \033[0m"# =======================自動打包部分(無特殊情況不用修改)====================== #echo "------------------------------------------------------"echo "\033[32m開始構(gòu)建項目? \033[0m"# 進(jìn)入項目工程目錄cd ${project_dir}# 指定輸出文件目錄不存在則創(chuàng)建if [ -d "$export_path" ] ; then? ? echo $export_pathelse? ? mkdir -pv $export_pathfi# 判斷編譯的項目類型是workspace還是projectif $is_workspace ; then# 編譯前清理工程xcodebuild clean -workspace ${workspace_name}.xcworkspace \? ? ? ? ? ? ? ? -scheme ${scheme_name} \? ? ? ? ? ? ? ? -configuration ${build_configuration}xcodebuild archive -workspace ${workspace_name}.xcworkspace \? ? ? ? ? ? ? ? ? -scheme ${scheme_name} \? ? ? ? ? ? ? ? ? -configuration ${build_configuration} \? ? ? ? ? ? ? ? ? -archivePath ${export_archive_path}else# 編譯前清理工程xcodebuild clean -project ${project_name}.xcodeproj \? ? ? ? ? ? ? ? -scheme ${scheme_name} \? ? ? ? ? ? ? ? -configuration ${build_configuration}xcodebuild archive -project ${project_name}.xcodeproj \? ? ? ? ? ? ? ? ? -scheme ${scheme_name} \? ? ? ? ? ? ? ? ? -configuration ${build_configuration} \? ? ? ? ? ? ? ? ? -archivePath ${export_archive_path}fi#? 檢查是否構(gòu)建成功#? xcarchive 實際是一個文件夾不是一個文件所以使用 -d 判斷if [ -d "$export_archive_path" ] ; then? ? echo "\033[32;1m項目構(gòu)建成功 ?? ?? ??? \033[0m"else? ? echo "\033[31;1m項目構(gòu)建失敗 ?? ?? ??? \033[0m"? ? exit 1fiecho "------------------------------------------------------"echo "\033[32m開始導(dǎo)出ipa文件 \033[0m"# 先刪除export_options_plist文件if [ -f "$export_options_plist_path" ] ; then? ? #echo "${export_options_plist_path}文件存在寞射,進(jìn)行刪除"? ? rm -f $export_options_plist_pathfi# 根據(jù)參數(shù)生成export_options_plist文件/usr/libexec/PlistBuddy -c? "Add :method String ${method}"? $export_options_plist_path#/usr/libexec/PlistBuddy -c? "Add :provisioningProfiles:"? $export_options_plist_path#/usr/libexec/PlistBuddy -c? "Add :provisioningProfiles:${bundle_identifier} String ${mobileprovision_name}"? $export_options_plist_path/usr/libexec/PlistBuddy -c? "Add :signingStyle String automatic"? $export_options_plist_path/usr/libexec/PlistBuddy -c? "Add :destination String export"? $export_options_plist_path/usr/libexec/PlistBuddy -c? "Add :compileBitcode bool false"? $export_options_plist_path? ? #如果您的工程是開啟Bitcode的話渔工,請把false改為trueecho "\033[31;1mexport_options_plist文件: ${export_options_plist_path}? ? ? \033[0m"xcodebuild? -exportArchive \? ? ? ? ? ? -archivePath ${export_archive_path} \? ? ? ? ? ? -exportPath ${export_ipa_path} \? ? ? ? ? ? -exportOptionsPlist ${export_options_plist_path} \? ? ? ? ? ? -allowProvisioningUpdates# 檢查ipa文件是否存在if [ -f "$export_ipa_path/$scheme_name.ipa" ] ; then? ? echo "\033[32;1mexportArchive ipa包成功,準(zhǔn)備進(jìn)行重命名\033[0m"else? ? echo "\033[31;1mexportArchive ipa包失敗 ?? ?? ??? ? \033[0m"? ? exit 1fi# 修改ipa文件名稱mv $export_ipa_path/$scheme_name.ipa $export_ipa_path/$ipa_name.ipa# 檢查文件是否存在if [ -f "$export_ipa_path/$ipa_name.ipa" ] ; then? ? echo "\033[32;1m導(dǎo)出 ${ipa_name}.ipa 包成功 ??? ??? ??? \033[0m"? ? open $export_pathelse? ? echo "\033[31;1m導(dǎo)出 ${ipa_name}.ipa 包失敗 ?? ?? ??? ? \033[0m"? ? exit 1fi# 刪除export_options_plist文件(中間文件)if [ -f "$export_options_plist_path" ] ; then? ? #echo "${export_options_plist_path}文件存在,準(zhǔn)備刪除"? ? rm -f $export_options_plist_pathfi# 輸出打包總用時echo "\033[36;1m使用AutoPackageScript打包總用時: ${SECONDS}s \033[0m"if [ "$uploadType" = "1" ] ; then? echo "App Store發(fā)布!!!"? xcrun altool --validate-app -f $export_ipa_path/$ipa_name.ipa -t ios --apiKey xxx --apiIssuer xxx? --verbose? ? ? ? xcrun altool --upload-app -f $export_ipa_path/$ipa_name.ipa -t ios --apiKey xxx --apiIssuer xxx --verbose? # xxx 就是你App Store管理后臺的秘鑰和apiKey信息elif [ "$uploadType" = "2" ] ; then? ? curl -F "file=@$export_ipa_path/$ipa_name.ipa" -F "uKey=xxx" -F "_api_key=xxx" https://www.pgyer.com/apiv2/app/uploadelif [ "$uploadType" = "3" ] ; then? fir login -T $upload_token? ? ? # fir.im token? fir publish $export_ipa_path/$ipa_name.ipaelse? ? echo "不發(fā)布!!!"? ? exit 0fiexit 0
使用方法
把腳本代碼復(fù)制保存為XXXX.sh文件桥温,并修改里面的XXX對應(yīng)你項目工程或者是換成你自己的信息
把XXXX.sh文件放在和你項目xxx.xcodeproj文件同一個文件夾下面
打開終端進(jìn)入你當(dāng)前工程xxx.xcodeproj所在文件夾
執(zhí)行命令sh ./XXXX.sh
根據(jù)提示輸入target的scheme名稱引矩、打包方式、發(fā)布平臺
作者:Lewis海
鏈接:http://www.reibang.com/p/4436fc383c0b
來源:簡書
著作權(quán)歸作者所有侵浸。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán)旺韭,非商業(yè)轉(zhuǎn)載請注明出處。