Две очереди · Маршрутизация лейблов · Concurrency · Наблюдаемость полосы merge
Запуская self-hosted runner на нескольких арендованных удалённых Mac, часто ошибаются, думая, что Merge Queue распределяет машинную очередь: очередь GitHub управляет порядком и защитными воротами в ветку по умолчанию, но backlog runner по-прежнему задают лейблы и группы concurrency. Статья разделяет две очереди таблицей контрольной плоскости, рекомендует маршрут ci-pr / ci-merge / ci-release, правила concurrency и cancel-in-progress, критерии p95 для добавления Mac или настройки GitHub; ссылки на общий пул сборки, мьютекс мест и оркестрацию Mac Mesh.
Merge Queue защищает целостность ветки по умолчанию: батчирует проверки перед интеграцией; она не гарантирует свободные CPU на удалённых Mac runner. Если PR и merge делят одни runs-on лейблы, GitHub может двигать слияния, пока runner занят опциональными PR.
Путаница очередей: \"Queued\" в Actions принимают за автоматический приоритет merge-джобов.
Смешение лейблов: размытый ci сваливает nightly, PR и merge на одни runner.
Плохие отмены: тот же cancel-in-progress: true на полосе merge, что и у PR, рвёт батчи.
Коллизии concurrency: несколько репо делят одну строку concurrency и гасят друг друга.
Слабая наблюдаемость: не разделяют ожидание merge queue и занятость runner.
Расхождение с mesh lease: полосе merge нужна стабильная занятость узла без порогов аренды.
Подсказка: если вы всё ещё сравниваете ноутбук и удалённый ролью, а не CI-плоскостью, сначала прочитайте лёгкое локальное редактирование и тяжёлые удалённые сборки.
Таблица ниже для ревью: делать оба имеет смысл только при честной ёмкости runner, а не театре лейблов.
| Плоскость | GitHub Merge Queue | Backlog runner (машинная очередь) |
|---|---|---|
| Отвечает за | Порядок в default branch, батчи merge, семантику required checks | Какой Mac когда выполняет какой workflow job |
| Не отвечает за | Сколько ядер M4 свободно | Должен ли PR логически обойти очередь |
| Типичный сбой | Батчи таймаутятся при верной логике, но нехватке CPU | Merge job днями в очереди при короткой merge queue |
| Первый шаг | Ужать required checks и допущения батчей | Разделить runs-on, добавить runner или резерв мест |
Гладкость merge зависит от честно зарезервированной ёмкости 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: что реально блокирует default branch, длительности, что можно поднять в PR.
Разделить runs-on: merge-only workflow или job получают ci-merge; одна машина может иметь много лейблов, но нужны слоты или выделенные узлы.
Проверить concurrency: PR с cancel-in-progress: true; merge/release с cancel-in-progress: false или более узкими ключами групп.
Именовать группы concurrency: репозиторий, workflow и суффикс среды.
Инструментировать: на доске раздельно ожидание merge queue и busy minutes runner.
Разбор ворот: дважды в неделю короткая очередь, но merge job висит — сначала топология 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 и допущения параллелизма |
| Короткая очередь, merge job долго в queue | Маршрут лейблов или мало runner | Разделить ci-merge, добавить узлы или места |
| Батчи падают как инфра | Таймауты, диск, связка ключей, сеть | Сверить логи runner с чеклистом управления подписями |
| Быстрые PR, медленные merge | PR и merge делят лейблы | Разделить runs-on, урезать опциональные PR jobs |
Внимание: более быстрые машины без разделения лейблов часто отодвигают голодание на ночи релиза; долгосрочно нужны отдельные имена ёмкости.
Диапазоны — типичные опоры для распределённых команд; привяжите SQL или поля API к внутреннему runbook.
ci-merge и busy минут > 85 % в рабочее время — nightly в пул ci-pr.concurrency.| Размер команды | Частота merge trunk | Первый ход |
|---|---|---|
| Малая | Несколько раз в день | Выделенный ci-merge runner + жёсткие required checks |
| Средняя | Непрерывные батчи | Мультирегион runner + явный release pool |
| Платформа | Общий пул на много репо | Орг-стандарт лейблов + cost board queue vs runner |
Ноутбук как временный runner даёт сон, термику и слабо аудируемый интерактивный вход; своя стойка Mac — закупка и кабель. Оба плохо для договорного merge SLO.
Для пулов удалённых Mac, где iOS CI/CD и длинные задачи AI-агентов сосуществуют, облачная аренда Mac Mini VpsMesh обычно лучше: масштабируйте флот по региону и SKU, разнесите merge, release и шум на именованные узлы, закрепляйте доступность и политику мест в договоре, а не в чате.
Не обязательно отдельный физический корпус, но нужно честно разделить лейблы и параллелизм, иначе PR-шум голодает merge-проверки. Надёжнее привязать ci-merge к фиксированным местам или узлам. Масштаб: страница цен и страница оформления заказа.
Push PR естественно устаревают проверки; повторная отмена merge-батчей увеличивает риск «уже влито, но автоматика не замкнулась». Фиксируйте политику в YAML и ведите runbook из центра помощи.
Сначала общий пул сборки для SSH и регистрации runner, затем эта статья для полосы merge; детали блокировок мест в статье про mutex TTL.