Что сохранять при миграции сборочной машины iOS? Чек-лист Xcode 27

Что сохранять при миграции сборочной машины iOS? Чек-лист Xcode 27

Победитель — миграция по критериям восстановления: новый Mac можно считать заменой только после независимого Archive, подписания, загрузки и проверки автоматизации. Простого копирования проекта или повторной установки Xcode 27 недостаточно: перед очисткой старой машины нужно отдельно подтвердить исходники, инструменты, Apple Distribution, приватные ключи, профили, архивы и сервисные учетные данные.

Этот материал предназначен:

  • независимым разработчикам, которые готовятся вернуть или заменить удалённый Mac;
  • сопровождающим CI/CD, которым нужно перенести сборку Xcode 27 на другую машину;
  • небольшим командам, принимающим чужой проект или восстанавливающим сломанный iOS-сборочный сервер.

Последнее обновление: 8 сентября 2026 года. Правила сверены по документации Apple и инструкции по удалению self-hosted Runner; будущие требования Xcode 27, которые ещё не подтверждены официально, не используются как основание для миграции.

Миграция iOS-сборочной машины с Xcode 27 начинается с измеримых критериев

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

Apple отдельно определяет системные требования Xcode и совместимость с версиями macOS. Поэтому перед переносом следует записать точный путь к Xcode, выбранный набор Command Line Tools и версию macOS, а затем сверить их с официальной страницей системных требований Xcode. Нельзя считать любую установленную копию Xcode 27 эквивалентной прежней: результат зависит от SDK, проекта, скриптов и настроек подписи.

Проверка считается пройденной, если новый Mac может:

  1. получить чистую копию исходников;
  2. разрешить зависимости без каталогов старой машины;
  3. выполнить обычную сборку;
  4. создать Archive;
  5. подписать архив нужной схемой;
  6. передать результат в требуемый канал распространения;
  7. выполнить автоматизированную задачу после отключения старого Runner.

Если один пункт зависит от файла в прежнем домашнем каталоге, миграция ещё не завершена.

Что нужно перенести с iOS-сборочной машины: только воспроизводимые входные данные

Главная ошибка при замене Mac — принять весь пользовательский каталог за резервную копию. Такой подход смешивает исходники, кэш, секреты, логи и временные файлы. Восстановление становится непрозрачным, а риск случайно перенести устаревший или лишний секрет увеличивается.

Исходники, подмодули и файлы зависимостей

В обязательный набор входят:

  • репозиторий приложения;
  • Git-подмодули;
  • файлы блокировки зависимостей;
  • Package.swift или служебные файлы Swift Package Manager;
  • конфигурации CocoaPods, если проект их использует;
  • скрипты сборки и публикации;
  • схемы, конфигурации и настройки проекта, находящиеся под контролем версий;
  • необходимые шаблоны конфигурации без раскрытых секретов;
  • инструкции доступа к приватным репозиториям.

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

Обычный порядок проверки выглядит так:

git clone <REPOSITORY_URL> app
cd app
git submodule update --init --recursive
xcodebuild -resolvePackageDependencies \
  -workspace <WORKSPACE>.xcworkspace \
  -scheme <SCHEME>

Пример ожидаемого результата:

Resolved source packages:
  <PACKAGE_NAME>: <VERSION>

Имена репозитория, схемы и пакета здесь намеренно заменены заполнителями. В реальной миграции нельзя оставлять токены в URL, командной истории или файлах журналов.

DerivedData, кэш Swift Package Manager и временные каталоги не являются доказательством воспроизводимости. Они могут ускорить первую сборку, но не заменяют чистое разрешение зависимостей. Для проверки следует использовать отдельный каталог DerivedData:

xcodebuild \
  -workspace <WORKSPACE>.xcworkspace \
  -scheme <SCHEME> \
  -configuration Release \
  -derivedDataPath "$PWD/.migration-derived-data" \
  build

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

Базовая запись инструментов и путей

На новой машине нужно сохранить не только название Xcode, но и фактическое состояние инструментов:

xcode-select -p
xcodebuild -version
xcrun --sdk iphoneos --show-sdk-path
xcodebuild -list \
  -workspace <WORKSPACE>.xcworkspace

Пример вывода:

/Applications/Xcode.app/Contents/Developer
Xcode <VERSION>
Build version <BUILD_VERSION>
<SDK_PATH>

Эти значения являются образцом формата вывода, а не универсальными версиями. Конкретные системные требования и доступные SDK нужно сверять с официальными требованиями Apple для Xcode. Пути, Team ID, Bundle ID и названия сертификатов в рабочей документации следует заменять на понятные заполнители, если документ передаётся подрядчику.

Подпись и Apple Distribution: сертификат без приватного ключа бесполезен

При резервировании подписи нельзя ограничиваться экспортом файла сертификата. Сертификат подтверждает открытые данные личности, но операция подписи требует связанного приватного ключа. В связке также участвуют Provisioning Profile, идентификатор команды, Bundle ID и выбранный режим автоматической или ручной подписи.

Как сохранить сертификаты и приватные ключи перед возвратом удалённого Mac

На старой машине сначала составляется инвентаризация:

  • сертификат Apple Distribution;
  • соответствующий приватный ключ;
  • сертификаты для других каналов, если они действительно используются;
  • Provisioning Profile;
  • настройки Keychain;
  • режим Automatically manage signing;
  • параметры fastlane или другого сценария публикации;
  • учетные данные, которые не должны храниться в открытом виде.

Идентичность обычно экспортируют из Keychain Access в защищённый контейнер PKCS #12. Apple описывает импорт такой идентичности и формат PKCS #12 в официальной документации по импорту identity. Пароль от экспортированного контейнера нельзя помещать рядом с самим файлом, в репозиторий или в команду shell.

После переноса импорт выполняется только на новом Mac. Затем проверяется наличие именно связки:

security find-identity -v -p codesigning
security find-certificate -a -c "Apple Distribution" \
  "$HOME/Library/Keychains/login.keychain-db"

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

<IDENTITY_COUNT> valid identities found
  <IDENTITY_HASH> "<CERTIFICATE_NAME>"

Количество и хэш в примере не являются данными конкретной конфигурации. Важен сам критерий: новый Mac видит пригодную identity, а не только отдельный файл .cer.

Provisioning Profile нельзя путать с приватным ключом. Профиль связывает проект с разрешённым способом запуска или распространения, но не переносит приватную часть подписи. Профили нужно сопоставить с Bundle ID и способом доставки, а правила их загрузки, редактирования и удаления проверить по документации Apple о Provisioning Profiles.

Что делать при отзыве или ротации

Отзыв сертификата, удаление профиля и ротация ключа — не обычные операции очистки. До действия фиксируются:

  • какие приложения затронуты;
  • какие workflow используют identity;
  • где находится резервная копия;
  • кто сможет восстановить доступ;
  • при каком результате выполняется откат.

Если старый приватный ключ утрачен, простое копирование сертификата его не восстановит. В таком случае нужно планировать новую identity и обновление профилей, а не продолжать удаление старой машины в надежде, что Xcode автоматически восстановит секрет.

xcarchive и dSYM: разные уровни ценности одного выпуска

IPA — это не полная резервная копия релиза. Для долгосрочного восстановления нужно разделять:

  • xcarchive;
  • dSYM;
  • xcresult;
  • экспортированную конфигурацию;
  • IPA или другой результат доставки;
  • сведения о версии и номере сборки;
  • запись фактической публикации.

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

xcarchive имеет более высокую ценность для восстановления, чем один IPA. Он помогает проверить состав архива и повторно выполнить экспорт при наличии нужной подписи и экспортных параметров. IPA удобен как опубликованный результат, но не заменяет исходный архив и символы.

Для каждого архива следует сохранить связь:

<ARCHIVE_UUID> → <VERSION> → <BUILD_NUMBER> → <DISTRIBUTION_CHANNEL>

Имена должны быть стабильными и не включать реальные секреты:

archives/<VERSION>-<BUILD_NUMBER>-<ARCHIVE_UUID>/
  App.xcarchive
  App.ipa
  dSYMs/
  export-options.plist
  xcresult/
  release-record.txt

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

find <ARCHIVE_PATH> -maxdepth 2 -type d -name "dSYMs"
xcodebuild -exportArchive \
  -archivePath <ARCHIVE_PATH> \
  -exportOptionsPlist <EXPORT_OPTIONS_PATH> \
  -exportPath <EXPORT_PATH>

Команда не должна выполняться с реальными секретами, вставленными в текст инструкции. Пароли, API-ключи и токены передаются через защищённое хранилище окружения.

Сравнение критериев: когда старая машина ещё нужна

Ниже приведена основная карта решения. Она отделяет восстановимые входные данные от активных полномочий и от результатов, которые невозможно безопасно заменить простым скачиванием проекта.

Объект миграции Что сохранить Доказательство на новом Mac Условие очистки старого Mac
Исходники и зависимости Репозиторий, подмодули, lock-файлы, скрипты Чистый checkout и успешное разрешение зависимостей Новый checkout не использует старые каталоги
Xcode 27 и SDK Версии, путь Xcode, выбранные Command Line Tools, схемы Build и Archive с зафиксированной конфигурацией Есть запись воспроизводимого toolchain baseline
Apple Distribution Сертификат, связанный приватный ключ, профили Подписание целевого Archive Подпись прошла в нужном канале
xcarchive и dSYM Архив, символы, xcresult, экспортные параметры Архив открывается, символы доступны, экспорт выполняется Копия читается из независимого хранилища
API-доступ Key ID, issuer, приватная часть ключа, область применения Тестовая передача или проверка статуса без старой машины Старый ключ отозван или ограничен по плану
Self-hosted Runner Метка, рабочая папка, сервис, секреты Изолированная задача завершается на новом Runner Старый Runner удалён и не принимает задания
Очистка Логи, shell history, временные файлы, общие каталоги Проверка отсутствия активных секретов Есть подтверждённый откат или резервная копия

Для сведений о распространении через Archive нужно ориентироваться на официальное описание Apple Archive и release workflow, а не на предположение, что наличие IPA автоматически подтверждает работоспособность всей цепочки.

App Store Connect и автоматизация: переносить нужно полномочия, а не только скрипты

Скрипт fastlane или shell-файл не содержит всей среды выполнения. В миграционном реестре отдельно перечисляются:

  • путь к проекту;
  • схема и конфигурация;
  • переменные окружения;
  • ссылка на хранилище секретов;
  • API Key и его область применения;
  • Team ID;
  • Bundle ID;
  • рабочая папка Runner;
  • метки Runner;
  • фоновые службы;
  • расписания;
  • журналы и точки оповещения.

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

Перенос self-hosted Runner выполняется в два этапа.

Сначала — изолированная проверка нового Runner

Новый Runner регистрируется с отдельной меткой или ограниченным тестовым заданием. До остановки прежней машины запускается задача, которая:

  1. получает чистый checkout;
  2. проверяет Xcode и выбранный SDK;
  3. разрешает зависимости;
  4. выполняет тестовую сборку;
  5. проверяет доступность подписи;
  6. сохраняет журнал без секретов.

Только после этого тестируется Archive и доставка результата. Параллельный запуск публикации на двух Runner опасен: задания могут использовать разные состояния Keychain, повторно отправлять один номер сборки или одновременно менять артефакты.

Затем — контролируемое снятие старого Runner

Сначала останавливается приём новых задач. Потом проверяется отсутствие активной работы, удаляется регистрация Runner и выключается локальная служба. Конкретный порядок зависит от автоматизационной платформы; процедуру удаления нужно сверять с официальной инструкцией по удалению self-hosted Runner.

В журнале миграции фиксируются:

Runner label: <RUNNER_LABEL>
Repository: <REPOSITORY_PLACEHOLDER>
Team ID: <TEAM_ID>
Key ID: <KEY_ID>
Old host state: <DISABLED_OR_REMOVED>
New host state: <VALIDATED>

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

Что проверяется после переноса до удаления старой машины

Финальная проверка должна имитировать потерю старого Mac. Это важнее, чем успешный запуск команды на двух одновременно доступных хостах.

Контрольный запуск

На новой машине выполняются следующие действия:

  1. создаётся чистая рабочая папка;
  2. исходники загружаются заново;
  3. зависимости разрешаются заново;
  4. запускается нужная схема;
  5. создаётся Release Archive;
  6. выполняется проверка подписи;
  7. выполняется тестовая или реальная загрузка по принятому процессу;
  8. сохраняются журнал, Archive, dSYM и результат экспорта;
  9. старый Mac временно отключается;
  10. ключевая задача повторяется без старого хоста.

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

codesign --verify --deep --strict <APP_PATH>
codesign -dvvv <APP_PATH> 2>&1 | grep -E "Identifier|TeamIdentifier"

Значения в выводе должны соответствовать ожидаемому Bundle ID и Team ID. Сама команда не доказывает успешную загрузку в App Store Connect, поэтому она является лишь одним из этапов, а не финальным критерием.

Разбор риска по активам

Каждый объект получает одно из трёх состояний:

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

Особенно опасны четыре ложных подтверждения:

  • сертификат виден, но приватного ключа нет;
  • профиль присутствует, но не подходит Bundle ID;
  • IPA сохранён, но dSYM потерян;
  • Runner зарегистрирован, но запускает старую рабочую папку или не имеет доступа к подписи.

Когда старую сборочную машину можно безопасно очистить

Удаление или возврат старого удалённого Mac разрешается только после одновременного выполнения условий:

  • новая машина прошла чистую сборку и Archive;
  • подпись выполнена нужной Apple Distribution identity;
  • тестовая или реальная загрузка завершилась по целевому сценарию;
  • xcarchive, dSYM и журналы открываются из независимой копии;
  • API-доступ проверен без старого хоста;
  • новый Runner принимает тестовое задание;
  • старый Runner удалён и больше не получает задачи;
  • фоновые службы старого Mac остановлены;
  • временные файлы, shell history и общие каталоги проверены;
  • оставшиеся ключи отозваны или сохранены по документированному плану;
  • существует понятный способ отката.

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

Для независимого разработчика удалённый Mac часто удобнее локального, когда требуется постоянно доступная сборочная среда, но доступность хоста не заменяет резервную копию. При выборе новой среды полезно заранее сравнить условия аренды Mac и отдельно проверить, подходит ли конфигурация удалённого Mac для Xcode 27. Это особенно важно перед окончанием текущего срока: перенос лучше начинать до даты отключения, а не после потери доступа к Keychain.

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