Контроль и безопасная очистка места Xcode на облачном Mac

DevOps и CI/CD ·~5 мин чтения

Контроль и безопасная очистка места Xcode на облачном Mac

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

Сначала определите базовый уровень использования диска

Сначала зафиксируйте доступное системе пространство, а затем проверьте каталоги разработки. Команда df показывает, сколько данных ещё можно записать в файловую систему, а du помогает найти основные источники расхода места. Эти команды решают разные задачи и не заменяют друг друга.

df -Pk /

for path in \
  "$HOME/Library/Developer/Xcode/DerivedData" \
  "$HOME/Library/Developer/Xcode/Archives" \
  "$HOME/Library/Developer/CoreSimulator" \
  "$HOME/Library/Developer/Xcode/iOS DeviceSupport"
do
  if [ -e "$path" ]; then
    du -sk "$path"
  fi
done

Рекомендуется выполнять замеры перед чистой сборкой, после завершения архивирования и после окончания тестов. Эти три значения показывают, насколько увеличивается объём данных за одно задание, и помогают не принять нормальный пик использования за постоянную утечку места. Чтобы найти самые крупные каталоги внутри DerivedData, выполните:

du -sk "$HOME/Library/Developer/Xcode/DerivedData"/* 2>/dev/null \
  | sort -nr \
  | head -20

Доступное пространство APFS может зависеть от объёма очищаемых данных. Проверка перед сборкой должна учитывать доступные блоки из df; не следует считать, что задача гарантированно завершится, ориентируясь только на номинальный размер каталогов.

Установите чёткий порог доступного места перед сборкой

Порог следует определять по фактическому пиковому потреблению, а не задавать на основании общих предположений. Начните с 30GB и зафиксируйте минимальный остаток места во время полного архивирования. После нескольких стабильных запусков установите порог на уровне 1,5-кратного пикового прироста и добавьте запас для экспортируемых артефактов.

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

#!/bin/zsh
set -euo pipefail

minimum_kb=$((30 * 1024 * 1024))
available_kb=$(df -Pk / | awk 'NR == 2 {print $4}')

if (( available_kb < minimum_kb )); then
  printf 'Insufficient disk capacity: %s KB available
' "$available_kb"
  exit 75
fi

printf 'Disk capacity check passed: %s KB available
' "$available_kb"

Храните порог отдельно для каждого узла. Разные версии Xcode, наборы симуляторов и масштабы проектов дают разные пиковые значения, поэтому результаты небольшого проекта не подтверждают достаточность ресурсов для крупного рабочего пространства.

Размещайте каждую сборку в отдельном каталоге

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

job_root="$HOME/build-jobs/$BUILD_ID"
derived_data="$job_root/DerivedData"
archive_path="$job_root/artifacts/App.xcarchive"

mkdir -p "$job_root/artifacts"

xcodebuild \
  -workspace App.xcworkspace \
  -scheme App \
  -configuration Release \
  -derivedDataPath "$derived_data" \
  -archivePath "$archive_path" \
  archive

Значение BUILD_ID должно предоставляться системой заданий и содержать только буквы, цифры, точки, символы подчёркивания или дефисы. Перед очисткой также необходимо убедиться, что целевой путь находится внутри build-jobs, чтобы пустая переменная не расширила область удаления до домашнего каталога.

Выполняйте очистку по уровням с учётом восстанавливаемости данных

Начинайте с данных, которые можно создать заново, а архивы, требующие ручной проверки, обрабатывайте в последнюю очередь.

Уровень Данные Рекомендуемое действие Основное ограничение
1 DerivedData завершённых заданий Удалять по каталогам заданий Убедиться, что данные не используются процессом сборки
2 Записи недоступных симуляторов Очищать с помощью simctl Не удалять каталог Devices напрямую
3 Старые файлы поддержки устройств Сверять с версиями, реально используемыми для тестирования Сохранять версии ОС, которые ещё нужны для отладки
4 Файлы xcarchive и dSYM Переносить после ручной проверки Должна сохраняться прослеживаемость выпущенных версий

Для удаления недоступных симуляторов используйте системную утилиту:

xcrun simctl delete unavailable

Не очищайте CoreSimulator/Devices напрямую. Если содержимое каталога не соответствует состоянию службы симуляторов, последующие проблемы с созданием и запуском устройств будет значительно сложнее диагностировать. Не следует удалять архивы и только потому, что они «старше определённого количества дней»: внутри xcarchive может храниться dSYM выпущенной версии. Сначала зарегистрируйте версию, номер сборки и место переноса, а затем удаляйте локальную копию.

Избегайте трёх ошибок при автоматической очистке

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

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

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

Проверьте результат с помощью воспроизводимой сборки

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

Итоговый список проверок может быть кратким: предварительная проверка места пройдена; задание использует отдельный DerivedData; после завершения не осталось процессов компиляции; архив и dSYM зарегистрированы; в simctl list нет устройств с ошибочным состоянием; остаток места на диске превышает порог следующего задания. Очистку можно считать завершённой только при одновременном выполнении всех этих условий.

Часто задаваемые вопросы

Сколько свободного места нужно оставлять для сборки Xcode?

Единого значения нет. Начните с порога 30GB перед сборкой, измерьте пиковый расход полного архива и для крупного многомодульного проекта оставляйте не менее полутора таких пиков.

Можно ли удалить весь каталог DerivedData?

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

Какие данные Xcode нельзя очищать автоматически?

Исключите незавершённые архивы, xcarchive без резервной копии, dSYM опубликованных версий и устройства симулятора, которые ещё входят в действующую тестовую матрицу.

Физический узел с выделенными ресурсами

Сохраняйте воспроизводимую среду на одном облачном Mac

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

Арендовать облачный Mac