Начните не с числа разработчиков, а с пикового числа одновременно занятых Job, длительности каждого задания, допустимого времени ожидания и требований к изоляции релиза. Для проекта с редкими коммитами обычно достаточно одного Mac; если Build, Test и публикация регулярно пересекаются — проверяйте второй Runner или временное расширение на период релиза.
Эта схема рассчитана на независимого разработчика, который уже использует GitHub Actions self-hosted runner и не понимает, выдержит ли один удалённый Mac. Она также подходит небольшой команде, которой нужно запускать Pull Request-проверки параллельно с TestFlight. Руководителям проектов с короткими, но резкими релизными пиками материал поможет сравнить постоянную ёмкость с арендой Mac на нужный период.
Единица расчёта: Job, а не разработчик
GitHub Actions разделяет Workflow, Job и Runner. Workflow описывает процесс целиком. Job — отдельное задание внутри этого процесса. Runner — среда, которая получает Job и выполняет его. Mac — физический хост, на котором работает Runner. Xcode, симулятор и внутренние параллельные задачи могут дополнительно использовать ресурсы того же хоста.
Это различие влияет на расчёт. Десять разработчиков не означают автоматически десять Mac. И наоборот, один разработчик может создать конкуренцию, если одновременно открыты функциональная ветка, ночной Test, повторная проверка после исправления и Archive для TestFlight.
В рабочей истории нужно отделить:
- Build для быстрой проверки исходников;
- Test с симулятором или несколькими схемами;
- Archive для подписываемого релизного артефакта;
- операции подписи и загрузки;
- последующую обработку сборки на стороне App Store Connect;
- ожидание внешних сервисов, которое не занимает Runner.
Для маршрутизации GitHub Actions использует метки и требования Job к среде. Поэтому два задания с одинаковой меткой могут попасть на один доступный Runner, если остальные условия совпадают. Правила выбора среды описаны в официальной документации GitHub по Runner для Job, а механизм меток — в документе о применении labels.
Не смешивайте продолжительность Archive с обработкой загрузки. Пока App Store Connect принимает или обрабатывает артефакт, Mac может уже выполнять следующий Job. Для проверки этой границы используйте инструкцию Apple по загрузке сборок в App Store Connect.
История очереди вместо среднего показателя
Средняя загрузка вводит в заблуждение. Один Runner может простаивать большую часть рабочего дня и всё равно создавать очередь в момент публикации. Поэтому фиксируйте не только среднее время выполнения, но и худшие наблюдаемые периоды.
Для каждого Job соберите следующие поля:
- имя Workflow без названий продукта и приватных путей;
- тип задания: Build, Test, Archive или Upload;
- время постановки в очередь;
- начало выполнения;
- завершение;
- результат и причина повторного запуска;
- выбранные метки Runner;
- версия Xcode;
- наличие симулятора;
- скачивание зависимостей;
- факт отмены устаревшего запуска.
В GitHub Actions доступны сведения о времени выполнения и ожидания, а организация может использовать Actions metrics для анализа производительности. В качестве источника используйте официальное описание метрик Actions. Для событий workflow_job полезна явная последовательность состояний queued, in_progress и completed; она приведена в документации GitHub по webhook-событиям.
Если организация не предоставляет нужные агрегированные показатели, сохраните историю запусков, выгрузите логи и добавьте собственную таблицу наблюдений. Для небольшого репозитория этого достаточно, если записи не смешивают разные типы Job.
Расчёт можно выразить так:
время ожидания = время начала выполнения − время постановки в очередь
время занятости Runner = время завершения − время начала выполнения
пиковая конкуренция = максимальное число Job,
которые одновременно находятся в состоянии выполнения
Не подставляйте в формулу время, когда сервис обработки сборки уже не использует Mac. Иначе базовая ёмкость окажется завышенной.
Xcode также записывает данные о длительности этапов сборки. Сверяйте историю CI с документацией Apple о Build Timing Summary. Для тестов отдельно анализируйте результаты и ошибки через руководство Apple по запуску и интерпретации тестов.
Профили нагрузки по аудитории
Независимый разработчик с низкой частотой запусков
Для одного приложения начинайте с одного Mac, если обычные коммиты не создают устойчивую очередь, тестовая матрица ограничена, а Archive можно запускать после завершения обычных проверок.
Здесь важнее порядок Workflow, чем покупка второго хоста:
- обычному Build назначьте базовый приоритет;
- Test запускайте только на изменениях, которые действительно требуют проверки;
- релизный Archive отделите от быстрой проверки;
- для устаревших запусков включите отмену, если новый коммит делает старый результат бесполезным;
- публикацию не связывайте с каждым промежуточным коммитом.
GitHub Actions поддерживает управление конкуренцией и отмену устаревших запусков. Настройки описаны в официальном руководстве по concurrency.
В этом профиле второй Mac нужен только при подтверждённой причине: регулярной очереди, обязательном резерве или невозможности остановить релизный Job ради тестов. Низкая средняя загрузка не является аргументом против одного Runner, если пиковая очередь остаётся приемлемой.
Независимый разработчик с частыми сборками
Ситуация меняется, когда один человек одновременно поддерживает несколько веток, исправляет ошибки после TestFlight и запускает повторные проверки. В этом случае один Mac может быть достаточен по общей мощности, но недостаточен по времени отклика.
Сначала устраните ложную конкуренцию:
- не устанавливайте зависимости заново в каждом Job без необходимости;
- проверьте, не запускается ли один и тот же тестовый набор дважды;
- отменяйте устаревшие проверки ветки;
- отделите быстрый Build от полного симуляторного Test;
- не запускайте Archive автоматически на каждый коммит.
После этого сравните три действия. Первое — перестроить Workflow. Второе — добавить второй Runner. Третье — арендовать дополнительный удалённый Mac только на релизный период.
Второй хост не обязан ускорить один Job. Его ценность — в одновременном выполнении независимых Job и в возможности продолжить работу при обслуживании первого Mac. Если очередь возникает внутри одного тяжёлого Xcode Job, сначала исследуйте этапы Build и Test, а не количество хостов.
Небольшая команда с общим Runner
Для команды основным критерием становится не отсутствие очереди, а допустимое время обратной связи по Pull Request. Быстрые проверки должны получать среду раньше длинных тестов и релизных операций.
Разделите маршрутизацию:
- метка для обычной проверки;
- метка для симуляторных тестов;
- отдельная метка для Archive и подписи;
- при необходимости отдельная Runner Group для производственного доступа.
Сертификаты, provisioning profile, ключи и переменные окружения нельзя считать просто ещё одним ресурсом. Если тестовый Job получает доступ к тем же секретам, что и публикация, добавление второго Mac не решает проблему изоляции.
В этой модели два Mac часто полезнее одного, когда обычный Test способен заблокировать Archive. Однако решение должно пройти проверку: очередь снизилась, релиз не зависит от завершения тестового пула, а остановка одного хоста не делает публикацию невозможной.
Несколько приложений и фиксированное окно релиза
Если несколько репозиториев используют общий macOS Runner, считайте нагрузку по типу работы и уровню риска. Нельзя ставить все Workflow под одну универсальную метку и затем объяснять длинную очередь «нехваткой мощности».
Разделите контуры:
- разработческий — Build и стандартные Test;
- тестовый — тяжёлые симуляторные сценарии;
- производственный — Archive, подпись и загрузка;
- резервный — среда для восстановления после отказа или обновления.
Здесь применимы три модели. Постоянная базовая ёмкость подходит при регулярной нагрузке. Постоянный пул плюс временный Mac подходит при резких релизных окнах. Полностью отдельный релизный Runner оправдан, если подпись и публикация должны быть доступны независимо от текущих тестов.
Перед арендой дополнительной среды зафиксируйте версию Xcode, список инструментов, сертификаты, Bundle ID, Team ID, пути к кешам и способ восстановления. Для Xcode 27 особенно важно не считать совпадение имени версии доказательством одинаковой среды: проверьте SDK, зависимости и скрипты проекта.
Пошаговая проверка перед расширением
Выполните действия в таком порядке. Каждый результат сохраните в обезличенной таблице.
- [ ] Отделите Workflow от входящих в него Job и перечислите Build, Test, Archive и Upload.
- [ ] Запишите для каждого типа момент постановки в очередь, старт, завершение и результат.
- [ ] Отдельно отметьте Job, которые были отменены, повторены или завершились из-за недоступности Runner.
- [ ] Проверьте, где заканчивается занятость Mac и начинается обработка App Store Connect.
- [ ] Сопоставьте Job с метками Runner, версией Xcode, симулятором и доступом к секретам.
- [ ] Включите отмену устаревших проверок там, где старый результат уже не нужен.
- [ ] Проверьте повторную установку зависимостей и дублирование тестов.
- [ ] Измерьте пиковое число одновременно выполняющихся Job, а не только среднее число запусков.
- [ ] Смоделируйте остановку текущего Mac и проверьте, может ли релиз перейти на другой Runner.
- [ ] Для временного расширения проверьте доставку среды, установку инструментов и восстановление после отключения.
- [ ] Сравните получившуюся очередь с допустимым временем обратной связи для Pull Request и релиза.
- [ ] Зафиксируйте условие остановки: оптимизация Workflow, постоянный второй Mac или аренда только на период публикации.
Важно: несколько процессов внутри Xcode не равны нескольким независимым Runner. Не объявляйте Mac «параллельным» только потому, что один Job использует внутреннюю параллельность тестов.
FAQ для выбора Runner
Один Mac и несколько iOS Job
Один Mac может выполнять параллельные процессы внутри задания, но независимые Job требуют отдельной проверки маршрутизации и ресурсов. Если два Job используют один рабочий каталог, симулятор, кеш или набор ключей, формальная доступность Runner не гарантирует безопасную конкуренцию.
Один удалённый Mac для независимого разработчика
Для низкочастотного проекта один Mac — разумная стартовая конфигурация. Она подходит, если обычные проверки не блокируют публикацию, а релизные задачи можно перенести на отдельное окно. Решение пересматривается после появления повторяющейся очереди, а не после достижения условного числа коммитов.
Расчёт по времени ожидания
Сначала разделите очередь и выполнение. Затем группируйте данные по типу Job. Если очередь возникает только во время релиза, считайте временную ёмкость. Если она сохраняется в обычном цикле разработки, сначала оптимизируйте Workflow, затем проверяйте второй Runner.
Разделение тестов и Archive
Один Mac возможен при низкой конкуренции и строгом контроле секретов. Отдельные среды предпочтительнее, когда тесты длинные, релиз срочный, версии Xcode различаются или производственные ключи не должны находиться в общем контуре.
Временный Mac на период публикации
Временная аренда оправдана при предсказуемом релизном пике. До начала окна проверьте одинаковость toolchain, маршрутизацию по меткам и процедуру восстановления. Если среду приходится поднимать почти постоянно, сравните её с постоянным вторым Runner.
Карта решений: один Mac, два или временное расширение
| Профиль нагрузки | Что наблюдать | Начальное решение | Когда менять решение |
|---|---|---|---|
| Один проект, редкие коммиты | Очередь появляется редко, релиз можно перенести | Один Mac | Повторяющаяся очередь или отсутствие резервного пути |
| Один проект, частые ветки и TestFlight | Перекрытие Build, Test и Archive | Один Mac после оптимизации, затем второй | Если задачи регулярно блокируют друг друга |
| Небольшая команда | Ожидание Pull Request и конкуренция тестов | Два контура или два Runner | Если второй хост не снижает очередь |
| Несколько приложений | Общая очередь разных репозиториев | Разделённые метки и базовая ёмкость | При появлении релизных окон и конфликтов секретов |
| Редкие, но резкие публикации | Пиковая нагрузка в ограниченный период | Временный дополнительный Mac | Если расширение требуется постоянно |
План расширения и аренды
| Модель | Основная задача | Преимущество | Риск | Условие приёмки |
|---|---|---|---|---|
| Один постоянный Mac | Build, Test и Archive в одном контуре | Простая эксплуатация | Очередь и общий отказ | Восстановление после перезапуска и приемлемое ожидание |
| Два постоянных Mac | Параллельные проверки и релиз | Разделение нагрузки и резерв | Сложнее метки и секреты | Job действительно расходятся по нужным Runner |
| Постоянный Mac плюс временный | Базовая разработка и релизный пик | Нет постоянной оплаты простаивающей среды | Нужно быстро подготовить среду | Совпадают Xcode, зависимости, подпись и пути восстановления |
| Отдельный релизный Mac | Archive и публикация | Изоляция производственного контура | Дублирование администрирования | Релиз проходит при занятом тестовом контуре |
| Оптимизация без нового Mac | Снижение лишней конкуренции | Не меняет инфраструктуру | Не помогает реальному пику | Очередь снижается после отмены и упрощения Workflow |
Карточка итогового решения
| Показатель | Фактическое значение проекта | Что делать |
|---|---|---|
| Максимум одновременно выполняющихся Job | Заполнить по истории | Сравнить с доступным числом Runner |
| Время ожидания Build и Test | Заполнить отдельно | Определить допустимый порог обратной связи |
| Время занятости Archive | Заполнить без серверной обработки | Проверить, блокирует ли релиз другие Job |
| Повторные запуски и отмены | Отметить причины | Устранить лишние Workflow и устаревшие задания |
| Доступ к сертификатам и ключам | Разделить по уровню риска | Назначить метки и Runner Group |
| Восстановление после отказа | Пройти тест остановки | Добавить резерв или принять ручной сценарий |
| Релизный пик | Указать период и частоту | Сравнить постоянный Mac с временной арендой |
| Версия Xcode и зависимости | Зафиксировать для всех сред | Не добавлять Runner до проверки toolchain |
Итоговая формула проста: один Mac — когда очередь контролируема и релиз не конкурирует с критичными тестами; два — когда независимые Job регулярно перекрываются; временное расширение — когда дефицит появляется только в релизное окно. Если после отмены устаревших запусков, устранения повторных установок и разделения Workflow очередь исчезает, покупать или постоянно арендовать второй хост рано.
Если потребуется проверить доступные циклы аренды удалённого Mac, начните с вариантов MESHLAUNCH для Mac, а затем сопоставьте период аренды с фактическим окном TestFlight или App Store. Для отдельного сценария с Mac mini можно изучить условия заказа Mac mini.
Что выбрать для текущей инфраструктуры
Локальный Mac удобен для постоянной тяжёлой разработки и физического доступа к устройству, но отдельная машина под CI часто простаивает между релизами, требует обновлений и становится единственной точкой отказа. Один общий Runner для всех задач дешевле по администрированию, но смешивает тестовые процессы, подпись и срочную публикацию. Полностью облачный Workflow может ограничивать контроль над средой, кешами и специфическими инструментами проекта.
Если расчёт показывает дефицит только на тестовом пике или в период публикации, аренда дополнительного Mac у MESHLAUNCH позволяет проверить параллельность и резерв без немедленной покупки оборудования. Закажите период, который соответствует реальной нагрузке, заранее проверьте одинаковость Xcode и сертификатов, а после релиза сравните фактическую очередь с карточкой решения. Если же нагрузка постоянная, требуется физический интерфейс или Mac должен непрерывно выполнять тяжёлые задачи, сначала оцените владение собственной машиной — аренда подходит не каждому профилю.