От подключения до релиза

Запустите первый CI-конвейер сборки iOS

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

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

Заказ и вход

Проверьте заказ и данные для подключения, выполните первый вход по SSH и добавьте открытый ключ.

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

Удалённое подключение

Для скриптов и CI используйте SSH. Для отладки Xcode, симулятора и графического интерфейса подключайтесь по VNC.

Настроить подключение

Подключение CI

Зарегистрируйте self-hosted runner, проверьте метки инструментов и сначала ограничьте параллелизм на каждом компьютере одной задачей.

Настроить runner

Оплата и продление

Проверьте расчётный период, дополнительные опции и срок аренды. Актуальные статусы заказа, оплаты и продления отображаются в консоли.

Информация об оплате
Сначала проверьте подключение

Первые четыре действия после заказа

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

  1. Проверьте экземпляр

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

  2. Первый вход по SSH

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

  3. Смените пароль

    В интерактивном сеансе SSH выполните passwd, затем следуйте подсказкам, чтобы сменить пароль текущего пользователя. Не указывайте пароль в аргументах команды и не сохраняйте его в репозитории, переписке или логах сборки. Не закрывайте текущий сеанс; откройте новый и проверьте, что новый пароль работает.

  4. Добавьте открытый ключ

    Создайте отдельную пару ключей на своём компьютере и добавьте на Mac только открытый ключ. Убедитесь, что вход по ключу работает, прежде чем менять настройки входа по паролю. Перед изменением настроек SSH оставьте активный сеанс, чтобы не потерять доступ к компьютеру.

Локальные параметры подключения и проверка на Mac
ssh -p "$MAC_SSH_PORT" "$MAC_USER@$MAC_HOST"

whoami
sw_vers
uname -m
xcode-select -p
df -h
passwd

Перед подключением задайте локально переменные MAC_SSH_PORT,MAC_USERиMAC_HOSTсо значениями из консоли. Остальные команды выполняйте на подключённом Mac; командаxcode-select -p показывает путь к текущим инструментам разработки.

На Mac · добавьте скопированный открытый ключ
install -d -m 700 "$HOME/.ssh"
touch "$HOME/.ssh/authorized_keys"
chmod 600 "$HOME/.ssh/authorized_keys"
printf '%s\n' "$LOGIN_PUBLIC_KEY" >> "$HOME/.ssh/authorized_keys"

Сначала присвойте переменной LOGIN_PUBLIC_KEY полный текст открытого ключа, затем выполните команду добавления. Не загружайте закрытый ключ и не добавляйте один и тот же открытый ключ повторно. Тайм-аут подключения, сбой аутентификации и изменение ключа хоста — разные проблемы; укажите в заявке, какая именно возникла.

Настройте воспроизводимую среду

Зафиксируйте версию Xcode и подготовьте симулятор

Сначала запишите, какие версии Xcode, SDK и runtime нужны проекту, а не обновляйте всё до последней версии. Совместимость системы и Xcode определяет, что можно установить. Для существующего проекта сначала используйте проверенную локальную конфигурацию и отдельно протестируйте обновление.

Если на Mac ещё не установлен xcodes, сначала подготовьте этот инструмент в соответствии с принятым в команде процессом установки ПО. Чтобы установить нужную версию, используйте легально полученный локальный установщик Xcode, подходящий требованиям проекта. Переменные XCODE_VERSION и XCODE_XIP ниже содержат проверенный номер версии и абсолютный путь к установщику соответственно. Не включайте интерактивные этапы установки в автоматические задания сборки.

На Mac · установка и проверка инструментов разработки
xcodes installed
xcodes install "$XCODE_VERSION" --path "$XCODE_XIP"
xcodes installed

export DEVELOPER_DIR="$XCODE_APP/Contents/Developer"
xcodebuild -version
xcodebuild -showsdks
xcrun simctl list runtimes

XCODE_APP должен указывать на фактический путь к установленному приложению. Для CI задавайте DEVELOPER_DIRв среде задания, чтобы несколько задач не пытались одновременно изменить глобальный выбор. Если всё же нужно переключить системную цепочку инструментов по умолчанию, выполните sudo xcode-select --switch "$XCODE_APP/Contents/Developer", затем ещё раз проверьте xcodebuild -version.

При первом запуске выбранного Xcode установите необходимые компоненты. Графический интерфейс доступен через удалённое подключение. Затем установите нужный runtime в настройках компонентов Xcode. Выполните xcrun simctl list devices available, выберите симулятор для целевых тестов, один раз запустите его в интерактивном режиме и дождитесь полной загрузки, а затем выполните минимальный тест. Архивация приложения для устройства и тестирование в симуляторе — разные этапы. Не принимайте отсутствие runtime за сбой инструментов архивации.

В начале логов CI выводите как минимум версию Xcode, список SDK и номер коммита. После смены Xcode сформируйте новый ключ кэша и проверьте сторонние зависимости, подпись и экспорт. Одна лишь смена метки runner без проверки фактического пути к инструментам не гарантирует одинаковую среду сборки.

Сначала одна задача, затем масштабирование

Зарегистрируйте Mac как self-hosted runner

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

GitLab Runner: проверьте метки и исполнитель

Создайте проектный runner в настройках проекта, подготовьте токен аутентификации и задайте три метки: macos,arm64иios-archive . Временно сохраните адрес экземпляра и токен аутентификации в переменных GITLAB_URLиGITLAB_RUNNER_TOKEN, затем зарегистрируйте shell executor от имени отдельного пользователя сборки. После регистрации удалите временную переменную с токеном.

GitLab Runner · регистрация и настройка параллелизма
gitlab-runner register \
  --non-interactive \
  --url "$GITLAB_URL" \
  --token "$GITLAB_RUNNER_TOKEN" \
  --executor "shell" \
  --description "armrdp-ios-archive"

unset GITLAB_RUNNER_TOKEN
gitlab-runner verify

В файле config.toml , который использует этот runner, установите глобальное значение concurrent = 1, а для соответствующего runner задайте limit = 1. Запустите runner способом, предусмотренным для установленной версии. Успешная интерактивная проверка ещё не означает, что фоновая служба работает.

В проекте · задание архивации в .gitlab-ci.yml
ios_archive:
  tags:
    - macos
    - arm64
    - ios-archive
  script:
    - xcodebuild -version
    - xcodebuild archive -workspace "$IOS_WORKSPACE" -scheme "$IOS_SCHEME" -destination 'generic/platform=iOS' -archivePath "$CI_PROJECT_DIR/output/App.xcarchive"
  artifacts:
    paths:
      - output/App.xcarchive
    expire_in: 7 days

В переменных проекта задайте фактические значения IOS_WORKSPACE и IOS_SCHEME, а также подготовьте подпись, описанную в следующем разделе. Этот пример выполняет только архивацию — без экспорта и загрузки. Хранение артефактов в течение 7 дней указано для примера и может быть изменено согласно политике команды. Не помещайте сертификаты, закрытые ключи или временный Keychain в artifacts.

GitHub Actions: один процесс runner выполняет одну задачу

Скачайте программу для macOS ARM64 по инструкциям установки runner в настройках репозитория и перейдите в распакованный каталог. Задайте переменную REPOSITORY_URL со значением адреса текущего репозитория, аRUNNER_TOKEN — токеном для этой регистрации. Укажите одинаковые метки в конфигурации регистрации и рабочем процессе, чтобы задача не попала на узел с неподходящими инструментами.

GitHub Actions · регистрация на Mac
./config.sh \
  --url "$REPOSITORY_URL" \
  --token "$RUNNER_TOKEN" \
  --name "armrdp-ios-archive" \
  --labels "macos,arm64,ios-archive" \
  --work "_work"

unset RUNNER_TOKEN
./run.sh
В проекте · рабочий процесс GitHub Actions
name: iOS archive
on:
  workflow_dispatch:

permissions:
  contents: read

concurrency:
  group: ios-archive
  cancel-in-progress: false

jobs:
  archive:
    runs-on: [self-hosted, macos, arm64, ios-archive]
    env:
      DEVELOPER_DIR: ${{ vars.DEVELOPER_DIR }}
      IOS_WORKSPACE: ${{ vars.IOS_WORKSPACE }}
      IOS_SCHEME: ${{ vars.IOS_SCHEME }}
    steps:
      - uses: actions/checkout@v4
      - name: Archive
        run: |
          xcodebuild -version
          xcodebuild archive \
            -workspace "$IOS_WORKSPACE" \
            -scheme "$IOS_SCHEME" \
            -destination 'generic/platform=iOS' \
            -archivePath "$RUNNER_TEMP/App.xcarchive"

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

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

Храните учётные данные отдельно от кода

Настройте подпись от имени пользователя сборки

Сертификат распространения, соответствующий закрытый ключ и профиль подготовки должны соответствовать команде и Bundle Identifier проекта. Сначала проверьте подпись в контролируемом задании, затем настройте автоматический процесс. Не отключайте проверку подписи, чтобы скрыть ошибку экспорта.

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

На Mac · проверка идентификатора подписи и каталога профилей подготовки
security list-keychains -d user
security find-identity -v -p codesigning
printf '%s\n' "$HOME/Library/MobileDevice/Provisioning Profiles"
printf '%s\n' "$HOME/Library/Developer/Xcode/UserData/Provisioning Profiles"

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

Если команда уже использует fastlane match, продолжайте работать с существующим зашифрованным репозиторием сертификатов и принятой политикой доступа. На этапе проверки выполните bundle exec fastlane match appstore --readonly, чтобы сначала получить имеющиеся материалы подписи и не допустить случайного изменения сертификатов команды на узле сборки. Отдельно управляйте доступом к репозиторию, паролем расшифровки и паролем Keychain. Переменные для производственной подписи предоставляйте только защищённым веткам или контролируемым задачам, запускаемым вручную.

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

Считайте кэш данными, которые можно пересоздать

Проверьте дополнительный диск и перенесите DerivedData

Можно заказать дополнительный SSD на +1TB или +2TB. Перед переносом проверьте в заказе и на Mac, что расширение уже предоставлено. Название тома, точка монтирования и файловая система зависят от фактической конфигурации — не копируйте идентификаторы дисков с других компьютеров.

Выполните diskutil list и df -h, чтобы проверить объём и точки монтирования. Не стирайте и не разбивайте на разделы диск, назначение которого вам неизвестно. Создайте каталог кэша с правом записи для пользователя сборки и проверьте чтение и запись небольшим файлом. Убедившись, что том подключается после перезагрузки, переключите на новый путь постоянно работающий runner.

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

На Mac · проверка монтирования и указание каталога кэша сборки
diskutil list
df -h

test -d "$BUILD_VOLUME" && test -w "$BUILD_VOLUME"
mkdir -p "$BUILD_VOLUME/DerivedData/$CACHE_KEY"

xcodebuild archive \
  -workspace "$IOS_WORKSPACE" \
  -scheme "$IOS_SCHEME" \
  -destination 'generic/platform=iOS' \
  -derivedDataPath "$BUILD_VOLUME/DerivedData/$CACHE_KEY" \
  -archivePath "$BUILD_VOLUME/Archives/$BUILD_ID/App.xcarchive"

Перед выполнением задайте для BUILD_VOLUME путь к смонтированному каталогу с проверенным правом записи.CACHE_KEY должен различаться для разных репозиториев, версий Xcode и конфигураций сборки. ПеременнаяBUILD_ID должна содержать уникальный идентификатор текущей задачи, чтобы архивы разных запусков не перезаписывали друг друга. Параллельные задачи не должны использовать один каталог DerivedData с правом записи.

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

Опишите проблему так, чтобы её можно было воспроизвести

Подробные шаги в заявке полезнее, чем просто текст ошибки

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

Добавьте сведения по типу проблемы. Не отправляйте пароли, закрытые ключи или полные платёжные данные.
ПолеЧто указатьЗачем это нужно
Номер компьютера или заказаНомер из консоли и текущий узелЧтобы найти нужную услугу и не проверять другой экземпляр
Время возникновенияВремя начала и окончания, часовой пояс и продолжается ли проблемаЧтобы сопоставить записи об услуге с логами задач
Тип проблемыТайм-аут подключения, сбой аутентификации, сборки или подписи либо статус оплатыЧтобы отличить проблемы сети, инструментов и расчётов
Шаги для воспроизведенияПорядок действий, минимальная команда, ожидаемый и фактический результатЧтобы сократить число уточняющих вопросов
Среда и логиВерсия Xcode, пользователь службы runner и обезличенные логи до и после ошибкиЧтобы определить связь с версией или правами доступа
Влияние на работуЗатронута одна задача или весь компьютер, есть ли альтернативный способ сборкиЧтобы понять масштаб и текущие меры по устранению проблемы

Время ответа и время решения — не одно и то же

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

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

Оплата, продление и проверка перед окончанием аренды

Услуга оплачивается заранее за день, неделю, месяц или квартал. Проверяя заказ, сверьте модель, узел, начало и окончание периода, а также дополнительные опции. Актуальные настройки продления, автопродления и статус платежа смотрите в консоли. Отправка платежа не означает, что заказ уже активирован; не определяйте статус услуги только по снимку экрана с оплатой.

Доступны USDT-TRC20 и Visa / Mastercard / Amex через Stripe. Все платежи проводятся в долларах США; доступность платёжного шлюза определяется ответом системы. При оплате в блокчейне проверьте сеть, реквизиты получателя и сумму. Для диагностики укажите номер заказа и идентификатор транзакции — не отправляйте закрытый ключ кошелька или полные данные банковской карты.

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

Сначала добейтесь стабильной сборки одного scheme

Начните с одного компьютера и одной задачи: проверьте инструменты, подпись и артефакты, а затем расширяйте парк runner. Выделенный физический Mac можно арендовать посуточно от $21.1/день. Фактическая доступность отображается в консоли.