Две очереди, один хост
Merge queue отвечает на вопрос: какой pull request может попасть в целевую ветку следующим и прошёл ли он проверки уже после перебазирования на актуальный main. Это снижает перекос слияний и поломку trunk на уровне Git. Метки runner отвечают на другой вопрос: какой физический или арендованный удалённый Mac имеет право выполнить job. Сами по себе метки не дают справедливости между репозиториями — они только фильтруют подходящие runner.
Когда активны оба механизма, наблюдаемая задержка часто упирается в пул runner: компиляция Xcode, архивы, Simulator и подпись — ресурсы одного хоста. Глубина merge queue может выглядеть здоровой, пока в Actions job копятся за узким набором меток. Поэтому материалы по коллаборации остаются актуальными: мультиузловая сетка Mac, Codespaces (SSH) против прямого узла. Базовую схему меток и разделения пулов см. в матрице маршрутизации runner и очередей.
Матрица: merge queue и маршрутизация меток
Выберите основной контрольный план. Зрелые команды обычно сочетают merge queue (trunk) с маршрутизацией по меткам (сборщики): строка «оба» — рекомендуемый дефолт для общего Mac CI при релизах чаще раза в неделю.
| Подход | Когда уместен | Главный риск | Смягчение на общем Mac |
|---|---|---|---|
| Сначала merge queue | Высокий темп слияний, жёсткая целостность default, много контрибьюторов в одну ветку. |
Дополнительные циклы CI на запись в очереди; ощущение «двойного ожидания» при перегруженных runner. | Ограничить параллельные сборки очереди, выровнять required checks, направить workflow очереди на метки ci-merge с выделенными хостами. |
| Сначала метки | Низкая частота merge, много вариантов toolchain или разных пинов Xcode. | Trunk всё ещё может ломаться из-за логических конфликтов, которые поймал бы merge queue. | Включить merge queue для ветки по умолчанию, оставить метки для изоляции Xcode/SDK. |
| Оба (масштаб) | Общий пул удалённых Mac для PR и trunk; релизам нужны предсказуемые слоты. | Разрастание политик — несовместимые таймауты или дубли ключей concurrency. |
Соглашения об именах групп concurrency, документировать вытеснение, зеркалить пороги в чеклисте ниже. |
| Только flock без дисциплины очередей | Один тяжёлый мьютекс (подпись) на машине. | Скрывает параллелизм на стороне GitHub; зависший замок блокирует чужие workflow. | Парить flock с настенными таймаутами и алертами; раньше добавить узлы, чем бесконечные критические секции. См. FAQ по очереди и flock. |
Чеклист параметров
Цифры ниже — стартовые базовые значения; подстраивайте по p95 длительности job, запасу диска и ограничениям подписи. Каждый параметр должен иметь владельца, запись в runbook и отображение в дашбордах.
| Параметр | Стартовая база | Заметки |
|---|---|---|
| Глубина / параллелизм merge queue | 1–2 одновременные сборки на пул при тяжёлом Xcode; до 3 только при запасе CPU и диска по метрикам. | Глубокий параллелизм умножает полные пересборки; сверяйте с аудитом неожиданного fan-out. |
| Алерт глубины очереди runner | Предупреждение примерно после 15–25 ожидающих job на набор меток; пейджинг после ~40. | Метки не создают fairness; алертите по времени ожидания (создание → назначение) по уровням SLA. |
| Метки runner (примеры) | self-hosted, macOS, arm64, xcode-16-2, ci-pr / ci-merge / ci-release. |
Отделите ci-merge от «шумных» PR-меток, чтобы job очереди слияний не голодали за опциональными проверками. |
concurrency в workflow |
group: ${{ github.workflow }}-${{ github.ref }} с cancel-in-progress: true для PR; false для релизных архивов. |
При необходимости общий mutex по репо добавьте группу уровня org/repo+trunk для шагов с общим ресурсом. |
Критическая секция flock |
Одна полоса подписи/нотаризации на связку ключей; файл замка в /var/tmp или документированном CI-томе. |
Всегда в паре с timeout; логируйте id держателя замка. Паттерны — в FAQ по очереди и замкам. |
timeout-minutes job |
PR-компиляция: 30–60; архив/экспорт: 90–120; перепроверка merge queue — как у PR, если дифф не микроскопический. | Короче — быстрее освобождаете зависшие worker; ориентир — p95, не лучший случай. |
Shell timeout (GNU/BSD) |
Сетевые вызовы: 120–300 с; загрузки: 300–600 с. | Зависший curl не должен держать runner до job timeout. |
| Правила вытеснения | PR < опциональный nightly < merge queue < релиз; не вытеснять держателей мьютекса подписи. | Кодируйте приоритет метками и concurrency; длинные job можно вешать на ручные метки. При политических конфликтах — балансировка и отказоустойчивость. |
Как совмещать политики на пуле Mac
Исходите из сигналов: медиана и p95 ожидания в очереди, минуты занятости runner, время до merge. Если merge queue короткая, а в Actions долго Queued, это топология runner — сначала узлы и метки, потом снова крутить GitHub-side concurrency.
Если merge queue длинная, а runner простаивают, проверьте required checks (целевые метки), фильтры веток для событий merge_group или org-level caps на concurrency, которые голодят только trunk. Сначала маршрутизация, потом замки.
Одна страница на пул: схема меток, имя merge queue, ключи concurrency, пути flock, таблица таймаутов и эскалация on-call — так командные тарифы с арендованными Mac остаются понятными между часовыми поясами без разбора YAML с нуля.
FAQ
- Должны ли job из merge queue использовать те же метки, что и PR?
- Общую метку toolchain (например
xcode-16-2) — да; общие «ёмкостные» метки с шумными опциональными workflow — нет. Выделите для очереди слияний и релиза суффиксыci-merge/ci-release. - Первая ручка, когда два репозитория борются за один Mac?
- Разнести runner по семейству репо или SKU, затем ужесточить
concurrency. Только после честной маршрутизации меняйте параллелизм merge queue — иначе задержка уйдёт в ревью без снятия конкуренции за железо.
Расширяйте пул, пока глубина очереди не бьёт по trunk
Откройте главную, каталог блога с коллаборационными материалами и страницу покупки тарифов — оформление доступно без логина. Справка по SSH/VNC для пулов сборщиков — в центре помощи.
Если метки честные, а ожидания всё ещё высокие, добавьте ёмкость: дополнительные узлы MeshMac или апгрейд командного пакета, чтобы полосы ci-merge и ci-release имели собственные CPU и диск, а не остатки после экспериментальных workflow.