1. 程式人生 > >objc系列譯文(6.5):為iOS專案搭建Travis CI伺服器

objc系列譯文(6.5):為iOS專案搭建Travis CI伺服器

你是否曾經試著為你的iOS專案搭建一臺支援持續整合的伺服器,從我的個人經驗而言,這可不是一個輕鬆的活。你需要準備一部Mac,安裝好全部所需的軟體和外掛。你要負責管理所有的使用者賬戶並提供安全保護。

原本你想節省的時間,最終你會發現你花費了大量的時間去維護這臺伺服器。不過如果你的專案託管在GitHub上,現在有了新的希望:Travis CI。該服務可以為你的專案提供持續整合的支援,也就意味著它會負責好託管一個專案的所有細節。在Ruby的世界中,Travis CI已久負盛名。從2013年4月開始,Travis也開始支援iOS和Mac平臺。

在這篇文章中,我會向你展示如何一步步為你的專案整合Travis。不僅包括編譯專案和進行單元測試,還能夠將你的應用投送到你所有的測試裝置上。為了演示,我在GitHub上放了一個示例專案。在這篇文章的最後,我會教你如何用Travis去定位程式中的錯誤。

GitHub整合

我最喜歡Travis的一點就是他與GitHub的Web UI整合的非常好。譬如pull請求。Travis會為每次請求都執行編譯操作。如果一切正常,pull請求在GitHub上看起來就像這樣:

萬一編譯不成功,GitHub頁面會相應的改變顏色給予提醒:

連結Travis和GitHub

讓我們看一下如何連結你的GitHub專案到Travis。使用你的GitHub賬號登陸Travis。對於私有工作目錄,你需要註冊一個Travis專業版賬號。

登陸成功後,你就可以為你的專案開啟Travis支援。找到屬性頁面,在此列出了你的所有GitHub專案。不過要注意,如果你此後建立了一個新的工作目錄,要使用Sync now按鈕進行同步。Travis只會偶爾更新你的專案列表。

現在只需要開啟這個開關就可以為你的專案新增Travis服務。以後你會看到Travis會和你的GitHub專案設定相關聯。下一步應該告訴Travis當它收到專案改動之後該做什麼。

輕量級的專案配置

Travis CI需要你的專案的一些基本資訊。在你專案的根目錄建立一個名叫.travis.yml的檔案,內容如下:

1 language:objective-c

Travis編譯器執行在虛擬機器環境下.已經使用Ruby,Homebrew,CocoaPods和一些編譯指令碼進行過配置。上述的配置項已經足夠編譯你的專案了。

預裝的編譯指令碼會分析你的Xcode專案,編譯專案下的所有Target。如果所有檔案都沒有編譯錯誤測試也沒有跳出專案就編譯成功了。現在可以將你的改動Push到GitHub看看能成功編譯。

雖然這看起來好像很簡單,不過對你的專案不一定適用。幾乎沒有什麼文件來指導使用者如何配置預設的編譯行為。舉個栗子, 有一次我沒有用模擬器的SDK導致檢查應用簽名時發生了錯誤。如果剛剛那個最輕量級的配置對你的專案不適用的話,讓我們來看一下如何用定製的編譯命令來適用Travis。

定義編譯命令

Travis使用命令列來編譯你的專案。因此,第一步就是使專案能夠在本地編譯。作為Xcode命令列工具的一部分,Apple提供了xcodebuild命令。

開啟你的終端輸入:

Shell
1 xcodebuildhelp

這會列出xcodebuild可用的所有引數。如果命令執行不成功,確保你的命令列工具已經成功安裝。通常一個常見的編譯命令看起來像這樣:

Shell
1 xcodebuild-project{project}.xcodeproj-target{target}-sdk iphonesimulator ONLY_ACTIVE_ARCH=NO

使用iphonesimulator SDK是為了避免應用簽名錯誤。這是必須的一步直到我們稍後引入證書為止。通過設定ONLY_ACTIVE_ARCH=NO我們可以確保在模擬器的架構下編譯。你也可以設定額外的屬性。用man xcodebuild來閱讀文件。

對於使用CocoaPods的專案,你需要指定workspace和scheme。

Shell
1 xcodebuild-workspace{workspace}.xcworkspace-scheme{scheme}-sdk iphonesimulator ONLY_ACTIVE_ARCH=NO

Schemes是由Xcode自動生成的,但這在伺服器上不會發生。確保所有的scheme都被設為shared並加入到工作目錄中。否則它只會在本地工作而不會被Travis CI識別。

我們的示例專案下的.travis.yml檔案現在應該看起來像這樣:

Shell
123 language:objective-cscript:xcodebuild-workspace TravisExample.xcworkspace-scheme TravisExample-sdk iphonesimulator ONLY_ACTIVE_ARCH=NO

執行測試

通常對於測試來說你會使用如下的命令(注意test屬性)

xcodebuild test -workspace {workspace}.xcworkspace -scheme {test_scheme} -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO

不幸的是xcodebuild並不能支援多target以及iOS的應用測試。蘋果已經在著手解決這個問題,不過我建議使用Xctool來代替。

Xctool

Xctool是來自Facebook的命令列工具,他可以幫助你更加輕鬆快捷的編譯測試你的應用。他的彩色輸出資訊比xcodebuild更加簡潔直觀,結構清晰。同時還添加了對邏輯測試,應用測試的支援。

Travis中已經預裝了xctool。要在本地測試的話,需要用Homebrew先安裝xctool:

Shell
123 brew updatebrew install xctool

用法非常簡單,xctool 使用跟 xcodebuild相同的引數:

xctool test -workspace TravisExample.xcworkspace -scheme TravisExampleTests -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO

這要這些命令在本地能正常工作,我們就可以把他們新增到.travis.yml檔案裡:

language: objective-c

script:

  – xctool -workspace TravisExample.xcworkspace -scheme TravisExample -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO

  – xctool test -workspace TravisExample.xcworkspace -scheme TravisExampleTests -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO

目前我們所新增的配置已經足夠編譯一個框架類的應用。我們能夠保證專案可以正常編譯並通過測試。但對於真正的iOS應用來說,我們希望在真實的物理裝置上進行測試。很顯然,我們要藉助Travis來幫我們自動部署。整個過程的第一步,我們需要給我們的應用簽名。

應用簽名

為了在Travis中給我們的應用簽名,我們需要準備好所有必要的證書和配置檔案。就像每個iOS開發人員知道的那樣,這可能是最困難的一步。後面我們將寫一些指令碼來幫助我們在伺服器上給應用簽名。

證書和配置檔案

  1. 蘋果全球開發者關係認證

從蘋果的配置頁面中下載或者從你的Keychain中匯出,將它儲存到你的專案目錄下scripts/certs/apple.cer這個位置。

2.  iPhone釋出證書 + 私鑰

如果你還沒有一個iPhone釋出證書你需要建立一個。登陸你的蘋果開發者賬號,你可以跟隨下面的步驟建立一個生產環境的新證書(Certificates > Production > Add > App Store and Ad Hoc)。確保你已經下載並安裝了這個證書。以後你可以在你的Keychain中找到它,還有一個捆綁的私鑰。現在開啟你Mac上的Keychain應用:

右擊證書選擇匯出將其放在scripts/certs/dist.cer路徑,在匯出捆綁的私鑰,儲存到scripts/certs/dist.p12。可以根據你的需要設定一個密碼。

Travis需要知道你的私鑰密碼,我們需要將其儲存在某個地方。顯然我們不想用簡單的文字來儲存這個密碼。我們可以利用Travis的安全環境變數。開啟終端進入包含.travis.yml檔案的目錄。首先用gem install travis命令安裝Travis gem。安裝完成後你就可以用以下命令新增密碼:

travis encrypt “KEY_PASSWORD={password}” –add

這樣就可以安裝一個叫做KEY_PASSWORD的加密環境變數到你的.travis.yml配置檔案。在任何可以被Travis CI執行的指令碼中都可以使用這個變數。

3. iOS 移動裝置備案檔案(釋出用)

如果你還沒有一個釋出用的移動裝置備案檔案。根據你的開發者賬號型別,你可以選擇Ad Hoc或者In House兩種不同的備案檔案(Provisioning Profiles > Distribution > Add > Ad Hoc or In House).下載將其儲存到scripts/profile/目錄下。

我們需要在Travis中訪問此備案檔案,所以我們需要將此檔案的名字儲存為一個全域性變數。譬如我們可以將其命名為TravisExample_Ad_Hoc.mobileprovision,像這樣新增:

12345 env:global:-APP_NAME="TravisExample"-'DEVELOPER_NAME="iPhone Distribution: {your_name} ({code})"'-PROFILE_NAME="TravisExample_Ad_Hoc"

這裡還有兩個宣告的全域性變數。APP_NAME通常指的就是你的專案主target的名字。DEVELOPER_NAME裡是你在專案主target下Xcode Build Settings 中Code Signing Identity > Release裡面看到的名字。最後搜尋一下你應用的Ad Hoc或者In House配置檔案,將其中的黑體文字全部去掉。根據你設定的不同,在一些屬性的方括號裡面可能不會有任何資訊。

加密證書和備案檔案

不過你的GitHub許可權是公開的。你可能會想要給你的證書和備案檔案加密,因為他們包含了你應用的重要資訊。如果你使用的是一個私有目錄,你可以跳過這一小節。

首先我們需要想出一個密碼來加密我們所有的檔案。在下面的例子中,我們使用foo這個單詞,你完全可以將其替換為使用於你專案的更安全的密碼。在命令列中需要使用openssl來加密這些敏感檔案:

123 openssl aes-256-cbc-k"foo"-inscripts/profile/TravisExample_Ad_Hoc.mobileprovision-out scripts/profile/TravisExample_Ad_Hoc.mobileprovision.enc-aopenssl aes-256-cbc-k"foo"-inscripts/certs/dist.cer-out scripts/certs/dist.cer.enc-aopenssl aes-256-cbc-k"foo"-inscripts/certs/dist.p12-out scripts/certs/dist.cer.p12-a

這樣可以建立.enc字尾的加密版本證書和配置檔案。現在你可以刪除或者忽略那些原始檔案。但是有一點千萬不要提交未加密的證書與配置檔案,否則它們會出現在GitHub上。如果你不小心這樣做了,立刻去尋求幫助。

現在我們的檔案都已經加密,我們需要告訴Travis如何解密。所以我們需要提供解密的密碼,使用之前建立KEY_PASSWORD變數一樣的方式:

travis encrypt “ENCRYPTION_SECRET=foo” –add

Lastly, we have to tell Travis which files to decrypt. Add the following commands to the before-script phase in the .travis.yml:

最後我們需要告訴Travis那些檔案需要解密。在.travis.yml檔案的before-script階段新增如下命令:

1234 before_script:-openssl aes-256-cbc-k"$ENCRYPTION_SECRET"-inscripts/profile/TravisExample_Ad_Hoc.mobileprovision.enc-d-a-out scripts/profile/TravisExample_Ad_Hoc.mobileprovision-openssl aes-256-cbc-k"$ENCRYPTION_SECRET"-inscripts/certs/dist.p12.enc-d-a-out scripts/certs/dist.p12-openssl aes-256-cbc-k"$ENCRYPTION_SECRET"-inscripts/certs/dist.p12.enc-d-a-out scripts/certs/dist.p12

現在你在GitHub上的都是安全的了,Travis可以正常的讀取使用它們。但是還有一個安全問題你需要知道:在Travis的編譯日誌裡可能會顯示出解密的密碼,不過對pull請求來說不會出現。

新增指令碼

現在我們需要確保所有的證書都匯入到Travis CI的鑰匙串中。這一步我們需要在scripts資料夾下面新增一個新的檔案add-key.sh:

Shell
1234567 #!/bin/shsecurity create-keychain-ptravis ios-build.keychainsecurity import./scripts/certs/apple.cer-k~/Library/Keychains/ios-build.keychain-T/usr/bin/codesignsecurity import./scripts/certs/dist.cer-k~/Library/Keychains/ios-build.keychain-T/usr/bin/codesignsecurity import./scripts/certs/dist.p12-k~/Library/Keychains/ios-build.keychain-P$KEY_PASSWORD-T/usr/bin/codesignmkdir-p~/Library/MobileDevice/Provisioning\Profilescp./scripts/profile/$PROFILE_NAME.mobileprovision~/Library/MobileDevice/Provisioning\Profiles/

這裡我們建立了一個新的臨時keychain叫做ios-build,其中包含了所有的證書。注意這裡我們使用$KEY_PASSWORD來匯入私鑰。在最後一步,備案檔案會拷貝到Library資料夾。

在建立這個檔案後,確保給予它可執行的許可權。在命令列裡輸入chmod a+x scripts/add-key.sh。下面所有的指令碼都需要執行這一步。

現在所有的證書和配置檔案都已就緒我們可以開始給我們的應用簽名。注意一定要先編譯應用再給其簽名。由於我們需要知道編譯好的二進位制檔案的位置,我推薦在編譯命令中使用OBJROOT和SYMROOT這兩個變數。另外,我們應該把SDK設定為iphoneos,configuration項改為Release。

xctool -workspace TravisExample.xcworkspace -scheme TravisExample -sdk iphoneos -configuration Release OBJROOT=$PWD/build SYMROOT=$PWD/build ONLY_ACTIVE_ARCH=NO

執行這個命令,你會發現應用編譯後的二進位制檔案出現在build/Release-iphoneos資料夾下面。現在我們可以使用如下的指令碼給應用簽名和打包。

Shell
1234567891011121314 #!/bin/shif[["$TRAVIS_PULL_REQUEST"!="false"]];thenecho"This is a pull request. No deployment will be done."exit0fiif[["$TRAVIS_BRANCH"!="master"]];thenecho"Testing on a branch other than master. No deployment will be done."exit0fiPROVISIONING_PROFILE="$HOME/Library/MobileDevice/Provisioning Profiles/$PROFILE_NAME.mobileprovision"OUTPUTDIR="$PWD/build/Release-iphoneos"xcrun-log-sdk iphoneos PackageApplication"$OUTPUTDIR/$APPNAME.app"-o"$OUTPUTDIR/$APPNAME.ipa"-sign"$DEVELOPER_NAME"-embed"$PROVISIONING_PROFILE"

第二行到第九行尤其重要。你不會想要給一個試驗用的分支建立一次新的release。對pull請求也是一樣。環境變數已經被禁用,所以pull請求也不會編譯。

第十四行才是真正的簽名操作。這會使build/Release-iphoneo檔案下下面出現兩個新檔案TravisExample.ipa和TravisExample.app.dsym。第一個檔案包含了將被安裝到手機的應用。dsym檔案包含了二進位制檔案的除錯資訊。這個檔案對記錄以應用在裝置上的crash非常重要。後面我們將會使用它們來部署我們的應用。

最後要新增一些指令碼語句移除臨時的Keychain,將備案檔案刪除。你可以在本地測試一下這些語句,雖然不是很必要。

Shell
123 #!/bin/shsecurity delete-keychain ios-build.keychainrm-f~/Library/MobileDevice/Provisioning\Profiles/$PROFILE_NAME.mobileprovision

最後一步我們需要告訴Travis什麼時候執行這三個指令碼。私鑰需要在應用編譯前新增,然後再進行簽名和清除等操作。在.travis.yml檔案裡新增如下語句:

123456789 before_script:-./scripts/add-key.sh-./scripts/update-bundle.shscript:-xctool-workspace TravisExample.xcworkspace-scheme TravisExample-sdk iphoneos-configuration Release OBJROOT=$PWD/build SYMROOT=$PWD/build ONLY_ACTIVE_ARCH=NOafter_success:-./scripts/sign-and-upload.shafter_script:-./scripts/remove-key.sh

完成這一步,我們可以將所有的檔案放到GitHub上等待Travis給我們的應用簽名。我們可以在專案頁面下的Travis控制檯驗證簽名是否成功。如果一切正常,我們來看一下如何將簽名好的應用提交給測試人員。

釋出應用

有兩個知名的服務可以幫助你釋出你的應用:TestFlight and HockeyApp。不管哪一個都足夠滿足你的需要。個人比較推薦HockeyApp,不過兩種服務我都會教你怎麼整合到專案裡。

我們在sign-and-build.sh中新增指令碼語句,首先新增一些釋出日誌:

12 RELEASE_DATE=`date'+%Y-%m-%d %H:%M:%S'`

相關推薦

objc系列譯文6.5iOS專案搭建Travis CI伺服器

你是否曾經試著為你的iOS專案搭建一臺支援持續整合的伺服器,從我的個人經驗而言,這可不是一個輕鬆的活。你需要準備一部Mac,安裝好全部所需的軟體和外掛。你要負責管理所有的使用者賬戶並提供安全保護。 原本你想節省的時間,最終你會發現你花費了大量的時間去維護這臺伺服器。

objc系列譯文6.3Mach-O 可執行檔案

當我們在Xcode中構建一個程式的時候,其中有一部分就是把原始檔(.m和.h)檔案轉變成可執行檔案。這個可執行檔案包含了將會在CPU(iOS裝置上的arm處理器或者你mac上的Intel處理器)執行的位元組碼。 我們將會過一遍編譯器這個過程的做了些什麼,同時也看一下

objc系列譯文6.4深入理解 CocoaPods

Cocoapods是 OS X 和 iOS 下的一個第三方庫管理工具。你能使用CocoaPods新增被稱作“Pods”的依賴庫,並輕鬆管理它們的版本,而不用考慮當前的時間和開發環境。 Cocoapods意義體現在兩個方面。首先,引入第三方庫無可避免地要進行各種各樣的

JavaWeb項目--網上商城 6-5

ava 註意 cname 案例 輸入 子節點 根節點 .get esp day5--後臺管理模塊開發 案例1-後臺所有分類展示 需求: 在左側

機器學習系列文章監督學習迴歸

在機器學習領域,最神奇的模型當屬迴歸模型,迴歸模型也是非專業人員一談機器學習就能無意涉及到的內容。在這裡,筆者先談談當前資訊學科被無良媒體誇大報道賺取點選率關注度的商業行為。不知何時起,國民自負的以為手裡拿著手機,包裡揹著筆記本就以為掌握了資訊時代發展的最前沿資訊。這種不理性

SpringBoot入門系列十六actuator監控模組入門

actuator是SpringBoot提供的一個用於監控的模組,想要在SpringBoot中使用則需要引入該jar包: <dependency> <groupId>org.springframework.boot</gro

Java抽象類總結6.5

參考《瘋狂java講義》 1. 抽象方法和抽象類 若定義一個父類時,父類只是知道其子類應該包含怎樣的方法,但無法準確的知道這些子類如何去實現這些方法。 可能有讀者會說,既然父類不知道子類如何去子類的某個方法,那乾脆就不要管它了,這不是一個好思路。假設有一個父類例項的引用變數,該變數實

hadoop學習之HDFS2.5windows下eclipse遠端連線linux下的hadoop叢集並測試wordcount例子

windows下eclipse遠端連線linux下的hadoop叢集不像在linux下直接配置eclipse一樣方便,會出現各種各樣的問題,處處是坑,連線hadoop和執行例子時都會出現問題,而網上的

SpringBoot入門系列十一實現檔案上傳

前情提要 現在大多數的web開發基本都會用到檔案上傳這一個功能,檔案上傳分為單檔案上傳和多檔案上傳,下面就一一講解一下通過SpringBoot框架對兩種上傳的實現 SpringBoot實現單檔案上傳 首先建立一個html介面,包含一個for

SpringBoot入門系列十四使用@Async註解進行非同步方法呼叫

非同步呼叫的概念 非同步呼叫相對於同步呼叫而言,通常的方法都是程式按照順序來執行的,程式的每一步都需要等到上一步執行完成之後才能繼續往下執行;而非同步呼叫則無需等待,它可以在不阻塞主執行緒的情況下執行高耗時方法 如何實現非同步呼叫 在不使用SpringBo

ZooKeeper系列十二服務端實現機制

服務端有3種執行方式:leader,follower,observer。leader是領導者,一個ZooKeeper叢集同一時刻最

ZooKeeper系列十六結束篇

ZooKeeper的設計原理講到這基本就結束了,有興趣的朋友可以下原始碼看看,ZooKeeper的原始碼寫的很好,很輕量級,是入門

《Java從入門到失業》第四章類和物件4.5

4.5包        前面我們已經聽過包(package)這個概念了,比如String類在java.lang包下,Arrays類在java.util包下。那麼為什麼要引入包的概念呢?我們思考一個問題:java類庫提供了上千個類,我們很難完全記住他們

WAS集群系列5集群搭建步驟3安裝IHS軟件

line col jsb eight none data 相關 blog mil 選擇“安裝IBM HTTPServer”選項,點擊“安裝向導”。例如以下圖提示: 安裝提示,逐步點擊“下一步”,當中偶有幾處細節註意就可以。列舉例如以下: (1)、產品安裝路徑與先

多線程面試題系列5經典線程同步 關鍵段CS

得到 bug oar -- 多線程同步 實現 unsigned 初始化 alt 上一篇提出了一個經典的多線程同步互斥問題,本篇將用關鍵段CRITICAL_SECTION來嘗試解決這個問題。本文首先介紹下如何使用關鍵段,然後再深層次的分析下關鍵段的實現機制與原理。關鍵段CRI

深入理解JavaScript系列5強大的原型和原型鏈

JavaScript 不包含傳統的類繼承模型,而是使用 prototypal 原型模型。 雖然這經常被當作是 JavaScript 的缺點被提及,其實基於原型的繼承模型比傳統的類繼承還要強大。實現傳統的類繼承模型是很簡單,但是實現 JavaScript 中的原型繼承則要困難的多。 &l

arcgis jsapi介面入門系列5幾何點線面基本操作

點 point: function () { //通過wkt生成點 //wkt,代表點的座標 let wkt = "POINT(113.566806 22.22445)";

python快速學習系列5裝飾器

裝飾器概述: -理解裝飾器要從三方面入手:why?what?how? -學習裝飾器要從模仿開始 1.why?為什麼會出現裝飾器這個東西? ·名稱管理 ·顯示呼叫 ·就近原則 ·充分複用 例如: def decorate(func): func.__doc__ += '\nDe

Spring學習65FactoryBean及使用註解配置

Spring學習6(5) FactoryBean  Spring通過反射機制利用<bean>的class屬性來指定實現類的方法在Bean的例項化過程較為複雜時會增加編碼繁瑣度。故此Spring提供了一個org.springframework.bean

Spring Security十五5.6 Authentication

Thus far we have only taken a look at the most basic authentication configuration. Let’s take a look at a few slightly more advanced options for configurin