Каждый коммит запускает полный набор тестов, а результат приходит уже после того, как контекст разработки потерян.
Самое быстрое решение — не покупать дополнительные вычислительные часы сразу: сначала разделите pull request-проверки, полное тестирование и Archive, отключите повторные запуски, а тяжёлые задачи при необходимости перенесите в связку Xcode Cloud и постоянного удалённого Mac.
Эта статья предназначена для трёх групп:
- независимых разработчиков, у которых каждый push запускает полный workflow;
- небольших команд, проверяющих совместимость с Xcode 27 Beta и одновременно поддерживающих стабильный релиз;
- владельцев CI/CD, у которых растёт расход вычислительного времени и возникает вопрос: оптимизировать Xcode Cloud или обслуживать постоянную машину.
Последнее обновление: 4 сентября 2026 года. Статус Xcode 27 и ограничения Beta сверены с официальными заметками к выпуску Xcode 27. Названия настроек и сценарии проверены по документации Xcode Cloud и App Store Connect.
Сначала разделите календарь сборки, а не увеличивайте лимит
Фраза «Xcode Cloud строится слишком медленно» описывает симптом, но не указывает на виновника. Полное время workflow нужно разложить на отдельные отрезки:
- ожидание запуска;
- получение исходного кода;
- подготовка Swift Package, CocoaPods и сторонних инструментов;
- Build;
- Test;
- Archive;
- загрузка и последующая обработка в App Store Connect.
Эти этапы относятся к разным типам задержек. Очередь не ускоряется изменением кода. Медленная установка зависимостей не исправляется уменьшением матрицы симуляторов. А загрузка Archive может завершиться успешно, пока сборка ещё ожидает обработки в App Store Connect. Apple отдельно описывает статусы загрузки и обработки сборок в справке по состояниям загруженных build.
Сравнивать следует не «вчерашнюю сборку» с «сегодняшней», а одинаковые условия:
- один commit;
- один workflow;
- одна версия Xcode;
- одинаковый Scheme;
- одинаковый набор тестов;
- одинаковый тип действия — Build, Test или Archive.
Сохраните из журнала время начала и окончания каждой фазы. Не смешивайте вычислительное время, ожидание в очереди и время, которое разработчик фактически ждёт ответа. Иначе можно потратить ресурс на оптимизацию компиляции, хотя основная задержка появляется ещё до запуска runner.
Карта первичной диагностики
| Наблюдение в журнале | Вероятная причина | Первое действие | Когда менять архитектуру |
|---|---|---|---|
| Долго до появления первых команд сборки | Очередь или повторные запуски | Проверить триггеры и Auto-cancel Builds | Если релизные задачи регулярно блокируются |
| Долго выполняется checkout и подготовка пакетов | Зависимости, доступ к репозиторию, установка инструментов | Проверить lock-файлы, авторизацию и скрипты | Если среду приходится восстанавливать почти для каждой тяжёлой задачи |
| Build короткий, Test занимает основное время | Слишком широкая матрица симуляторов или UI-тесты | Разделить smoke-, regression- и release-проверки | Если нужны постоянный сервис, фиксированное состояние или интерактивная отладка |
| Archive заметно тяжелее обычного Build | Подпись, упаковка, загрузка и обработка | Вынести Archive в отдельный workflow | Если Archive запускается часто и требует предсказуемого окружения |
| Успешная загрузка долго не видна в TestFlight | Серверная обработка после upload | Проверять статус обработки отдельно | Если публикация требует ручного доступа к хосту и повторного запуска |
Документация Apple рекомендует проектировать workflow по назначению, а не превращать один workflow в универсальный конвейер для каждого события. Это описано в руководстве по стратегии workflow для Xcode Cloud.
Быстрая проверка против полного теста: что запускать на каждый push
Если каждый push запускает долго, проблема обычно находится не в самом факте использования Xcode Cloud. Чаще один триггер выполняет слишком много несвязанных действий: компилирует приложение, проверяет несколько симуляторов, запускает UI-тесты, создаёт Archive и готовит TestFlight-загрузку.
Для pull request разумно оставить только то, что отвечает на вопрос: «Изменение вообще собирается и не ломает ключевую логику?» Практическая схема:
- Build выбранного Scheme;
- небольшой набор критичных unit-тестов;
- статические проверки, если они уже встроены в проект;
- сохранение лога и результата тестов.
Полную матрицу устройств, UI-автоматизацию и регрессионные тесты следует запускать по отдельному условию. Подходящее условие зависит от риска: изменение авторизации, платежей или фоновой синхронизации требует более строгой проверки, чем правка текста экрана.
Не задавайте универсальный порог времени. Для одного проекта критична обратная связь сразу после push, для другого допустима длинная проверка перед слиянием. Важнее зафиксировать рабочую цель каждой очереди и не смешивать её с релизной задачей.
Auto-cancel Builds и дублирующие запуски
Когда разработчик быстро отправляет несколько исправлений подряд, старые проверки могут потерять ценность. Если новый commit уже заменил предыдущий, завершение старой проверки не всегда помогает принять решение по текущему состоянию ветки.
Проверьте настройку Auto-cancel Builds. Правила Xcode Cloud для автоматической отмены описаны в официальном справочнике workflow. Настройка должна соответствовать риску:
- для последовательных pull request-проверок можно отменять устаревшие запуски;
- для Archive, который уже начал выпускной процесс, автоматическая отмена требует осторожности;
- для диагностического запуска старый build лучше сохранить, если он нужен для сравнения ошибки.
Здесь важна не сама отмена, а условие её применения. Если отменяются только заменённые проверки, ресурс не тратится на результаты, которые уже не относятся к текущему коду. Если же отмена затрагивает публикацию, можно потерять единственный полезный лог.
Мини-чек-лист для pull request
- [ ] У workflow есть отдельное условие запуска для pull request.
- [ ] В нём нет TestFlight-загрузки.
- [ ] Archive не запускается на каждый push.
- [ ] Набор unit-тестов отражает изменённый модуль.
- [ ] Устаревшие проверки отменяются только до начала релизного процесса.
- [ ] Лог и результат проверки сохраняются для анализа отказа.
Симуляторы: широкая матрица против проверок по риску
Вопрос о том, как сократить время тестов симулятора, нельзя решать простым удалением устройств. Сначала разделите назначение теста.
Проверка здоровья отвечает на базовый вопрос: приложение собирается, запускается и выполняет несколько критичных действий. Её можно связывать с частыми изменениями.
Проверка совместимости ищет различия между устройствами, версиями системы, разрешениями и размером экрана. Она полезна при изменении интерфейса, навигации, хранилища или системных API.
UI-автоматизация проверяет пользовательские сценарии, но обычно требует больше подготовки и чаще создаёт сложные для разбора сбои.
Предрелизная регрессия нужна перед Archive и должна подтверждать именно кандидат на выпуск, а не каждый промежуточный коммит.
Следовательно, один набор тестов не обязан запускаться с одинаковой частотой. Для каждой группы определите:
- какую ошибку она обнаруживает;
- как часто такая ошибка уже возникала;
- можно ли быстро воспроизвести отказ;
- какой артефакт остаётся после выполнения;
- кто принимает решение по результату.
После изменения матрицы не делайте вывод по субъективному ощущению ускорения. Проверьте несколько одинаковых рабочих сценариев на одном проекте, затем сравните найденные дефекты, скриншоты падений и тестовые отчёты. Если после удаления редких устройств перестали обнаруживаться реальные ошибки, покрытие уменьшили слишком сильно.
Важно: отсутствие ошибки в одной короткой проверке не доказывает, что устройство можно исключить из релизной регрессии. Решение подтверждается историей дефектов и результатами кандидата на выпуск.
Вторая таблица: какое действие куда помещать
| Рабочая ситуация | Что запускать часто | Что запускать реже | Что не включать по умолчанию |
|---|---|---|---|
| Pull request | Build и критичные unit-тесты | Выборочную совместимость | Archive и TestFlight |
| Изменение UI или системной интеграции | Build и затронутые тесты | Несколько целевых симуляторов | Полную матрицу без связи с риском |
| Ночной или плановый прогон | Полный набор автоматизированных тестов | Расширенную совместимость | Ручные действия разработчика |
| Подготовка релиза | Кандидатный Test и проверка подписи | Полную регрессию | Случайный commit из рабочей ветки |
| Финальный выпуск | Archive, загрузка и проверка статуса | Повторное подтверждение результата | Параллельные неуправляемые Archive |
Такой подход отвечает на поисковый вопрос о том, почему Xcode Cloud долго работает на каждом изменении: потому что частый триггер выполняет работу, предназначенную для другой стадии жизненного цикла.
Зависимости и скрипты: чистая среда против повторной подготовки
Xcode Cloud работает с временной средой. Поэтому нельзя без проверки переносить предположение о локальном кэше на удалённый workflow. Если лог показывает, что Build занимает небольшую долю, а подготовка пакетов и инструментов повторяется перед каждым Action, увеличивать вычислительный лимит преждевременно.
Разделите задержки по источнику:
- checkout репозитория;
- Swift Package Manager;
- CocoaPods;
- установка стороннего CLI;
- получение секретов и сертификатов;
- пользовательские скрипты;
- подготовка файлов для конкретного Action.
Правила подготовки зависимостей и требования к их доступности описаны в документации Apple о зависимостях Xcode Cloud. Для каждого пакета проверьте, что версия фиксируется lock-файлом, а доступ к закрытому репозиторию воспроизводится без ручного ввода.
Скрипты часто становятся скрытым дубликатором работы. Например, один и тот же инструмент устанавливается отдельно перед Build, Test и Archive, хотя он нужен только Archive. Другой сценарий — подготовка тестовых данных перед каждым действием, даже если данные не меняются.
Организуйте условное выполнение по:
- источнику запуска;
- имени workflow;
- типу действия;
- наличию нужного файла или переменной;
- ветке или тегу релиза.
Правила пользовательских скриптов и доступные переменные следует сверять с официальным руководством по custom build scripts и справочником переменных окружения. Все примеры должны использовать обезличенные значения: sample-repository, DemoScheme, TEAMID0000 и условный путь. Реальные ключи, Bundle ID и идентификаторы команды нельзя помещать в статью или открытый лог.
Как обрабатывать медленную установку зависимостей
Если Xcode Cloud долго устанавливает зависимости, порядок действий такой:
- Откройте лог конкретного workflow, а не только сводку результата.
- Отметьте начало и конец checkout, разрешения пакетов и каждого пользовательского скрипта.
- Сверьте версии пакетов с lock-файлами.
- Проверьте, не запускается ли один установщик в нескольких Actions.
- Уберите из pull request-проверки инструменты, нужные только для Archive.
- Повторите тот же commit в том же workflow.
- Сравните не среднее ощущение, а состав фаз и повторяемость.
Если после этого подготовка остаётся главным ограничением, а workflow требует постоянных сервисов, локального состояния или заранее установленного инструмента, это уже аргумент в пользу постоянного удалённого Mac. Временная среда удобна для воспроизводимой проверки, но не обязана быть заменой постоянно работающему хосту.
Archive и TestFlight: выпускной конвейер против ежедневной обратной связи
Archive нельзя считать просто «ещё одной сборкой». В нём участвуют подпись, упаковка, экспорт, загрузка и обработка на стороне App Store Connect. В справке Apple отдельно описаны загрузка и обработка build, поэтому успешное завершение upload ещё не означает, что сборка уже доступна для тестирования.
Для выпуска задайте более строгий триггер:
- тег версии;
- ручной запуск;
- выделенная release-ветка;
- подтверждение кандидата после регрессии.
Archive должен иметь отдельный лог и отдельный набор артефактов. Не прячьте его внутри pull request-workflow: иначе быстрый отказ компиляции смешивается с ошибкой подписи или последующей обработкой.
Проверка после разделения должна быть реальной. Возьмите обезличенный кандидат на выпуск и пройдите цепочку:
- собрать Release-конфигурацию;
- проверить подпись и provisioning;
- создать Archive;
- загрузить его;
- дождаться статуса обработки;
- убедиться, что результат виден там, где его ожидает команда;
- проверить сценарий повторного запуска после отказа.
Время ожидания обработки не следует записывать как время компиляции. Для владельца проекта это всё равно задержка выпуска, но техническое решение будет разным: оптимизация Scheme помогает Build, а проблема обработки решается проверкой статуса и процесса публикации.
Когда достаточно Xcode Cloud, а когда нужен постоянный удалённый Mac
После разделения workflow используйте условия, а не общее впечатление.
Оставляйте Xcode Cloud основным контуром, если:
- каждый workflow воспроизводится в чистой временной среде;
- зависимости фиксированы;
- pull request можно проверять коротким набором действий;
- полная матрица запускается по риску, а не автоматически;
- Archive не блокирует каждое изменение;
- команде не нужен интерактивный доступ к постоянно работающей машине.
Выбирайте двойной контур: Xcode Cloud для лёгкой проверки, удалённый Mac для тяжёлых задач, если:
- проекту нужен установленный набор инструментов и фиксированная версия Xcode;
- повторная подготовка зависимостей занимает значительную долю workflow;
- в сборке участвуют фоновые сервисы или локально сохраняемое состояние;
- Archive запускается часто;
- требуется быстро зайти на хост, посмотреть окружение и повторить команду вручную.
Переносите тяжёлые задачи на удалённый Mac, если:
- они требуют длительного постоянного процесса;
- CI должен работать с фиксированной файловой системой;
- диагностика регулярно требует SSH или графического доступа;
- Xcode Cloud остаётся полезным только для коротких проверок.
Это не означает, что Xcode Cloud нужно отключить. Двойная схема сохраняет независимую проверку pull request и одновременно даёт постоянное окружение для Release Archive, миграций и ручной диагностики.
Решение по трём веткам
- Если основное время уходит на тесты, а матрицу можно разделить по риску, выберите дальнейшую оптимизацию Xcode Cloud.
- Если быстрые проверки стабильны, но зависимости, сервисы или Archive требуют постоянного состояния, выберите двойной контур.
- Если большая часть полезной работы — это фиксированная среда, частые тяжёлые Archive и ручное устранение сбоев, перенесите тяжёлые workflow на удалённый Mac.
- Если не удалось определить фазу задержки, не меняйте тариф и не переносите проект: сначала повторите один commit в одинаковых условиях и сохраните обезличенный журнал.
- Если после разделения выпуск всё ещё задерживается, проверьте полный Archive и статус обработки, а не только время Build.
Перед выбором машины можно изучить варианты удалённого Mac для CI/CD, а затем проверить конкретную конфигурацию в руководстве по оформлению Mac mini M4. Важен не сам факт аренды, а соответствие окружения нагрузке: версия Xcode, объём проекта, способ доступа и необходимость постоянной доступности.
Для итоговой проверки отметьте:
- [ ] Один и тот же commit проверен в Xcode Cloud и на удалённом Mac.
- [ ] Разделены Build, Test, Archive, upload и обработка.
- [ ] Зафиксированы версии Xcode 27 и зависимостей.
- [ ] Release Archive прошёл подпись и загрузку.
- [ ] Проверен повторный запуск после отказа.
- [ ] Секреты и идентификаторы удалены из журналов.
- [ ] Решение принято по фазе задержки, а не по общему времени workflow.
Если текущая схема продолжает запускать полный тест на каждый push, она платит вычислительным временем за работу, которая нужна только перед релизом. После разделения слабые места становятся видны точнее: Xcode Cloud остаётся удобным для воспроизводимых лёгких проверок, а удалённый Mac оправдан там, где требуются постоянные зависимости, фоновые сервисы, фиксированная среда и частые Archive. Именно так следует оценивать ситуацию, когда Xcode Cloud строится слишком медленно: сначала один реальный кандидат на выпуск, затем решение о двойном контуре.