2026 年共享遠端 Mac 跑 GitHub Actions:
Merge Queue 與 Runner 標籤怎麼分工,才不讓「合併驗證」被 PR 雜務餓死

雙佇列思維 · 標籤路由 · concurrency · 合併車道可驗收

2026 GitHub Merge Queue 與遠端 Mac 自架 Runner

在多台租用的遠端 Mac 上掛自架 Runner時,最常栽在「以為 Merge Queue 會替你排機器隊」:GitHub 側的合併佇列管的是變更進入預設分支的順序與安全閘,Runner 側的 backlog 仍然由標籤與併發組決定。本文用控制面分工表拆開兩道「佇列」,給出ci-pr/ci-merge/ci-release標籤路由、concurrencycancel-in-progress的勾選規則,以及p95 排隊先改拓撲還是先調 GitHub 旋鈕的判準;並與共享建置池並發席位互斥鎖Mac Mesh 任務調度互相連結。

01

兩道「佇列」與六類痛點:為什麼 Merge Queue 開了仍會合併飢餓

Merge Queue 解決的是主幹完整性:把多部併入預設分支的檢查編排成可循序推進的批次;它不替你保證遠端 Mac Runner 上永遠有空閒 CPU。若 PR 檢查與 merge 檢查共用同一組runs-on標籤,會出現「GitHub 認為可以推進合併,但 Runner 正在跑多條可選檢查」的錯位。

  1. 01

    雙佇列誤讀:把 Actions 列表裡的「Queued」誤以為 Merge Queue 會自動抬高 merge 作業優先順序。

  2. 02

    標籤混用:ci一類籠統標籤把 nightly、PR、merge 壓在同一台 Runner 上。

  3. 03

    錯誤取消:在 merge lane 上啟用與 PR 相同的cancel-in-progress: true,批次中途被反覆沖掉。

  4. 04

    併發組名碰撞:多倉或多 workflow 共用同一concurrency字串,互相誤殺。

  5. 05

    觀測缺失:沒有區分「merge queue 等待時間」與「Runner 忙時佔比」,擴容談判缺少資料。

  6. 06

    與 mesh 鎖衝突:合併車道需要穩定佔用節點時,未與切節點租約對齊。

提示:若你仍在比較本機與遠端分工而非 CI 控制面,請先讀本機輕編輯與遠端重編譯閾值文。

02

控制面分工與標籤路由:什麼時候必須拆 ci-merge 車道

以下對照表用於審查會白板;「兩者兼顧」通常是預設起步點,前提是 Runner 容量誠實,而不是標籤自欺。

控制面GitHub Merge QueueRunner backlog(機器佇列)
管什麼進入預設分支的順序、合併批次、required checks 語意哪台 Mac 什麼時候執行哪條 workflow job
不管什麼你的 M4 有幾個空閒效能核心PR 是否「邏輯上該插隊」
典型失敗批次反覆逾時(邏輯正確但算力不足)merge job 長期 Queued 而 queue 很短
緩解第一刀收緊 required checks、拆分批次假設拆分runs-on標籤、加 Runner 或專席 Reserve

合併是否「滑順」取決於 Runner 是否給 merge 留了名字誠實的容量,而不是 Merge Queue 開關本身。

推薦標籤模式(可按團隊縮寫替換)

  • PR 雜務:self-hosted + macOS + ci-pr + 工具鏈版本(如 xcode-16-2)。
  • 合併車道:共用工具鏈版本標籤,但追加獨佔容量後綴ci-merge,由至少一台遠端 Mac Runner 承接。
  • 發版/封存:ci-release,與 merge 分開,避免發版巨型任務餓死 trunk。
03

六步 Runbook:把 merge 車道釘進 YAML 而不是群聊口頭約定

下列步驟可與共享池 SSH 編排文並行:舊文解決「能否連上 Runner」,本文解決「誰有權佔用哪條 CPU 時間線」。

  1. 01

    盤點 required checks:把預設分支真正阻塞合併的檢查列成表,標註預計時長與是否可在 PR 階段前置。

  2. 02

    拆分 runs-on:為 merge 專用 workflow 或 job 配上 ci-merge 標籤,實體上可由同一台機器註冊多標籤,但必須能預留時間區段或使用獨立節點

  3. 03

    檢查 concurrency:PR workflow 使用cancel-in-progress: true減少過時提交排隊;merge/release lane 使用cancel-in-progress: false或更窄的分組鍵。

  4. 04

    命名 concurrency 組:包含 repo、workflow 名與環境後綴,避免組織內撞車。

  5. 05

    埋點:至少在團隊看板區分 GitHub「merge queue 等待」與 Runner「busy minutes」兩類序列。

  6. 06

    門禁覆盤:若一週出現兩次以上「queue 短但 merge job 長 Queued」,優先改 Runner 拓撲再討論 GitHub 並行度。

yaml
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"
04

可觀測性與判準:先加 Mac 還是先改 GitHub 旋鈕

下列訊號來自常見工程覆盤口徑,請用自有資料替換閾值;關鍵是不要把兩類等待混在同一頁圖上

現象更可能根因第一動作
merge queue 很長,Runner 很閒required checks 或批次策略過嚴審查 checks 圖與並行假設
queue 很短,merge job 長期 Queued標籤路由或 Runner 數不足拆 ci-merge、加節點或專席
批次頻繁失敗「基礎設施」逾時、磁碟、鑰匙圈或網路抖動對照 Runner 日誌與簽章治理清單
PR 很快 merge 很慢PR 與 merge 爭用同一標籤拆分 runs-on 並收緊 PR optional jobs

注意:給 merge 加「更快機器」而不拆標籤,往往只是把飢餓推遲到發布夜;長期仍需獨立容量名。

05

可引用指標與決策底線(工程核對用)

下列區間為多國團隊常見立案核對經驗值;請把採集 SQL 或 API 欄位寫進內部 runbook。

  • merge job 佇列等待:連續兩個發布週內多次出現P95 大於 20 分鐘而 merge queue 深度穩定低於 3,優先檢查 Runner 標籤誠實度而非 GitHub 並行度。
  • PR 搶佔率:optional workflow 佔用ci-merge同名 Runner 時,busy 分鐘佔比若在工作時段高於 85%,應拆 nightly 到ci-pr池。
  • 取消風暴:若 merge lane 週報出現多於 1 次「被取消的合併驗證」,立即稽核concurrency是否與 PR 共用同一分組策略。
團隊規模主幹合併頻率推薦第一招
小團隊每日多次一台專用 ci-merge Runner + 嚴格 required checks
中型團隊持續有批次多區域 Runner + 明確定義的 release 池
平台化多倉共用池組織級標籤規範 + 成本看板拆分 queue vs runner

把筆電當「暫時 Runner」會引入休眠、溫控與不可稽核互動登入;自建機房 Mac 則要扛採購與多地佈線。兩者都難以把合併 SLO寫進可覆盤合約。

對需要iOS CI/CD 與 AI Agent 長任務共存的遠端 Mac 池,VpsMesh 的 Mac Mini 雲端租賃通常是更優解:可按區域與規格擴展 Runner Fleet,把 merge、release 與日常雜務拆到可命名節點上,並把可用性與席位策略落到維運條款,而不是口頭默契。

FAQ

常見問題

不強制「實體獨佔」,但必須誠實拆標籤與併發:否則 PR 雜務會餓死合併驗證。更穩妥是為 ci-merge 綁定固定席位或獨立節點;擴容路徑見價格頁訂購頁

PR 推送會產生自然過期的檢查;merge 批次若被反覆取消,會放大「已合併但自動化未閉環」的風險。把策略寫入 YAML 並在說明中心連結團隊 runbook,可降低誤配。

先讀共享建置池建立 SSH 與 Runner 註冊閉環,再用本文拆 merge 車道;席位鎖細節見併發鎖 TTL 文