Для тех, кто отвечает за слияние и релизы

Поручите следующую сборку выделенному узлу

Сначала вручную соберите проверяемый ipa, затем передайте задачу CI. Шаги охватывают запуск, подключение, настройку, распространение и повседневную эксплуатацию — переписывать существующий pipeline не нужно.

Рассчитывайте примерно на час для пробного подключения — это не обещание срока. Загрузка крупных зависимостей, установка Xcode и подготовка материалов подписи могут занять дополнительное время. Если узел уже есть, начните с проверки подключения.

Перед запуском соберите исходные данные

Выберите узел под текущий проект

Если сборки нужны лишь изредка и у вас уже есть свободный Mac, самостоятельная настройка может обойтись дешевле. Если слияния происходят несколько раз в день и вы не хотите следить за питанием, сетью и охлаждением, рассмотрите выделенный сервер. OSXPort предоставляет целиком физический Mac mini: один узел — одному клиенту, это не виртуальная машина.

  1. 01

    Проверьте требования проекта

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

  2. 02

    Выберите конфигурацию и срок

    На странице заказа выберите модель, регион и срок аренды: день, неделю, месяц или квартал. Port M4 Base подойдёт для лёгкой пробной сборки; для сборок из нескольких веток и задач с симуляторами сначала оцените Port M4 Plus, а для крупных проектов с несколькими target — Port M4 Pro.

  3. 03

    Сохраните данные узла

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

  4. 04

    Выберите ближайший регион

    Доступны Сингапур, Япония (Токио), Южная Корея (Сеул), Гонконг и запад США. Учитывайте не только расположение команды, но и местонахождение репозитория и источников зависимостей. Качество связи между регионами проверьте на собственных задачах загрузки и выгрузки.

Доступны три конфигурации: Apple Silicon M4 · 16 ГБ объединённой памяти · SSD 256 ГБ; Apple Silicon M4 · 24 ГБ объединённой памяти · SSD 512 ГБ; Apple Silicon M4 Pro · 64 ГБ объединённой памяти · SSD 2 ТБ. Для первой проверки не стоит сразу увеличивать параллелизм: сначала измерьте расход памяти и диска, а также размер артефактов при одной сборке.

Сначала проверьте узел, затем подключайте pipeline

Выполните вход, сборку и экспорт от имени одного пользователя

При первом подключении проверьте адрес узла и имя пользователя, затем — инструменты разработки. Ниже приведён пример сеанса, а не актуальный вывод с узла. Версии указаны для примера; проверьте их непосредственно на своём узле.

Проверьте три уровня — переустанавливать всё сразу не нужно

Уровень подключения:Подключитесь, используя адрес, порт и имя пользователя из консоли. При первом подключении проверьте отпечаток ключа хоста. Если он неожиданно изменился, сначала выясните, не заменили ли узел, и не пропускайте проверку. При тайм-ауте проверьте адрес и сеть; при отказе в аутентификации — имя пользователя и учетные данные.

Уровень инструментов:Выполните xcode-select -p и проверьте текущий каталог разработчика. Командой xcodebuild -version зафиксируйте версию. Если проекту нужна другая версия, сначала убедитесь, что она установлена, а затем явно переключите путь.

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

В примере NODE_USER и NODE_ADDRESS замените значениями из консоли;App.ipa — пример имени артефакта. Если проект управляет fastlane через Bundler, используйте принятую в проекте команду bundle exec fastlane gym.

osxport · tokyo-node
$ ssh "$NODE_USER@$NODE_ADDRESS"
$ xcode-select -p
/Applications/Xcode.app/Contents/Developer
$ xcodebuild -version
Xcode 16.4
Build version 16F6
$ cd ~/workspace/App
$ fastlane gym
Creating archive
Exporting archive
Successfully exported and compressed dSYM file
Successfully exported and signed the ipa file
Exported ipa: ./build/App.ipa
$ ls -lh ./build/App.ipa

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

Используйте существующий CI команды

Перед регистрацией runner сначала выполните одну задачу вручную

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

Self-hosted runner GitHub Actions

Подходит:Командам примерно из 3–15 человек, уже работающим через workflow-файлы. Отдельная система планирования не нужна: достаточно зарегистрировать узел в репозитории или организации с ограниченным доступом.

  1. В настройках репозитория или организации скачайте пакет runner и получите команду регистрации для вашей версии macOS и архитектуры процессора.
  2. Зарегистрируйте runner от имени отдельного пользователя, добавьте метку команды и укажите её в параметре workflow runs-on .
  3. Сначала проверьте версии и запустите сборку без конфиденциальных данных, затем настройте фоновую службу, передачу секретов и загрузку артефактов.

Не рекомендуется:Открывать узел с материалами подписи для недоверенных внешних pull request. Выделенный узел не изолирует workflow друг от друга.

Проверить runner по списку

GitLab Runner · shell executor

Подходит:Командам примерно из 3–30 человек, централизовавшим код и управление доступом в GitLab. shell executor напрямую использует Xcode и инструменты командной строки на узле.

  1. Установите GitLab Runner для macOS и зарегистрируйте его с данными, предоставленными проектом или группой.
  2. Выберите shell executor, назначьте отдельную метку и ограничьте доступ к защищённым веткам и допустимым задачам.
  3. Разбейте восстановление зависимостей, сборку, экспорт и сохранение артефактов на отдельные проверяемые этапы. Начните с одного параллельного задания.

Не рекомендуется:Запускать на одном shell executor задачи из недоверенных репозиториев разных клиентов. Контролируйте рабочие каталоги и права на хосте самостоятельно.

Проверить runner по списку

Jenkins agent

Подходит:Командам примерно из 10–30 человек, у которых уже есть Jenkins controller и процесс согласования релизов. Добавьте узел как macOS agent — переносить весь pipeline не придётся.

  1. Создайте в controller отдельный agent и задайте метку узла, отдельный рабочий каталог и пользователя для запуска.
  2. Настройте подключение по конфигурации controller, проверьте совместимость требуемой версии Java со средой agent, затем включите постоянную работу.
  3. В тестовых задачах явно указывайте метку macOS и проверяйте переменные среды, пути к инструментам и права на архивирование артефактов.

Не рекомендуется:Создавать controller ради редких сборок. Если у вас уже есть лёгкий CI, добавлять ещё один компонент для обслуживания обычно незачем.

Проверить runner по списку

Runner в сети? Проверьте ещё четыре пункта

Выполняйте проверки от имени пользователя, под которым фактически работает runner, а не только в личном интерактивном сеансе.
ПроверкаКак проверитьУсловие успеха
Рабочий каталог и инструментыВыполните whoami,pwd и xcodebuild -versionИмя пользователя, каталог и версия Xcode соответствуют настройкам задачи
Доступ к репозиторию и зависимостямПолучите нужную ветку с ограниченными учетными данными, переданными CI, и восстановите зависимости по lock-файлуНе используются незадекларированные токены или пути из личного терминала
Доступность подписиВыполните архивирование и экспорт в неинтерактивном режимеНет диалоговых окон, ожидающих подтверждения; учетные данные не попадают в журналы
Повторное подключение и сохранение артефактовПроверьте статус фоновой службы, а после выполнения задачи получите артефакты и журналыRunner восстанавливает соединение; артефакты не остаются только во временном рабочем каталоге

На одном узле можно зарегистрировать несколько управляемых runner, но все они используют общие CPU, объединённую память и SSD. Начните с одной сборки за раз и постепенно увеличивайте параллелизм на основе собственных измерений. Несколько имён runner не добавляют физических ресурсов.

Пишите код в Windows, собирайте на macOS

Выполняйте этап сборки iOS для Flutter на удалённом узле

В Windows можно писать код, отправлять изменения и просматривать журналы; компиляция iOS и подпись выполняются на облачном Mac. Выделенный узел не заменяет действующее членство в программе разработчиков Apple, сертификат подписи, закрытый ключ и профиль подготовки, соответствующий приложению.

  1. 01

    Зафиксируйте зависимости

    Синхронизируйте один и тот же commit и lock-файл, проверьте совместимость Flutter, Dart, CocoaPods и Xcode. Сначала выполните flutter doctor -v для проверки инструментов, затем flutter pub get. Не добавляйте в проект абсолютные пути с другого компьютера.

  2. 02

    Импортируйте материалы подписи

    Передайте сертификат, закрытый ключ и профиль подготовки безопасным способом, согласованным командой. Импортируйте сертификат в отдельную связку ключей, доступную пользователю, от имени которого выполняется сборка; настройте профиль подготовки и параметры экспорта. Убедитесь, что bundle identifier, ID команды и тип распространения совпадают.

  3. 03

    Соберите и скачайте артефакт

    Выполните flutter build ipa --release. Если проекту нужны специальные правила экспорта, укажите соответствующий параметр --export-options-plist. Обычно артефакт находится в каталоге проекта build/ios/ipa/. Ориентируйтесь на фактический вывод команды, затем сохраните артефакт из CI в хранилище команды.

  4. 04

    Учитывайте ограничения тестирования

    На удалённом узле можно запускать тесты симулятора и автоматические сборки. Проверки с физическими устройствами, датчиками и взаимодействием с ними оставьте на стороне устройств. Команды React Native тоже могут собирать iOS на узле, но зависимости следует восстанавливать по скриптам конкретного проекта.

Кэш ускоряет сборку, но не заменяет резервную копию. Формируйте ключи кэша с учётом проекта, версии Xcode и lock-файла зависимостей. При проблемах с подписью сначала проверьте срок действия, закрытый ключ и соответствие профиля — не удаляйте сразу весь кэш сборки.

Сначала проверьте экспорт, затем настройте загрузку

Храните ключи распространения отдельно от учетных данных узла

Для распространения через TestFlight приложение должно пройти необходимую настройку в App Store Connect, а у вас должны быть соответствующие права на выпуск. API Key авторизует загрузку, но не заменяет сертификат подписи и профиль подготовки, необходимые для сборки.

Порядок настройки

  1. Подготовьте устанавливаемый артефакт.Сначала используйте fastlane gym или принятую в проекте команду для архивирования и экспорта. Проверьте bundle identifier, версию и номер сборки.
  2. Подготовьте API Key.Пользователь с нужными правами должен создать API Key для App Store Connect с подходящей ролью, сохранить Key ID и Issuer ID и надёжно защитить файл закрытого ключа.
  3. Передайте ключ в CI.Храните закрытый ключ и идентификаторы в системе управления секретами команды. В начале задачи создавайте конфигурационный файл с ограниченным доступом, а в конце удаляйте его. Не добавляйте конфигурацию или закрытый ключ в репозиторий.
  4. Загрузите сборку и проверьте её обработку.Запустите pilot и проверьте ID приложения и результат загрузки. Успешная загрузка ещё не означает, что сборка доступна тестировщикам: дождитесь завершения обработки и подтвердите распространение.

Команда загрузки готового ipa

fastlane pilot upload \
  --api_key_path "$ASC_API_KEY_JSON" \
  --ipa "$IPA_PATH" \
  --skip_waiting_for_build_processing true

ASC_API_KEY_JSON должен указывать на временный конфигурационный файл API Key, созданный в формате fastlane, аIPA_PATH — на фактический ipa-файл. Если используете Bundler, добавьте перед командой bundle exec.

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

Если загрузка не проходит, разберите тип ошибки

При ошибке аутентификации проверьте Key ID, Issuer ID, закрытый ключ и права роли. Если номер сборки уже использован, измените его — перенастраивать runner не нужно. При ошибке подписи или ID приложения вернитесь к этапу архивирования и экспорта. Разделите сборку, подпись и загрузку на три точки проверки, чтобы не перезапускать весь pipeline.

Включите передачу узла в pipeline

Узел работает круглый год — задачи должны переноситься

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

Заранее подготовьте инструкции для восстановления

Запишите метки runner, версии инструментов, названия переменных среды, порядок установки зависимостей и шаги импорта подписи. Скрипты автоматического восстановления упрощают передачу дел и надёжнее личных заметок.

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

Открыть список проверок подключения

При сбое сохраните данные для диагностики

Запишите ID узла, время и часовой пояс, последнюю успешную задачу и краткое описание ошибки. Отдельно укажите, доступен ли SSH, в сети ли runner и запускаются ли задачи. Вместо расплывчатого «сборка сломалась» приведите конкретные симптомы.

Если вход ещё доступен, сначала сохраните нужные данные и журналы, затем приостановите новые задачи. Не включайте в заявку конфиденциальные сведения. Если нужна помощь с доступом, точно укажите, что разрешаете проверить; не отправляйте закрытые ключи или пароли целиком.

Войти в консоль и сообщить о проблеме

После замены узла повторите проверку

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

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

Повторно проверить подключение

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

Передавайте вместе узел и сведения о счетах

Проверьте срок действия до релиза, не дожидаясь последнего напоминания

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

Перед изменением среды уточните ограничения

Шесть частых вопросов команд, которые используют узел

Можно ли установить Homebrew и зависимости проекта?

Инструменты разработки и зависимости проекта можно устанавливать стандартным способом для macOS. Перед установкой проверьте архитектуру, путь и требования к правам, а версии и порядок установки внесите в реестр среды. Сначала воспроизведите существующие зависимости проекта. Не обновляйте все инструменты одновременно — иначе трудно понять, вызван ли сбой проектом или изменением среды.

Можно ли выбрать версию Xcode?

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

Есть ли права root? Нужно ли запускать runner от root?

На узле доступны графический интерфейс macOS и командная строка. Проверьте, какие права администратора и sudo предусмотрены учетными данными из консоли. Если для установки нужны дополнительные права, сначала уточните это через заявку. Не используйте прямой вход root по умолчанию и не запускайте обычные CI-задачи с повышенными правами. Разделяйте сборку, ключи и рабочие каталоги согласно принципу наименьших привилегий.

Может ли несколько участников команды пользоваться одним узлом?

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

Может ли кэш удалить другой клиент?

Узел целиком выделен одному клиенту, поэтому ресурсы сборки не используются совместно с другими клиентами. Кэш, однако, может пострадать от скриптов очистки команды, управления диском или изменений среды. Считайте его восстанавливаемым средством ускорения; отдельно резервируйте код, материалы подписи и итоговые артефакты. После замены узла зависимости должны восстанавливаться по lock-файлу.

Что приложить к заявке, если настройка не удаётся?

Укажите ID узла, тип CI, commit, связанный с задачей, время и часовой пояс, а также журнал без конфиденциальных данных рядом с первой ошибкой. Сообщите, одинаково ли ведёт себя та же команда в интерактивном терминале и runner. Удалите токены доступа, закрытые ключи, пароли и внутренние данные из конфиденциальных путей. Если для дальнейшей диагностики понадобится доступ, поддержка согласует его объём через заявку.

Проверьте сервер сборки на реальной задаче

Сначала арендуйте на день и проверьте ночную сборку, а затем решайте, нужен ли постоянный узел. Port M4 Base — от $19.7 в день. Сохраните ID commit, журнал сборки и артефакт — выбирайте конфигурацию на основе своего проекта.