DevOps / CI·CD 20 апреля 2026

2026-04-20 Детерминированный CI Ruby Bundler и CocoaPods на арендованном облачном Mac Apple Silicon

Инженерная команда MacXCode 20 апреля 2026 ~15 мин чтения

Команды, которые арендуют Mac mini M4 или Mac Studio по SSH для iOS CI, по-прежнему ведут много кодовых баз на CocoaPods. Режим отказа никогда не в том, что «Pods плохие», а в недетерминированных Ruby toolchain: один job вызывает системный pod, другой — обновление Homebrew со вторника, третий — то, что оставил gem install cocoapods в ~/.gem. Этот ранбук от 2026-04-20 стандартизирует CocoaPods под управлением Bundler на арендованных Apple Silicon хостах в HK / JP / KR / SG / US, выравнивает каталоги кэша с рабочими областями задач и делает использование NVMe предсказуемым на мультитенантных машинах. Перекрёстно читайте SwiftPM против CocoaPods, CLT против полного Xcode и параллельные задачи xcodebuild, чтобы разрешение зависимостей и компиляция шли в одной логике.

Почему Bundler всё ещё важен на безголовых билдерах

CocoaPods — это программа на Ruby. Стабильность вызываемого pod определяется набором гемов за ним. Bundler фиксирует этот набор через Gemfile.lock — именно то, что нужно, когда двенадцать продуктовых команд делят один флот облачных Mac. Без Bundler «зелёный на моей ветке» часто означает «кто последний заходил, обновил CocoaPods глобально».

  • Воспроизводимость — один Gemfile.lock → одинаковое поведение резолвера между регионами.
  • Аудит — безопасность может сравнивать версии гемов между релизами.
  • Изоляцияbundle install --path vendor/bundle держит гемы в workspace, а не в общих домашних каталогах.

Матрица Ruby toolchain (3.1 против 3.2 против 3.3)

Образы macOS на Apple Silicon часто содержат свежий системный Ruby; некоторые команды добавляют rbenv или asdf. Выберите одну политику на флот и закодируйте её в инфра-репозитории. Зафиксируйте точный ruby -v рядом с xcodebuild -version в метаданных сборки.

Подход Плюсы Риски
Системный Ruby + Bundler Быстрый bootstrap на новых SSH-хостах Обновления ОС могут поднять Ruby; фиксируйте plist или env CI
rbenv на пользователя Точные patch-уровни Задачи launchd должны явно подключать shims rbenv
asdf с .tool-versions Один файл для Ruby, Node и др. Дольше первый запуск установки

Дисциплина Gemfile и lock-файла

Коммитьте и Gemfile, и Gemfile.lock. Закрепите cocoapods на проверенном minor и явно перечислите плагины (например cocoapods-acknowledgements) — не полагайтесь на «что последний плагин резолвит». Для CI предпочтительно:

bundle config set --local deployment 'true' bundle config set --local path 'vendor/bundle' bundle install --jobs 4 --retry 3

Совет: запускайте bundle check перед pod install, чтобы быстро упасть, если кто-то забыл обновить Gemfile.lock после правки Gemfile.

bundle exec pod install (и когда добавлять --deployment)

Всегда вызывайте bundle exec pod install (или bundle exec pod install --deployment, если Bundler должен строго применять lockfile). Не вызывайте голый pod в продакшен-пайплайнах, если не любите пятничный недетерминизм. Для CI-кэшей передайте детерминированный CP_HOME_DIR или рекомендуемые переменные кэша CocoaPods в пределах каталога задачи.

Предупреждение для общего хоста: если два job пишут в один ~/Library/Caches/CocoaPods без пространств имён, возможны частичные загрузки — изолируйте по $CI_JOB_ID или пути клона репозитория.

Кэши, Pods/ и раскладка workspace

Держите Pods/ и генерацию *.xcworkspace внутри клона репозитория для этой сборки. На эфемерных workspace кэшируйте vendor/bundle и кэш specs CocoaPods между запусками только когда контрольные суммы совпадают с Gemfile.lock + Podfile.lock; иначе агрессивно инвалидируйте — устаревший specs-кэш даёт смутные ошибки резолвера, похожие на сеть.

NVMe и гигиена мультитенанта

Загрузки CocoaPods могут добавлять сотни мегабайт за установку; монорепозитории с несколькими Podfile умножают стоимость. На общих хостах 512 ГБ сочетайте проходы резолвера с дисковыми рекомендациями из очистки симуляторов и архивов. Если во время pod-шагов диск стабильно выше 70 %, разделяйте lane или переходите на узел 1 ТБ / 2 ТБ через страницу тарифов, вместо бесконечной подрезки посреди пайплайна.

Региональные билдеры: CDN и задержка

Доступ к CDN specs из Сингапура или Токио обычно отличный, но корпоративные прокси или TLS-инспекция добавляют повторы. Добавьте флаги повтора для bundle install и при необходимости зеркало или кэширующий прокси — документируйте исключения по регионам, чтобы Гонконг и US East вели себя одинаково.

Если переносите lane на SwiftPM, сравните размеры кэша и семантику блокировок с разрешением и кэшем SwiftPM. После разрешения Pods вернитесь к статьям про подпись — Bundler не заменяет provisioning profiles.

FAQ: Bundler + CocoaPods на облачных Mac

Вопрос Практический ответ
Можно ли CocoaPods из Homebrew? В CI избегайте — предпочитайте гемы через Bundler, чтобы обновления шли через код-ревью, а не случайный bump пакета.
Bundler 2 против 1? Стандартизируйте один major; расхождение между ноутбуками разработчиков и CI — частая причина «локально работает».
Коммитить Pods/ в CI? Политика команды — либо полностью для герметичных сборок, либо генерировать каждый раз; не делайте наполовину.

Итог: относитесь к CocoaPods как к любой другой компиляторной toolchain — фиксируйте версии, ограничивайте кэш и на общих SSH-билдерах всегда идите через bundle exec.

Арендуйте выделенные Apple Silicon CI Mac

SSH в приоритете · HK · JP · KR · SG · US