На ревью миграции руководство задаёт один вопрос: «Если уйти с GitHub Actions на собственные Mac-узлы — насколько вырастет эффективность разработки?» Ответ «сборка чуть быстрее» редко убеждает. В 2026 мы проводили A/B с несколькими iOS-, Flutter- и React Native-командами: после перехода на self-hosted Mac (офисный Mac mini, bare metal или Cloud Mac с runner) главный выигрыш — не компилятор, а исчезновение очереди и ожидания. Ниже — четыре типа метрик, три реальных сравнительные таблицы, двухнедельный чеклист миграции и грубый ROI.
Quick Answer: насколько быстрее?
| Что важно | Hosted macOS runner (до) | Собственный Mac-узел (после) | Типичный выигрыш |
|---|---|---|---|
| PR до зелёной галочки (end-to-end) | 42–68 мин | 9–16 мин | ~70–80% короче |
| Ожидание в очереди | 15–45 мин/запуск | 0–2 мин | почти ноль |
| Один Archive-build | 11–14 мин | 8–11 мин | ~15–25% (с кэшем) |
| Сборок TestFlight за релизную ночь | 1–2 | 3–5 | пропускная способность ~2–3× |
| Пассивное ожидание/нед/разработчик | 3–6 чел·ч | 0,5–1,2 чел·ч | ~75% меньше |
Коротко: главный рост — в ожидании, а не в «ускорении компилятора». Собственный узел выводит дефицитный macOS-пул из shared queue; плюс персистентный DerivedData — и получаются цифры из таблицы.
Сначала мерить, потом говорить «насколько»
После миграции многие говорят «почти не быстрее», потому что смотрят только job duration в GitHub Actions и игнорируют queue time и ожидание в Slack. Две недели до и после — минимум четыре показателя:
- Очередь: секунды от
job queuedдоjob started, P50 / P95 - PR-цикл: последний push до всех required checks зелёные
- Пропускная способность релиза: успешные загрузки TestFlight в фиксированном 4-часовом окне
- Пассивное ожидание: опрос «сколько ждали CI сегодня» или метки времени в PR
Экспорт: GitHub API run_started_at минус created_at; или шаг workflow, пишущий секунды очереди в artifact. Без baseline ROI руководству доказать сложно.
| Метрика | Как собирать | Сигнал успеха после миграции |
|---|---|---|
| Queue P95 | Actions API / свой step | с >20 мин до <3 мин |
| PR feedback P50 | Метки времени PR | снижение >50% |
| Hit rate кэша | Размер DerivedData + лог сборки | с <20% до >60% |
| Частота сбоев при параллелизме | Доля падений при нескольких job на одной машине | после изоляции каталогов <2% |
Три команды: до и после миграции
Все три набора — реальные проекты (анонимно), тот же репозиторий, та же мажорная версия Xcode, две недели будних дней.
Кейс A: iOS-команда 12 человек, одно приложение + extensions
До: всё на macos-14; после: 2× M4 16 ГБ Cloud Mac как self-hosted runner, DerivedData на локальном NVMe. ~18 PR/день.
| Метрика | До | После | Изменение |
|---|---|---|---|
| PR feedback P50 | 52 мин | 11 мин | −79% |
| Queue P95 | 38 мин | 0,8 мин | −98% |
| Archive разово | 12,4 мин | 9,1 мин | −27% |
| TestFlight/ночь | 1,5 | 4 | +167% |
Tech Lead дословно: «Раньше push в пять — merge только в пол-седьмого; сейчас наливаю воду — PR уже зелёный».
Кейс B: 28 человек, KMP + Android-основной репо, Mac только для iOS-оболочки
До: macOS- и Android-job в одном релизном окне; после: 1× постоянный M4 Pro + 2 burst Cloud Mac в релизную неделю (см. playbook burst-релизов).
| Метрика | До | После | Изменение |
|---|---|---|---|
| Dual-platform PR зелёный P50 | 71 мин | 24 мин | −66% |
| Суммарная queue/день в релизную неделю | 6,2 ч | 0,4 ч | −94% |
| Ожидание/нед (опрос) | 4,8 чел·ч | 1,1 чел·ч | −77% |
Кейс C: indie 8 человек, 2 релиза в месяц
Контрпример: почти без выигрыша — мало PR, очереди нет, зато обслуживание keychain на своей машине. Archive лишь 10,2 → 9,4 мин (−8%), queue и так ~0. «Насколько» сильно зависит от профиля нагрузки.
Откуда рост: очередь, кэш, параллелизм
Разбейте общее ожидание — так проще объяснить нетехническим stakeholders:
PR total ≈ очередь + подготовка среды + сборка/тесты + upload
1. Очередь (самый большой блок): macOS pool GitHub общий; в релизную или Xcode-upgrade неделю P95 30+ мин — норма. Свой узел = выделенный executor, queue почти исчезает.
2. Cold start и кэш: hosted job уничтожается — DerivedData, Pods, SwiftPM каждый раз заново. Персистентные тома на своих машинах: вторая сборка часто ~20% быстрее; подробнее в FAQ по кэшу и диску self-hosted runner.
3. Параллелизм: 2–3 Mac на matrix-job — релизная ночь не «вереница». На одном хосте — изоляция каталогов, иначе flakiness съест выигрыш.
| Фаза | Hosted runner типично | После своих узлов |
|---|---|---|
| Очередь | 45–70% | <5% |
| Распаковка deps / индекс | 15–25% | 5–10% (персистентный кэш) |
| Чистая сборка/тесты | 20–35% | 15–30% |
Двухнедельный путь: сначала сравнение, потом трафик
Переключать прод в пятницу вечером — плохая идея. Воспроизводимый ритм:
- Дни 1–2: экспорт двух недель queue/duration из Actions; 1× Cloud Mac (~5 мин), runner,
runs-on: [self-hosted, macos, canary]только вручную - Дни 3–5: персистентные
~/ci/DerivedDataи SwiftPM; один и тот же commit main — A/B по 5 раз, P50 - Дни 6–8: release/nightly 50% на self-hosted label; hosted как fallback
- Дни 9–10: все PR required checks на self-hosted; порог диска 80% и cron очистки артефактов
- Дни 11–14: сводная таблица, ROI для руководства; решение: 1 постоянная машина или burst по дням
Оркестрация остаётся в GitHub Actions — YAML, permissions, environment protection без смены платформы, меняется только runs-on. Та же логика, что в корпоративном Mac CI pool: разделить оркестрацию и исполнение.
Минимальное изменение workflow
jobs:
ios-build:
# До: runs-on: macos-14
ios-build:
runs-on: [self-hosted, macos, ios-pool]
steps:
- uses: actions/checkout@v4
- name: Log queue metrics
run: echo "QUEUE_SEC=${QUEUE_SEC:-0}" >> $GITHUB_STEP_SUMMARY
Ещё не решили про железо? Аренда M4 Cloud Mac по дням на две недели сравнения — часто дешевле, чем час простоя всей команды.
Грубый ROI: перекрывает ли эффективность стоимость машин?
На примере кейса A (ставка blended $55, иллюстрация):
- 12 человек × 3,7 ч меньше ожидания/нед ≈ 44 чел·ч/мес ≈ $2 420/мес эквивалентного output
- 2× M4 16 ГБ Cloud Mac ≈ $206/мес ($103×2, по странице тарифов)
- Ops платформы ≈ 4–8 чел·ч/мес (диск, сертификаты, upgrade runner)
Чистый результат часто положительный — у малых команд с редкими сборками (кейс C) может не сойтись. Подставьте свой queue P95:
выигрыш/мес ≈ разработчики × меньше ч ожидания/нед × 4 × ставка − аренда − ops ч × ставка
В релизную неделю — третья машина burst, в спад — отказ. Долгий TCO покупка vs аренда: купить Mac mini или арендовать Cloud Mac.
Когда лучше не мигрировать
В этих случаях советую подождать или арендовать на неделю для проверки:
- <30 macOS job/мес и queue P95 стабильно <5 мин — потолок низкий (кейс C)
- Некому on-call обслуживать runner — полный диск хуже очереди
- Compliance: машина только в своей VPC — сначала сеть и secrets
- Ожидание «без GitHub Actions» — оркестрация, audit, permissions всё ещё ценны
Миграция — средство; цель — измеримо меньше ожидания. Если за две недели сравнения нет >30% улучшения PR-цикла — сначала оптимизируйте workflow (split job, реже archive), а не покупайте три Mac.
FAQ
Насколько обычно растёт эффективность?
У частых iOS-сборок часто ~70% короче PR-цикл и очередь почти ноль; чистая компиляция +15–25%. Редкие сборки — часто однозначные проценты; сначала baseline.
Хватит ли одного Mac?
Для <10 человек и серийных релизов обычно да; при matrix или нескольких app — от 2, с лимитом concurrency против конфликтов кэша.
Уменьшится ли счёт Actions?
macOS-минуты часто −60–90% (сколько job перенесли); растут аренда и ops. Смотреть суммарно с ROI выше.
Cloud Mac vs офисный Mac mini?
Один chip/RAM — близкое время сборки. Разница: RTT (deps, upload) и NVMe. Узел ближе к хостингу кода и registry артефактов.
Подпись и notarization?
Сами по себе не улучшаются — но стабильная среда снижает drift keychain/provisioning и «только в CI» ночные пожары.
Когда виден эффект?
Runner + каталог кэша: первый рабочий день в метриках queue; PR-цикл — две недели измерений перед отчётом.
Итог и дальнейшее чтение
Миграция с GitHub Actions на собственные Mac-узлы: ответ не «намного быстрее». Типичные iOS-команды видят ~70% короче PR и ~2× пропускную способность релиза — главная доля исчезновение очереди, затем персистентный кэш. Двухнедельное сравнение, четыре метрики и ROI дают цифры для руководства; без явного эффекта сначала workflow, не железо.