2026-04-17 iOS dSYM и символикация крэшей CI на арендованном облачном Apple Silicon Mac
Когда iOS-команда арендует безголовый Mac mini M4 в Гонконге, Токио, Сеуле, Сингапуре или на востоке США, билд-машина — лишь половина истории: символикация крэшей зависит от dSYM-бандлов с UUID, совпадающими с поставленными бинарниками. Рунбук 2026-04-17 описывает DWARF внутри .xcarchive, разрывы при ротации CI-хостов, порядок загрузки символов после xcodebuild archive и ретеншн с учётом NVMe на общих билдерах. Читайте вместе с экспортом IPA и API App Store Connect, очисткой симулятора и архивов и изоляцией DerivedData. Для параллельных очередей — параллельные xcodebuild и структурированные логи.
Почему dSYM всё ещё побеждают в 2026
Отчёты Apple — Organizer, App Store Connect или сторонние бэкенды — раскрывают стеки через DWARF. Неверный strip, неверный коммит или другой уровень оптимизации дают вечные анонимные фреймы. На арендованных облачных Mac эфемерные диски подталкивают удалять ~/Library/Developer/Xcode/Archives, ожидая символикацию неделями спустя.
- Точность UUID — у каждого среза архитектуры свои идентификаторы; одна несостыковка ломает бандл.
- Наследие bitcode — большинство не поставляет bitcode, но старые доки путают.
- Мультиархитектура — не перепутайте device/simulator dSYM в скриптах загрузки.
Закрепите сверку UUID как гейт перед мержем в релизную ветку и сохраняйте вывод в метаданных CI.
Где реально лежат символы
После xcodebuild archive Xcode вкладывает бинарники и символы в один .xcarchive. До успешной загрузки держите каталог как неизменяемый артефакт. Для объектного хранилища используйте детерминированные имена zip (схема, конфигурация, короткий SHA).
| Путь (типично) | Содержимое | CI-заметка |
|---|---|---|
…/dSYMs/*.dSYM | DWARF на таргет | Zip с фиксированным именем: ${SCHEME}-${GIT_SHA:0:7}.dSYM.zip |
…/Products/Applications/*.app | stripped release | Не переподписывать после dSYM — риск дрейфа UUID |
BCSymbolMaps (если есть) | legacy maps | Вместе с dSYM, если требует шаблон ASC |
dwarfdump --uuid Your.app/YourBinary
Пайплайн после архива: порядок важен
- Заморозить входы —
CURRENT_PROJECT_VERSION,MARKETING_VERSION, SHA Git, номер сборки Xcode в JSON sidecar. - Экспорт IPA (опционально) — см. export options;
methodменяет дефолты загрузки символов. - Стейдж dSYM zip — из архива, не из DerivedData.
- Загрузка — ASC/совместимый Transporter или сторонний endpoint до удаления архивов.
- Проверка — опрос бэкенда крэшей или статуса ASC; не чистить локальные артефакты без подтверждения или SLA.
При параллельных export-полосах разносите sidecar и добавляйте lane id в ключи объектов.
Матрица хранения: горячий, тёплый, холодный
| Уровень | Срок | Место | Причина |
|---|---|---|---|
| Горячий | 7–14 дней | NVMe билдера | Быстрые повторные скачивания и инциденты |
| Тёплый | 90 дней | Объектное хранилище / второй Mac | Ревью App Store и ранние крэши |
| Холодный | 1–7 лет | Комплаенс-архив | Регулируемые отрасли, шифрование at rest |
Паттерны CI на общих облачных Mac
Создавайте отдельный подкаталог на job в /Volumes/ci-artifacts (или вашем NVMe), чтобы параллельные полосы не перезаписывали dSYM zip. Если DerivedData уже изолирован, распространите правило на ARCHIVE_PATH. Для GitHub Actions/Jenkins SSH оборачивайте загрузки в экспоненциальный backoff.
DerivedData/Build/Products после локального build, а не настоящего archive.Бюджеты NVMe и согласование уборщиков
Каждый сохранённый .xcarchive часто 6–25 ГБ для среднего SwiftUI-приложения. Ночные билды заполнят 512 ГБ раньше финансов. Прежде чем добавлять ноду через pricing, убедитесь, что рунбук уборки оставляет только проверенные после загрузки сборки. Свободно < ~12% — жёсткий стоп новых архивов.
Региональные билдеры: задержка и приватность
Команды в Японии и Корее часто архивируют ближе к тестировщикам при глобальной обработке ASC — нормально, если загрузка символов остаётся в разрешённых регионах или шифруется к вендору крэшей. При зеркалировании фиксируйте, какие build id где лежат.
Связанные рунбуки
Сочетайте с параллельными очередями xcodebuild, чтобы не голодать диск при zip, и с структурированными логами для корреляции «нет символов» и реальных сбоев загрузки.
FAQ: дисциплина dSYM на облачном Mac CI
| Вопрос | Практический ответ |
|---|---|
| Синхронная загрузка dSYM в CI? | Лучше асинхронно с блокирующей проверкой до удаления архива; синхронно проще, но длиннее пайплайн. |
| Можно ли пересобрать dSYM позже? | Только при бит-в-бит тех же входов компилятора; не политика, а крайний случай. |
| Апгрейд Xcode в середине недели? | Заморозьте toolchain на релизной ветке; смешивание миноров между архивом и re-sign — топовая причина рассинхрона UUID. |
Итог: dSYM — как налоговые квитанции: неизменяемые, датированные, аудируемые; не удаляйте под давлением NVMe без подтверждения загрузки.
Арендуйте Apple Silicon CI с запасом NVMe
SSH в приоритете · HK · JP · KR · SG · US