VPSSpark ブログ
← 開発日記に戻る

GitHub Actions が iOS 開発を遅くしている——2026年に効いた Xcode CI の現実解

サーバールーム手記 · Cloud Mac CI #9 · 2026.06.12 · 約12分
現場メモ:47分キュー、パイプライン分離、Cloud Mac 自ホステッド、Agent ガードレール

検索例:GitHub Actions iOS 遅い · Xcode CI キュー · 自ホステッド macOS runner · Cloud Mac

MacBook のエディタとターミナル——GitHub Actions の Xcode CI を調査する iOS チーム
木曜15時の Slack——「まだ Queued」——多くの iOS チームが見慣れた光景。

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 ライン、また詰まってる。」

Slack #ios-ci チャンネル実録:開発者が Queued 47 分を報告、Release 担当が Archive による PR ライン詰まりを指摘
図 5 · Slack #ios-ci 実録抜粋(リポジトリ・組織名はマスク、時刻と数値はそのまま)

以下のスクリーンショットはトラブルシュート支援時にクライアントから提供された資料(マスク済み)。数値は加工していません。GitHub 公式ドキュメントの Job 実行時間と queue_wait_seconds を参照すれば、同じ統計を自分で再現できます。

このチームは 2 本のアプリをモノレポで運用し、CI はすべて GitHub ホスト macOS Runner 経由。2025 年までは我慢できた。2026 年春になると、フィードバックループが耐えられないほど伸びた。GitHub Actions 自体は「壊れている」わけではない——iOS チームにとっては、ピーク時に必ず渋滞する共有シャトルのように感じられるようになっていた。

2832s
queue_wait_seconds
724s
run duration
3.9×
queued / run 比

あの木曜:Job ページを開くと、黄バーが緑の 4 倍

Run #18472910356 の Job ページのスクリーンショットが届いた——口頭の報告ではなく、タイムライン付きの実録だ。黄バー(Queued)47 分 12 秒、緑バー(Run)12 分 4 秒。画面下部には queue_wait_seconds: 2832run duration: 724。式は単純で刺さる:wait time >> run time

GitHub Actions Job タイムライン:Queued 47m12s、Run 12m4s、run 18472910356
図 1 · Run #18472910356 · ios-pr.yml · macos-latest · 2026-05-29 15:04 CST

当時チームは -jobs 並列化や DerivedData キャッシュキーの変更を会議で議論していた——それなのに、直近 10 件の macOS job の queued / run 列を誰も集計していなかった。Release ラインはさらに窮屈:ios-release.ymlxcodebuild 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_srun_s。queued の中央値 2650 秒、run 724 秒。比は最大 4.5×。会議室が数秒静まった:「Xcode 17.4 のせいでは?」という話は出なくなった。

failed macOS job 10 件の queued_s と run_s 手書き統計表
図 3 · 2026-05-22 — 05-29 failed macOS job 10 件手書き表(匿名化)
よくある誤解図 3 のシグナルより有力な原因
GitHub 障害10/10 で queued_s > run_smacOS 同時実行 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 がループ化したあとに起きること を参照。

Pull Request #847 上の GitHub Actions workflow 実行 6 件
図 2 · PR #847 · 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 回)

ホスト macOS · queued
38 min
ホスト macOS · run
12 min
クラウド Mac セルフホスト · queued
41 s
クラウド Mac セルフホスト · run
9 min

データソース:クライアント対照実験ログ(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 チームにとって、それが最高の称賛だ。

GitHub Actions セルフホスト Runner:Queued 41s、Run 9m17s、cloud-mac
図 4 · Run #18510488201 · self-hosted, cloud-mac · 2026-06-09 09:11 CST

Agent に柵を:Wiki に書いた 4 条

パイプライン分離で Archive による PR 詰まりは解消。bot ループは別問題。チームは bot 専用ブランチと低優先 Runner プールを設け、人が review してから merge する方針に。4 条のハードルールを Wiki に明文化した:

  • PR workflow で Archive / ストアアップロードを禁止
  • macOS job に concurrency を必須化し、同一ブランチの重複実行を防止
  • セルフホスト Runner はラベル必須。実験 workflow とプール混在禁止
  • Agent の自動 push は独立ブランチのみ。保護ブランチへの直接 push 禁止
30 分でできるセルフチェック
直近 10 件の macOS job を開き、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+ 人、複数 AppApp 別ラベルの 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 を登録する。

期間限定

iOS CI がずっと Queued? Cloud Mac で自ホステッド Runner

GitHub Actions · Apple Silicon 専用 · PR/Release 分離

ホームへ
期間限定 プランを見る