DevOps / CI·CD 12 мая 2026

2026-05-12 Схемы Xcode, конфигурации сборки и слои xcconfig для изоляции многоветвевой CI на арендованном облачном Mac Apple Silicon (HK / JP / KR / SG / US)

MacXCode Engineering Team 2026-05-12 ~21 мин чтения

Когда main, release/x.y и множество feature/* сходятся на одном арендованном Mac mini M4 в Гонконге, Токио, Сеуле, Сингапуре или США, типичный сбой — не «Xcode не компилирует», а тихий дрейф конфигурации: вчерашняя дорожка шла по Release с продакшн-профилями, сегодняшняя тематическая ветка думает, что она в Debug, либо два параллельных задания пишут в один CONFIGURATION_BUILD_DIR, потому что обёртка забыла префикс задания. Этот гайд 2026-05-12 связывает изоляцию индекс-хранилища по дорожкам, параллельные очереди xcodebuild и самохостный runner GitHub Actions с явной картой схем, версионируемым стеком xcconfig и CI-проверками, которые трактуют разрешённые настройки сборки как инфраструктурный код.

Почему на общем арендованном хосте схемы важнее, чем на личном ноутбуке

Локально Xcode UI и мышечная память ловят ошибки. У безголового xcodebuild на общем UID есть только строки оркестратора. Устаревшее имя схемы по умолчанию в YAML workflow может превратиться в межтенантный инцидент подписи с неверным DEVELOPMENT_TEAM или PRODUCT_BUNDLE_IDENTIFIER. Промышленная арендованная CI публикует позитивную карту от шаблонов веток к парам схема+конфигурация, версионирует её вместе с .xcconfig и блокирует слияния при расхождении с xcodebuild -list на образе билдера.

Золотое правило: не полагаться на «первую схему по алфавиту». Всегда передавать -scheme и до дорогой компиляции проверять, что разрешённая configuration совпадает с намерением.

Таксономия веток → карта схем без взрыва числа схем

Зрелые команды держат поверхность схем малой: одно потребительское приложение, пакет расширений, опциональные виджеты и отдельная архивная схема, когда экспорт в App Store сильно отличается. main может использовать App-CI+Debug для юнитов, release/*App-Store+Release. Регексы (например ^release/) документируйте рядом с workflow, чтобы ревью видело условие Git и строку схемы в одном diff. Если на том же хосте крутится OpenClaw или другая автоматизация, выделите схемы, которые даже при ошибочном вызове не достигнут продакшн-удостоверений подписи.

  • Схемы trunk — быстрая обратная связь, отладочные символы, более мягкие предупреждения.
  • Релизный поезд — жёстче предупреждения, dSYM и загрузки ASC согласованы.
  • Хотфикс — записи с TTL и автоматическим снятием через CI-тикеты.

Слои xcconfig: база, среда, дорожка, секреты

Считайте .xcconfig составной политикой: Base.xcconfig фиксирует режимы Swift и профили предупреждений; Staging.xcconfig суффиксирует PRODUCT_BUNDLE_IDENTIFIER; LaneJob.xcconfig (генерируется заданием, не коммитится) задаёт префиксы CONFIGURATION_BUILD_DIR и OBJROOT в стиле DerivedData. Include разрешаются в глубину — порядок важен: летучие файлы в конце, секреты через шаблоны секрет-хранилища вне Git. Назначьте code owners на цепочки include для переносов ATS-исключений или материалов подписи между слоями.

Совет ревью: кроме одного CI-сгенерированного суффикса все концы цепочек include должны лежать в отслеживаемых путях; запретите include-шаблоны, ползущие за пределы checkout.

Аргументы xcodebuild, которые идут вместе с выбором схемы

Помимо -scheme и -configuration на аренде часто экспортируют -derivedDataPath, -resultBundlePath и для SwiftPM -clonedSourcePackagesDirPath. Согласуйте эти рычаги со статьёй о параллельных дорожках, чтобы сгладить дрожь APFS. Для xcodebuild archive используйте ту же карту схем, что и для тестов — разнесённая логика в несвязанных workflow даёт классику «тесты зелёные, архив красный». Каждое задание прикладывайте xcodebuild -showBuildSettings -json как артефакт для посмертного сравнения.

xcodebuild -scheme "App-CI" -configuration Debug -destination 'platform=iOS Simulator,name=iPhone 16' -derivedDataPath "$DD" -resultBundlePath "$RESULT" build

Очереди слияний, стек PR и «контракт стабильности схем»

Очереди слияний переставляют коммиты относительно конца ветки; если карта зависит только от имени ветки, обычно безопасно, но для синтетических имён добавьте явные запасные варианты. Инструменты стековых diff, переписывающие историю, требуют повторного определения схемы после каждого rebase — оформите это как предусловие CI, а не заплатку. Контракт стабильности: переименование схемы только в две фазы (алиас, миграция YAML, удаление старого), чтобы Runner не остался наполовину мигрированным, пока разработчики уже удалили legacy локально.

Автоматическая и ручная подпись: где xcconfig помогает и мешает

CODE_SIGN_STYLE = Automatic упрощает ноутбуки, но на общем хосте по-прежнему нужны детерминированные DEVELOPMENT_TEAM и UUID профилей в логах. Ручной стиль требует профили на диске или в связке ключей — синхронизируйте с runbook, чтобы include на feature-ветке не перевернул стиль незаметно. Добавьте CI-grep к -showBuildSettings против опасных пар (например Debug + профиль распространения App Store). В монорепозиториях с несколькими приложениями разнесите xcconfig по целям.

Матрица: где хранить политику

Политика Лучшее место Причина
Уровни предупреждений компилятора Версионируемый xcconfig Диффабельно и ревьюится как код приложения
Префикс каталога сборки на задание CI-сгенерированный xcconfig или env Не в Git; привязка к ID задания
Какие тесты на какой ветке YAML workflow + тест-план Ближе к оркестрации, чем к проекту Xcode
Способ экспорта архива ExportOptions.plist + выделенная схема Согласуется с существующими runbook ASC

Восемь шагов: развёртывание осознанной к схемам многоветвевой CI

  1. На каждом региональном образе выполнить xcodebuild -list -json и архивировать JSON в infra-репозитории.
  2. Составить таблицу regex ветки → схема/конфигурация и привязать к чек-листу PR.
  3. Ввести слои xcconfig; мигрировать по одной цели, сохраняя зелёные сборки.
  4. Добавить CI-шаг с JSON разрешённых настроек для release-подобных конфигураций.
  5. Согласовать DERIVED_DATA_PATH и экспорт каталогов сборки с конвенциями параллельных дорожек.
  6. Если появляются синтетические имена веток слияний — дополнить правилами именования.
  7. Обучить дежурных релиза хотфикс-схемам и истечению срока.
  8. Ежеквартально сравнивать списки схем между регионами и убирать дрейф шаблонов.

Сигналы SLO для управления конфигурацией

Сигнал Порог Действие
Задания без явного -scheme 0 допускается Падение сборки; переиздать шаблоны workflow
Разрешённый DEVELOPMENT_TEAM вне белого списка Любое расхождение Остановить продвижение артефактов; вызвать владельца подписи
Переименование схемы без периода двойной записи Любое незадекларированное переименование Заморозить слияния в релизные ветки до обновления карты

FAQ

Вопрос Практический ответ (2026-05-12)
Нужны ли отдельные схемы для Debug и Release? Обычно нет: если обе конфигурации под одной схемой, выбирайте через -configuration.
Нужен ли отдельный репозиторий на дорожку? Нет — достаточно префиксов каталогов и суффиксов xcconfig при последовательном применении.

Почему аренда Mac mini M4 упрощает итерации политики схем под нагрузкой

Быстрый NVMe и щедрая unified memory позволяют подряд гонять зонды -showBuildSettings, холодные сборки симулятора и сухие прогоны архива, наблюдая за выделением APFS — петля обратной связи перед заморозкой релиза укорачивается. Сравнивайте региональную ёмкость на странице ценообразования; перед расширением поверхности схем направляйте колеблющихся инженеров в руководство SSH/VNC.

Арендуйте билдеры, где политику схем можно проверять

HK / JP / KR / SG / US · SSH / опционально VNC