Симулятор запускается, но готового iOS-архива нет: на Windows или Linux не хватает Xcode, CocoaPods и подписывающих ключей.

Самый быстрый путь — оставить JavaScript-разработку на своём компьютере, а проект с папкой ios синхронизировать с удалённым Mac; зависимости, Release-сборку, подпись, Archive и загрузку в TestFlight выполнять там последовательно.

Эта схема соответствует границе официального инструментария: документация React Native указывает Xcode как часть среды нативной iOS-разработки, а документация Xcode описывает Archive, распространение и последующую обработку сборки. Требования React Native к среде и официальный порядок распространения из Xcode подтверждают именно этот подход.

Эта статья для вас, если вы:

  • разрабатываете React Native App в Windows или Linux и впервые готовите iOS-релиз;
  • используете React Native CLI или нативные модули и должны видеть проект Xcode;
  • хотите превратить удалённый Mac из разовой «машины для подписи» в восстанавливаемую среду сборки.

Ниже используется проект React Native CLI с уже созданной папкой ios. Expo Managed Workflow и облачная сборка Expo здесь не рассматриваются: у них другая граница ответственности и другой порядок диагностики.

01

До первой сессии: разделите работу между компьютерами

Главная ошибка — пытаться перенести на удалённый Mac вообще весь процесс. Для React Native это необязательно.

На Windows или Linux можно оставить:

  • редактирование JavaScript и TypeScript;
  • работу с Git;
  • запуск Android-части;
  • анализ React Native-кода;
  • подготовку веток и pull request;
  • локальную проверку линтеров и тестов, если они не требуют macOS.

На удалённом Mac должны выполняться:

  • установка и проверка Xcode;
  • установка CocoaPods и восстановление iOS-зависимостей;
  • компиляция нативных модулей;
  • запуск iOS Simulator;
  • Release-сборка;
  • подпись приложения;
  • создание Archive;
  • передача сборки в App Store Connect.

Перед подключением зафиксируйте четыре решения.

Первое — источник кода. Надёжнее использовать контролируемый Git-репозиторий, а не копировать рабочую папку через удалённый рабочий стол. Второе — базовую ветку: укажите, какой commit считается исходным для первой публикации. Третье — права Apple Developer Account: владелец команды должен заранее определить, кто может создавать подписи и загружать сборки. Четвёртое — ответственность за проверку на физическом iPhone. Удалённый симулятор не заменяет устройство.

Не записывайте в статью, скрипт или журнал реальные имена проекта, пользователя, хоста, Bundle ID, Team ID, сертификата и токена. Используйте такие значения:

<REPOSITORY_URL>
<PROJECT_DIR>
<APP_BUNDLE_ID>
<TEAM_ID>
<BUILD_HOST>
<ASC_API_KEY_PATH>

Такой шаблон помогает отделить инструкцию от секретов и не отправить закрытые данные в Git.

Если нужен только один релиз

Выберите короткую аренду удалённого Mac, если:

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

Если сборки повторяются каждую неделю

Сохраняйте отдельную среду, если:

  • вы регулярно меняете нативные модули;
  • нужно повторять Release-сборку после исправлений;
  • в команде больше одного человека;
  • необходимо быстро восстановиться после сбоя или перезапуска хоста.

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

02

Первый час: зафиксируйте удалённый инструментальный набор

Начните не с очистки кэшей, а с инвентаризации. Подключитесь к удалённому Mac через SSH для команд и через VNC либо веб-консоль для Xcode и Simulator. Запишите:

xcode-select -p
xcodebuild -version
node --version
npm --version
yarn --version
pod --version
git --version

Не все проекты используют один и тот же менеджер пакетов. Определите его по файлам в репозитории:

Что найдено в репозитории Что должно быть источником истины Ошибка, которой следует избежать
yarn.lock Yarn и зафиксированный lock-файл Запускать npm install без необходимости
package-lock.json npm и этот lock-файл Пересоздавать зависимости другой версией npm
pnpm-lock.yaml pnpm и его lock-файл Устанавливать пакеты через другой менеджер
Podfile.lock CocoaPods и сохранённые версии pod-зависимостей Удалять lock-файл до выяснения причины сбоя
.xcode.env Путь к Node и переменные React Native Надеяться, что GUI-сессия видит тот же PATH, что и SSH

React Native отдельно документирует настройку Node, Watchman, Xcode и CocoaPods. Сверьте удалённую среду с официальной инструкцией подготовки React Native, а не с памятью о другой машине.

Проверьте также активный каталог разработчика:

xcode-select -p
sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
sudo xcodebuild -license

Команды с sudo выполняйте только после проверки пути. Если на хосте установлено несколько копий Xcode, неправильный active developer directory даст сбой ещё до компиляции.

До изменения инструментов сохраните текущие значения:

Xcode: <XCODE_VERSION>
Node: <NODE_VERSION>
Package manager: <PACKAGE_MANAGER_VERSION>
CocoaPods: <COCOAPODS_VERSION>
Developer directory: <DEVELOPER_DIRECTORY>
Git commit: <COMMIT_SHA>

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

03

Второй этап: восстановите проект и отделите четыре вида проверки

Получите исходный код из контролируемого источника:

git clone <REPOSITORY_URL> <PROJECT_DIR>
cd <PROJECT_DIR>
git checkout <RELEASE_BRANCH>
git rev-parse HEAD

Установите JavaScript-зависимости командой, соответствующей lock-файлу. Затем восстановите iOS-зависимости:

cd ios
pod install
cd ..

В проекте с CocoaPods открывайте .xcworkspace, а не .xcodeproj. Это правило особенно важно для React Native с нативными модулями: workspace содержит интегрированные pod-цели, тогда как прямой запуск проекта может скрыть проблему до более поздней стадии.

Проверяйте результат по слоям:

  1. Разрешение зависимостей. Команда установки завершается без конфликта версий и без незапланированного изменения lock-файлов.
  2. Нативная компиляция. Xcode собирает Swift, Objective-C и подключённые модули.
  3. JavaScript Bundle. Release-конфигурация получает пакет JavaScript и нужные ресурсы.
  4. Запуск симулятора. Приложение устанавливается и открывается на выбранном iOS Simulator.

Документация React Native по запуску приложения в iOS Simulator полезна для проверки среды, но успешный запуск симулятора ещё не означает, что подпись и публикационный Archive готовы.

Сохраняйте журнал каждой стадии:

mkdir -p <LOG_DIR>

npx react-native run-ios \
  --scheme "<SCHEME_NAME>" \
  2>&1 | tee <LOG_DIR>/simulator-build.log

Если команда завершилась ошибкой, сначала определите слой: JavaScript, CocoaPods, native compilation, запуск или подпись. Не выполняйте подряд rm -rf Pods, удаление DerivedData и пересоздание lock-файлов. Без причины вы потеряете диагностический материал и можете получить другую версию зависимости.

Важно: симулятор подтверждает только совместимость выбранной сборки с симулятором. Он не подтверждает работу Push Notifications, камеры, Bluetooth, Keychain-доступа, фоновых режимов и других функций, зависящих от физического устройства или entitlements.

04

Третий этап: подготовьте Release и Archive

Перед первым Archive откройте workspace в Xcode и проверьте не только основной Target. В проекте могут быть Notification Service Extension, Share Extension, виджеты и другие дополнительные цели.

Проверьте:

  • Scheme и выбранную конфигурацию Release;
  • Bundle ID основного приложения;
  • Team;
  • Signing & Capabilities;
  • Bundle ID каждого App Extension;
  • entitlements;
  • версии приложения и номер сборки;
  • режимы подписи для всех целей.

Apple рекомендует предварительно проверить проект перед распространением; используйте документ о подготовке приложения к распространению. Для закрытых ключей заранее определите владельца и способ хранения. Рекомендации по безопасному обмену signing identities объясняют, почему сертификат без соответствующего приватного ключа не решает задачу подписи.

Схема принятия решения выглядит так:

  • Если у проекта один Target, автоматическая подпись разрешена командой, а физическое устройство доступно — сначала проверяйте обычную Release-сборку, затем переходите к Archive.
  • Если есть Extensions или ручные Provisioning Profiles — до Archive сопоставьте Bundle ID, Team и profile для каждой цели.
  • Если ошибка появляется до компиляции — проверяйте Scheme, workspace и зависимости, а не сертификат.
  • Если Archive создаётся, но экспорт невозможен — отделяйте успех компиляции от права на распространение.
  • Если после перезапуска хоста пропадают ключи или профиль — остановите публикацию и восстановите секреты, не создавая новые сертификаты без необходимости.

Для командной строки можно использовать xcodebuild, но подставляйте реальные значения только в локальной сессии:

xcodebuild \
  -workspace "<PROJECT_NAME>.xcworkspace" \
  -scheme "<SCHEME_NAME>" \
  -configuration Release \
  -archivePath "<ARCHIVE_PATH>/<PROJECT_NAME>.xcarchive" \
  archive \
  | tee "<LOG_DIR>/archive.log"

Archive успешен только тогда, когда команда завершилась без ошибки и файл .xcarchive существует в ожидаемом месте. Это ещё не означает, что сборка выгружена или доступна тестировщикам.

05

Что меняется между симулятором, Release и TestFlight

Стадия Что она доказывает Что она не доказывает
Debug на Simulator Проект запускается в выбранной симулируемой среде Готовность подписи, entitlements и физического устройства
Release Build Код и ресурсы проходят публикационную конфигурацию Право экспортировать и отправить сборку
Archive Xcode создал архив для дальнейшего распространения Что сервер обработал загруженный файл
Upload Файл передан в App Store Connect Что он уже доступен тестировщикам
Processing Сервер завершил обработку сборки Что установленная версия прошла регрессионную проверку
TestFlight testing Тестовая сборка назначена группе или тестировщику Что приложение готово к публичному релизу

Эту границу нельзя сокращать до фразы «сборка прошла». Apple описывает распространение из Xcode как отдельную последовательность; документация по созданию App Record также показывает, что запись приложения должна существовать до привязки загрузки.

06

Четвёртый этап: загрузите Archive в TestFlight

Сначала убедитесь, что в App Store Connect создана запись приложения с правильным Bundle ID. Затем выберите один из контролируемых способов передачи Archive:

  • Organizer в Xcode;
  • Transporter, если его использование разрешено вашей командой;
  • автоматизированная команда с API-ключом, когда процесс уже проверен вручную.

Для первой публикации предпочтителен Organizer: он показывает этапы проверки и позволяет связать архив с конкретным проектом. Ориентируйтесь на официальную инструкцию загрузки сборок.

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

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

Статус TestFlight — часть процесса распространения, а не доказательство готовности к App Store Review. Если нужно автоматизировать отправку, сначала стабилизируйте ручной путь. Затем можно перейти к API-ключу, отдельному файлу конфигурации и ограниченным правам. Не храните приватный ключ в репозитории и не передавайте его через открытый чат.

07

Две архитектуры удалённого процесса

Вариант Преимущества Ограничения
SSH-команды плюс Xcode через VNC Хорошо подходит для первой настройки; легко разделить логи и графические действия Нужно отдельно проверять GUI-сессию, Keychain и доступность Xcode
Повторяемые shell-задачи на удалённом Mac Удобно для регулярных Release-сборок; проще сохранять логи и повторять Archive Требует аккуратной настройки секретов, путей и восстановления после перезапуска
Полностью ручной запуск в Xcode Наглядно видно Scheme, Signing и Organizer Сложно воспроизводить действия и сравнивать результаты
Гибрид: ручная подпись, автоматизированная сборка Снижает число случайных изменений в проекте Нужно документировать, где создаётся архив и какие права используются

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

08

Пятая часть: первая неделя — проверка восстановления

Разовая удача не является рабочим процессом. В течение первой недели выполните контрольный повтор:

  1. Отключите SSH и подключитесь снова.
  2. Откройте новую удалённую графическую сессию.
  3. Проверьте xcode-select, путь к Node и доступность Keychain.
  4. Перезапустите хост в согласованное окно.
  5. Повторите получение ветки и восстановление зависимостей.
  6. Выполните Release Archive с новым журналом.
  7. Проверьте, где лежит архив и кто имеет к нему доступ.
  8. Удалите временные копии секретов после проверки.

Зафиксируйте условия остановки. Например: если изменился lock-файл, процесс не должен автоматически продолжать публикацию; если пропал сертификат, скрипт должен завершиться до создания Archive; если Bundle ID не совпал, загрузка не должна запускаться.

Разделите доступы:

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

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

09

Где удалённый Mac лучше локального компьютера, а где нет

Удалённая схема полезна, когда вам нужно получить настоящий macOS-инструментарий без покупки отдельного компьютера. Она даёт доступ к Xcode, CocoaPods, Simulator, Keychain и Organizer в одном окружении. Для Windows-разработчика это устраняет главный разрыв между JavaScript-частью и iOS-публикацией.

Но недостатки тоже реальны:

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

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

10

Итоговое решение для вашего проекта

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

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

Локальный Windows или Linux остаётся удобным компьютером для кода, Git и Android. Но для React Native iOS-сборки нативная часть, Release, Archive и подпись должны проходить в macOS-среде. Если текущий вариант — разово одолженный Mac или непостоянная виртуальная машина, у него есть три заметных минуса: среда может исчезнуть к следующему релизу, версии зависимостей не зафиксированы, а доступ к сертификатам и журналам часто организован небезопасно. В таком случае аренда Mac через VpsMesh обычно практичнее: вы получаете отдельную удалённую среду, можете повторять процедуру и выбирать короткий или более длительный срок под реальную частоту публикаций. Начните с первой успешной Archive-сборки, а затем закрепите подходящий формат в условиях заказа Mac mini.