2026 年 5 月 29 日、木曜 15:03。12 名の iOS チーム——Slack #ios-ci に Run リンクが貼られ、「ローカル Xcode では 12 分で通ったのに、PR はまだ Queued」と添えられていた。30 分、誰も返信しない。こういう投稿は日常茶飯事だ。48 分後、同じ開発者が追記する:「Queued 47 分、run 12 分。今夜の merge は無理だな。」会議室から出てきた Release 担当がスマホを見て一言:「ios-release の Archive がまだキューに入ったまま。PR ライン、また詰まってる。」
以下のスクリーンショットはトラブルシュート支援時にクライアントから提供された資料(マスク済み)。数値は加工していません。GitHub 公式ドキュメントの Job 実行時間と queue_wait_seconds を参照すれば、同じ統計を自分で再現できます。
このチームは 2 本のアプリをモノレポで運用し、CI はすべて GitHub ホスト macOS Runner 経由。2025 年までは我慢できた。2026 年春になると、フィードバックループが耐えられないほど伸びた。GitHub Actions 自体は「壊れている」わけではない——iOS チームにとっては、ピーク時に必ず渋滞する共有シャトルのように感じられるようになっていた。
あの木曜:Job ページを開くと、黄バーが緑の 4 倍
Run #18472910356 の Job ページのスクリーンショットが届いた——口頭の報告ではなく、タイムライン付きの実録だ。黄バー(Queued)47 分 12 秒、緑バー(Run)12 分 4 秒。画面下部には queue_wait_seconds: 2832、run duration: 724。式は単純で刺さる:wait time >> run time。
ios-pr.yml · macos-latest · 2026-05-29 15:04 CST当時チームは -jobs 並列化や DerivedData キャッシュキーの変更を会議で議論していた——それなのに、直近 10 件の macOS job の queued / run 列を誰も集計していなかった。Release ラインはさらに窮屈:ios-release.yml が xcodebuild archive、公証、TestFlight アップロードを PR 単体テストと同じライン・同じ macos-latest ラベルに詰め込んでいた。Archive は 1 回 25〜40 分、希少な同時実行スロットを占有し、PR の赤ランプを早く返す job までキューに巻き込む。
Queued だけ先に片付けたいなら、サイト内の macOS runner キュー診断 Runbook から読み始めてよい。彼らの転換点は、「問題は供給側にある」と認め、体感ではなく数字で会議室を説得してから始まった。
証拠:failed job 10 件の手書き表
5 月 30 日のスタンドアップ前、誰かが Actions 実行一覧から failed macOS job を 10 件手動で転記した(下図)。BI ツールは使っていない——表 1 枚、2 列の核心数字:queued_s と run_s。queued の中央値 2650 秒、run 724 秒。比は最大 4.5×。会議室が数秒静まった:「Xcode 17.4 のせいでは?」という話は出なくなった。
| よくある誤解 | 図 3 のシグナル | より有力な原因 |
|---|---|---|
| GitHub 障害 | 10/10 で queued_s > run_s | macOS 同時実行 cap、重い job がスロット占有 |
| プロジェクト肥大化 | run_s が 690–811s で安定 | コンパイルより待ちが主因 |
| 乱 push | 同一 PR で複数 run(図 2 参照) | Agent / bot ループ |
| 証明書期限切れ | 署名失敗が run ごとに分散 | キーチェーン cold start、並列競合 |
図 2:同一 PR が 6 回トリガーされた
キュー問題は前半にすぎない。3 月にチームはコーディング Agent を導入した:CI 赤 → ログ読み取り → 自動 commit → Actions 再トリガー。PR #847 の Checks ページのスクショがはっきり示す——workflow run が 6 回。うち 4 回の actor は bot、2 回は人。名目上は CI だが、挙動は retry loop だ。詳しくは CI がループ化したあとに起きること を参照。
ios-pr.yml 6 回トリガー(4× bot · 2× 人)· 2026-05-29後から誰かが冗談めかして言った:「CI は死んでない。永動機にしちゃっただけ。」悪いのは自動化そのものではなく、bot のたびに公共キューを奪い合うこと、専用 Runner プールがないことだ。
転換点:クラウド Mac 1 台と、5 月 31 日のパイプライン分離
手書き表のあと、チームはログを job 種別で分解した:PR 検証と統合ビルドが約 7 割、Simulator 単体テスト 2 割、Archive とアップロード 1 割——別チームの 1 日 500 回 iOS CI 実測構成 と驚くほど一致した。Mac mini 8 台購入案、Xcode Cloud 移行案も出た。最終的に着地したのは 2 点:
5 月 31 日、Apple Silicon クラウド Mac を 1 台レンタルし、セルフホスト Runner として登録(ラベル self-hosted, macOS, cloud-mac)。対照実験は素朴:同一 commit をホスト macos-latest とクラウド Mac で各 50 回 build——queued の分散が「40 分の日も 5 分の日も」から「ほぼ数秒」に収束した。
その夜、パイプラインを分離。 Archive、export、アップロードを ios-pr.yml から ios-release.yml へ移し、PR ラインは build と単体テストだけに。暖機 cron も追加:毎日深夜にクラウド Mac で xcodebuild build を 1 回走らせ、DerivedData をディスクに残す。actions/cache から毎回 cold pull するより安定した。
図 6 · 同一チーム wall time 中央値(PR build、2 週間各 50 回)
データソース:クライアント対照実験ログ(2026-05-31 — 06-08)。図 1・図 4 の単発 run と相互検証可能。
6 月 9 日:図 4 の Job ページが、ようやく「普通」に見えた
パイプライン分離から 2 週間後の月曜朝、Slack に Run #18510488201 のスクショが貼られた:queued 41 秒、run 9 分 17 秒、runner は self-hosted, cloud-mac。リアクションは少ない——iOS チームにとって、それが最高の称賛だ。
self-hosted, cloud-mac · 2026-06-09 09:11 CSTAgent に柵を:Wiki に書いた 4 条
パイプライン分離で Archive による PR 詰まりは解消。bot ループは別問題。チームは bot 専用ブランチと低優先 Runner プールを設け、人が review してから merge する方針に。4 条のハードルールを Wiki に明文化した:
- PR workflow で Archive / ストアアップロードを禁止
- macOS job に
concurrencyを必須化し、同一ブランチの重複実行を防止 - セルフホスト Runner はラベル必須。実験 workflow とプール混在禁止
- Agent の自動 push は独立ブランチのみ。保護ブランチへの直接 push 禁止
queue_wait_seconds と run duration を転記(図 3 参照)。単一 PR の workflow 回数を数える(図 2 参照)。Archive が PR workflow に残っていないか確認。queued 中央値 > run なら、まず Runner 供給を議論し、コンパイルパラメータ調整は後回しに。
新しい解法:GitHub を捨てるのではなく、供給の持ち方を変える
このチームの経験は、2026 年 iOS チームがよく着地する 4 点に凝縮される:クラウド Mac セルフホスト Runner プール、PR / Release 分離、暖機とディスクキャッシュ、Agent ガードレール。Xcode Cloud で代替できるか? Apple エコシステムに閉じた構成なら向く。GitHub PR チェックや Android 混在ラインと組み合わせるなら、多くのチームは Actions を残し、Archive だけ専用 macOS 算力へ移す。
| チーム規模・リズム | よくある着地 |
|---|---|
| 1–3 人、週次リリース | ホスト macOS + 強キャッシュ;Release は手動 Archive |
| 5–15 人、日次 merge | クラウド Mac セルフホスト 1–2 台 + PR/Release 分離 |
| 15+ 人、複数 App | App 別ラベルの Runner プール + 暖機 cron |
| Agent 修正が多い | 独立 bot プール + PR workflow への Archive 禁止 |
Apple 公式 xcodebuild ドキュメント は scheme と destination の一致を強調する。CI 環境が毎回 cold start なら「ローカルでは通る」は意味を失う。クライアントの言葉を借りれば:47 分の黄バーを毎日見るより、証明書ローテーションや Xcode メジャーアップグレードの方がマシだ、と。
最初の 1 台:クラウド Mac セルフホスト Runner から
Job ページが図 1 のように黄バーが緑を押しのけているなら、次に効く投資はたいてい専用 Apple Silicon クラウド Mac 1 台:GitHub セルフホスト Runner として登録し、PR ビルドを「キューくじ」から図 4 のような予測可能な 9 分へ。
2 週間の対照実験から:同一ブランチをホスト macOS とクラウド Mac セルフホストで各 50 回 build し、図 3 のような表を 1 枚書く。データが教えてくれる——遅いのは Xcode か、供給か。
予測可能なクラウド Mac 1 台から始め、Archive を Release ラインに戻す。 VPSSpark クラウド Mac プランを見る、 最初の iOS セルフホスト Runner を登録する。