Mac なしで build する
Situation
1.1.1 の開発ループで、Expo Go による動作確認と修正のサイクルは回るようになった。開発中は build なしで進む。
Complication
ただし、App Store に出すとなると話が変わる。Apple に申請するには、アプリを build して submit しなければならない。そして iPhone アプリの build には Mac が必要 — これは Apple のエコシステム上、避けて通れない事実である。
Question
build には Mac が必要。Mac を持たずに、どうやって App Store まで届けるか?
Criteria
- Mac を所有していなくても成立すること (買わない・借りない・置かない)
Answer
# 初回のみ (証明書作成) PC ブラウザ → GitHub → GitHub Codespaces → EAS (build) # 2 回目以降 (すべて iPhone から) iPhone → GitHub → GitHub Actions → EAS (build) iPhone → GitHub → GitHub Actions → EAS (submit) → App Store Connect → TestFlight → iPhone
鍵は、Mac は「クラウドの中」にあればいいという点である。EAS (Expo Application Services) の build サービスは、クラウド側の macOS 環境で iPhone アプリを build してくれる。手元に必要なのは、コマンドを投げる端末だけ。それは iPhone で足りる。
Reason
初回だけ PC ブラウザを使ったのは、対話操作のためである。 初回 build では署名用の証明書 (App Store 用の credentials) を作る必要があり、その過程で Y/N を聞かれる対話式の入力が発生する。基本は Y を答えるだけなのだが、これを GitHub Actions で自動化しようとすると、応答のタイミング合わせのような面倒なコーディングが必要になる。年に数回あるかどうかの操作を自動化する価値はないと判断して、初回だけ手動にした。
その手動操作も、Mac は要らない。GitHub Codespaces — GitHub がブラウザ上に用意してくれる VS Code 環境 — を開けば、そこからコマンドを叩ける。個人アカウントの無料枠 (120 コア時間/月) で十分足りる。理屈の上ではスマホのブラウザでも可能だが、ターミナル操作にはさすがに画面が小さすぎたので、ここだけ PC のブラウザを使った。繰り返すが、PC であって Mac である必要はない。
2 回目以降は対話が不要になるので、iPhone から GitHub Actions の workflow を実行するだけで build が走る。build が成功したら、同じく Actions から submit すると、App Store Connect に上がり、TestFlight で実機に降ってくる。申請の直前まで、すべて iPhone で完結する。
Options
- Xcode Cloud — Apple 純正の CI/CD。ただし初回のセットアップに Xcode つまり Mac が必要で、「Mac を所有しない」という Criteria と矛盾するため見送り。アプリを EXPO で実装している以上、EAS との親和性が高いことも決め手になった。
- GitHub Actions の macOS ランナー — Actions 上で直接 macOS を立ち上げて build する手もある。ただし macOS ランナーの利用は Linux の 10 倍の分数消費で課金される。無料枠 2,000 分/月がみるみる溶けるので、チャレンジしていない。
Good
build も submit も EAS に集約されたので、管理が一元化された。EXPO での開発 (1.1.1) と地続きのまま、申請直前の工程までスマホで届く。「Mac が要る」という iPhone アプリ開発最大の参入障壁が、実は「Mac を持つ必要」ではなかったと分かったのは収穫だった。
Bad
無料枠の組み合わせには制約がある。執筆時点の値で:
| サービス | 無料枠 | 備考 |
|---|---|---|
| EAS build | iOS 15 回/月 (+ Android 15 回/月) | build エラーでも回数を消費する |
| GitHub Actions | 2,000 分/月 | Free プランの private リポジトリの場合 |
通常の開発でこの上限を超えることはまずない。ただし、ネイティブまわりの動作確認でバグが出て build を繰り返すと、一気に持っていかれる。特に痛いのが、build エラーでも回数がカウントされること。設定ミスで 3 連続エラー、などとやると月の 2 割が消える。
Follow-up
EAS の無料枠 build は優先度が低く、キュー待ちが異様に長いことがある。気長に待てばいいのだが、ここに落とし穴がある。Actions 上で build の完了を待っていると、その待ち時間が Actions の 2,000 分/月からも消費されていく。待っても待たなくても build の結果は同じなので、eas build には --no-wait を付けて、trigger したら workflow を即終了させるのが正解である。
その代わり build と submit が 1 本の workflow で繋がらなくなるので、EAS のダッシュボードで build の成功を確認してから、Actions で submit を実行する、という 2 段運用にしている。submit 側も同様に --no-wait が使える。
ここまでで「作って届ける」の縦の線が通った。次は横に広げる話 — 多言語対応 (1.2) に続く。(作成中)