2026-04-20 Детерминированный CI Ruby Bundler и CocoaPods на арендованном облачном Mac Apple Silicon
Команды, которые арендуют 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 в пределах каталога задачи.
~/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