Официальные ограничения GitHub Actions указывают максимальную длительность одной job — 6 часов: после этого задача принудительно завершается. Это подтверждено в документации по лимитам GitHub Actions. Поэтому в 2026 году выбирайте macOS Runner GitHub Actions не по цене одной минуты. Для редких коротких сборок и небольшой команды обычно подходит GitHub-hosted Runner. Для стабильной высокой загрузки, фиксированного Xcode и доступа к приватной сети оценивайте self-hosted Mac. В обоих случаях сначала посчитайте очередь, повторные запуски, кэш и часы обслуживания.
Кому пригодится этот материал
Он предназначен для DevOps-инженеров, у которых macOS-задачи GitHub Actions часто стоят в очереди или завершаются по тайм-ауту. Руководители команд найдут здесь модель расчёта полной стоимости iOS-сборки. Платформенным инженерам статья поможет подготовить безопасный self-hosted Runner.
Последнее обновление — 4 сентября 2026 года. Данные сверены с официальными документами GitHub по тарифам, ограничениям, образам Runner и безопасности self-hosted Runner.
Полная стоимость вместо цены минуты
Как рассчитывается стоимость GitHub Actions macOS Runner?
Начните с единой строки расчёта для одинакового периода, например одного календарного месяца. Не сопоставляйте самый быстрый локальный запуск с суммой минут GitHub Actions: это разные показатели.
В модель включите пять компонентов:
- Время выполнения. Считайте фактические минуты всех macOS jobs, включая тесты, архивирование, экспорт и публикацию.
- Платные повторные запуски. Отдельно фиксируйте повтор после сбоя инфраструктуры, ошибки сертификата, недоступного кэша или нестабильного теста.
- Ожидание в очереди. Время до старта не всегда отражается в минутной стоимости, но напрямую влияет на скорость доставки сборки и рабочее время разработчиков.
- Хранение и передача данных. В зависимости от схемы это могут быть кэш зависимостей, артефакты, архивы приложения и загрузка больших SDK.
- Человеческое обслуживание. Для self-hosted Mac сюда входят обновление macOS и Xcode, контроль диска, ремонт или замена узла, обновление Runner и восстановление после сбоя.
GitHub публикует текущие тарифы и коэффициенты для macOS на официальной странице расчёта стоимости Actions Runner. Используйте значения именно оттуда: тарифы и доступные типы машин могут измениться, а сторонние сводки быстро устаревают.
Для внутренней аналитики заведите такие поля:
- идентификатор workflow;
- тип Runner и версия macOS;
- версия Xcode;
- длительность job;
- время ожидания;
- причина повторного запуска;
- размер восстановленного и сохранённого кэша;
- стоимость аренды или эксплуатации узла;
- минуты инженера, потраченные на обслуживание.
Так вы увидите, что «дорогая» hosted-сборка иногда обходится дешевле собственной. Если self-hosted Mac простаивает большую часть месяца, его фиксированная стоимость распределяется на небольшое число задач. Если же машина занята почти постоянно, картина меняется.
Не смешивайте в одном сравнении разные задачи. Сборка приложения с xcodebuild, UI-тесты на симуляторе и публикация в App Store Connect требуют разного времени и дискового пространства. Сначала разделите их на типы, затем сравнивайте одинаковые jobs.
Опыт для оценки. Если после перехода на другой Runner время сборки уменьшилось, это ещё не доказывает экономию. Проверьте полный статистический период: в него должны попасть обычные коммиты, pull request, ночные тесты и повторные запуски после ошибок.
Параллелизм и очередь сборок
Параллелизм — это не число разработчиков и не количество macOS-машин «на глаз». Для предварительной оценки используйте три величины:
P— максимальное число одновременно возникающих сборок;T— средняя длительность одной macOS job в минутах;W— допустимое время ожидания до старта.
Начальная оценка числа Runner выглядит так:
необходимое число Runner ≈ округление вверх(P × T / (T + W))
Это не заменяет измерение. Формула нужна, чтобы не покупать узел только по месячному объёму минут. Большой месячный объём при равномерной загрузке может обслуживаться небольшим пулом. Тот же объём, собранный в короткое окно перед релизом, создаст очередь.
Проверьте план GitHub и его лимиты до проектирования архитектуры. В официальной документации отдельно описаны ограничения Actions, включая максимальную длительность job — 6 часов — и другие пределы workflow: справочник лимитов GitHub Actions. Также сверяйте доступные метки и типы hosted Runner в документе о выборе Runner для job.
Что делать, если iOS-сборкам не хватает параллелизма?
Сначала определите, где возникает ограничение:
- jobs ждут свободный hosted Runner;
- workflow искусственно ограничен настройкой
concurrency; - слишком много задач используют один label;
- тесты выполняются последовательно;
- узкое место находится не в Runner, а в доступе к репозиторию, кэшу или внешнему сервису.
После этого действуйте по порядку:
- Соберите данные об очереди за обычные рабочие дни и релизные окна.
- Разделите build, unit-тесты, UI-тесты и deployment на отдельные job.
- Проверьте, какие jobs действительно требуют macOS.
- Запустите независимые тестовые группы параллельно, если они не используют один и тот же ресурс.
- Добавьте Runner только после измерения пиковой потребности.
- Повторите замер после изменения конфигурации.
Решение по условиям
Используйте этот список перед покупкой дополнительных слотов или Mac. Отмечайте только подтверждённые факты по вашим логам.
- [ ] Если macOS jobs запускаются редко, длятся недолго, а команда не хочет обслуживать инфраструктуру, выберите GitHub-hosted Runner.
- [ ] Если сборки регулярно ждут свободный слот, а пик приходится на короткие релизные окна, сначала проверьте увеличение hosted-пула и настройку workflow, затем оцените смешанную схему.
- [ ] Если вам необходимы фиксированные версии macOS, SDK и Xcode, выберите self-hosted Mac для этой группы jobs, сохранив hosted Runner как резерв.
- [ ] Если release-сборка должна видеть приватную сеть, используйте изолированный self-hosted Runner, а не общий узел для pull request.
- [ ] Если средняя загрузка будущего узла будет низкой или сильно волнообразной, не делайте покупку оборудования первым шагом: рассмотрите временную аренду или hosted-пул.
- [ ] Если вы не можете назначить ответственного за обновления, сертификаты, диск и восстановление, вернитесь к GitHub-hosted Runner.
- [ ] Если в команде есть постоянная базовая нагрузка и отдельные релизные пики, выберите смешанный режим: self-hosted для предсказуемых jobs и hosted Runner для всплесков.
- [ ] Если pull request приходят из недоверенных fork, запретите им запуск на release Runner независимо от его производительности.
Если ни один пункт нельзя подтвердить логами, не принимайте решение по рекламной оценке. Сначала соберите статистику очереди и длительности.
Версии Xcode и повторяемость окружения
GitHub-hosted Runner удобен тем, что образ уже подготовлен, а список изменений публикуется в репозитории официальных Runner Images. Это сокращает время установки инструментов. Обратная сторона — автоматическое обновление образов и риск, что workflow начнёт использовать другой SDK или набор системных пакетов.
В 2026 году при переходе на Xcode 27 не ограничивайтесь заменой одной строки в workflow. Зафиксируйте:
- версию macOS;
- версию Xcode и активный путь
xcode-select; - версию Swift и набор SDK;
- Ruby, Bundler, CocoaPods или Swift Package Manager;
- версии Fastlane и прочих CLI;
- список симуляторов;
- версию кэша;
- параметры подписи и provisioning profile.
В hosted-схеме проверяйте label и доступность нужного образа перед миграцией. В self-hosted-схеме вы можете фиксировать окружение дольше, но только при наличии собственного процесса обновления. Фиксированная версия не означает забытую версию: устаревший Xcode создаёт отдельный риск совместимости и безопасности.
Пошаговая миграция выглядит так:
- Сохраните текущий успешный лог сборки и список версий.
- Создайте отдельную ветку для Xcode 27.
- Подготовьте новый Runner или отдельный label, не заменяя рабочий сразу.
- Соберите один и тот же commit на старом и новом окружении.
- Сравните предупреждения компилятора, SDK, тесты, архив и подпись.
- Проверьте TestFlight или внутреннюю доставку.
- Переведите небольшую часть workflow на новое окружение.
- После успешного периода наблюдения измените основной label.
В GitHub Actions выбирайте Runner по меткам, а не по неявному предположению о версии. Для self-hosted узлов используйте отдельные labels вроде macos-xcode27 и ios-release, чтобы job для публикации не попала на машину с неподготовленным окружением.
Для команд, которые одновременно меняют CI и инструменты разработки, полезно заранее прочитать материал о миграции iOS-конвейера и релизных проверках.
Кэш, диск и длительность job
Кэш уменьшает повторную загрузку зависимостей, но не превращает hosted Runner в постоянный диск. Изучите официальные правила dependency caching: размер кэша, ключи, область доступности и политика удаления влияют на результат не меньше, чем сам Runner.
Разделите кэш на независимые слои:
- Swift Package Manager;
- CocoaPods;
- Bundler;
- DerivedData;
- промежуточные результаты тестов;
- симуляторы и инструменты;
- финальные архивы и логи.
DerivedData часто плохо подходит для безусловного долгого хранения. Она зависит от Xcode, SDK, настроек проекта и commit. Если ключ слишком общий, сборка может использовать неподходящие объекты. Если ключ слишком узкий, кэш почти не даёт выигрыша.
На hosted Runner кэш удобен для зависимостей, но каждый job следует считать чистым окружением, если документация не гарантирует обратное. На self-hosted Mac вы получаете постоянный диск и можете сохранить крупные зависимости между job. Вместе с этим появляются обязанности:
- регулярно удалять старые DerivedData;
- ограничивать рост архивов;
- проверять свободное место перед стартом;
- не смешивать рабочие данные разных репозиториев;
- очищать временные файлы после неуспешной job.
Для измерения проведите два прогона одного commit:
- холодный — без подходящего кэша;
- тёплый — после восстановления зависимостей.
Запишите отдельно скачивание, компиляцию, тесты и упаковку. Если выигрыш относится только к скачиванию, не обещайте сокращение всей job на ту же величину. При смене Xcode 27 кэш старой версии нужно либо исключить из ключа, либо проверять совместимость явно.
Напоминание. Постоянный кэш ускоряет последующие jobs только при аккуратной очистке. Без лимита на DerivedData и архивы self-hosted Mac постепенно превращается в узел с непредсказуемым свободным местом, а случайный сбой диска может затронуть несколько репозиториев.
Теме кэширования стоит посвятить отдельное техническое испытание. В руководстве по оптимизации iOS-сборок можно сверить вопросы Fastlane, TestFlight и размещения артефактов перед переносом их в новый Runner.
Подпись, секреты и приватная сеть
Как безопасно управлять сертификатами подписи на self-hosted Runner?
Считайте self-hosted Runner доверенной машиной, а не просто более дешёвой заменой hosted-инфраструктуры. GitHub прямо описывает ответственность владельца за безопасность собственного узла: границы ответственности self-hosted Runner.
Минимальная схема выглядит так:
- Выделите отдельный Mac для CI, не используйте его как рабочее место разработчика.
- Создайте отдельного системного пользователя без административных прав для обычных jobs.
- Разделите labels для pull request, внутренних веток и release-процесса.
- Поместите release Runner в отдельную Runner Group.
- Разрешите этой группе только доверенные репозитории и ветки.
- Храните секреты в GitHub Secrets или другом одобренном хранилище, а не в репозитории.
- Импортируйте сертификат в отдельную временную keychain.
- Открывайте keychain только на время подписи.
- После job удаляйте временную keychain, профили и экспортированные секреты.
- Регулярно отзывайте и заменяйте сертификаты.
Для настройки доступа используйте документ GitHub о добавлении self-hosted Runner. Особенно опасны workflow, которые запускаются из недоверенных fork или получают содержимое pull request. Такой код нельзя автоматически пускать на узел, где остались signing certificate, App Store Connect API key или доступ к внутренней сети.
Runner Group помогает отделить release-машины от обычных сборок; правила описаны в документации по Runner Group. Labels дают более точный выбор среды, но сами по себе не являются границей безопасности.
Сетевая изоляция должна быть двухуровневой:
- pull request Runner получает только доступ к необходимым внешним сервисам;
- release Runner имеет доступ к приватным системам только через разрешённые адреса и порты.
Не выдавайте всем jobs доступ к одной VPN-сессии. Иначе ошибка в стороннем action или вредоносная команда из ветки может превратить CI-узел в путь к внутренней инфраструктуре.
Обслуживание и восстановление
Hosted Runner переносит большую часть операционных задач на GitHub. Вам всё равно нужно поддерживать workflow, зависимости, секреты и тесты, но не требуется самостоятельно менять вышедший из строя Mac.
В self-hosted схеме список работ шире:
- обновление macOS;
- установка и проверка Xcode;
- обновление Runner-приложения;
- контроль диска и температуры;
- восстановление после зависшей job;
- резервирование конфигурации;
- замена неисправного узла;
- проверка сети и VPN;
- аудит доступов;
- очистка секретов;
- контроль доступности симуляторов.
Самостоятельный Runner не означает нулевую стоимость минут. Расходы просто переходят в устройство или аренду Mac, сетевой доступ, хранение, резервирование и часы инженера. Если восстановление занимает рабочий день, низкая условная цена вычислений уже не выглядит низкой.
Для повышения устойчивости используйте два независимых labels: основной и резервный. В workflow задайте понятный fallback, но не отправляйте release job на случайную машину без проверки сертификата и версии Xcode. В идеале новый узел проходит автоматическую проверку готовности:
- запускается
xcodebuild -version; - проверяется нужный SDK;
- создаётся тестовая keychain;
- выполняется пробная компиляция;
- проверяется свободное место;
- подтверждается доступ только к разрешённым endpoints.
Итоговый выбор для iOS-команды
GitHub-hosted Runner выигрывает по простоте. Не нужно покупать или обслуживать узел. Окружение легче подключить к новому репозиторию. Его слабые места — очередь в пиковые часы, временный диск, зависимость от доступных образов и необходимость следить за изменениями labels.
Собственный физический Mac даёт постоянный кэш, контроль над Xcode и доступ к приватной сети. Но вы оплачиваете простой, обновления, резервирование, сертификаты, мониторинг и восстановление. Покупка устройства особенно невыгодна, если нагрузка нерегулярна или команда не может быстро заменить неисправный узел.
Аренда Mac через Hashvps занимает промежуточное положение. Вы получаете выделенную среду без первоначальной покупки оборудования, но должны проверить срок аренды, способ подключения, изоляцию, доступность сети, сохранность диска и процесс замены узла. Это не универсальная замена hosted Runner. Для постоянной тяжёлой нагрузки и требований к физическим интерфейсам собственное оборудование может быть разумнее.
Проведите испытание в течение полного цикла релиза. Зафиксируйте:
- медианное и пиковое время ожидания;
- длительность холодной и тёплой сборки;
- долю повторных запусков;
- успешность подписи;
- количество ручных вмешательств;
- время восстановления узла;
- свободное место после серии jobs;
- совпадение результата на старом и новом Xcode;
- фактическую стоимость каждого типа задачи.
Так вы сравните текущую схему с Mac-решением по реальным недостаткам, а не по одной минутной ставке. Hosted Runner может давать нестабильное ожидание и ограниченный жизненный цикл кэша. Покупной Mac требует капитальных затрат и постоянного обслуживания. Self-hosted узел также создаёт ответственность за сертификаты, сеть и восстановление.
Если эти ограничения уже влияют на релизы, начните с пробного CI-узла Hashvps и используйте те же критерии приёмки: очередь, холодный кэш, тёплый кэш, подпись, восстановление и полная стоимость цикла. Только после такого сравнения вы поймёте, улучшает ли аренда Mac ваш процесс, не изменяя production-пайплайн вслепую.
Запустите собственный macOS Runner с Hashvps
Арендуйте удалённый Mac в Hashvps для сборок, тестирования и CI-задач без покупки собственного оборудования.
Выбирайте конфигурацию с необходимыми ресурсами и планируйте расходы на macOS-инфраструктуру по понятной модели.