GitHub Actions macOS Runner в 2026 году выбирайте не по цене одной минуты, а по полной стоимости успешной сборки. Для редких запусков, публичных репозиториев и команд без желания обслуживать узел лучше подходит GitHub-hosted Runner. Если сборки идут стабильно, требуют фиксированного Xcode, ключей подписи, кэша или доступа во внутреннюю сеть, self-hosted Runner на удалённом Mac обычно даёт больше контроля. Для большинства команд разумнее начать с двухконтурной схемы: обычные тесты оставить на hosted, а подпись, архивирование и чувствительные к окружению задачи перенести на self-hosted.
Этот материал предназначен для трёх групп:
- независимых разработчиков, которые оценивают небольшое количество iOS-сборок;
- мобильных команд, которым нужно зафиксировать Xcode, кэш и окружение подписи;
- DevOps-инженеров и руководителей платформ, считающих стоимость нескольких репозиториев и параллельных задач.
Последнее обновление: 15 августа 2026 года. Данные проверены по официальным документам GitHub Actions и Apple Developer, указанным в статье.
01 Считайте стоимость успешной сборки, а не одной минуты
Цена GitHub-hosted Runner — только один элемент счёта. Для корректного сравнения возьмите последний полностью закрытый расчётный период и разделите расходы на реальные категории:
- время выполнения macOS-задач;
- число параллельных заданий и время ожидания в очереди;
- хранение артефактов и кэшей;
- аренда или содержание self-hosted узла;
- часы инженера на обновления, очистку и восстановление;
- стоимость неудачных запусков и повторной проверки;
- потери от недоступности сборочного узла.
Официальный тариф GitHub для стандартного macOS Runner с 3 ядрами на M1 или 4 ядрами на Intel указан как 0,062 доллара США за минуту для платных запусков. Эта ставка относится к биллингу GitHub-hosted Runner, а не ко всей стоимости CI/CD. Для публичных репозиториев стандартные hosted Runner могут использоваться без оплаты минут, но это не отменяет расходы на хранилище, артефакты, секреты, внешние сервисы и поддержку. (тарифы GitHub Actions Runner)
Используйте такую модель:
Полная стоимость hosted =
минуты macOS × тариф
+ хранилище
+ внешние сервисы
+ стоимость ожидания и повторных запусков
Полная стоимость self-hosted =
период аренды удалённого Mac
+ обслуживание
+ контроль доступа
+ простои
+ время восстановления
+ стоимость очереди при нехватке мощности
Не подставляйте в формулу идеальную загрузку узла. Если Mac работает весь месяц, но задачи запускаются только несколько часов в неделю, оставшееся время является частью стоимости каждой сборки. Если один узел постоянно занят и задания встают в очередь, низкая фиксированная цена перестаёт быть преимуществом.
Для сравнения подготовьте пять фактических показателей из GitHub Actions:
- суммарное время выполнения macOS-задач;
- медианное и максимальное время ожидания;
- долю повторных запусков;
- объём кэша и артефактов;
- количество ручных вмешательств инженера.
Считать нужно не «стоимость минуты», а цену одного принятого pull request, релизного архива или успешной ночной сборки.
02 GitHub Actions macOS Runner и self-hosted различаются не только оплатой
GitHub-hosted Runner запускает каждую задачу в новом экземпляре образа, выбранного через runs-on. Это снижает риск накопленного состояния: предыдущий workflow не должен оставлять на машине старые зависимости, временные файлы или изменённый системный параметр. Одновременно чистое окружение означает повторную установку зависимостей и меньшую возможность использовать долгоживущий DerivedData.
Self-hosted Runner работает на машине, которую контролируете вы или ваша инфраструктурная команда. GitHub указывает, что такой узел должен запускать Runner application, иметь связь с GitHub Actions и соответствовать аппаратным требованиям рабочих процессов. Для macOS поддерживается macOS 11.0 и новее, а ARM64 для macOS обозначен в справочной документации как предварительная функция. (справочник self-hosted Runner)
Это создаёт четыре важных различия.
Фиксированная ёмкость. Один удалённый Mac имеет ограниченное число одновременно выполняемых задач. Если он занят, новые jobs ждут. Hosted-инфраструктура сама добавляет доступную ёмкость, тогда как self-hosted требует второго узла, масштабирования или принятия очереди.
Постоянное состояние. Предустановленный Xcode, CocoaPods, Swift Package Manager, Ruby и локальные инструменты ускоряют повторные сборки. Но состояние может стать причиной ошибки, которую нельзя воспроизвести на чистом Runner.
Ответственность за узел. В self-hosted варианте вы отвечаете за обновления macOS, свободное место, перезапуск, связь, версию Runner application, секреты и восстановление после сбоя.
Контроль доступа. Фиксированный Mac удобнее для ключей подписи, приватных пакетов, VPN и внутренних API. Но долгоживущие секреты на узле увеличивают последствия компрометации.
Если для вас важна изоляция каждого запуска и нет жёстких требований к постоянному окружению, начинайте с hosted. Если ошибка из-за версии инструмента блокирует релиз или каждый запуск повторяет тяжёлую установку зависимостей, тестируйте self-hosted на реальном workflow.
03 При редких сборках hosted Runner обычно проще оправдать
Для независимого разработчика или небольшой команды основной риск self-hosted — оплачивать доступный, но простаивающий узел. В этом сценарии фиксированная аренда удалённого Mac может оказаться дороже переменного потребления hosted Runner, даже если отдельная минута GitHub выглядит дорогой.
Проверяйте не количество коммитов, а фактическую нагрузку:
- сколько workflow стартует в неделю;
- сколько macOS jobs выполняется в каждом workflow;
- сколько времени занимает один job;
- сколько запусков приходится на pull request, а сколько — на релиз;
- есть ли ночные или плановые сборки;
- сколько времени узел простаивает между задачами.
Для публичного проекта hosted-вариант дополнительно привлекателен тем, что стандартные Runner доступны без оплаты минут. Для закрытого репозитория действуют тарифные условия и бесплатные квоты соответствующего плана, поэтому стоимость нужно сверять по официальной странице биллинга в день расчёта. (цены GitHub Actions)
Не существует универсального числа минут, после которого self-hosted автоматически становится выгоднее. Оно зависит от тарифа аренды, длительности расчётного периода, параллельности, скорости сборки, стоимости работы инженера и цены простоя. Поэтому вывод «после определённого количества минут всегда берите свой Runner» будет ненадёжным.
Очередь важнее номинальной экономии
Если релизная сборка ждёт свободный узел, это уже операционная стоимость. В self-hosted конфигурации GitHub направляет job на подключённый и свободный Runner с подходящими labels. Если подходящего узла нет, job остаётся в очереди до появления Runner. После ожидания более 24 часов задание завершается ошибкой. Если назначенный узел не принимает задание в течение 60 секунд, GitHub ставит его в очередь повторно. (выбор Runner для job)
В журнале измеряйте отдельно:
- время до назначения Runner;
- фактическое время выполнения;
- время установки зависимостей;
- время загрузки и сохранения кэша;
- время до получения артефакта.
Если self-hosted сокращает выполнение, но увеличивает очередь в периоды релизов, один узел не решает задачу. Потребуется второй узел, ограничение параллельности или возврат части jobs на hosted.
04 Кэш и Xcode меняют эффективное время Xcode CI
Hosted Runner полезен как чистая контрольная среда. Каждый job получает новый экземпляр образа, поэтому результат меньше зависит от предыдущих запусков. Self-hosted Runner позволяет заранее установить Xcode, Ruby, Bundler, CocoaPods, SPM-зависимости и локальные инструменты. Это сокращает повторяющиеся подготовительные шаги, но одновременно создаёт риск загрязнения окружения.
Для честного теста сравните два варианта на одном и том же:
- репозитории;
- commit;
- версиях Xcode и macOS;
- настройках подписи;
- наборе тестов;
- параметрах кэша;
- количестве параллельных jobs.
Не называйте результатом кэша ускорение, которое на самом деле дал другой процессор или иной объём памяти. GitHub указывает для стандартных private macOS Runner конфигурации с 14 ГБ памяти и 14 ГБ SSD; для arm64-варианта в документации приведён M1 с 3 ядрами и 7 ГБ памяти, а для Intel — 4 ядра и 14 ГБ памяти. Эти характеристики нужно учитывать при интерпретации Xcode CI, но сравнивать их с удалённым Mac можно только по одинаковому проекту и измеренному времени. (конфигурации GitHub-hosted Runner)
Проверяйте четыре значения:
- время без кэша;
- время после прогрева кэша;
- размер кэша после нескольких циклов;
- число ошибок после очистки или восстановления.
Постоянная машина не всегда лучше. Если на ней остаются старые DerivedData, устаревшие SPM-пакеты или изменённые настройки keychain, сборка становится быстрой, но нерепродуцируемой. Для критичного пайплайна используйте периодическую очистку или отдельный job, который создаёт чистое рабочее состояние.
Важно: наличие статуса «Online» не доказывает производственную готовность Runner. Узел может принимать heartbeat, но не иметь свободного места, доступа к приватному репозиторию или исправного Xcode.
05 Фиксированный Xcode и подпись оправдывают контроль над узлом
Выбор self-hosted становится обоснованным, когда окружение само является частью продукта. Это относится к проектам, где необходимо:
- удерживать конкретную версию Xcode;
- использовать фиксированную версию macOS;
- хранить сертификаты подписи и provisioning profiles;
- обращаться к приватному package registry;
- подключаться к внутреннему API;
- повторять архивирование в одном и том же окружении;
- сохранять локальные инструменты или плагины, которые трудно готовить на каждом запуске.
Apple публикует матрицу совместимости Xcode и macOS. На странице требований указано, что Xcode 27 beta 5 требует macOS Tahoe 26.4 или новее, а разработка для visionOS требует Mac на Apple silicon. Такие ограничения делают label и образ Runner частью технического контракта проекта, а не простой настройкой CI. (системные требования Xcode)
При этом не следует утверждать, что hosted Runner никогда не может обращаться к внутренним ресурсам. Возможность зависит от конкретной сетевой схемы, GitHub-плана, приватных подключений, firewall и политики вашей организации. Проверяйте это отдельно на тестовом job. Наличие доступа к API не означает, что на Runner можно безопасно оставлять ключи подписи.
Для подписывающего job задайте минимальные права:
- используйте отдельную группу Runner;
- ограничьте список репозиториев;
- не запускайте на этом узле непроверенные pull request;
- удаляйте временные файлы после архивации;
- журналируйте операции с keychain;
- проверяйте восстановление после перезапуска;
- меняйте секреты по внутреннему регламенту.
Самостоятельный Runner даёт больше контроля, но не отменяет требования к защите цепочки поставки. Если подписываются непроверенные изменения, постоянный узел превращается в удобную точку для извлечения секретов.
06 Поддержка и восстановление входят в цену self-hosted
Официальная документация GitHub описывает self-hosted Runner как машину, которую вы разворачиваете и управляете самостоятельно. Узел должен поддерживать связь с GitHub Actions и иметь ресурсы для ваших workflows. Autoscaling также требует отдельной архитектуры и добавляет сложность по сравнению с одним постоянным узлом. (требования к self-hosted Runner)
В план обслуживания включите:
- обновление macOS;
- установку и переключение Xcode;
- обновление Runner application;
- контроль свободного места;
- очистку DerivedData и архивов;
- проверку SSH и сетевых маршрутов;
- автоматический перезапуск;
- уведомления о потере связи;
- сценарий полной реконфигурации узла.
Проведите приёмку в четырёх режимах:
- перезапуск во время ожидания job;
- отключение сети на время выполнения;
- остановка процесса Runner;
- полное удаление и повторное создание окружения.
Для каждого режима зафиксируйте обнаружение проблемы, время восстановления, необходимость ручного доступа и судьбу прерванного workflow. Именно эти записи показывают, дешевле ли self-hosted в вашей команде, а не рекламная цена аренды.
07 Решение по условиям: hosted, self-hosted или оба варианта
Используйте этот список как рабочий инструмент выбора.
-
[ ] Если запусков мало, требования к Xcode стандартны, а команда не хочет обслуживать узел, выбирайте hosted Runner.
Иначе переходите к следующему условию. -
[ ] Если главная проблема — фиксированная версия Xcode, подпись или приватные зависимости, тестируйте self-hosted Runner на удалённом Mac на одной выделенной группе jobs.
Иначе оставляйте hosted и измеряйте очередь и подготовку окружения. -
[ ] Если self-hosted узел простаивает большую часть периода, а очередь почти отсутствует, сравните стоимость простоя с фактическим биллингом hosted.
Иначе проверьте, не создаёт ли один узел ограничение пропускной способности. -
[ ] Если очередь возникает только в релизные окна, оставьте обычные тесты на hosted, а подпись и архивирование перенесите на self-hosted.
Иначе оцените второй узел или ограничение параллельности. -
[ ] Если стоимость ручного обслуживания нельзя измерить, не объявляйте self-hosted более дешёвым. Сначала записывайте часы инженера и время восстановления.
-
[ ] Если приватная сеть допускает hosted Runner после подтверждённого теста, сравните риски и стоимость обоих вариантов, а не исключайте hosted автоматически.
Такой подход отвечает и на вопрос о смешивании Runner. Hosted и self-hosted можно использовать в одном workflow: разные jobs получают разные значения runs-on, labels или группы. GitHub документирует выбор Runner на уровне job, поэтому общий pipeline может оставить lint и unit tests на hosted, а подпись и archive job отправлять на self-hosted. (выбор Runner для разных jobs)
08 Проведите двухконтурное испытание на реальном workflow
Не переносите весь Xcode CI сразу. Выполните проверку по шагам.
-
Выберите один реальный workflow. Возьмите pipeline, который создаёт полезный артефакт или проверяет pull request. Искусственный benchmark не показывает операционные расходы.
-
Зафиксируйте исходные данные. Сохраните commit, Xcode, macOS, время выполнения, очередь, ошибки, объём кэша и число ручных вмешательств на hosted Runner.
-
Разделите jobs по риску. Обычные проверки оставьте на hosted. Для self-hosted выберите job с фиксированным Xcode, подписью, архивированием или доступом к внутреннему сервису.
-
Добавьте labels. Используйте признаки вроде
self-hosted,macos,arm64,xcode-27и отдельную группу для signing jobs. Labels должны отражать проверенные свойства. -
Повторите тот же commit. Не сравнивайте разные изменения. Иначе изменение кода может оказаться важнее различия между Runner.
-
Измерьте прогрев и чистое состояние. Выполните серию запусков с кэшем и после очистки. Отдельно запишите ошибки, связанные с остаточным состоянием.
-
Проверьте сбой. Перезапустите узел, отключите сеть и остановите Runner application. Убедитесь, что job не зависает без уведомления.
-
Посчитайте трудозатраты. Внесите в расчёт установку Xcode, очистку диска, исправление keychain, восстановление после сбоя и контроль доступа.
-
Примите решение по данным. Увеличивайте долю self-hosted только если выигрыш в контроле, очереди или повторяемости перекрывает аренду и поддержку.
Если для теста нужен готовый постоянный macOS-узел без покупки собственного оборудования, можно проверить вариант аренды удалённого Mac для CI-задач. Не переносите туда весь pipeline до завершения измерений: сначала подтвердите, что конкретная связка Xcode, подписи, кэша и сетевых зависимостей работает именно в вашем проекте.
09 Итоговый выбор для команды
Выбирайте hosted Runner, если:
- сборки редкие или непредсказуемые;
- проект публичный;
- чистое окружение важнее сохранённого кэша;
- нет постоянных ключей и особых сетевых требований;
- команда не хочет обслуживать macOS-узел;
- очередь не мешает релизам.
Выбирайте self-hosted на удалённом Mac, если:
- Xcode должен оставаться фиксированным;
- подпись и архивирование регулярно входят в процесс;
- кэш заметно влияет на время сборки;
- нужны приватные пакеты или внутренние API;
- вы готовы тестировать восстановление;
- стоимость простоя и обслуживания рассчитана по фактическим данным.
Оставляйте двухконтурную схему, если:
- lint, unit tests и матрица совместимости хорошо работают на hosted;
- подпись, архивирование и release jobs требуют постоянной среды;
- релизные пики создают очередь на одном узле;
- безопасность позволяет изолировать signing Runner;
- команде нужен постепенный переход без остановки CI.
Не сравнивайте только счёт GitHub с месячной арендой. У hosted есть повторная подготовка чистой среды и зависимость от доступной конфигурации. У self-hosted есть простой оплаченного узла, ручные обновления, риск загрязнения состояния, обслуживание ключей и необходимость восстанавливать машину после сбоя. Если эти расходы не записаны, сравнение будет неполным.
После аудита текущей нагрузки выберите одну signing или archive pipeline и прогоните её на удалённом Mac в течение полного арендного периода. Сопоставьте фактическую стоимость, очередь, время сборки, процент ошибок и часы обслуживания. Если результат устойчив, переносите следующие задачи, чувствительные к окружению. Для временного CI, миграционного проекта или проверки новой версии Xcode такой подход обычно безопаснее покупки отдельного Mac. Если же вы строите постоянный высоконагруженный кластер, требуете физические устройства или готовы самостоятельно управлять резервированием, аренда не заменит полноценную инфраструктурную платформу. Доступные варианты можно проверить на странице заказа CALMVPS, сохранив hosted Runner для задач, которым не нужен постоянный macOS-контур.