Резервное копирование артефактов сборки Xcode Cloud нужно запускать в день успешной сборки, а не тогда, когда понадобится старый архив: по официальной документации, информация о сборках и связанные с ними артефакты доступны максимум 30 дней. Для редких релизов достаточно ручного скачивания, но регулярно выпускаемый проект лучше сразу подключить к App Store Connect API и хранить копии отдельно.
Эта статья для независимых разработчиков, которые публикуют приложения через Xcode Cloud, но ещё не сохраняют архивы, символы и результаты тестов вне сервиса. Она также подойдёт тем, кому нужно расследовать старый сбой по crash report, и небольшим командам, планирующим проверять xcarchive и xcresult на постоянном удалённом Mac.
До релиза: разделите артефакты по их будущей задаче
Не каждый файл из рабочего процесса нужно хранить одинаково долго. Сначала определите, какой доказательный или диагностический смысл имеет конкретный результат. Иначе резервная копия быстро превращается в набор безымянных архивов, среди которых невозможно найти нужную версию.
| Артефакт | Для чего он нужен после релиза | Что записать рядом с копией |
|---|---|---|
App Archive, обычно xcarchive |
Повторная проверка версии, идентификатора приложения и связанных файлов публикации | Имя приложения, версия, номер сборки, workflow и идентификатор запуска |
| Символьная информация, включая dSYM | Символизация адресов из отчётов о сбоях и связь crash report с исходными именами методов | Версию, номер сборки и контрольную сумму файла |
xcresult |
Анализ тестов, диагностика ошибок и просмотр результата выполнения | Статус тестов, workflow, дату запуска и краткий журнал |
| Логи сборки | Поиск причины неудачной компиляции, подписи или загрузки | Ссылку на запуск и итоговый статус |
| Артефакты обычной ветки | Разбор регрессии или воспроизведение промежуточного состояния | Ветка, commit, workflow и причину сохранения |
Apple описывает Xcode Cloud как среду, где workflow создаёт сборки и связанные результаты; типы доступных артефактов следует проверять по документации, а не выводить из имени скачанного файла. Для этого полезно сопоставить первичную настройку workflow Xcode Cloud с тем, что реально появляется в интерфейсе проекта.
Как долго хранятся записи и артефакты Xcode Cloud?
На дату, указанную в задании этой статьи — 30 августа 2026 года — официальная граница доступа составляет максимум 30 дней. Это не означает, что каждый файл следует хранить именно такой срок или что сервис является архивом для долгосрочного хранения. Это окно, за которое вы должны успеть найти успешный запуск и вывести нужные данные во внешнее хранилище.
Для расследования сбоев особенно важны не только архив приложения, но и символы. Документация Apple по анализу crash reports и журналов устройств объясняет, почему без соответствующих символов отчёт может остаться набором адресов и служебных обозначений. Поэтому для каждого релизного номера сохраняйте связку «архив — символы — сведения о сборке», а не только один .ipa.
Важно: успешное скачивание не доказывает, что копия пригодна для восстановления. Повреждённый архив, потерянный Build ID или символы от другой сборки обнаружатся только при контрольной проверке.
День сборки: создайте воспроизводимую точку архива
Первый ручной архив нужен не только как запасная копия. Он становится эталоном для будущего скрипта: вы увидите, какие файлы доступны, как они названы и какие метаданные необходимо сохранить вместе с ними.
Шаг 1. Найдите конкретный запуск
Откройте нужный проект и workflow в Xcode Cloud или App Store Connect. Не выбирайте последний запуск вслепую: сопоставьте статус, ветку, commit, версию приложения и номер сборки. Для релизной копии выбирайте успешный Archive или запуск рабочего процесса, который действительно использовался для публикации.
Занесите в отдельный манифест:
- название приложения и bundle identifier;
- marketing version и Build Number;
- идентификатор запуска и название workflow;
- commit или другой идентификатор исходного состояния;
- итоговый статус;
- дату создания копии;
- перечень скачанных файлов.
Имена аккаунтов, App ID, Build ID и пути к локальным каталогам в документации команды должны быть обезличены, если вы передаёте журнал подрядчику или публикуете пример.
Шаг 2. Скачайте результаты официальным способом
Скачайте доступные артефакты из Xcode или App Store Connect, затем проверьте, что загрузился именно ожидаемый тип файла. Если вам нужен xcarchive, не подменяйте его экспортированным .ipa: это связанные, но не одинаковые результаты. Аналогично xcresult предназначен для чтения результатов тестирования, а не для замены архива приложения.
Для тестовых запусков ориентируйтесь на описание Apple о запуске тестов и интерпретации результатов. Сохраните исходный файл результата целиком: выборочное копирование отдельных скриншотов или текста отчёта лишает вас части контекста.
Шаг 3. Зафиксируйте структуру и контрольные значения
Один из безопасных вариантов каталога:
app-name/
version-build/
archive/
symbols/
test-results/
logs/
manifest.json
Папку version-build формируйте из обезличенных и однозначных значений, например release-<VERSION>-<BUILD>. В manifest.json запишите идентификатор запуска, workflow, статус и относительные имена файлов. Контрольную сумму вычисляйте локально после скачивания и сохраняйте в манифесте:
shasum -a 256 path/to/artifact.zip
Команда не подтверждает корректность содержимого, но помогает обнаружить изменение файла между скачиванием и восстановлением. Приватные ключи сертификатов, секреты API и пароли удалённого доступа не должны находиться в каталоге артефактов. Их нужно хранить в отдельном защищённом хранилище с иной политикой доступа.
Первая неделя: переведите повторяющиеся загрузки на API
Ручной процесс подходит для редких выпусков, но при регулярной публикации он зависит от памяти одного человека. App Store Connect API позволяет автоматизировать поиск запусков и получение связанных артефактов; логика должна начинаться не с перебора всех файлов, а с отбора нужных сборок.
Может ли App Store Connect API автоматически резервировать артефакты сборки?
Да, API можно использовать как основу автоматической выгрузки: найти подходящий build run, получить его actions, запросить artifacts, скачать доступные файлы и записать результат выполнения. API не превращает App Store Connect в бессрочное хранилище: скрипт должен выполнить скачивание до окончания окна доступности и сохранить копию за пределами сервиса. Схему ресурсов проверяйте по описанию build runs, ресурсу artifacts и методу получения артефактов action.
Шаг 4. Разделите поиск, загрузку и фиксацию результата
Практический сценарий состоит из отдельных операций:
- Получить список недавних запусков и отфильтровать успешные релизные workflow.
- Сопоставить результат с приложением, версией и Build Number.
- Получить actions выбранного запуска.
- Запросить список доступных artifacts.
- Скачать каждый нужный файл во временный каталог.
- Проверить размер, распаковку и контрольную сумму.
- Переместить файл в каталог релиза и записать
manifest.json. - Сохранить статус:
downloaded,verified,failedилиskipped.
Вызовы и поля зависят от актуальной схемы API, поэтому не копируйте в production-скрипт случайный пример без сверки с официальной документацией App Store Connect API. В примерах используйте только заменители:
ISSUER_ID=<ваш_issuer_id>
KEY_ID=<ваш_key_id>
PRIVATE_KEY_PATH=<путь_к_ключу>
APP_ID=<обезличенный_app_id>
BUILD_ID=<обезличенный_build_id>
API-ключ для App Store Connect, сертификаты и provisioning profile, а также доступ по SSH к удалённому Mac — это три разные группы полномочий. Нельзя считать наличие одной из них заменой остальных. Скрипту выгрузки не нужны права на интерактивный вход в рабочую станцию, а пользователю, который проверяет архив, не обязательно выдавать секрет API.
Шаг 5. Сделайте повторный запуск безопасным
Основой идемпотентности может быть комбинация Build ID, имени workflow и типа артефакта. Перед загрузкой проверьте манифест: если файл уже имеет статус verified, не скачивайте его повторно. Если предыдущий запуск оборвался после загрузки, но до проверки, оставьте временный файл и выполните проверку заново.
Сохраняйте журнал ошибок отдельно от самих артефактов. В нём достаточно обезличенного идентификатора запуска, стадии, времени операции и текста ошибки без токенов. Так вы сможете отличить «артефакт недоступен» от «сбойнуло подключение к хранилищу», не раскрывая секреты.
Между релизами: выберите триггер и резервный маршрут
Webhook сообщает внешней системе о событии, но не является хранилищем. После получения уведомления внешний обработчик всё равно должен найти запуск, запросить артефакты, скачать их и подтвердить результат. Возможность получать события Xcode Cloud через webhook описана в официальной документации по настройке webhook.
| Подход | Когда выбрать | Обязательное дополнение |
|---|---|---|
| Периодический опрос | Релизы выходят нерегулярно, а задержка в обнаружении новой сборки допустима | Повторная проверка после каждого релиза и журнал последнего успешного прохода |
| Webhook после завершения | Команда выпускает часто и хочет начать архивирование сразу после события | Повторный запрос данных, потому что уведомление само не сохраняет файл |
| Комбинация webhook и опроса | Нельзя допустить пропуск события или временный сбой обработчика | Компенсационное сканирование незавершённых и недавно успешных запусков |
Для редкого выпуска начните с планировщика: он проще для сопровождения и не требует постоянно доступного обработчика событий. При высокой частоте релизов используйте webhook, но оставьте периодический компенсационный проход. Это защищает от сетевого сбоя, недоступности внешнего сервиса или ошибки в обработчике.
Как не получить две копии одного запуска?
Перед скачиванием проверяйте ключ идемпотентности. После загрузки сначала выполняйте проверку, затем атомарно меняйте статус на verified. Если webhook пришёл дважды, второй обработчик увидит уже подтверждённый манифест и завершится без повторной записи.
День выпуска: проведите восстановление, а не только скачивание
Релизная копия считается готовой, когда вы можете её найти, открыть и связать с нужной сборкой. Проверка должна проходить в среде, отличной от каталога, куда первоначально скачивался файл.
Шаг 6. Проверьте архив и соответствие версии
Распакуйте архив во временную директорию с ограниченными правами. Убедитесь, что структура не повреждена, файл читается, а версия и Build Number совпадают с манифестом и записью в App Store Connect. Не используйте исходную рабочую папку как единственную точку проверки: так легко незаметно прочитать старую локальную копию.
Для xcresult откройте результат средствами Xcode и проверьте, что доступны тестовые действия, ошибки и вложения, необходимые для расследования. Если файл был сжат, сначала протестируйте распаковку в чистую директорию, а не поверх существующих данных.
Шаг 7. Проверьте символы на реальном отчёте
Возьмите обезличенный crash report, относящийся к той же версии, и выполните символизацию с сохранёнными dSYM. Сверьте Build ID, UUID символов и номер сборки. Наличие файла с подходящим названием ещё не доказывает совместимость: символы от другой сборки могут лежать рядом и создать ложное ощущение готовности.
Не включайте сертификаты, приватные ключи и provisioning profile в обычную папку резервных копий. Для восстановления анализа crash report обычно нужна соответствующая символическая информация и метаданные сборки, а не экспорт всех секретов команды.
Можно ли восстановить Xcode Cloud после удаления сборки?
App Store Connect API помогает скачать доступные артефакты, но не заменяет заранее созданную внешнюю копию и не должен рассматриваться как механизм восстановления удалённых данных. Если запуск или его результат больше недоступен в официальном интерфейсе и у вас нет внешнего архива, рассчитывать на возврат нельзя. Поэтому автоматизация должна отслеживать не только успешные загрузки, но и пропуски до окончания окна доступа.
Долгосрочная эксплуатация: храните по риску, а не по привычке
Не задавайте единственный срок для всех файлов без решения команды. Внутренние сборки могут требовать короткой истории для поиска регрессий, кандидат на выпуск — подтверждения перед публикацией, а официальный релиз — полного набора материалов для поддержки и анализа сбоев. Конкретный срок выбирайте по требованиям продукта, договорённостям с заказчиком и регуляторным обязанностям.
Разделите роли хранилищ:
- локальный диск подходит для временной загрузки и первичной проверки;
- объектное хранилище удобно для независимой копии и автоматического доступа;
- постоянный удалённый Mac полезен, если нужно регулярно открывать архивы в Xcode, запускать символизацию или выполнять сценарии восстановления;
- рабочая папка CI не должна быть единственным местом хранения.
Если вы собираетесь централизовать такие операции на удалённом Mac, сначала определите, нужен ли вам краткосрочный доступ только для загрузки или постоянно работающий узел для проверок. На странице VMSPIN для русскоязычных пользователей можно отдельно оценить такой формат среды, но решение принимайте после проверки требований к диску, доступу и секретам.
Ежемесячная контрольная проверка
Поставьте в календарь повторяющийся процесс:
- выбрать старую релизную копию;
- проверить наличие манифеста и контрольной суммы;
- распаковать
xcarchiveи открытьxcresult; - сопоставить Build Number и идентификатор запуска;
- проверить символизацию тестовым crash report;
- убедиться, что журнал автоматизации содержит успешный статус.
Если автоматическое архивирование работает молча, его отказ может обнаружиться только после исчезновения исходного результата. Поэтому после каждого релиза проверяйте не только код возврата скрипта, но и появление полного набора файлов во внешнем каталоге.
Итог: когда текущей схемы уже недостаточно
Если вы оставляете всё внутри Xcode Cloud, у вас остаются три слабых места: ограниченное окно доступа, зависимость от ручного поиска старых запусков и отсутствие доказательства, что скачанный файл действительно восстанавливается. При редких выпусках ручной архив может быть достаточен, но для постоянного проекта безопаснее связка «API — внешнее хранилище — контрольное восстановление».
Если проверка требует регулярно открывать исторические xcarchive, читать xcresult, выполнять символизацию или поддерживать постоянно работающий скрипт загрузки, аренда удалённого Mac у VMSPIN может оказаться удобнее разовых локальных запусков: вам не нужно покупать отдельный компьютер для редкой задачи, а среду можно держать доступной для команды. При этом для длительной тяжёлой нагрузки, строгой потребности в физических интерфейсах или хранения секретов по внутренним правилам собственный Mac может быть оправданнее. Для временного узла архивирования и восстановления сначала сопоставьте требования с вариантами аренды Mac, а затем проведите одну полноценную тестовую выгрузку и восстановление до переноса всей цепочки.