2026-05-20 Пути профилей provisioning Xcode 16 и параллельный многопоточный archive на безголовом арендованном облачном Mac Apple Silicon (HK / JP / KR / SG / US)
Команды, которые арендуют билдеры Mac mini M4 в Гонконге, Токио, Сеуле, Сингапуре или США и гоняют Xcode 16 без графической сессии, сталкиваются с тихим breaking change: профили provisioning больше не «живут» только под устаревшим деревом MobileDevice. Xcode 16 читает и пишет каноническое хранилище в UserData, тогда как старые скрипты, хелперы Fastlane и сторонние CLI по-прежнему копируют .mobileprovision в путь «до Xcode». Когда на одном арендованном хосте добавляются несколько параллельных дорожек xcodebuild archive, этот дрейф путей превращается в гонки подписи, фантомные ошибки «профиль не найден» и прерывистые сбои errSecInternalComponent, которые на ноутбуке разработчика не воспроизводятся. Этот рунбук 2026-05-20 сразу формулирует политику: зеркалировать профили в UserData и legacy, пока каждый инструмент на машине не осознаёт Xcode 16, изолировать CI-связки ключей по дорожкам и корни DerivedData, и ограничить параллельные archive-дорожки двумя на стандартном Mac mini M4 без измеренного запаса NVMe и унифицированной памяти. Вы получите таблицу сравнения путей, матрицу многопоточности, триаж безголовой подписи, восемь шагов внедрения и ответы FAQ, согласованные с нашей базовой статьёй про связку ключей и provisioning в CI, руководством авто против ручной подписи и материалом о параллельных задачах xcodebuild.
Кому достаётся дрейф путей provisioning на арендованном безголовом Mac
Сбой редко объявляет себя как «неправильный каталог». Дорожка B успешно архивирует, а дорожка A выдаёт No profile for team 'XXXXXXXXXX' matching, хотя оба job импортировали один UUID. На арендованном хосте радиус поражения больше: golden-образы зашивают вспомогательные скрипты 2024 года, плагины Jenkins всё ещё зовут ~/Library/MobileDevice/Provisioning Profiles, а fastlane-лейн новичка качает в UserData, пока ночной cron обновляет только legacy-папку. Мульти-веточная CI с одним пользователем macOS усиливает дрейф: каждая дорожка читает один и тот же домашний каталог, если пути специально не разделить.
- Релиз-инженеры, запускающие два и больше параллельных archive для разных bundle ID на одном Mac mini M4, нуждаются в детерминированном разрешении профиля на дорожку.
- Платформенные команды, ведущие golden-образы, обязаны задокументировать, какой путь читают Xcode 16,
xcodebuildи вспомогательные утилиты во времяarchiveиexportArchive. - Специалисты по безопасности требуют доказательства, что дорожка A не читает сертификат распространения дорожки B — отдельные связки ключей на дорожку обязательны при горячей замене профилей.
Каждое архитектурное ревью начинайте с обещания главной MacXCode: Apple Silicon рядом с API Apple, затем отметьте, какие артефакты подписи должны жить рядом с checkout на арендованном хосте. Если вы копируете профили только в MobileDevice, считайте это техническим долгом, который блокирует устойчивую многопоточную пропускную способность — наш гайд по удалённому archive написан до сдвига UserData и читается вместе с этим обновлением.
Устаревший MobileDevice и пути UserData профилей Xcode 16
Xcode 16 считает ~/Library/Developer/Xcode/UserData/Provisioning Profiles основным on-disk-хранилищем при загрузке из панели учётных записей Xcode или когда xcodebuild -allowProvisioningUpdates обновляет entitlements. Устаревшее расположение ~/Library/MobileDevice/Provisioning Profiles остаётся важным: многие CI-рецепты, старые действия Fastlane и внутренние shell-инсталляторы пишут только туда. Пока не проверен каждый вход, безопасный операторский дефолт — байт-в-байт копии в обоих деревьях после каждой ротации профиля, с именем файла UUID из plist Apple (security cms -D -i file.mobileprovision → ключ UUID).
| Путь | Типичный потребитель | Поведение Xcode 16 | Заметка CI на аренде |
|---|---|---|---|
~/Library/Developer/Xcode/UserData/Provisioning Profiles |
IDE Xcode, современный xcodebuild |
Каноническое чтение/запись для GUI-загрузок | Закрепить xcode-select перед копированием; проверить экспортом учётных записей |
~/Library/MobileDevice/Provisioning Profiles |
Legacy-скрипты, часть версий Fastlane | По-прежнему учитывается многими CLI-потоками | Зеркалировать сюда, пока скрипты не сняты |
Staging по дорожке (напр. /var/ci/lane-a/profiles) |
Свои инсталляторы до копирования | Не читается напрямую; снижает гонки в home | Копировать в оба канонических пути на job дорожки |
API ASC + -allowProvisioningUpdates |
Потоки автоматической подписи | Может заполнять только UserData | Изолировать ключи API; см. Fastlane против нативного ASC |
security find-identity -v -p codesigning, как в базовой статье про связку ключей.
Матрица параллельного многопоточного archive на одном Mac mini M4
Параллельные archive — не «бесплатный параллелизм» на арендованном Mac mini M4: унифицированная память, глубина очереди NVMe и состояние сессии подписи под нагрузкой всё равно частично сериализуются. Матрица ниже предполагает выделенный -derivedDataPath на дорожку, отдельную CI-связку ключей и зеркалированные профили — шаблоны из гайда по параллельным задачам и статьи схемы + xcconfig для нескольких веток.
| Число дорожек | Типичный запас NVMe | Унифицированная память | Вердикт оператора |
|---|---|---|---|
| 1 серийный archive | 120 ГБ+ свободно на системном томе | 16 ГБ минимум; 24 ГБ комфортно | Дефолт для общих релизных поездов; проще всего логи |
| 2 параллельных archive | 120–180 ГБ свободно на дорожку под /var/ci |
24 ГБ+ рекомендуется | Практический потолок на серийном M4; изолируйте DerivedData и связки ключей |
| 3+ параллельных archive | Класс NVMe 2 ТБ; агрессивная уборка | 32 ГБ+ или ждите затыков компрессии | Только после замеров; планируйте гигиену диска |
| Archive + тяжёлый тестовый шард | Раздельные корни; ModuleCache не шарить | Оставьте 4 ГБ запаса под XCTest | Предпочтительно серийный archive после тестов или отдельные хосты |
Пример вызова archive в разрезе дорожки (ручная подпись с явным specifier):
KEYCHAIN_PATH=/var/ci/lane-a/ci.keychain-db DERIVED=/var/ci/lane-a/dd xcodebuild -workspace App.xcworkspace -scheme Release -configuration Release -archivePath /var/ci/lane-a/out/App.xcarchive -derivedDataPath "$DERIVED" CODE_SIGN_STYLE=Manual PROVISIONING_PROFILE_SPECIFIER='MyApp AppStore' archive
Триаж безголовой подписи, когда профили кажутся «установленными»
Сессии SSH ощущаются интерактивно; launchd и CI-раннеры — нет. Самые частые безголовые сбои после апгрейда до Xcode 16: профили скопированы только в MobileDevice, дистрибутивные идентичности импортированы в связку входа, пока xcodebuild смотрит на пустую CI-связку, и дорожка B разблокирует связку, которая дорожке A ещё нужна монопольно. Считайте каждый archive отпечатком из трёх частей: security list-keychains, security find-identity -v -p codesigning и ls -lt обоих каталогов профилей, ограниченный тремя новейшими UUID.
Когда codesign печатает errSecInternalComponent, разблокируйте CI-связку без диалога до archive, задайте partition lists для доступа codesign и убедитесь, что entitlements профиля совпадают с возможностями таргета — особенно Push, App Groups и Associated Domains после правок портала. Автоподпись через API ASC может скрывать дрейф путей до экспорта; ручные дорожки выставляют его сразу. Прочитайте авто против ручной подписи, прежде чем смешивать стили на одном хосте.
ci-lane-a.keychain-db и ci-lane-b.keychain-db под /var/ci, импортируйте distribution .p12 через security import -k "$KEYCHAIN_PATH" -P "$P12_PASS" -T /usr/bin/codesign и ограничьте security list-keychains -s длительностью job.
| Симптом | Вероятная причина | Следующая команда или исправление |
|---|---|---|
| Профиль отсутствует в отчёте Xcode | UserData пуст; только legacy-установка | Зеркалировать UUID-файл в UserData; повторить archive |
errSecInternalComponent |
Заблокированная связка или неверный partition list | security unlock-keychain -p "$PASS" "$KEYCHAIN_PATH"; set-key-partition-list |
| Дорожка A проходит, B падает на том же коммите | Общий DerivedData или гонка профилей | Разделить -derivedDataPath; сериализовать копирование профилей |
| Export успешен, upload отклонён | Неверный тип профиля или устаревшие entitlements | Проверить по чек-листу export + загрузка ASC |
После archive загрузите dSYM до удаления каталогов дорожек — гайд по символикации dSYM предполагает, что archive остаются адресуемыми по дорожке под /var/ci/…/out.
Восемь шагов: пути Xcode 16 + многопоточный archive
- Закрепить
xcode-select -pна целевой Xcode 16.app; записатьxcodebuild -versionв манифест golden-образа. - Проверить каждый скрипт, копирующий
.mobileprovision; обновить инсталляторы, чтобы писать и в UserData, и в MobileDevice с UUID-именами файлов. - Создать CI-связки ключей по дорожкам и импортировать сертификаты распространения; запретить дорожкам чужие файлы связок.
- Экспортировать
KEYCHAIN_PATH,PROVISIONING_PROFILE_SPECIFIER(или UUID профиля) иDERIVED_DATA_ROOTв разрезе дорожки в блоках окружения CI. - Сухой прогон
xcodebuild -showBuildSettingsна дорожку; убедиться, чтоCODE_SIGN_STYLEсоответствует политике из гайда по режимам подписи. - Включать
-allowProvisioningUpdatesтолько когда учётные данные API ASC изолированы и мониторятся — см. нативный ASC против Fastlane. - Начать с одной archive-дорожки, пока зеркалирование профилей не стабилизируется; добавить вторую с отдельными корнями NVMe и логами.
- Планировать еженедельную уборку диска и ротировать профили с перекрытием; держать горячие копии в staging-каталогах дорожек.
Шаблон неинтерактивной установки профиля (подставьте свой staging-каталог дорожки):
UUID=$(security cms -D -i "$PROFILE" | plutil -extract UUID raw -) && cp "$PROFILE" "$HOME/Library/Developer/Xcode/UserData/Provisioning Profiles/$UUID.mobileprovision" && cp "$PROFILE" "$HOME/Library/MobileDevice/Provisioning Profiles/$UUID.mobileprovision"
FAQ
Где Xcode 16 хранит профили provisioning? Основной путь — ~/Library/Developer/Xcode/UserData/Provisioning Profiles. Устаревшие инструменты могут читать ~/Library/MobileDevice/Provisioning Profiles — зеркалировать оба на CI-хостах, пока все инсталляторы не обновлены.
Сколько параллельных archive-дорожек на Mac mini M4? Две дорожки с запасом NVMe 120–180 ГБ каждая — практичный дефолт; третья дорожка требует 2 ТБ хранилища, агрессивной уборки и аккуратного бюджета памяти по матрице выше.
Почему codesign падает с errSecInternalComponent по SSH? Обычно заблокированная связка ключей, отсутствие partition list для CI-связки или профили только в legacy-пути, пока Xcode 16 сначала разрешает UserData.
Нужно ли дорожкам шарить DerivedData для ускорения сборок? Нет для release-archive — ModuleCache и index store гоняются при параллельных archive. Используйте -derivedDataPath на дорожку и опциональные общие только для чтения кэши зависимостей только после того, как один writer разрешил пакеты.
Для навигации добавьте в закладки индекс блога и справочный центр, чтобы дежурные находили этот рунбук без поиска по чатам.
Почему аренда Mac mini M4 подходит под многопоточные archive Xcode 16
Apple Silicon M4 даёт достаточную пропускную способность унифицированной памяти, чтобы компилировать два средних iOS-графа параллельно при изоляции DerivedData и честном ограничении дорожек. Нативная подпись macOS обходит странности связки ключей гипервизора, которые мучают эмулируемые Mac-среды — это важно, когда три ночные ветки каждый раз требуют обновления distribution-профиля. Аренда убирает CapEx в пиковые релизные недели: поднять билдер в Токио для близости к App Store Connect, в Сингапуре для выхода в ASEAN или в США для конечных точек API US-West, затем снизить нагрузку после релиза. Сравните регионы на странице цены, отработайте SSH в справочном центре и сочетайте эту статью с удалёнными сценариями archive при онбординге нового репозитория на безголовую аренду.
Арендуйте Apple Silicon там, где подпись Xcode 16 остаётся предсказуемой
HK / JP / KR / SG / US · безголовый SSH · готово к многопоточному archive