Симулятор запускается, но готового 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 здесь не рассматриваются: у них другая граница ответственности и другой порядок диагностики.
До первой сессии: разделите работу между компьютерами
Главная ошибка — пытаться перенести на удалённый 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-цели, тогда как прямой запуск проекта может скрыть проблему до более поздней стадии.
Проверяйте результат по слоям:
- Разрешение зависимостей. Команда установки завершается без конфликта версий и без незапланированного изменения lock-файлов.
- Нативная компиляция. Xcode собирает Swift, Objective-C и подключённые модули.
- JavaScript Bundle. Release-конфигурация получает пакет JavaScript и нужные ресурсы.
- Запуск симулятора. Приложение устанавливается и открывается на выбранном 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-файлов. Без причины вы потеряете диагностический материал и можете получить другую версию зависимости.
04Важно: симулятор подтверждает только совместимость выбранной сборки с симулятором. Он не подтверждает работу Push Notifications, камеры, Bluetooth, Keychain-доступа, фоновых режимов и других функций, зависящих от физического устройства или entitlements.
Третий этап: подготовьте 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 существует в ожидаемом месте. Это ещё не означает, что сборка выгружена или доступна тестировщикам.
Что меняется между симулятором, 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Пятая часть: первая неделя — проверка восстановления
Разовая удача не является рабочим процессом. В течение первой недели выполните контрольный повтор:
- Отключите SSH и подключитесь снова.
- Откройте новую удалённую графическую сессию.
- Проверьте
xcode-select, путь к Node и доступность Keychain. - Перезапустите хост в согласованное окно.
- Повторите получение ветки и восстановление зависимостей.
- Выполните Release Archive с новым журналом.
- Проверьте, где лежит архив и кто имеет к нему доступ.
- Удалите временные копии секретов после проверки.
Зафиксируйте условия остановки. Например: если изменился 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.