注:此文現(xiàn)在已經(jīng)落伍妄帘,iOS自動(dòng)化打包持續(xù)集成構(gòu)建推薦使用 Fastlane + Jenkins楞黄。
作為開(kāi)發(fā)人員,免不了要為測(cè)試人員打包抡驼,讓其測(cè)試鬼廓。而打包這個(gè)行為是非常無(wú)聊的,特別是在每個(gè)新版本上線前一兩天致盟,總會(huì)出現(xiàn)一些莫名其妙的bug
桑阶,然后這兩天打包活動(dòng)也是特別頻繁。一天要重復(fù)好幾次同樣的動(dòng)作勾邦,作為一個(gè)程序員蚣录,去做這樣的事情,是完全無(wú)法容忍的眷篇。自動(dòng)化打包
萎河,好在有你。所以今天就來(lái)談一談iOS應(yīng)用自動(dòng)化打包
蕉饼,但是本篇文章主要談的是打單一的測(cè)試包虐杯,并不是在講持續(xù)集成
。
xcodebuild & xcrun
Xcode
提供了一套構(gòu)建打包的命令昧港,就是xcodebuild
和xcrun
擎椰。xcodebuild
將對(duì)應(yīng)的項(xiàng)目打包成.app
文件,xcrun
將對(duì)應(yīng)的.app
文件轉(zhuǎn)換為對(duì)應(yīng)的.ipa
文件创肥。了解這兩套命令可以查看對(duì)應(yīng)的 xcodebuild官方文檔达舒、xcrun官方文檔 ,或者在終端輸入man xcodebuild
及man xcrun
命令,查看對(duì)應(yīng)的man page
叹侄。下面挑出來(lái)這兩個(gè)命令的一部分為例大致介紹一下他們的使用方法巩搏。
xcodebuild
xcodebuild的所有命令
NAME
xcodebuild -- build Xcode projects and workspaces
SYNOPSIS
xcodebuild [-project name.xcodeproj] [[-target targetname] ... | -alltargets]
[-configuration configurationname] [-sdk [sdkfullpath | sdkname]]
[action ...] [buildsetting=value ...] [-userdefault=value ...]
xcodebuild [-project name.xcodeproj] -scheme schemename
[[-destination destinationspecifier] ...] [-destination-timeout value]
[-configuration configurationname] [-sdk [sdkfullpath | sdkname]]
[action ...] [buildsetting=value ...] [-userdefault=value ...]
xcodebuild -workspace name.xcworkspace -scheme schemename
[[-destination destinationspecifier] ...] [-destination-timeout value]
[-configuration configurationname] [-sdk [sdkfullpath | sdkname]]
[action ...] [buildsetting=value ...] [-userdefault=value ...]
xcodebuild -version [-sdk [sdkfullpath | sdkname]] [infoitem]
xcodebuild -showsdks
xcodebuild -showBuildSettings
[-project name.xcodeproj | [-workspace name.xcworkspace -scheme schemename]]
xcodebuild -list [-project name.xcodeproj | -workspace name.xcworkspace]
xcodebuild -exportArchive -archivePath xcarchivepath -exportPath destinationpath
-exportOptionsPlist path
xcodebuild -exportLocalizations -project name.xcodeproj -localizationPath path
[[-exportLanguage language] ...]
xcodebuild -importLocalizations -project name.xcodeproj -localizationPath path
以上命令中最常用的應(yīng)該就是SYNOPSIS
中的前三行,其中分別對(duì)應(yīng).project
和.xcworkspace
類型的工程趾代。除了這三個(gè)贯底,我先講一下第七行的xcodebuild -list
這個(gè)命令。
xcodebuild -list命令介紹
以我們自己的工程為例在終端切入到工程文件夾撒强,然后使用xcodebuild -list
這個(gè)命令輸出信息為:
Information about project "yeemiao":
Targets:
yeemiao
yeemiao-inhouse
yeemiaoTests
yeemiaoInhouseTests
Build Configurations:
Debug
Release
If no build configuration is specified and -scheme is not passed then "Release" is used.
Schemes:
yeemiao
yeemiao-inhouse
-
Targets:
我們的工程有四個(gè)Targets
禽捆,yeemiao
是發(fā)布App Store
的,yeemiao-inhouse
是對(duì)應(yīng)的測(cè)試版本飘哨,下面兩個(gè)則是對(duì)應(yīng)的性能測(cè)試胚想。 -
Build Configurations:
由于我們?cè)赥argets中區(qū)分了測(cè)試版和正式版,這里面就沒(méi)有在添加一個(gè)Build Configurations
杖玲,而是系統(tǒng)默認(rèn)的兩個(gè)Debug
和Release
版本顿仇。 -
Schemes:
上面顯示的兩個(gè)Schemes
默認(rèn)是.xcodeproj
的,如果你使用xcodebuild -list -workspace yeemiao.xcworkspace
去查看就能看到第三方庫(kù)對(duì)應(yīng)的Schemes
.
xcodebuild前三行命令介紹
了解了以上三個(gè)知識(shí)摆马,在來(lái)看SYNOPSIS
中的前三行命令就很容易理解了
-
-project -workspace
:這兩個(gè)對(duì)應(yīng)的就是項(xiàng)目的名字也就是說(shuō)哪一個(gè)工程要打包臼闻。如果有多個(gè)工程,這里又沒(méi)有指定囤采,則默認(rèn)為第一個(gè)工程述呐。 -
-target
:打包對(duì)應(yīng)的targets,如果沒(méi)有指定這默認(rèn)第一個(gè)蕉毯。 -
-configuration
:如果沒(méi)有修改這個(gè)配置乓搬,默認(rèn)就是Debug和Release這兩個(gè)版本,沒(méi)有指定默認(rèn)為Release版本代虾。 -
buildsetting=value ...
:使用此命令去修改工程的配置进肯。但是在實(shí)際應(yīng)用中,我選擇了讀取文件去修改一個(gè)配置棉磨,而沒(méi)有應(yīng)用此種方法江掩。 -
-scheme
:指定打包的scheme。
一個(gè)Demo的簡(jiǎn)單使用
在進(jìn)入實(shí)際的使用之前乘瓤,先用一個(gè)簡(jiǎn)單的Demo
演示一下环形。
首先創(chuàng)建一個(gè)工程命名為Toyun
,然后確保此工程可以真機(jī)調(diào)試衙傀。打開(kāi)終端進(jìn)入Toyun
這個(gè)工程下抬吟,然后運(yùn)行以下命令:
xcodebuild -project Toyun.xcodeproj -target Toyun -configuration Release
此行命令的意思是將Toyun
這個(gè)工程targets
對(duì)應(yīng)的也是Toyun
,打包成Release
版本统抬。當(dāng)終端出現(xiàn)** BUILD SUCCEEDED **
字樣時(shí)火本,表示成功。這時(shí)候在去Toyun
這個(gè)工程的文件夾下聪建,你會(huì)發(fā)現(xiàn)多了一個(gè)名為build
的文件夾发侵,此下面兩個(gè)子文件夾,Release-iphoneos
和Toyun.build
妆偏。Release-iphoneos
文件夾下有Toyun.app
這個(gè)文件刃鳄。這就是xcodebuild
命令的作用,最終生成.app
文件钱骂。但是我們需要的是.ipa
文件叔锐,這時(shí)在終端下面執(zhí)行此行命令
xcrun -sdk iphoneos -v PackageApplication ./build/Release-iphoneos/Toyun.app -o ~/Desktop/Toyun.ipa
此行命令的意思為,將Release-iphoneos
文件夾下的Toyun.app
文件轉(zhuǎn)換為Toyun.ipa
文件并且放在桌面上见秽。iphoneos
是使用的sdk
愉烙,PackageApplication
為使用的開(kāi)發(fā)者工具。此時(shí)你回到桌面可以看到Toyun.ipa
文件解取,則為成功步责。
實(shí)際使用自動(dòng)化打包
通過(guò)上面簡(jiǎn)單Demo
的練習(xí),我們已經(jīng)可以使用短短的兩行命令來(lái)打出我們需要的.ipa文件
了。但是這據(jù)我們實(shí)際使用還有一段距離蔓肯,在實(shí)際應(yīng)用中情況復(fù)雜多變遂鹊。這里以我們自己的打測(cè)試包的過(guò)程為例來(lái)說(shuō)明實(shí)際中的一些情況。我寫(xiě)此自動(dòng)化打包程序選的是Shell腳本
蔗包,當(dāng)然你也可以選擇其他的語(yǔ)言去寫(xiě)秉扑。
打包流程
首先說(shuō)一下我們打包的流程。先從svn
上拉取最新的代碼调限,然后修改對(duì)應(yīng)的測(cè)試版本號(hào)舟陆,選擇對(duì)應(yīng)的證書(shū)和描述文件然后開(kāi)始archive打包
,打包完成后耻矮,需要export
出對(duì)應(yīng)的ipa文件
秦躯,而且我們下載安裝包使用了itms-services協(xié)議
,這個(gè)時(shí)候就要去修改導(dǎo)出來(lái)的測(cè)試包包名和協(xié)議相關(guān)的.plist文件
裆装。然后上傳到服務(wù)器踱承,這時(shí)測(cè)試根據(jù)協(xié)議生成的鏈接去下載對(duì)應(yīng)的測(cè)試包開(kāi)始測(cè)試。這個(gè)整套流程走下來(lái)米母,大概需要10分鐘勾扭。
將打包流程準(zhǔn)換為腳本語(yǔ)言
#! /bin/bash
# 傳入這次的版本號(hào)
version_string=$1
# build號(hào) 我們是使用前時(shí)間作為build號(hào)的 2016041517 即為16年4月15號(hào)17點(diǎn)
build_number=$(date +%Y%m%d%H)
# 清空上一次的文件夾
rm -rf ~/Desktop/project
# 創(chuàng)建要工作的文件夾
mkdir ~/Desktop/project
# 進(jìn)入要工作的文件夾
cd ~/Desktop/project
# 去svn上拉取最新的代碼 如果你們使用的git或其他版本控制則修改對(duì)應(yīng)的拉取代碼命令即可
svn export svn://
# 下面是一些用到的變量給抽取出來(lái)了
# 工程環(huán)境路徑
workspace_path=~/Desktop/project/yeemiao2016/yeemiao
# 打包項(xiàng)目名字
scheme_name=yeemiao-inhouse
# 打包使用的證書(shū)
CODE_SIGN_IDENTITY="替換為你們的證書(shū)名字"
# 打包使用的描述文件 這描述文件的名字不是自己命名的那個(gè)名字,而是對(duì)應(yīng)的8b11ac11-xxxx-xxxx-xxxx-b022665db452這個(gè)名字
PROVISIONING_PROFILE="替換為你們的描述文件的名字"
# 指定yeemiao.app的輸出位置 也就是Demo中build文件夾的位置
build_path=~/Desktop/project/build
# 指定yeemiao.ipa的輸出位置
ipa_path=~/Desktop/project
# info.plist文件的位置
info_plist=~/Desktop/project/yeemiao2016/yeemiao/yeemiaoInhouse-Info.plist
# 下面是讀取.plist文件的位置然后修改版本號(hào)和build號(hào)铁瞒,這點(diǎn)沒(méi)有使用xcodebuild提供的命令妙色,在上面也有敘述
# 修改版本號(hào)
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $version_string" ${info_plist}
# 修改build號(hào)
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $build_number" ${info_plist}
# 生成yeemiao.app, 在build_path路徑下面
xcodebuild -workspace ${workspace_path}.xcworkspace -scheme ${scheme_name} -configuration Release clean -sdk iphoneos build CODE_SIGN_IDENTITY="${CODE_SIGN_IDENTITY}" PROVISIONING_PROFILE="${PROVISIONING_PROFILE}" SYMROOT="${build_path}"
# 生成yeemiao.ipa, 在ipa_path路徑下面
xcrun -sdk iphoneos -v PackageApplication ${build_path}/Release-iphoneos/yeemiao.app -o ${ipa_path}/yeemiao_ios_${version_string}.ipa
# itms-services協(xié)議需要使用的.plist文件的位置
plist_path=~/Desktop/project/yeemiao_ios_${version_string}.plist
# 生成plist文件 在替換對(duì)應(yīng)的路徑中替換為你們的路徑
cat << EOF > $plist_path
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>items</key>
<array>
<dict>
<key>assets</key>
<array>
<dict>
<key>kind</key>
<string>software-package</string>
<key>url</key>
<string>替換對(duì)應(yīng)的路徑</string>
</dict>
</array>
<key>metadata</key>
<dict>
<key>bundle-identifier</key>
<string>com.threegene.yeemiao.inhouse</string>
<key>bundle-version</key>
<string>1.0.0</string>
<key>kind</key>
<string>software</string>
<key>title</key>
<string>小豆苗</string>
</dict>
</dict>
</array>
</dict>
</plist>
EOF
# .ipa文件的位置
ipa_file_path=~/Desktop/project/yeemiao_ios_${version_string}.ipa
# .plist文件的位置
plist_file_path=~/Desktop/project/yeemiao_ios_${version_string}.plist
# 這里就要把.ipa和.plist文件上傳到對(duì)應(yīng)的服務(wù)器上,當(dāng)然這一步也是可以使用命令來(lái)完成的慧耍。
# 這里要看你們要把測(cè)試包上傳到哪兒身辨,F(xiàn)ir、蒲公英芍碧、七牛等一般都提供了命令上傳文件的方式煌珊。
# 如果需要修改數(shù)據(jù)庫(kù)中測(cè)試包的指向,也可以開(kāi)一個(gè)網(wǎng)絡(luò)請(qǐng)求接口然后使用curl命令共同集成到測(cè)試包中泌豆。
# 同樣可以增加一些判斷(判斷需要上次的文件存在不存在)和一些Log輸出來(lái)讓此腳本更為清晰安全和準(zhǔn)確定庵。
腳本最終完善之后,就可以敲一下enter鍵
踪危,整個(gè)打包過(guò)程就完成了蔬浙。比我我給這段程序命名為autoArchive.sh
。然后我在打包的時(shí)候只需要在終端輸入命令:
~ ./autoArchive.sh 3.0.0000
其他
在寫(xiě)此腳本的時(shí)候也遇到了一些問(wèn)題贞远,其中一個(gè)就是當(dāng)時(shí)我們的xcshareddata數(shù)據(jù)
是沒(méi)有提交到svn
上的畴博,然后在指向打包命令那一行,腳本就會(huì)卡死不動(dòng)蓝仲。后來(lái)提交了xcshareddata
俱病,此問(wèn)題也就好了官疲。
網(wǎng)絡(luò)上也有對(duì)自動(dòng)化打包進(jìn)行的各種封裝,其中比較出名的就是facebook出的xctool亮隙。這個(gè)工具規(guī)范了輸出的log日志
途凫,而且一些錯(cuò)誤信息也更為清晰一些。還是可以安裝體驗(yàn)一下的咱揍。