GitHub Actions Runner Scale Set Client для Mac стоит запускать в пилот только тогда, когда у вас уже автоматизированы выдача, подготовка, возврат узлов и вынос журналов. Если Mac создаётся вручную, оставьте фиксированный пул, а для переменной нагрузки используйте двухконтурную схему: небольшой прогретый пул плюс ручное расширение.

Кому подходит этот материал: DevOps-инженерам, которые управляют несколькими Mac Runner и хотят связывать их количество с очередью GitHub Actions. Он также полезен мобильным платформенным командам, которым нужны отдельные узлы для подписи, и руководителям CI-инфраструктуры, сравнивающим постоянные, прогретые и одноразовые Mac.

Последняя проверка: 6 сентября 2026 года. Статус и поведение сверены с документацией GitHub, официальным репозиторием Runner Scale Set Client и документацией REST API.

Что именно масштабируется: клиент управления или Mac-инфраструктура

Runner Scale Set Client — это управляющий слой. Он получает сигнал о необходимости изменить размер набора, запрашивает конфигурацию для временного runner и связывает жизненный цикл runner с внешним механизмом поставки. Сам клиент не арендует физический Mac, не устанавливает Xcode, не восстанавливает сертификаты и не уничтожает хост после завершения задания. Рабочий процесс описан в официальном README Runner Scale Set Client.

Это ключевая граница для проектного решения. Если ваша платформа умеет:

  • выбрать подходящий Mac;
  • создать или включить узел;
  • дождаться доступности macOS;
  • восстановить зависимости и инструменты;
  • зарегистрировать временный runner;
  • забрать журналы;
  • удалить или изолировать узел после задания,

то Client можно проверять в ограниченном пилоте. Если эти действия выполняются оператором вручную, масштабирование существует только на уровне сигнала, но не на уровне реальной вычислительной мощности.

Официальный репозиторий обозначает Runner Scale Set Client как Public Preview. Поэтому интерфейсы, примеры и поддерживаемые сценарии нужно проверять перед каждым изменением платформы, а не считать их неизменной частью производственного контракта. Текущий статус доступен в официальном репозитории actions/scaleset.

Отсутствие Kubernetes само по себе не блокирует использование Client. Важнее наличие собственного контроллера и API, через которые можно управлять Mac-узлами. Однако это не означает, что без Kubernetes появляется готовый механизм поставки: очередь, планировщик, управление хостами и откат остаются вашей ответственностью.

Вопрос о поддержке macOS: что подтверждено

Официальная документация указывает, что Runner Scale Set Client может применяться для пользовательских схем масштабирования, включая macOS. Это подтверждает возможность строить решение для Mac Runner, но не гарантирует наличие готового образа, совместимость с вашим поставщиком Mac или автоматическую настройку среды.

Для проверки разделите утверждение «клиент поддерживает macOS» на четыре отдельных теста:

  1. управляющий слой получает запрос на новый runner;
  2. внешний провайдер выдаёт реальный Mac;
  3. Mac проходит подготовку и регистрацию;
  4. задание выполняется, после чего узел корректно выводится из эксплуатации.

Только четвёртый результат доказывает работоспособность цепочки для CI. Успешная регистрация без выполнения настоящей сборки не является доказательством готовности.

Шесть метрик, по которым выбирается стратегия

Не начинайте с количества узлов. Сначала зафиксируйте шесть измерений: поставка, изоляция, холодный старт, воспроизводимость, безопасность и совокупные операционные затраты. В каждом измерении сравнивайте постоянный пул, прогретый временный пул и создание Mac по запросу.

Стратегия Поставка узлов Жизненный цикл Холодный старт Изоляция Когда выбирать
Постоянные Mac Runner Узлы уже доступны Рабочее состояние сохраняется Минимальная дополнительная задержка, если узел свободен Рабочая область и секреты требуют строгой очистки Стабильная нагрузка, небольшое число узлов
Прогретый временный пул Часть узлов заранее подготовлена Узел используется ограниченное время и затем заменяется Ниже, чем у полностью нового Mac Лучше при отдельном узле на задание Пиковая нагрузка, но автоматизация поставки ещё неполная
Mac по запросу Создаётся внешним контроллером Выдача, JIT-регистрация и уничтожение автоматизированы Полностью зависит от поставки и подготовки Наиболее сильная модель при корректном уничтожении Неровная очередь и готовая платформа управления

Эта таблица не заменяет замеры. Она показывает, где искать причину задержки и риска. Например, переход на временный runner не исправит медленную загрузку образа, а постоянный runner не решит проблему секретов, если после задания сохраняются рабочая папка и токены.

Первая метрика — способность реально выдать Mac

Запрос масштабирования нужно связать с журналом поставки. Для каждого узла сохраняйте:

  • время получения сигнала;
  • идентификатор запроса;
  • выбранный Mac;
  • результат включения или создания;
  • версию подготовленного окружения;
  • причину отказа;
  • действие отката.

Не записывайте в журнал секреты, токены регистрации и содержимое сертификатов. Достаточно идентификаторов и статусов, чтобы связать событие масштабирования с заданием GitHub Actions.

Проверьте негативный сценарий: Mac не отвечает после выдачи. Платформа должна снять такой узел с маршрутизации, вернуть задачу в очередь по принятой политике и освободить неудавшийся ресурс. Если оператор вручную удаляет зависший узел, автоматическое масштабирование ещё не доказано.

Вторая метрика — временный JIT Runner против постоянного узла

Постоянный Mac Runner удобен тем, что Xcode, зависимости и кеш уже находятся на диске. Но это же создаёт скрытый риск: следующее задание может увидеть рабочие файлы, артефакты, переменные окружения или состояние инструмента подписи от предыдущего запуска.

Временный JIT Runner уменьшает период существования регистрационных данных. REST API GitHub возвращает конфигурацию для регистрации runner, а документация API для JIT-конфигурации описывает параметры запроса и ответа. Полученный секрет нельзя помещать в общедоступный журнал, образ Mac или постоянный файл.

Рекомендация по выбору такая:

  • обычные тестовые и разработческие сборки можно включить в пилот временных узлов;
  • задания с кодовой подписью нужно направить в отдельный пул;
  • публикацию приложений не следует смешивать с открытыми pull request;
  • если удаление узла не подтверждено, не считайте JIT-модель изолированной.

GitHub отдельно описывает ограничения безопасности для временных self-hosted runner в руководстве по безопасному использованию. Возможность принять задание не равна безопасной готовности к продакшену.

Третья метрика — где возникает ожидание

Общее время workflow скрывает структуру задержки. Разделите его на четыре отрезка:

  1. ожидание задания в очереди;
  2. выдача или запуск Mac;
  3. установка и проверка среды;
  4. регистрация runner и начало работы.

Так вы увидите, требуется ли вам эластичность вообще. Если очередь почти отсутствует, а большая часть времени уходит на подготовку нового узла, создание Mac по запросу может ухудшить опыт разработчика. Если очередь растёт из-за коротких пиков, небольшой прогретый пул способен дать лучший баланс.

Не переносите универсальные пороги из чужих проектов. На задержку влияют тип Mac, состояние диска, способ поставки, версия Xcode, объём Simulator runtime, кеши и сетевой маршрут. Сравните три режима на одинаковом workflow:

  • только JIT и полностью новый узел;
  • минимальный прогретый пул;
  • фиксированные постоянные Mac Runner.

Фиксируйте время каждого из четырёх отрезков, а не только итог workflow. Документация GitHub по концепции Runner Scale Set полезна для проверки терминов и общей модели, но ваши пороги должны следовать из собственных журналов.

Четвёртая метрика — воспроизводимость Xcode-среды

JIT Runner не решает задачу сборки, если узел зарегистрировался, но не имеет нужной версии Xcode, Simulator runtime или зависимостей проекта. До запуска пилота опишите среду как код:

  • версию macOS;
  • версию Xcode;
  • требуемые Simulator runtime;
  • версии Swift Package Manager, CocoaPods или других менеджеров;
  • параметры проекта и Scheme;
  • способ восстановления кеша;
  • процедуру получения сертификатов и профилей.

Проведите три контрольных прогона:

  1. первая сборка на полностью новом Mac;
  2. повторная сборка с восстановленным кешем;
  3. сборка после уничтожения узла и его повторного создания.

Сравнивайте не только успешный статус, но и перечень установленных компонентов, итоговые артефакты, предупреждения подписи и журналы восстановления. Если третий прогон отличается от первого без объяснимой причины, временный пул пока не готов.

Кеш следует считать ускорителем, а не обязательной частью корректности. Он может находиться во внешнем хранилище, однако его ключ должен зависеть от проекта, версии инструментов и архитектуры. Кеш, общий для доверенных и недоверенных заданий, способен вернуть в рабочую область нежелательные файлы.

Как разделить безопасность и эксплуатацию

Вопрос о кодовой подписи: где размещать секреты

Для регистрации runner выбирайте GitHub App или токен с минимально необходимыми правами, а не личный токен администратора без ограничения срока. Сравните:

  • кто выпускает учётные данные;
  • кто отвечает за ротацию;
  • какие действия разрешены;
  • что произойдёт при компрометации;
  • как отозвать доступ без остановки всего CI.

В командах с несколькими репозиториями GitHub App обычно удобнее привязать к организации и централизованно контролировать. Но итоговый выбор зависит от требуемого API и вашей модели доступа; проверяйте актуальные ограничения в документации GitHub REST API для self-hosted runner.

В командах и примерах используйте только заполнители:

export GH_APP_ID="<APP_ID>"
export GH_INSTALLATION_ID="<INSTALLATION_ID>"
export RUNNER_NAME="<RUNNER_NAME>"
export RUNNER_GROUP="<RUNNER_GROUP>"

Не подставляйте реальные значения в образ, issue, workflow-лог или команду, которую копируют в общий чат.

Пятый шаг — вынесите журналы за пределы Mac

Локальный журнал исчезает вместе с временным узлом. Поэтому до включения JIT-пула настройте передачу:

  • журнала поставки;
  • лога подготовки среды;
  • лога регистрации runner;
  • лога задания;
  • результата уничтожения;
  • идентификатора коммита и workflow.

После удаления Mac вы должны ответить, почему задание завершилось ошибкой и был ли узел действительно уничтожен. Проверяйте это на намеренно прерванном задании, а не только на успешной сборке.

Публичные репозитории, недоверенные pull request и публикацию с подписью разделяйте по группам runner и политике доступа. Временный узел для тестов не должен автоматически получить тот же набор секретов, что и узел релизной подписи.

Пошаговый план пилота без перехода к полному продакшену

Шаг 1. Опишите контракт узла

Запишите минимальные требования к macOS, Xcode, Simulator runtime, диску, сети, доступу к хранилищам и инструментам подписи. Не смешивайте технические требования с предположением, что любой Mac сможет принять любое задание.

Шаг 2. Проверьте поставку отдельно от GitHub Actions

Сначала создайте и уничтожьте тестовый Mac через собственный механизм. Подтвердите, что повторный запуск не оставляет старую рабочую папку, ключи и фоновый процесс. Только после этого подключайте Runner Scale Set Client.

Если для проверки нужен отдельный удалённый Mac, можно начать с заказа Mac для тестовой CI-среды и использовать его только для непубликующих workflow. Такой узел должен быть отделён от производственных секретов и легко заменяться после каждого контрольного прогона.

Шаг 3. Подключите JIT-регистрацию

Получите временную конфигурацию через разрешённый API, зарегистрируйте runner на новом узле и проверьте, что регистрационные данные не попали в журнал. Изучите рекомендации GitHub по жизненному циклу self-hosted runner.

Шаг 4. Запустите непубликующий workflow

Начните с тестовой сборки без релизной подписи и без доступа к производственным секретам. Проверьте выбор группы, метки, рабочую директорию, завершение процесса и автоматический выход runner после задания.

Шаг 5. Проверьте холодный старт и восстановление

Запустите новые узлы с одинаковым workflow, затем намеренно прервите один из процессов. В журнале должны быть видны причина сбоя, повторная постановка или отказ по политике, а также результат удаления Mac.

Шаг 6. Подключите внешнее хранение логов

Убедитесь, что после удаления хоста можно восстановить цепочку «очередь — узел — runner — workflow — артефакт». Если хотя бы один участок остаётся только на локальном диске, ограничьте пилот непроизводственными заданиями.

Шаг 7. Сравните три режима

Сопоставьте фиксированный пул, прогретые временные Mac и полную выдачу по запросу. Считайте не только время сборки, но и простои, сбои подготовки, ручные вмешательства, восстановление и расход логов.

Как принять итоговое решение: пилот, два контура или пауза

Выбирайте ограниченный пилот, если автоматическая поставка и уничтожение Mac уже работают, JIT-регистрация проверена, журналы доступны после удаления узла, а среда Xcode восстанавливается без ручного доступа.

Выбирайте двухконтурную схему, если очередь меняется, но автоматизация неполная. Оставьте небольшой фиксированный или прогретый пул для срочных сборок, а новые узлы добавляйте по контролируемой процедуре. Такой вариант даёт время довести восстановление среды и откат поставки, не блокируя команду.

Выбирайте отложенное внедрение, если нагрузка стабильна, узлов мало, подготовка Mac выполняется вручную или вы не можете доказать удаление секретов. В этом случае эластичный слой добавит компоненты отказа, но не даст измеримой пользы.

Для расчёта полной стоимости учитывайте аренду узлов, простаивающие прогретые Mac, подготовку среды, неудачные выдачи, повторное создание, хранение логов и время инженеров. Сравнивайте эту сумму с обслуживанием фиксированного удалённого Mac-пула, а не только с минутами фактической сборки.

Если собственных Mac для такого теста ещё нет, аренда Mac для CI-задач позволяет собрать проверяемый стенд без немедленной покупки оборудования. Для первого этапа выбирайте узлы, которые можно независимо пересоздать и отключить; не начинайте с релизного контура и постоянных ключей подписи.

Почему фиксированный удалённый пул иногда лучше масштабирования

Текущая схема на постоянных Mac обычно проигрывает по трём пунктам: рабочие области дольше живут, очистка после заданий требует дисциплины, а редкие пики создают очередь. Но она выигрывает предсказуемостью среды и отсутствием холодной выдачи.

Эластичный вариант, напротив, добавляет задержку подготовки, зависимость от внешнего контроллера и стоимость неудачных пересозданий. При отсутствии автоматического удаления он ещё и создаёт ложное ощущение изоляции. Поэтому VMSPIN разумно использовать как источник отдельных удалённых Mac для проверяемого пилота: вы сможете сравнить фиксированный узел и одноразовую выдачу на настоящем workflow, не покупая оборудование заранее.

Начните с непубликующих заданий, соберите журналы поставки и восстановления, затем решите, оправдано ли расширение пула. Если нагрузка окажется постоянной или вам нужны физические интерфейсы, локальный Mac или собственная инфраструктура может быть рациональнее аренды. Для временной CI-мощности, тестов и проверки архитектуры отдельные Mac VMSPIN дают более обратимый путь к решению, чем немедленное приобретение нескольких машин.