PRの待ち時間が伸び、リリース用ジョブまで止まっている。
最短の解決策は、開発者数ではなくピーク時の到着量、タスク時間、許容待ち時間、障害用の予備容量からMac Runner台数を算出することです。
この判断は、GitHub Actionsの自社運用macOS Runnerを管理しているDevOpsエンジニア向けです。複数のiOSプロジェクトにビルド枠を割り当てる責任者や、リモートMacの契約期間を決める購買担当者にも使えます。
まず「オンライン台数」と「処理能力」を分けて見る
GitHub Actionsでは、Runnerがオンラインでも、別のジョブを安全に同時処理できるとは限りません。1台のMacでXcodeのコンパイル、Simulator、テストワーカーを重ねると、CPUだけでなくメモリ、ディスクI/O、Simulatorの起動状態が競合します。
GitHubは自社運用Runnerのラベルやグループを使って、条件に合うRunnerへジョブをルーティングします。ただし、何台あれば何件を安定処理できるかという固定容量公式は示していません。台数は対象プロジェクトの実行履歴と実機の試運転で決めます。
まずGitHub Actionsの実行記録から、次の項目をワークフロー別に取り出してください。
- タスクの到着時刻とピーク時間帯
- Runner待機時間と実行時間
- 失敗後の再実行回数
- キャンセルされた古いコミット
- Runnerのオフライン時間と復旧時間
平均実行時間だけでは、リリース日や集中コミット時の負荷を隠します。通常日、PRが集中する時間帯、夜間回帰、リリース前の短時間ピークを分け、高分位のタスク時間を基準にします。GitHubの公式メトリクスと監視手順は、自社運用Runnerの監視・トラブルシューティング資料で確認できます。
台数を決める前に使う容量モデル
ワークフローごとに、次の形で基礎負荷を置きます。
必要な同時実行枠 ≒ ピーク時の到着率 × 典型または高分位の実行時間
ここに、許容待ち時間、再実行分、リリースの予約枠、故障時に失われる処理能力を加えます。結果をそのままMac台数に置き換えてはいけません。1台で許容できる同時処理数を、プロジェクトのXcode CIで実測してから割り当てます。
| タスクの種類 | 主な負荷 | 先に確保する容量 | 他タスクとの扱い |
|---|---|---|---|
| PRのコード検査・単体テスト | 継続的な到着、短時間の応答要求 | 基礎ノード | 軽い処理は共有候補 |
| 増分ビルド | キャッシュ、コンパイル、ディスクI/O | PRノード | UIテストと同居させる前に実測 |
| Simulator・UIテスト | Simulator、テストワーカー、メモリ競合 | 独立テストノード | 専用分離を優先 |
| 署名・アーカイブ・公開 | 証明書、キーチェーン、環境の再現性 | 専用または予約枠 | 一般PRから隔離 |
| 夜間回帰・リリース前ピーク | 短時間の集中負荷 | 時間限定の追加枠 | 短期増設を検討 |
Mac miniを自社購入して常設する案もあります。購入、設置、交換、稼働監視まで含めて比較したい場合は、Mac miniをサーバーとして使う判断材料も確認してください。
PR用の基礎ノードはフィードバック時間から決める
PRビルドでは、コード検査、単体テスト、増分ビルドが勤務時間中に継続して到着します。ここで基礎ノードを少なくしすぎると、リリース処理が低頻度でも、日常の開発速度が先に悪化します。
必要な台数は、開発者の人数ではなく、次の順で決めます。
- ピーク時間帯のPRジョブ到着数を記録します。
- ジョブごとに待機時間と実行時間を分けます。
- 許容できる待機時間をプロジェクト単位で定義します。
- 同じMac上で同時実行数を増やし、完了時間と失敗率を比較します。
- 許容時間を超える待機が続く場合だけ、基礎ノードを増やします。
増設前に、Macを使わなくてもよい処理をLinux側へ移せないか確認してください。古いコミットのPRジョブは、GitHub ActionsのConcurrency設定でキャンセルできる場合があります。ワークフローのキャンセルと実行制御は、Concurrencyの公式仕様に沿って設計します。
また、複数ジョブに分かれた重複チェックを統合し、必須のMac処理だけを残します。これでピーク時の到着量そのものが減るなら、Runnerを増やすより先に待ち時間を改善できます。
UIテストはコンパイル用Runnerと分けるべきか
Simulatorを使うiOS UIテストは、通常のコンパイルとは別の負荷として扱います。複数のテストワーカーを1台で動かすと、ワークフロー上は同時実行が増えても、Mac内部ではCPU、メモリ、ストレージを奪い合います。
AppleはXcodeの並列テスト機能と、テスト実行時の分散方法を文書化しています。xcodebuildの並列テストオプションを確認する際は、AppleのXcodeリリースノートを参照してください。並列数を増やせば必ず短縮できるわけではありません。
試運転では、同じコミットを使い、次の状態を比較します。
- 1つのUIテストジョブを単独実行
- 同一Mac内でテストワーカーを増加
- 独立したMacへテストジョブを分散
- Simulatorの起動失敗、タイムアウト、再試行を記録
ワーカーを増やした結果、実効完了時間が伸びる、Simulatorが不安定になる、再実行が増える場合は、単機内の並列数を制限します。そのうえで独立したテストノードを追加します。ワークフローの同時実行数と、1台のMac内部の並列数を足し算して、見かけの容量を作らないことが重要です。
Xcodeのビルド時間を比較するときは、Appleのビルド時間計測に関する資料にあるBuild Timing Summaryの考え方を使い、キャッシュの有無も同じ条件に揃えます。
署名・公開ジョブは空き台数だけで判断しない
アーカイブ、署名、ストア公開のジョブは、低頻度だからPR用Runnerと共有できるとは限りません。キーチェーン、証明書、プロビジョニング、作業ディレクトリの残留状態が、失敗復旧と監査に影響します。
GitHub Actionsでは、ラベルとRunner Groupを使って実行先を分けられます。たとえばPR用に mac-pr、UIテスト用に mac-ui、公開用に mac-release のような役割を付け、公開ノードは通常のジョブから選ばれない設計にします。ラベルとグループによるルーティングは、Runnerのラベル指定に関する公式手順とRunner Groupの管理資料で確認できます。
完全なアーカイブから署名、成果物保存、失敗後の再実行までを一度通し、次を測定します。
- 公開ジョブが意図したRunner Groupへ到達するか
- PRジョブに占有されて待たされないか
- キーチェーンの初期化と後処理が完了するか
- ノード再起動後に同じ手順で復旧できるか
公開時間帯に専用ノードを常時用意するか、予約枠だけ確保するかは、締切の厳しさで決めます。通常のPRが公開枠を消費してしまうなら、共有による節約より納期リスクの方が大きくなります。
FAQ:タスク種別ごとの台数判断
自社運用のMac Runner 1台で同時に処理できるジョブ数は?
GitHub ActionsやAppleが、Mac 1台の安定した同時ジョブ数を固定値として保証しているわけではありません。オンライン状態は待機可能であることを示すだけです。Xcodeのコンパイル、Simulator、テストワーカーを段階的に増やし、完了時間、メモリ圧迫、失敗率をプロジェクトごとに測定してください。
Xcode CIの待ち時間が増えたら、すぐMacを増やすべきか?
すぐに増設するのではなく、ピーク時間帯の待機が繰り返されているかを確認します。古いコミットのキャンセル、重複チェックの統合、Mac不要の処理の分離を先に実施します。それでも許容待ち時間を超え、到着量と実行時間から基礎容量不足が確認できる場合にノードを追加します。
iOS UIテストとコンパイルは同じRunnerでよいか?
小規模な処理なら共有できますが、Simulatorや複数ワーカーを使うUIテストでは分離が安全です。同じMac上の並列化は、Runner数を増やさずに内部競合だけを増やす可能性があります。単独実行、同居、独立ノードを同じ条件で比較し、失敗率と実効時間で決めてください。
タスク時間からリモートMacの必要台数を出す方法は?
ピーク時の到着率に、典型値または高分位の実行時間を掛けて基礎負荷を求めます。そこへ許容待ち時間、失敗再実行、リリース予約、障害時の予備を加えます。これは公式の台数計算式ではありません。GitHubの履歴とリモートMacの試運転を照合し、段階的に補正する容量モデルです。
Mac Runnerは長期運用とピーク時追加のどちらがよいか?
PRが毎日詰まるなら基礎ノードの長期運用を検討します。夜間回帰やリリース前だけ集中するなら、時間帯の変更、キュー制御、短期間のリモートMac追加を先に試します。長期契約へ移る前に、通常日とピーク日の実行履歴を分け、予備容量を含めても継続的に必要かを確認してください。
夜間処理とリリース前ピークは固定台数にしない
夜間回帰テストは、PRフィードバックほど即時性を求めない場合があります。開始時間をずらし、キューを許容できるなら、日中の基礎ノードと同じ設備を共有できます。
一方、公開前の回帰や複数プロジェクトのリリースが重なる場合は、短時間だけ必要な容量が跳ね上がります。年間最大値に合わせて常設台数を増やすのではなく、次の順で検討します。
- 締切のない処理を夜間の別時間帯へ移す
- 再実行可能な回帰処理にキューを設ける
- 公開用の予約枠をPR用から切り離す
- 実績が確認できた期間だけリモートMacを短期追加する
- 同じピークが繰り返されるなら、常設ノードへの移行を検討する
試運転から四つの容量枠を確定する
最初から完成したMacファームを作るのではなく、タスクを種類別に分けて小規模に試します。GitHubのメトリクスには、Runnerの待機、実行、オフライン、失敗の記録を残します。
- PR、増分ビルド、UIテスト、公開、夜間処理にラベルを付けます。
- 各グループの到着時刻、待機時間、実行時間、再実行を記録します。
- 1台あたりの同時実行数を少しずつ増やします。
- CPU、メモリ、ディスクI/O、Simulatorの状態を確認します。
- 同じタスクを独立ノードへ移し、単機内並列との差を比較します。
- 公開ジョブを予約枠へ分け、通常PRによる占有を防ぎます。
- 再起動後のRunner接続、作業ディレクトリ、署名環境の復旧を確認します。
- 通常日とピーク日の記録を分け、基礎、テスト、公開、予備の枠を確定します。
判断は次の条件分岐にすると、購買会議でも説明しやすくなります。
- ピーク時の待機が許容範囲内で、失敗再実行も増えていない
→ 現状維持。ただし公開用の予約枠は別に確認します。 - 待機が長いが、古いコミットや重複処理が多い
→ Concurrency、ジョブ統合、Mac不要処理の分離を先に行います。 - 最適化後もPRのピーク待機が続き、UIテストも競合する
→ テスト用の独立ノードを短期追加します。 - 公開時間帯だけ容量が不足する
→ 公開用の専用または予約Runnerを確保します。 - 同じピークが複数のリリース周期で再現する
→ 短期追加から長期ノードへ移行する根拠にします。 - 障害や再起動で納期に影響する
→ 予備ノードを置き、復旧手順を検証します。
GitHub Actionsのワークフロー構文やジョブの条件分岐は、公式のワークフロー構文リファレンスで確認できます。設定変更後は、待機時間だけでなく、実際に成果物が完成するまでの時間を比較してください。
現在のWindowsやLinuxマシンだけで運用すると、macOS専用のXcodeツールチェーンを別経路で補う必要があり、Simulator、署名環境、公開ジョブの分離も複雑になります。仮想環境では実機に近い再現性や復旧手順を保ちにくく、固定のMac miniを購入すると、ピーク時以外も設置・保守の負担が残ります。常設購入を比較する場合は、日本向けMac miniの調達条件も判断材料にできます。
まずは一周期分のPR、UIテスト、公開タスクを表に記録してください。ピークだけ不足しているなら、KVMNODEのリモートMacを短期間追加して実測し、基礎ノードまで不足していると確認できた段階で長期運用へ移す方が、最高負荷を前提にした過剰な固定容量を避けやすくなります。