ユビレジではTravis CIを使って、テストの実行とベータ版のTestFlightへのアップロードを自動化しています。
Pull Requestが送られた時と、マージされた時に自動でマージした結果のベータ版が配布されるので、手元で変更をすぐに試すことができて便利です。
【参考】
Travis CIでiOSアプリのテスト&ベータ版の配信に使っているRakefileを改善したメモ - 24/7 twenty-four seven
ユビレジのiPadアプリのCI環境をJenkinsからTravis CIに移行したときのまとめ - 24/7 twenty-four seven
ただ、これは導入当初からあった問題なのですが、Travis CIにジョブが登録されてから終了するまで、だいたい20〜25分くらいと、少し時間がかかるのが気になっていました。
そこでジョブの並列化と、BundlerとCocoaPodsのキャッシュ2点で高速化を試みました。
まずジョブの並列化は、テストの実行とTestFlightへのアップロードを分けて並列で実行することにしました。
これまでテストがすべて成功した後に再度デバイス用のバイナリをビルドしてTestFlightにアップロードしていました。
それをテストの終了を待たずに、TestFlightのアップロードをするように変更しました。
テストが失敗するビルドがTestFlightで配信されることが起こりますが、テストが通らないビルドがマージされることは無いので、手元で早く確認できるということを優先しました。
変更は簡単で.travis.ymlの呼び出し方法を少し直すだけでした。
↓ もともとこうだったのが、
language: objective-c script: - bundle exec rake test after_success: - bundle exec rake profile:download - bundle exec rake certificate:add - bundle exec rake distribute - bundle exec rake certificate:remove
↓ まず、Rakeタスクの呼び出しをそれぞれ1行にします。
language: objective-c script: - bundle exec rake test after_success: - bundle exec rake profile:download certificate:add distribute certificate:remove
↓ タスクをBuild Matrixのパラメータに振り分けます。
language: objective-c script: - bundle exec rake ${ACTION} env: matrix: - ACTION='profile:download certificate:add distribute certificate:remove' - ACTION=test
これだけで、Matrixの上段はTestFlightの配信、下段はテストの実行で並列に実行されます。
次にBundlerとCocoaPodsをキャッシュする設定です。
↓ OSXのビルド環境でもキャッシュの設定が有効になったということで試しました。
The Travis CI Blog: Caching (all the things) on the Mac platform
language: objective-c cache: - bundler - cocoapods
↑ のオーソドックスな設定ではなぜかうまく動かなかったので、下のようにディレクトリをキャッシュする設定を使いました。
language: objective-c cache: directories: - vendor/bundle - Pods install: - bundle install --path=vendor/bundle --binstubs=vendor/bin - bundle exec pod install
ビルド時間の半分以上がBundlerとCocoaPodsのインストールにかかる時間だったので、これはかなり有効でした。
最終的に、TestFlightへのアップロードが3〜5分、テストの実行が4〜6分くらいで合計で8〜12分くらい、並列で実行されるのでPull Requestしてからだいたい5分くらいで手元で試せるベータ版が届くという環境になっています。