二段キュー思考 · ラベルルーティング · concurrency · マージレーンの可観測性
複数台のレンタルしたリモートMacにセルフホストRunnerを載せるとき、「Merge Queueが機械側の行列まで整列してくれる」と誤解しやすいです。GitHub側のマージキューはデフォルトブランチへの統合順序と安全ゲートを担いますが、Runner側のバックログは依然としてラベルとconcurrencyグループ次第です。本文では制御面の分担表で二つの「キュー」を切り分け、ci-pr/ci-merge/ci-releaseのラベル設計、concurrencyとcancel-in-progressの扱い、p95待ちからMac追加とGitHub設定のどちらを先に触るべきかの判断まで整理し、共有ビルドプール、並列席ロック、Mac Meshタスクオーケストレーションと相互リンクします。
Merge Queueが守るのはデフォルトブランチの整合性です。複数PRを安全に順序付けして統合しますが、リモートMac Runnerに常に空きCPUがあることは保証しません。PR検証とマージ検証が同一のruns-onラベルを共有すると、「GitHub上はマージを進められるが、Runnerは任意のPRチェックを数本走らせている」というズレが起きます。
二段キューの誤読:Actionsの「Queued」を、Merge Queueがマージジョブ優先度を自動で上げると勘違いする。
ラベルの混線:ciのような曖昧ラベルにnightly・PR・mergeが同居する。
誤ったキャンセル:マージレーンでPRと同じcancel-in-progress: trueを使い、バッチ途中を何度も破棄する。
concurrency名の衝突:複数リポやworkflowで同一のconcurrency文字列を使い誤爆する。
観測の欠如:「merge queue待ち」と「Runner稼働率」を分けず、増設議論がデータ不足になる。
Meshロックとの衝突:マージレーンでノード占有を安定させるのにノードリースと揃えていない。
ヒント:まだノートPCとリモートの役割比較に留まりCI制御面まで降りていない場合は、先にローカル軽作業とリモート重コンパイルの閾値記事を読んでください。
次の対照表はレビュー会議用です。「両方やる」はRunner容量が正直な場合の出発点であり、ラベルでの自己欺瞞ではありません。
| 制御面 | GitHub Merge Queue | Runner backlog(機械キュー) |
|---|---|---|
| 管轄 | デフォルトブランチへの順序、マージバッチ、必須チェックの意味論 | どのMacがいつどのworkflowジョブを走らせるか |
| 管轄外 | M4に性能コアがいくつ空いているか | PRが論理的に割り込むべきかどうか |
| 典型失敗 | 論理は正しいが算力不足でバッチがタイムアウト反復 | queueは短いのにmergeジョブが長時間Queued |
| 最初の手 | 必須チェックとバッチ前提を締める | runs-onを分割しRunnerを増やすか専用席を確保 |
マージが滑らかかは、Merge Queueスイッチではなく、マージ用に正直な容量名をRunnerが確保できているかで決まります。
self-hosted + macOS + ci-pr + ツールチェーン版(例 xcode-16-2)。ci-mergeを付与し、少なくとも1台のリモートMac Runnerが受ける。ci-releaseをmergeから分離し、巨大ジョブがtrunkを飢餓させないようにする。次の手順は共有プールSSH記事と併走します。旧文が「Runnerに届くか」、本文が「どのCPU時間軸を誰が占有するか」を扱います。
必須チェックの棚卸し:デフォルトブランチで実際にマージを止める検証を表にし、所要時間とPR段階へ前倒し可否を書く。
runs-onの分割:マージ専用workflowまたはジョブへci-mergeを付与。同一物理機に複数ラベルは可だが、時間帯予約または専用ノードが必須。
concurrencyの確認:PR側はcancel-in-progress: trueで古いコミット検証を削ぎ、merge/release側はcancel-in-progress: falseかより狭いキー。
concurrencyグループ命名:リポジトリ、workflow名、環境接尾辞を含め組織内衝突を防ぐ。
計測:チームボードでGitHubの「merge queue待ち」とRunnerの「busy分」を別系列で見る。
ゲート振り返り:週に2回以上「queueは短いのにmergeジョブが長Queued」なら、GitHub並列議論の前にRunnerトポロジを変える。
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
merge-gate:
runs-on: [self-hosted, macOS, ci-merge, xcode-16-2]
timeout-minutes: 45
steps:
- run: echo "merge lane only"
以下はよくあるインシデントレビュー口径です。閾値は自社データに置換してください。重要なのは二種類の待ちを同一グラフに混ぜないことです。
| 現象 | 想定原因 | 第一動作 |
|---|---|---|
| merge queueは長いがRunnerは遊んでいる | 必須チェックまたはバッチ戦略が厳しすぎる | チェックグラフと並列前提をレビュー |
| queueは短いがmergeジョブが長時間Queued | ラベル経路またはRunner台数不足 | ci-mergeを分離しノード/専用席を追加 |
| バッチがインフラ失敗を繰り返す | タイムアウト、ディスク、キーチェーン、ネット揺らぎ | Runnerログと署名ガバナンス照合 |
| PRは速いがmergeが遅い | PRとmergeが同一ラベルで奪い合う | runs-on分割とPR任意ジョブの整理 |
注意:ラベルを分けずにマージ向けに「速い機械」だけ足すと、飢餓はリリース夜へ先送りされがちです。長期はやはり別の容量名が要ります。
以下は多拠点チーム向けのざっくり目安です。取得SQLやAPIフィールドを社内Runbookに落としてください。
ci-merge同名Runnerを握るとき、営業時間のbusy分が85%超ならnightlyをci-prへ寄せる。| チーム規模 | trunkマージ頻度 | 推奨の第一手 |
|---|---|---|
| 小規模 | 1日複数回 | 専用ci-merge Runner1台+厳格な必須チェック |
| 中規模 | バッチが途切れない | 多地域Runner+明示的releaseプール |
| プラットフォーム化 | 複数リポで共有プール | 組織ラベル規範+queue対runnerのコストボード分割 |
ノートPCを「仮Runner」にするとスリープ・熱・監査不能な対話ログインが混ざります。自前コロケMacは調達と配線の負債になります。いずれもマージSLOを契約として追跡しにくいです。
iOS CI/CDとAIエージェント長時間タスクを同居させるリモートMacプールでは、VpsMeshのMac Miniクラウドレンタルがしばしば最適解です。リージョンとスペックでRunner Fleetを伸ばし、merge・release・日常雑務を名前付きノードに載せ、可用性と席ポリシーをチャットの暗黙知ではなく運用条項へ落とせます。
PRは新コミットで古い検証が自然失効します。マージバッチを繰り返し打ち切ると、統合済みだが自動化が閉じないリスクが膨らみます。方針をYAMLに書き、ヘルプセンターからRunbookへリンクして誤設定を減らしてください。
まず共有ビルドプールでSSHとRunner登録を閉じ、本文でマージレーンを分割してください。席ロックの詳細はmutex TTL記事を参照してください。