Долгое время iOS-сборки в GitHub Actions были «черной дырой» бюджета: минута на macOS-раннере съедает 10 минут квоты (или стоит в 10 раз дороже Linux). Старый пайплайн на 90 строк YAML требовал ручного управления 6 секретами, профилями и ключами — хрупко, больно и дорого. 😭
Решение — переезд на Xcode Cloud. И это гейм-чейнджер: 25 часов compute-времени в месяц уже входят в стандартную подписку Apple Developer Program ($99/год). Релиз теперь стоит 0 минут GitHub Actions и всего ~6 минут оплачиваемого времени Apple. 💸
Главные плюсы, за которые стоит сказать «спасибо»:
✅ Managed Signing — Apple сама управляет подписью. Никаких keychain, base64, правок
pbxproj и секретов в репозитории.✅ Доставка в TestFlight настраивается галочкой в UI, без API-ключей.
✅ Кастомизация через три shell-скрипта в папке
ci_scripts (post-clone, pre-xcodebuild, post-xcodebuild): ставим Flutter, проверяем версию в теге vs pubspec.yaml, генерируем Generated.xcconfig, шлём уведомления в Telegram. 🤖Есть и минус: конфигурация уходит из Git в веб-интерфейс App Store Connect (No code-as-config). Лечится обязательным ранбуком (документацией с датой) в репозитории, иначе пайплайн превращается в «фольклор». 📝
Триггеры разделили префиксами тегов:
ios/v* — Xcode Cloud, android/v* — GitHub Actions. Обычный v* ничего не запускает — защита от случайных затрат. 🛡Путь первого успешного билда пролегал через 7 кругов ада за 6 коммитов (ни одна ошибка не была виной дизайна миграции!):
1️⃣ Права доступа к репо — помогло переключение на «New Primary Repository».
2️⃣ Устаревший Flutter тянул старый
intl (на Android замаскировалось).3️⃣ Swift Package Manager требует закоммиченный
Package.resolved — пришлось откатиться на CocoaPods.4️⃣ Ошибка «specs repository is too out-of-date» — ложный след.
5️⃣ Настоящая причина — конфликт Ruby: системный 2.6 не видел
xcodeproj из Homebrew. Лечится gem install --user-install xcodeproj. 💎6️⃣ Двойной
pod install (flutter build --config-only уже делает это сам).7️⃣ Застарелый
Podfile.lock (4 месяца!) — версии нативных SDK расходились с pubspec.lock. Локально тоже было сломано! 🤯💡 Главный урок: CI, который не запускаешь регулярно, не находит ошибки. Ошибка CocoaPods «too out-of-date» почти всегда вводит в заблуждение — смотрите логи выше!
📊 Итоговые замеры:
⏱️ Wall-clock: 10 мин (оценка 15).
⚡️ Compute-time: 6 мин (оценка 15).
📈 Экономия: было ~45 мин GH Actions → стало 0. Запас релизов в месяц вырос с ~100 до ~250. Xcode Cloud тарифицирует CPU-время, а не ожидание сети!
Читать здесь: полная статья на Хабре
FlutterPulse — канал о мире Flutter!
#flutter #dart #flutterpulse #flutterpulsehabr #ci_cd #xcodecloud #iosdev