В выводе df -h для Xcode CI важны как минимум два параметра — доступное место и занятый объём конкретного тома; именно такой контроль следует выполнить до удаления файлов, а не после. Рекомендации Apple по управлению хранилищем macOS подтверждают необходимость анализировать категории хранения, но для аварийного восстановления этого недостаточно: сначала остановите запись, зафиксируйте первый No space left on device, затем разберите рабочие каталоги, DerivedData, Simulator runtime, архивы и кэши по владельцам.

Если после удаления подтверждённых воспроизводимых данных нормальная сборка снова заполняет диск, прекращайте повторные «полные чистки». Для удалённого Mac CI нужны новая политика хранения, разделение задач или узел большей ёмкости.

Эта инструкция предназначена для дежурного разработчика, который должен быстро вернуть рабочее пространство без потери доказательств сбоя. Она также пригодится DevOps-инженеру, обслуживающему общий Runner, и платформенному инженеру, принимающему решение между очисткой, пересозданием и расширением узла.

01

Первые минуты: остановка записи и фиксация границы сбоя

Ошибка Xcode No space left on device не указывает, какой именно каталог исчерпал ресурс. Пространство может закончиться на системном томе, в отдельном рабочем каталоге, в каталоге данных виртуальных устройств или в области, куда процесс пытается записать архив. Поэтому команда, удаляющая «все кэши», до диагностики создаёт дополнительный риск.

Дежурный разработчик должен действовать в следующем порядке:

  • остановить очередь новых сборок и повторные попытки текущего задания;
  • не перезапускать узел, пока не сохранены журнал, идентификатор коммита и параметры сборки;
  • сохранить первое полезное сообщение No space left on device, а не только финальный статус CI;
  • записать исполняющую учётную запись, имя задания, рабочий каталог и активную схему;
  • проверить, какие процессы всё ещё пишут на диск;
  • зафиксировать состояние файловой системы до очистки.

Для первичной проверки подставьте фактический том и рабочий путь вместо заполнителей:

df -h /
df -i /
du -sh "<WORKSPACE>"
du -sh "<DERIVED_DATA>"
ps aux | grep -E 'xcodebuild|simctl|Simulator|swift|clang'

df -h показывает размер в удобном виде, а df -i помогает обнаружить ситуацию, когда блоки ещё доступны, но исчерпаны файловые записи. Если второй отчёт недоступен в конкретной конфигурации, это не повод переходить к удалению: сохраните вывод df -h, список процессов и перечень каталогов, который удалось получить.

Справочник Apple по инструментам командной строки Xcode полезен для сверки доступных команд и параметров именно с установленной версией инструментов. На общем узле нельзя переносить команду из чужого скрипта без проверки локальной справки.

Предупреждение. rm -rf по корню рабочего каталога, каталогу пользователя или всему каталогу разработчика может уничтожить архивы, журналы, локальные настройки и материалы расследования. Сначала сохраните доказательства и остановите процессы, затем удаляйте только явно определённый набор данных.

02

Карта ответственности и порядок действий

Ниже приведено разделение не по каталогам, а по владельцам результата. Такой подход снижает вероятность, что дежурный разработчик удалит данные, за которые отвечает релизная или платформенная команда.

Роль Что проверить Что обычно можно удалить после проверки Что обязательно сохранить
Дежурный разработчик Рабочее пространство, временные файлы, повторные клоны, остановленные задания Только результаты завершённых задач, которые воспроизводятся тем же коммитом Исходный код, первый журнал ошибки, незавершённый релизный результат
Владелец сборки DerivedData, Swift Package и инструментальные кэши, активные процессы Неиспользуемые результаты конкретного проекта после проверки владельца Данные параллельных заданий и кэш, необходимый для расследования
Ответственный за тесты Runtime, устройства Simulator, тестовые данные Неиспользуемые устройства и компоненты через поддерживаемые средства Runtime и устройства, входящие в текущую матрицу
Ответственный за релиз xcarchive, экспорт, символы, материалы загрузки Только просроченные или уже перенесённые копии по политике хранения Архив, символы, журнал подписи и текущие материалы поставки
Платформенный инженер Рост по проектам, учётным записям и типам задач Данные по утверждённой политике очистки Метрики, правила хранения и сведения о восстановлении узла

Такой порядок отвечает на главный вопрос аварии: кто имеет право удалить объект и каким тестом подтверждается, что удаление не сломало следующий этап.

03

Рабочая область и повторные результаты

Первым владельцем восстановления обычно становится дежурный разработчик. Ему не требуется сразу изучать всю систему. Сначала нужно отделить исходный код и конфигурацию от результатов, которые можно получить повторно.

Проверяются:

  • несколько копий одного репозитория;
  • каталоги незавершённых и отменённых заданий;
  • временные файлы экспорта;
  • результаты предыдущих попыток упаковки;
  • локальные отчёты тестов, если они уже переданы в систему хранения;
  • файлы, созданные процессом, который был прерван из-за заполнения диска.

У каждого объекта должны быть подтверждены владелец, статус задания и возможность воспроизведения. Если каталог относится к активному процессу, его нельзя удалять только по возрасту. Если задание завершено неуспешно и продуктовая команда подтверждает, что результат не нужен, очистка допустима при сохранённом логе и идентификаторе коммита.

После освобождения места выполняется не произвольная сборка, а повторение исходного сценария:

git status --short
git rev-parse HEAD
xcodebuild \
  -workspace "<WORKSPACE>.xcworkspace" \
  -scheme "<SCHEME>" \
  -configuration "<CONFIGURATION>" \
  -destination "<DESTINATION>" \
  build

Значения <WORKSPACE>, <SCHEME>, <CONFIGURATION> и <DESTINATION> должны быть взяты из исходного задания. Подмена назначения или схемы создаёт ложное ощущение восстановления.

Если место снова исчезает во время той же операции, нужно остановить повторные попытки и передать владельцу узла снимок состояния: свободное место до запуска, каталог, который вырос, PID процесса, коммит и параметры задания.

04

DerivedData и зависимости

Владелец сборочного контура отвечает за DerivedData, но этот каталог нельзя считать безусловным мусором. Он может содержать промежуточные результаты конкретного проекта, данные индексации и материалы, которые ускоряют последующие действия. Фактический путь зависит от активного Xcode, учётной записи и параметров CI, поэтому его сначала находят в конфигурации задания или выводе сборки.

Перед очисткой нужно проверить:

  • нет ли параллельного задания с тем же каталогом;
  • относится ли каталог к остановленному проекту;
  • когда он изменялся;
  • есть ли сохранённый коммит и параметры, позволяющие повторить сборку;
  • не используется ли этот путь несколькими этапами конвейера.

Удаление должно быть адресным. Пример с заполнителем показывает принцип, но не является универсальным путём:

du -sh "<DERIVED_DATA>"
find "<DERIVED_DATA>" -maxdepth 1 -type d -print

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

rm -rf "<DERIVED_DATA>/<PROJECT_HASH>"

Перед выполнением следует ещё раз проверить PID процессов и владельца файлов. Если rm запрещён из-за прав или каталог принадлежит другой учётной записи, это сигнал передать задачу администратору узла, а не обходить ограничение сменой владельца.

Swift Package, Homebrew и другие кэши рассматриваются отдельно. Их очистка может привести к повторному разрешению зависимостей, скачиванию пакетов и полной перекомпиляции. Поэтому после освобождения пространства нужны две проверки: чистая сборка тем же коммитом и последующая сборка с повторным использованием кэша. Успешный возврат одной команды ещё не доказывает, что конвейер восстановлен.

Документация Apple о Command-line tools помогает сверить установленный набор инструментов, но не заменяет проверку фактических путей в конкретном Runner.

Объект Риск удаления Условие очистки Проверка после очистки
DerivedData проекта Повторная индексация и компиляция Нет активных потребителей, результат воспроизводим Чистая сборка тем же коммитом
Кэш зависимостей Повторное разрешение и загрузка Зафиксирован источник зависимостей и доступ к нему Разрешение зависимостей и сборка
Кэш инструмента Повторная подготовка окружения Кэш принадлежит завершённым задачам Полный запуск задания
Рабочий каталог Потеря исходных или диагностических данных Объект признан временным владельцем проекта Клонирование или сборка из сохранённого коммита
05

iOS Simulator и компоненты платформы

Ответственный за тесты должен разделить два разных типа данных: установленные Simulator runtime и экземпляры виртуальных устройств с их содержимым. Удаление устройства не равно удалению runtime, а удаление runtime может вывести из строя всю матрицу тестов.

Сначала зафиксируйте состояние:

xcrun simctl list devices
xcrun simctl list runtimes
xcrun simctl list devicetypes

Команды и доступные параметры следует сверить с локальной справкой. Документация Apple по запуску приложений на симуляторах описывает работу с назначениями и устройствами, а материалы по Device Hub — управление зарегистрированными устройствами и компонентами.

Безопасный порядок выглядит так:

  • сопоставить runtime с тестовой матрицей;
  • определить устройства, которые не используются текущими заданиями;
  • проверить, не выполняется ли тест и не идёт ли запись диагностических данных;
  • удалить только утверждённые экземпляры через штатный интерфейс или команду;
  • не менять защищённые системные каталоги вручную;
  • проверить запуск нужного runtime;
  • выполнить тестовый сценарий и проверить поведение после разрыва соединения.

Устройство, которое выглядит старым, может быть частью ночного задания или воспроизводить редкий сбой. Поэтому возраст файла не является достаточным условием удаления. Если неизвестно, какая версия runtime нужна проекту, сначала запросите матрицу у владельца тестов.

Опыт эксплуатации. Список установленного runtime показывает наличие компонента, но не доказывает, что он не нужен. Решение принимается по фактическим назначениям заданий, а не по размеру каталога или дате последнего изменения.

06

Архивы, подпись и материалы поставки

После сбоя архивации приоритет меняется: ответственному за релиз запрещено воспринимать xcarchive как обычный кэш. Архив может быть частью доказательства поставки, источником символов для диагностики или единственным результатом успешной сборки до переполнения диска.

Перед очисткой составьте реестр:

  • путь к архиву;
  • проект, схему и коммит;
  • статус экспорта;
  • наличие символов;
  • состояние загрузки;
  • место хранения резервной копии;
  • срок хранения по правилам команды.

Официальное описание архивации и распространения приложений следует использовать для проверки последовательности Archive, Export и передачи результата. Отдельно учитывайте рекомендации Apple по отладочной информации и архивам, поскольку символы могут понадобиться уже после завершения сборки.

Нельзя освобождать место за счёт связки ключей, сертификатов, профилей и описаний подписи. Их удаление не решает проблему ёмкости безопасным способом и может сделать повторный экспорт невозможным. Если секреты хранятся в каталоге пользователя, его нельзя включать в общий скрипт очистки.

После перемещения или удаления разрешённой копии проведите полный контрольный цикл:

xcodebuild \
  -workspace "<WORKSPACE>.xcworkspace" \
  -scheme "<SCHEME>" \
  -archivePath "<ARCHIVE_PATH>" \
  archive

Затем проверьте существование архива, экспорт, подпись и доступность результата следующему этапу. Если архив создаётся, но экспорт или загрузка всё ещё падают, проблема уже не сводится к свободному месту.

07

Перечень безопасного восстановления

Этот список предназначен для дежурной смены и должен заполняться по факту, а не отмечаться заранее.

  • [ ] Остановлена очередь новых заданий и повторные попытки.
  • [ ] Сохранён первый лог с No space left on device.
  • [ ] Зафиксированы коммит, схема, назначение и учётная запись.
  • [ ] Проверены свободное место и файловые записи нужного тома.
  • [ ] Определены процессы, которые ещё пишут на диск.
  • [ ] Разделены исходные данные, воспроизводимые результаты и артефакты поставки.
  • [ ] Проверен владелец рабочего каталога и каждого кэша.
  • [ ] Исключены активные потребители DerivedData и Simulator.
  • [ ] Runtime, нужные тестовой матрице, помечены как сохраняемые.
  • [ ] Архивы, символы и материалы подписи вынесены из общей политики очистки.
  • [ ] Удалены только подтверждённые воспроизводимые данные.
  • [ ] Выполнена чистая сборка тем же коммитом.
  • [ ] Выполнена повторная сборка с предусмотренным использованием кэша.
  • [ ] Запущен нужный Simulator runtime и пройден тестовый сценарий.
  • [ ] Выполнены Archive и Export, если сбой затронул релиз.
  • [ ] Результаты и снимок диска переданы платформенному владельцу.
  • [ ] Повторный рост занятого места связан с конкретным проектом или типом задания.

Если любой пункт, связанный с активным процессом, владельцем или архивом, остаётся неизвестным, очистку следует остановить и передать узел платформенной команде.

08

Политика хранения общего Runner

Платформенный инженер должен превратить разовую аварию в наблюдаемое правило. Для каждого класса данных назначается владелец, допустимый срок хранения и проверка завершения. Политика должна отдельно описывать окончание задания, завершение релиза и перезапуск узла.

Минимальная схема управления включает:

  • отчёт по росту рабочей области каждого проекта;
  • учёт DerivedData и зависимостей по учётной записи;
  • перечень Simulator runtime и назначений, которые их используют;
  • реестр архивов и символов с ответственным за хранение;
  • проверку свободного места до постановки задания;
  • остановку задания при достижении внутреннего порога, а не после сбоя записи;
  • контроль восстановления после очистки и перезапуска;
  • журнал всех удалений с причиной и владельцем.

Для shared Mac Runner особенно опасны разные политики для разных проектов: одна команда сохраняет архивы, другая повторно клонирует рабочие каталоги, третья оставляет тестовые устройства. Поэтому итоговый лимит должен рассчитываться по нормальной совокупной нагрузке, а не по самому маленькому проекту.

Если обязательные рабочие данные, поддерживаемая тестовая матрица и архивы уже занимают больше доступного пространства, у команды есть несколько честных вариантов:

  • разделить сборку, тестирование и публикацию между узлами;
  • сократить срок хранения только тех результатов, которые действительно можно восстановить;
  • выделить отдельный узел для долгоживущих архивов;
  • выбрать конфигурацию удалённого Mac с большей ёмкостью;
  • временно сократить параллельность, пока не изменена инфраструктура.

В руководстве NodeMini по удалённому Mac перед выбором узла следует сопоставить не только доступ к macOS, но и фактический профиль проекта: размер рабочей области, Simulator, архивы и срок удержания результатов. Для процедур передачи ответственности пригодится справочный центр NodeMini.

09

Когда очистка уже не является решением

После безопасной очистки необходимо сравнить состояние до и после, а не ограничиваться сообщением «команда завершилась успешно». Если тот же проект, тот же набор тестов и тот же релизный процесс снова исчерпывают место при сохранении обязательных артефактов, причина находится в несоответствии политики хранения и ёмкости узла.

В такой ситуации повторное удаление всего DerivedData ухудшает время следующей сборки, удаление runtime ломает тестовую матрицу, а удаление архивов уничтожает путь к восстановлению поставки. Пересоздание узла без анализа роста также лишь переносит проблему на следующий рабочий цикл.

Локальный Mac удобнее там, где нужны физические устройства, локальные интерфейсы и постоянная работа одного инженера; Linux-узел не заменяет macOS-инструменты для Xcode; виртуальная среда добавляет отдельные ограничения совместимости и хранения. Но и удалённая машина не является автоматическим решением: при долгом хранении архивов, тяжёлых Simulator-данных и параллельных задачах её нужно принимать по реальному проекту, а не по формальному доступу к macOS.

Если после проверки и очистки требуется временный CI-узел, тестовая среда для релизной ветки или отдельная машина для сравнения профиля хранения, аренда Mac через NodeMini позволяет провести такую приёмку без немедленной покупки оборудования. Перед продлением следует повторить сборку, Simulator-тест, Archive, Export и восстановление после перезапуска; если нормальная нагрузка всё равно не помещается, нужно выбрать другой объём или разделить роли узлов, а не возвращаться к ручному удалению всего диска.