雙佇列思維 · 標籤路由 · concurrency · 合併車道可驗收
在多台租用的遠端 Mac 上掛自架 Runner時,最常栽在「以為 Merge Queue 會替你排機器隊」:GitHub 側的合併佇列管的是變更進入預設分支的順序與安全閘,Runner 側的 backlog 仍然由標籤與併發組決定。本文用控制面分工表拆開兩道「佇列」,給出ci-pr/ci-merge/ci-release標籤路由、concurrency與cancel-in-progress的勾選規則,以及p95 排隊先改拓撲還是先調 GitHub 旋鈕的判準;並與共享建置池、並發席位互斥鎖、Mac Mesh 任務調度互相連結。
Merge Queue 解決的是主幹完整性:把多部併入預設分支的檢查編排成可循序推進的批次;它不替你保證遠端 Mac Runner 上永遠有空閒 CPU。若 PR 檢查與 merge 檢查共用同一組runs-on標籤,會出現「GitHub 認為可以推進合併,但 Runner 正在跑多條可選檢查」的錯位。
雙佇列誤讀:把 Actions 列表裡的「Queued」誤以為 Merge Queue 會自動抬高 merge 作業優先順序。
標籤混用:ci一類籠統標籤把 nightly、PR、merge 壓在同一台 Runner 上。
錯誤取消:在 merge lane 上啟用與 PR 相同的cancel-in-progress: true,批次中途被反覆沖掉。
併發組名碰撞:多倉或多 workflow 共用同一concurrency字串,互相誤殺。
觀測缺失:沒有區分「merge queue 等待時間」與「Runner 忙時佔比」,擴容談判缺少資料。
與 mesh 鎖衝突:合併車道需要穩定佔用節點時,未與切節點租約對齊。
提示:若你仍在比較本機與遠端分工而非 CI 控制面,請先讀本機輕編輯與遠端重編譯閾值文。
以下對照表用於審查會白板;「兩者兼顧」通常是預設起步點,前提是 Runner 容量誠實,而不是標籤自欺。
| 控制面 | GitHub Merge Queue | Runner backlog(機器佇列) |
|---|---|---|
| 管什麼 | 進入預設分支的順序、合併批次、required checks 語意 | 哪台 Mac 什麼時候執行哪條 workflow job |
| 不管什麼 | 你的 M4 有幾個空閒效能核心 | PR 是否「邏輯上該插隊」 |
| 典型失敗 | 批次反覆逾時(邏輯正確但算力不足) | merge job 長期 Queued 而 queue 很短 |
| 緩解第一刀 | 收緊 required checks、拆分批次假設 | 拆分runs-on標籤、加 Runner 或專席 Reserve |
合併是否「滑順」取決於 Runner 是否給 merge 留了名字誠實的容量,而不是 Merge Queue 開關本身。
self-hosted + macOS + ci-pr + 工具鏈版本(如 xcode-16-2)。ci-merge,由至少一台遠端 Mac Runner 承接。ci-release,與 merge 分開,避免發版巨型任務餓死 trunk。下列步驟可與共享池 SSH 編排文並行:舊文解決「能否連上 Runner」,本文解決「誰有權佔用哪條 CPU 時間線」。
盤點 required checks:把預設分支真正阻塞合併的檢查列成表,標註預計時長與是否可在 PR 階段前置。
拆分 runs-on:為 merge 專用 workflow 或 job 配上 ci-merge 標籤,實體上可由同一台機器註冊多標籤,但必須能預留時間區段或使用獨立節點。
檢查 concurrency:PR workflow 使用cancel-in-progress: true減少過時提交排隊;merge/release lane 使用cancel-in-progress: false或更窄的分組鍵。
命名 concurrency 組:包含 repo、workflow 名與環境後綴,避免組織內撞車。
埋點:至少在團隊看板區分 GitHub「merge queue 等待」與 Runner「busy minutes」兩類序列。
門禁覆盤:若一週出現兩次以上「queue 短但 merge job 長 Queued」,優先改 Runner 拓撲再討論 GitHub 並行度。
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 很閒 | required checks 或批次策略過嚴 | 審查 checks 圖與並行假設 |
| queue 很短,merge job 長期 Queued | 標籤路由或 Runner 數不足 | 拆 ci-merge、加節點或專席 |
| 批次頻繁失敗「基礎設施」 | 逾時、磁碟、鑰匙圈或網路抖動 | 對照 Runner 日誌與簽章治理清單 |
| PR 很快 merge 很慢 | PR 與 merge 爭用同一標籤 | 拆分 runs-on 並收緊 PR optional jobs |
注意:給 merge 加「更快機器」而不拆標籤,往往只是把飢餓推遲到發布夜;長期仍需獨立容量名。
下列區間為多國團隊常見立案核對經驗值;請把採集 SQL 或 API 欄位寫進內部 runbook。
ci-merge同名 Runner 時,busy 分鐘佔比若在工作時段高於 85%,應拆 nightly 到ci-pr池。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 與日常雜務拆到可命名節點上,並把可用性與席位策略落到維運條款,而不是口頭默契。