Help us understand the problem. What is going on with this article?

Xcode Server を使ってビルド環境を整える

More than 5 years have passed since last update.

初めに

Xcode Server を利用してビルド環境を整えたので、その作業内容をまとめてみます。

成果

iPhoneでBot実行結果を表示
BotResultOniPhone.png

xcworkspaceでBotの動作状況を確認
Xcode.png

目標

  • commit したら自動的にテストが行われるようにする。
  • ビルドバージョン CFBundleVersion を自動で上げる仕組みにする。
    • ビルドバージョンの変更はリポジトリには含めない。
  • アプリのビルド(Archive)を一元管理する。
    • プロジェクトをビルドして実機にインストールのは iOS アプリのプログラマーだけが行う。
    • 他のメンバーはビルド済みのアプリをテストできるようにする。
    • クラッシュログの追跡をしやすくするのが目的。
  • 常に最新版のテスト用アプリを実機に落とせるようにする。

どのサービス/ツールを利用するか?

自動テストとアプリ配布を実現するためのサービスやツールについて調べてみて、自分の環境にあったものを選びました。

自動テスト

自動テストについては KIF を採用することにしました。
このフレームワークを利用すると、XCTest 上で Objective-C/Swift で UI テストのコードが書くことができます。
また、CocoaPods を利用してプロジェクトに組み込めるので、リポジトリにはテストコードのみを commit しておいて、Xcode Bot がテスト実行前に KIF を組み込んでテストを走らせることができます。

アプリ配布

アプリの配布は開発チーム向け/社内テスト向け/ユーザー向けの 3 つを想定しました。

開発チーム向け

Xcode Server が Bot 実行時に出力したものを開発チームは利用するようにしました。

アプリのインストールまでの流れを簡単に説明します。

Bot は実行のタイミングを Periodically / On Commit / Manual の 3 つから選ぶことができます。この設定を On Commit にしておくと、Xcode Server が新しい commit を 5 分おきに確認するようになります。
そして git リポジトリに commit が push されると、Bot が自動的に開始されテストとアプリの Archive 化が行われます。
Bot の実行結果は開発チームのみがアクセスできる Web ページに表示されます。iOS デバイスからその Web ページにアクセスするとアプリのインストールが行えます。

社内テスト向け

社内テストは、開発チーム以外のメンバーやベータテスターに対しての配布を想定しています。
Beta by CrashlyticsDeployGate も気になりましたが、TestFlight を利用することにしました。
TestFlight は iOS 8 以上でないと利用できない欠点がありますが、今後のことを考えると動作対象を iOS 8 以上とした方がいい時期になってきていると思います。

ユーザー向け

一般ユーザーには App Store から配布します。

作業内容

用意した環境

  • Mac mini ( Mac OS X 10.10.3 )
  • 固定 IP
  • 独自ドメイン
  • SSL 証明書

利用するツール

  • KIF
  • CocoaPods
  • OS X Server 4.1
  • Xcode

Server の準備

Xcode Server and Continuous Integration Guide を参考にして作業を進めました。
Server (Mac mini) で行った主なことは次の通り。

Xcode

  • Mac App Store から Xcode をインストールする。
  • Xcode の Preferences 画面の Accounts を表示して、利用する git リポジトリを登録する。

OS X Server

  • iOS Dev Center にログインして OS X Server 4.1 をダウンロードする。買わなくて済む。
  • OS X Server をインストールする。
  • ドメインや証明書の設定を行う。
  • Xcode Server をオンにする。

CocoaPods

Terminal に $ sudo gem install cocoapods を打ち込んで CocoaPods をインストールする。

Client の準備

  • Xcode の Preferences 画面の Accounts を表示して Server を登録する。
  • Server と同様に Terminal $ sudo gem install cocoapods を打ち込んで CocoaPods をインストールする。

KIF を利用するための設定

今回の作業の中で、プロジェクトの設定に半日ほどの時間を費やしました。
KIF をリポジトリには入れずに、Xcode Server で KIF を利用してテストを行うための設定をなかなか導き出せなかったためです。

基本は KIF:README.md に沿って作業しましたが、工夫した点を書いておきます。
なお、サンプルで作成したプロジェクトが BotTest2 にあります。

xcodeproj の上の階層に xcworkspace を用意しておく

開発対象のアプリをターゲットに含むプロジェクトを BBB.xcodeproj とした場合、そのプロジェクトを含む BotTest2.xcworkspace を上の階層に作成しました。

BotTest2.png

なお、xcworkspace は単に xcodeproj をドラッグして追加した状態のものを、git リポジトリに追加しました。手元では pod install を行って、この xcworkspace ファイルで作業していきます。Bot の生成や実行もこの xcworkspace で行います。

Podfile

Podfile は xcworkspace と同列に配置し、Podfile 内で xcodeprojworkspace を指定するようにしました。

platform :ios, "8.0"

xcodeproj 'BBB/BBB.xcodeproj'
workspace 'BotTest2'

target 'BBBTests', :exclusive => true do
  pod 'KIF', '~> 3.0', :configurations => ['Debug']
end

https://github.com/satoshimuraki/BotTest2/blob/master/Podfile の内容です。

Bot - Before Integration - Run Script

Xcode Bot の開始前に KIF をインストールします。
基本的には pod install を呼び出せばいいのですが、警告の抑制などを行うと下記のようになりました。

beforeIntegration.sh
#!/bin/sh

# ディレクトリ内に移動
cd BotTest2

# KIF をインストール
export LANG=en_US.UTF-8
pod install

# KIF 内で static analyzer の警告が発生するので
# 警告が出ないようにコードを書き換えている
sed -i -e 's/AbsoluteTime timeStamp = \*(AbsoluteTime \*) &abTime/AbsoluteTime timeStamp; memcpy(\&timeStamp, (AbsoluteTime *)\&abTime, sizeof(timeStamp))/g' Pods/KIF/Additions/UIEvent+KIFAdditions.m

CFBundleVersion の自動更新

この作業の目標である「ビルドバージョン CFBundleVersion を自動で上げる仕組みにする」を実現するために、Bot の Before Integration に下記のスクリプトを追加しました。

updateBundleVersion.sh
#!/bin/sh

# xcodeproj が存在するディレクトリに移動
cd BotTest2/BBB

# commit ログから日付を取得
commitDate=$(git log -1 --format='%ci')

# 数字以外を空白に置き換える
comps=(`echo $commitDate | sed -e 's/[^0-9]/ /g'`)

# 年 (2000年を0とする)
y=$(( ${comps[0]} - 2000 ))

# 月日 (先頭の0を取り除く)
m_d=(`echo ${comps[1]}${comps[2]} | sed 's/^0*//'`)

# 時分秒 (先頭の0を取り除く)
h_m_s=(`echo ${comps[3]}${comps[4]}${comps[5]} | sed 's/^0*//'`)

# '.' でつないでバージョン番号にする
version=$y.$m_d.$h_m_s

# agvtool を利用して Info.plist の CFBundleVersion を置換する
agvtool new-version -all $version

このスクリプトでは Apple のコマンドラインツール agvtool を利用しています。このツールの利用方法については Technical Q&A QA1827
Automating Version and Build Numbers Using agvtool
に詳しい説明がありますが、利用対象のプロジェクト内のビルド設定で Current Project VersionVersioning System を正しく設定しておく必要があります。

このスクリプトが正常に動作すると、例えば最後の commit の日時が 2015年 5月 3日 9時 35分 47 秒であった場合、15.503.93547 というビルドバージョンが設定されてアプリが Archive されます。

最後に

これで当初の目標を全て満たせるビルド環境が整えられました。
TestFlight については方針を決めたのみで、まだ利用していませんが、Bot のテスト結果から Submit が行えるので、ここは問題なく TestFlight への配布に繋げられると思っています。

おまけ

はまったところ

  • 初め OS X Server の Self-signed Certificate で試みたところ、iOS デバイスでテスト結果が表示できるところまではいったが、「インストール」ボタンを押しても「**に接続できません」のアラートで出てうまくいかなかった。そこで SSL 証明書を $9.5/year で購入した。
  • SSL 証明書を購入したはいいが、そのインストール作業は初めてだったため、はまってしまった。RapidSSL のマニュアルに振り回されたのも 1 つの原因。最終的に Chrome や Mail で正しく SSL 証明書が有効と判断されるようになったが、なぜか GeoTrust の SSL 証明書チェッカーでまだ 1 つのエラーが残ってしまっている。
  • 原因が分からないが Xcode Server 上でシミュレータが起動せずにテストがタイムアウトしてしまう現象に陥ってしまった。Mac OS X の再インストールからやり直す結果になってしまった。関係あるか分からないが、Mac mini を終了するときには Xcode Server を手動でオフにしてから行うようにしようと思う。
  • オーストラリアの会社でドメインを買ったところ、本人確認の国際電話がかかってきたので驚いた。Yes と No しか言えなかった…

参考文献

ツール選定の参考文献

バージョン更新スクリプトの参考文献

Apple のドキュメント

気になったサービスやツール

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした