自分専用のマシンでiOS CI/CDパイプラインを動かす
iOSのCIに関するアドバイスの多くは、見当違いの部分を最適化しています。時間を食っているのは、たいていビルドの工程ではありません。ここでは、実際のパイプラインで本当に効く対策と、専用ハードウェアで計算がどう変わるかを説明します。
時間は実際どこで使われているか
ホスト型runnerでの一般的なiOSジョブは、コードを1行もコンパイルしないうちに多くの時間を使います。依存関係の解決とダウンロード、空のDerivedDataディレクトリのウォームアップ、ツールのインストール、シミュレータの起動です。マシンは実行後に破棄されるので、この作業が毎回繰り返されます。
専用マシンなら、この作業のほとんどはすでに済んでいます。WikipediaのiOSアプリを使った当社のベンチマークでは、M6 miniでのクリーンビルドはGitHubの標準runnerより53パーセント速くなりました。一般的なCIジョブは269秒から27秒になりました。専用のMacはビルドフォルダを保持し、変更された部分だけを再ビルドしたからです。
参考にしたいパイプライン
- 作業を分けます。Lint、共有Swiftパッケージのテスト、リリースの自動化はLinuxで実行できます。Macに載せるのは、シミュレータと実機の作業だけにします。
- 正しいパスをキャッシュします。DerivedData、SwiftPM、CocoaPods、Gemsです。専用マシンなら、これらは何もしなくても残ります。
- 退屈な部分はfastlaneに任せます。build、test、screenshot、uploadのレーンを使えば、ローカルとCIで同じコマンドを使えます。
- 署名は予測可能にしておきます。プライベートの証明書リポジトリとfastlane matchの組み合わせが、今でも最も確実な方法です。MacRunは署名を管理しません。そのぶん、予期しないことも起きません。
- マトリックスを絞ります。デバイスとOSのマトリックス全体は、mainと夜間の実行で回します。プルリクエストのたびに回す必要はありません。
ワークフローの例
name: iOS
on: [pull_request]
jobs:
test:
runs-on: [self-hosted, macOS, macrun-unit-01]
steps:
- uses: actions/checkout@v4
- run: sudo xcodes select 26.6
- run: bundle install
- run: bundle exec fastlane testrunnerが専用なので、ここにはキャッシュの復元ステップがありません。前回の実行の依存関係とDerivedDataは、すでにディスク上にあります。
これで解決しないこと
専用ハードウェアでも、遅いテストスイートは直りません。フルビルドを強いるモジュール構成や、不安定なシミュレータテストも同じです。専用ハードウェアがなくすのは、毎回のセットアップの手間と分単位の課金です。残りは、引き続きお客様側のエンジニアリング作業です。
よくある質問
GitHub ActionsでiOSのビルドを速くするには?
+
コンパイルを最適化する前に、繰り返されるセットアップを減らします。DerivedData、SwiftPM、CocoaPodsのキャッシュを残し、Mac以外の作業はLinuxのrunnerに移します。プルリクエストではデバイスのマトリックスを絞り、Xcodeのバージョンを1つに固定します。専用ハードウェアなら、キャッシュは実行の間も自動的に残ります。
セルフホストのmacOS runnerでfastlaneを使えますか?
+
はい。MacRunのマシンには、fastlane、CocoaPods、Ruby、Nodeがプリインストールされています。ローカルとまったく同じように呼び出せます。fastlane matchでの署名も、ほかのMacと同じように動きます。
MacRunはコード署名をやってくれますか?
+
いいえ。これは意図的です。証明書とプロビジョニングプロファイルは、お客様が管理します。通常は、お客様のプライベートリポジトリに対してfastlane matchを使います。当社が提供するのはマシンで、署名の管理サービスではありません。
専用runnerでiOSのUIテストを実行できますか?
+
はい。シミュレータは普通に動きます。マシンが使い回されないので、シミュレータの起動状態とDerivedDataが実行の間もウォームなまま残ります。これでUIテストのジョブが、たいてい数分短くなります。