Активация за 5 минут

Выделенный macOS Runner
Пропустить очередь сборки

$21.2 С/день · выделенное оборудование
Арендовать сейчас
Полный Xcode SSH доступ

CI/CD Xcode на облачном Mac: от сборки до TestFlight — полное руководство

Цепочка сборки iOS и macOS должна работать на реальном железе Apple — поэтому публичные macOS Runner в GitHub Actions заставляют ждать по полчаса, а Mac Studio за тысячи долларов многим недоступен. В статье — полный процесс на выделенном Mac mini M4 SpinMac: Xcode, сертификаты, подпись Archive, TestFlight и подключение как выделенный Runner для GitHub Actions и Jenkins, плюс сравнение трёх типичных CI-подходов.

Почему сборка iOS требует выделенного macOS?

В отличие от Android, где Gradle в Linux-контейнере, цепочка Apple — xcodebuild, подпись кода, notarytool, API App Store Connect — привязана к macOS и физическому Apple Silicon / Intel. Каждая команда с продуктом iOS рано или поздно решает: кто даст этот Mac.

Типичные боли в трёх категориях: очереди публичных Runner (мало бесплатных macOS-минут в GitHub Actions, в пик workflow ждут 20–45 минут), локальная машина занята CI (после push коллеги Xcode тормозит, вентиляторы на полную), хаос с сертификатами (.p12 на разных машинах, срок истёк — никто не заметил). Выделенный облачный Mac решает первые две и даёт единую доверенную среду для третьей.

Тестовая среда

Железо: Mac mini M4 · CPU 10 ядер · 16 ГБ unified memory · SSD 256 ГБ · выделенный канал 1 Gbps (узел SpinMac Япония).
Система: macOS 15 Sequoia, Xcode 16.4. Проект: среднее SwiftUI-приложение (~120 тыс. строк, 3 Extension target).
CI: GitHub Actions self-hosted runner 2.323.0, Jenkins 2.479 LTS + macOS agent.
Подпись: Apple Distribution + ключ API App Store Connect (Issuer ID + Key ID + .p8).

Три подхода CI: что выбрать?

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

Подход Типичная стоимость Очередь / параллелизм Подходит командам
macOS Runner от GitHub Поминутно (от ~$0.08/мин) Общий пул, заметные очереди в пик < 500 мин/мес, ожидание допустимо
Свой Mac mini в серверной Железо $599+ разово + электричество и обслуживание Эксклюзив, но система и сертификаты на вас Офис, частые сборки долгосрочно
Выделенный Mac в облаке (посуточно) SpinMac от $21.2/день, без контракта Физическая машина, сразу доступна Малые команды, релизы по этапам, удалённая работа

На среднем SwiftUI-проекте полный xcodebuild archive на узле M4 занял около 4 мин 12 с (компиляция и линковка Swift). На macOS-14 Runner GitHub: 18 минут очереди и 5 мин 40 с сборки — почти 24 минуты. Для «push и сразу тест» очередь часто важнее самой сборки.

4m 12s Время Archive на M4
18m Очередь GitHub (пик)
1–5 min Выдача узла SpinMac
16 GB Unified memory (без swap)

Инициализация узла: Xcode и материалы подписи

Mac mini SpinMac поставляется с полным macOS и правами администратора. После активации — SSH или VNC в браузере, затем подготовка CI в указанном порядке. Храните сертификаты и профили в фиксированных путях для единообразия в workflow.

  1. 01
    Установка Xcode и CLI

    Xcode 16.x из App Store или через xcode-select, затем sudo xcodebuild -license accept и xcodebuild -runFirstLaunch. Проверка: xcodebuild -version показывает нужную версию.

  2. 02
    Импорт сертификата и Provisioning Profile

    Передайте Distribution .p12 и пароль в ~/certs/, импортируйте через security import; .mobileprovision — в ~/Library/MobileDevice/Provisioning Profiles/. В CI — отдельная связка ключей с доверием -T /usr/bin/codesign.

  3. 03
    Настройка ключа API App Store Connect

    Создайте API Key в Apple Developer, сохраните AuthKey_XXXXXX.p8 в ~/private_keys/. Для TestFlight — xcrun altool или fastlane pilot upload, без интерактивного входа Apple ID.

  4. 04
    Клонирование репозитория и кэш DerivedData

    После первого git clone сделайте локальный Archive и проверьте цепочку подписи. DerivedData на локальном SSD (256 ГБ хватает для среднего проекта) — инкрементальные сборки быстрее на 30–50%.

Типичные проблемы связки ключей в CI

В headless (SSH / Runner) 90% сбоев codesign — неразблокированная или неавторизованная связка ключей. В начале скрипта: security unlock-keychain -p "$KEYCHAIN_PASSWORD" ~/Library/Keychains/ci.keychain-db и set-key-partition-list для codesign. Пароль не в Git — GitHub Secrets или Jenkins Credentials.

Подключение self-hosted Runner GitHub Actions

После регистрации выделенного Runner workflow направляется через runs-on: self-hosted или label (например macos-m4), минуя общий пул. Шаги проверены на узле SpinMac.

В репозитории GitHub: Settings → Actions → Runners → New self-hosted runner, macOS ARM64, скачайте и распакуйте actions-runner, затем:

./config.sh --url https://github.com/YOUR_ORG/YOUR_REPO --token RUNNER_TOKEN --labels macos-m4,ios-build --unattended

После регистрации установите как системный сервис: sudo ./svc.sh installsudo ./svc.sh start. В YAML workflow укажите label:

runs-on: [self-hosted, macos-m4]

Типичный iOS job: checkout → разблокировка связки ключей → xcodebuild archivexcodebuild -exportArchivexcrun altool --upload-app или Fastlane upload_to_testflight. На M4 одна lane Fastlane от push до обработки TestFlight (с очередью Apple) в среднем ~11 минут, из них чуть больше 6 — локальная сборка и загрузка.

Безопасность

Self-hosted Runner видит код и ключи подписи: ограничьте права collaborators, регулярно меняйте registration token, не запускайте workflow с секретами на fork PR автоматически (pull_request_target — с осторожностью). На общем узле — отдельные Runner по проектам или изоляция через песочницу OpenClaw.

Настройка macOS Agent Jenkins

Если контроллер Jenkins уже есть (часто на Linux), сборка macOS — через agent. На Mac SpinMac в облаке: JDK 17 и agent.jar Jenkins как LaunchDaemon; контроллер забирает задачи по SSH или JNLP.

Сильные стороны Jenkins — визуальные pipeline и плагины: Xcode, Credentials Binding, AnsiColor, архив артефактов. Типично: stage('Archive') с sh 'xcodebuild ...', stage('Upload') с Fastlane или altool. Зафиксируйте DEVELOPER_DIR как /Applications/Xcode.app/Contents/Developer.

По сравнению с GitHub Actions Jenkins лучше для многоветочных внутренних процессов с ручным approval. Облачный Mac посуточно — «эластичный agent»: узел на неделю релиза, в спад — отключение, без Mac в серверной 365 дней в году.

Archive, подпись и загрузка в TestFlight

Независимо от CI цепочка одна: Archive → .xcarchive, Export → .ipa, загрузка в App Store Connect. В CI стандарт — командная строка без GUI Xcode.

Пример Archive (Release, scheme и путь вывода):

xcodebuild archive -workspace MyApp.xcworkspace -scheme MyApp -configuration Release -archivePath build/MyApp.xcarchive CODE_SIGN_STYLE=Manual PROVISIONING_PROFILE_SPECIFIER="MyApp AppStore"

Для Export нужен ExportOptions.plist (method app-store), затем:

xcodebuild -exportArchive -archivePath build/MyApp.xcarchive -exportPath build/export -exportOptionsPlist ExportOptions.plist

Для TestFlight лучше API Key — без зависания 2FA в unattended-среде:

xcrun altool --upload-app -f build/export/MyApp.ipa -t ios --apiKey KEY_ID --apiIssuer ISSUER_ID

На среднем проекте 10 ядер M4 ускоряют параллельную компиляцию Swift vs старые Intel CI; 16 ГБ unified memory хватает на полный clean build без swap. При многих Swift Package — кэш -clonedSourcePackagesDirPath для следующих сборок.

Нет серверной в офисе — как стабильно гонять iOS CI?

Дилемма многих инди и малых команд: нужен macOS для сборки, но не хочется офис, кабели и отключения ради одной CI-машины. Публичные VM не подходят (нет полного macOS и цепочки подписи Apple); б/у Mac mini дома — нестабильный uplink, смена IP, случайное выключение.

SpinMac — выделенный физический Mac mini M4: без виртуализации и overselling, 16 ГБ RAM и 1 Gbps на машину, активация за 1–5 минут после оплаты. Пять регионов (Сингапур, Япония, Корея, Гонконг, восток США) — например Токио для приложения на японский рынок, меньше задержка при загрузке в TestFlight.

Тарифы: от $21.2/день, $57.3/неделя, $106.1/месяц, без долгого контракта. Узел на неделю релиза с Runner, в простой — отключение, часто выгоднее года своей машины и электричества. Для параллельных сборок — параллель Thunderbolt 5, кластер 80 Gbps для крупных monorepo или матрицы приложений.

  1. 01
    Выбор узла и активация в SpinMac

    Войдите в консоль, выберите регион и срок; после оплаты SSH и VNC выдаются автоматически. Подробнее в центре помощи.

  2. 02
    По разделу 3 настройте Xcode и подпись

    Пути связки ключей и API Key — в переменные окружения для GitHub Actions / Jenkins.

  3. 03
    Зарегистрируйте Runner и запустите первый pipeline

    Сначала Debug-сборка, затем Release Archive + TestFlight; закрепите Fastlane или нативные скрипты в репозитории.

Стоимость и выбор: одна таблица для принятия решения

Ваша ситуация Рекомендуемый путь Роль облачного Mac
Индивидуальная разработка, 1–2 релиза в месяц. Арендуйте SpinMac в день релиза + Архив вручную. Временная сборочная машина — освобождайте после работы
Команда 5–15 человек, несколько операций в день Всегда включен self-hosted Runner Помесячная аренда, выделено, без очередей
Jenkins есть, нужен агент macOS Облачный Mac как эластичный Agent Масштабируйте пики, не покупайте новое оборудование
Матрица для нескольких приложений + пакетные сборки в ночное время TB5 связывание кластеров Параллельное архивирование нескольких M4

Главная сложность iOS CI/CD не в Xcode, а в стабильной macOS-инфраструктуре и воспроизводимой среде подписи. Общие Runner подходят для редких сборок; локальный CI — для зрелых команд с сильным DevOps; выделенный облачный Mac закрывает разрыв между «без очередей» и «без покупки железа» — оплата по дням, предсказуемая производительность физического сервера, близкие глобальные узлы. Перенесите сборку и подпись в облако — пусть MacBook пишет код, а не отдаёт вентиляторы и память ночному CI.

Выделенная физическая машина · запуск за 5 минут

Предоставьте своему проекту iOS машину для сборки macOS без очереди.

SpinMac Mac mini M4 выделенный узел: полная macOS и Xcode, 16 GB унифицированная память, SSH/VNC доступ, GitHub Actions и Jenkins готовый Runner — от $21.2/день.

$21.2 / день от
ЧипApple M4
CPU10-core посвященный
Память16 GB единый
Пропускная способность1 Gbps посвященный
SLA99.9%
Доставка1–5 minutes