2026: выделенный удалённый Mac CI — CocoaPods и Swift Package Manager: смешанные зависимости, каталоги кэша, изоляция конкурентности и воспроизводимая по SSH матрица параметров xcodebuild + FAQ
Когда CocoaPods и SPM живут в одном проекте Xcode, боль в CI редко сводится к вопросу «собирается ли?» — куда попадают кэши, не мешают ли параллельные задачи друг другу и как повторить те же флаги xcodebuild по SSH. Здесь — опорные пути, правила изоляции и матрица параметров для выделенного удалённого Mac: можно вставить в runbook.
Почему смесь CocoaPods + SPM всё ещё норма в 2026 году
Многие продакшен-кодовые базы iOS по-прежнему считают CocoaPods источником истины по доставке (Podfile.lock), а SPM используют для своих Swift-пакетов или официальных библиотек. Графы разрешения, раскладка на диске и то, как Xcode их подключает, различаются. На выделенном удалённом Mac CI вы владеете машиной — но всё равно имеете разделение времени между задачами или параллелизм внутри job, которые конкурируют за диск. Сначала зафиксируйте, куда пишет каждый инструмент; затем — конкурентность и флаги.
При выборе «железного» выделенного узла полезно сопоставить ожидания по стабильности с материалом Реальный Mac mini 2026 против виртуального Mac: Производительность и Стабильность, а по пиковым нагрузкам iOS CI — с Решение для пикового сезона iOS CI 2026: Почему аренда Mac — лучший выбор.
Каталоги кэша и источник истины
Пути ниже — типичный домашний каталог пользователя; в CI задайте глобальные кэши и вывод каждой сборки явными переменными окружения, чтобы значения по умолчанию не «плыли» между безлогинными учётными записями.
| Область | Типичное расположение / истина | Рекомендация для CI |
|---|---|---|
| Репозитории и кэш CocoaPods | ~/.cocoapods (репозитории specs, загрузки и т.д.) |
Смонтируйте зеркало только для чтения для ускорения; записываемые job — отдельные поддеревья или разные корни HOME |
| Вывод workspace Pods | В репозитории Pods/, Podfile.lock |
Коммитьте lockfile; выполняйте pod install до тяжёлого xcodebuild, чтобы не ловить гонки блокировок |
| Глобальный кэш SPM | ~/Library/Caches/org.swift.swiftpm (типично) |
В крупных репозиториях сочетайте с -clonedSourcePackagesDirPath, чтобы клоны лежали под контролируемым путём |
| SPM и интеграция с Xcode | SourcePackages в Derived Data, артефакты разрешения |
Изолируйте через -derivedDataPath; упорядочивайте после того, как CocoaPods сгенерировал workspace, если оба трогают проект |
Изоляция конкурентности на «выделенном» хосте
Выделенный не значит однопоточный: на одном удалённом Mac могут работать несколько runner’ов, SSH-сессий или очередь job. Практические правила:
- Derived Data на job: передавайте отдельный
-derivedDataPath(или эквивалент), чтобы артефакты разрешения SPM и индексы модулей не смешивались. - Сериализация тяжёлых шагов разрешения:
pod install, первыйresolvePackageDependenciesи крупные git-clone могут забить IO; разносите их по времени с CPU-тяжёлымxcodebuild archiveили ограничивайте параллелизм. - Границы учётной записи и связки ключей: несколько job под одним пользователем macOS делят подпись и учётные данные SPM; сильнее изоляция — отдельные пользователи или ВМ, выше операционные затраты.
Матрица параметров xcodebuild, воспроизводимая по SSH
Матрица рассчитана на частый сценарий: CocoaPods уже собрал workspace, а пакеты SPM подключены. В каждой SSH-сессии зафиксируйте рабочий каталог и выбор Xcode (xcode-select), затем подберите флаги. Точный набор зависит от версии Xcode — проверяйте через xcodebuild -help.
| Сценарий | Рекомендуемые флаги / окружение | Заметки |
|---|---|---|
| Сборка / тесты только для симулятора | -destination 'platform=iOS Simulator,name=…'; опционально CODE_SIGNING_ALLOWED=NO |
Меньше разброса по подписи; с Pods всегда собирайте *.xcworkspace |
| Заморозить разрешение SPM | -disableAutomaticPackageResolution, -skipPackageUpdates |
После того как зависимости разрешены, воспроизводите сборки без сети на каждом прогоне CI |
| Явный каталог клонов | -clonedSourcePackagesDirPath <path> |
Отвязка от глобального кэша SPM; проще монтировать кэш и чистить |
| Изоляция выходов | -derivedDataPath <path> |
Промежуточные файлы Pods + SPM на job — для параллельных сборок и разборов инцидентов |
| Нужно заново разрешить пакеты | Отдельный шаг xcodebuild -resolvePackageDependencies, затем сборка |
Чище логи, чем смешивать с pod install в одном шумном шаге |
В скриптах дополнительно логируйте xcodebuild -version, swift --version и pod --version, чтобы проще бисектить регрессии вида «код не менялся, сборка другая».
FAQ
Изменились и Pods, и SPM — что запускать первым?
Обычно сначала pod install, чтобы пересобрать проект/workspace Xcode, затем разрешение SPM или сборка. Если оба меняют файлы проекта, ведите Podfile.lock и состояние разрешения пакетов Xcode под единым процессом контроля изменений.
Кэшируем Derived Data — почему SPM всё равно переклонирует?
Каталог клонов может быть вне кэша, либо меняющийся -derivedDataPath заставляет SPM считать окружение новым. Убедитесь, что -clonedSourcePackagesDirPath стабилен и что вы не удаляете его в каждом job по ошибке.
На выделенном Mac закончился диск — что чистить в первую очередь?
Сначала уберите устаревшие per-job Derived Data и деревья клонов SPM; затем при необходимости подрежьте глобальный кэш CocoaPods. Перед удалением убедитесь, что параллельные job не держат эти пути открытыми.
Почему Mac mini успокаивает CI со смешанными зависимостями
Связка CocoaPods и SPM опирается на предсказуемую семантику Unix-файлов и ровную пропускную способность диска. macOS на Apple Silicon даёт стабильный IO и полосу памяти — это снижает шум «локально прошло, в CI флакнуло» из-за среды. Класс аппаратуры Mac mini может простаивать с очень низким энергопотреблением — порядка нескольких ватт — и удобен для круглосуточного выделенного удалённого узла сборки. Gatekeeper, SIP и FileVault сужают поверхность атаки по сравнению с типичной Windows-рабочей станцией в роли фермы.
Если хотите, чтобы схема кэшей и матрица xcodebuild из этой статьи работали на тихом железе, которое можно не выключать сутками, Mac mini M4 — одна из лучших точек входа по соотношению цена/стабильность. Оформите подходящую выделенную машину через SSHMac и сделайте установку зависимостей и конвейеры сборки действительно скучными — в хорошем смысле.