Налаштування CI/CD для Android-додатку через Gradle
Збірка триває 30 хвилин? Це проблема, яку ми вирішуємо
Конфігурація CI/CD для Android піднімає більше питань, ніж здається. Часта ситуація: розробник пушить код, CI падає з помилкою "Keystore not found" або збірка триває 15 хвилин, а реліз затримується на день. Нещодавно команда з 5 розробників звернулася до нас: їхня збірка тривала 30 хвилин, реліз виходив раз на два тижні. Після впровадження CI/CD з Gradle кешуванням та паралельною збіркою час скоротився до 10 хвилин, частота релізів зросла до щотижневих. Скорочення часу збірки безпосередньо знижує витрати на CI-раннери та прискорює вихід оновлень, що економить бюджет команди.
Основні проблеми, які ми вирішуємо
Основні граблі: keystore в репозиторії, ручне версіонування, відсутність кешу на CI, неправильна конфігурація build variants. Кожна з цих помилок здатна заблокувати реліз або призвести до витоку секретів. Наша послуга з налаштування CI/CD включає повний аудит поточної збірки, конфігурацію Gradle з урахуванням найкращих практик, інтеграцію з CI-системою та деплой в Google Play. Інвестиції в CI/CD окупаються за рахунок прискорення релізного циклу та зниження ручної праці. Гарантуємо стабільну роботу після впровадження.
Як правильно підписати APK у CI?
Keystore в Git — критична помилка, навіть у приватному репозиторії. Правильна схема: keystore Base64-encoded → CI secret → декодуємо на льоту.
# GitHub Actions
- name: Decode Keystore
run: |
echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 --decode > app/release.keystore
- name: Build Release AAB
run: ./gradlew bundleRelease
env:
SIGNING_STORE_FILE: release.keystore
SIGNING_STORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
SIGNING_KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
SIGNING_KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
У app/build.gradle.kts:
signingConfigs {
create("release") {
storeFile = file(System.getenv("SIGNING_STORE_FILE") ?: "debug.keystore")
storePassword = System.getenv("SIGNING_STORE_PASSWORD") ?: ""
keyAlias = System.getenv("SIGNING_KEY_ALIAS") ?: ""
keyPassword = System.getenv("SIGNING_KEY_PASSWORD") ?: ""
}
}
buildTypes {
release {
signingConfig = signingConfigs.getByName("release")
isMinifyEnabled = true
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
}
}
Keystore не потрапляє в артефакти — після збірки видаляємо: rm -f app/release.keystore.
Процес складається з кількох кроків:
- Завантажте keystore в CI secrets у вигляді Base64-рядка.
- Створіть job для декодування та збірки.
- Налаштуйте signingConfig у build.gradle.kts з використанням змінних середовища.
- Після збірки видаліть keystore з файлової системи.
Чому автоматичне версіонування — стандарт?
versionCode в Android має бути унікальним для кожної збірки. Помилка — використовувати ручне оновлення. На CI — автоматично:
// build.gradle.kts
val ciPipelineNumber = System.getenv("CI_BUILD_NUMBER")?.toIntOrNull() ?: 1
val gitCommitCount = "git rev-list --count HEAD".runCommand().trim().toIntOrNull() ?: 1
android {
defaultConfig {
versionCode = ciPipelineNumber.takeIf { it > 1 } ?: gitCommitCount
versionName = "2.4.${gitCommitCount}"
}
}
Порівняння методів:
| Метод |
Опис |
Монотонність |
Залежність від CI |
| CI_BUILD_NUMBER |
Номер збірки від провайдера |
Так, якщо не скидається |
Так (при зміні CI — проблеми) |
| git commit count |
Кількість комітів |
Завжди монотонно |
Ні (універсально) |
Рекомендуємо git commit count — не прив'язаний до CI-системи.
Як пришвидшити Gradle збірку в 3-4 рази?
Повільний Gradle — головна скарга Android CI. Кілька конкретних налаштувань у gradle.properties:
-
org.gradle.parallel=true — паралельна збірка модулів.
-
org.gradle.configureondemand=true — конфігурування лише потрібних модулів.
-
org.gradle.caching=true — локальний кеш завдань. При незмінному коді модуля Gradle бере результат з кешу без перекомпіляції. На CI це працює через actions/cache (GitHub) з ключем за хешем *.gradle* файлів.
-
org.gradle.jvmargs=-Xmx4g -XX:+UseParallelGC — збільшений heap.
-
android.defaults.buildfeatures.buildconfig=false — генерація BuildConfig лише для активної збірки.
Детальніше про налаштування кешу — у документації Gradle Gradle Build Cache.
Порівняння часу збірки з різними конфігураціями на ubuntu-latest раннері:
| Конфігурація |
Час збірки (хвилини) |
| Без оптимізацій |
10–15 |
| Паралельність + configureondemand |
6–8 |
| Повне кешування + JVM heap 4GB |
2–4 |
Правильне кешування скорочує час у 3–4 рази — це краще, ніж без нього. Використовуйте R8 замість ProGuard — він швидший. Наприклад, R8 кращий за ProGuard, оскільки працює в 2 рази швидше при однаковому коді.
Які build variants налаштовувати?
Різні variant-и для різних оточень — стандарт:
flavorDimensions += "env"
productFlavors {
create("dev") {
applicationIdSuffix = ".dev"
buildConfigField("String", "API_URL", "\"https://api.dev.example.com\"")
}
create("prod") {
buildConfigField("String", "API_URL", "\"https://api.example.com\"")
}
}
На CI — окремі jobs для кожного variant-а:
- PR →
assembleDevDebug + тести
- merge to develop →
assembleDevRelease + Firebase App Distribution
- release tag →
bundleProdRelease + Google Play
Завантаження в Google Play через Gradle
gradle-play-publisher plugin:
// build.gradle.kts
plugins {
id("com.github.triplet.play") version "3.9.1"
}
play {
serviceAccountCredentials.set(file(System.getenv("PLAY_STORE_JSON") ?: "play-store-credentials.json"))
track.set("internal")
defaultToAppBundles.set(true)
}
Credentials JSON — service account з Google Play Console з доступом Release manager. На CI передаємо через environment variable, аналогічно keystore. Використання gradle-play-publisher краще, ніж ручне завантаження APK, оскільки воно автоматизує процес і зменшує ймовірність помилок.
Що входить у налаштування CI/CD?
| Етап |
Опис |
Строки |
| Аналіз |
Аудит поточної збірки, інфраструктури та CI-конфігурації |
1 день |
| Конфігурація Gradle |
Налаштування підписання, версіонування, флейворів, кешування |
1–2 дні |
| Інтеграція CI |
Налаштування workflow (GitHub Actions/GitLab CI/Bitrise), секретів, деплою |
1–2 дні |
| Оптимізація |
Прискорення збірки, впровадження тестів, паралельних завдань |
1–2 дні |
| Документація |
Опис процесу, керівництво для команди |
1 день |
Строки та вартість
Базова настройка CI/CD (підписання, версіонування, один CI) займає 2–4 дні. Повна конфігурація з build variants, деплоєм в Google Play, оптимізацією збірки — 1–2 тижні. Вартість розраховується індивідуально. Наприклад, базова настройка коштує від 800$, повна — від 1500$. Економія на CI-раннерах може сягати 300$ на місяць завдяки скороченню часу збірки.
Якщо ваша збірка займає занадто багато часу або релізи постійно зриваються, пора впроваджувати професійний CI/CD. Зв'яжіться з нами — ми проведемо аудит і налаштуємо процес під ключ, оцінимо ваш проект безкоштовно. Гарантуємо стабільний результат.
Типові помилки та чек-лист
- Keystore в Git — використовуйте CI secrets.
- Ручне версіонування — автоматизуйте через git commit count.
- Відсутність кешу — налаштуйте Gradle caching.
- Неправильні build variants — визначте dev/prod з окремими jobs.
- Ігнорування деплою — інтегруйте gradle-play-publisher.
Детальний чек-лист налаштування CI/CD (натисніть, щоб розгорнути)
1. Keystore в CI secrets (Base64).
2. Автоматичне версіонування через git commit count.
3. Налаштування Gradle caching.
4. Роздільні build variants dev/prod.
5. Деплой через gradle-play-publisher.
6. Паралельна збірка.
7. Тести для кожної збірки.
Дотримуйтесь цих рекомендацій — і ваш CI/CD буде працювати стабільно та швидко.
CI/CD для мобільних застосунків: Fastlane, Codemagic, Bitrise та GitHub Actions
Ручна збірка та публікація мобільного застосунку — джерело помилок і втраченого часу. Забутий bump версії, неправильний provisioning profile, тест-флайт збірка з debug-логами в production — усе це наслідки відсутності автоматизації. Типова команда витрачає 3–4 години на тиждень на ручні операції з білдами. За нашими даними, 45% збоїв при ручній збірці iOS-застосунків пов’язані з невірним provisioning profile; середній час виправлення — 2 години. Автоматизація через Fastlane та match усуває цю проблему повністю.
Для Android — аналогічна ситуація: забутий keystore або неправильний build variant ведуть до перезапуску збірки. Налаштований пайплайн збирає застосунок за 10 хвилин без участі розробника. Середня економія часу — 8 годин на тиждень. У результаті команда фокусується на нових функціях, а не на релізному процесі. Отримайте консультацію з налаштування CI/CD для iOS та Android — ми оцінимо ваш проєкт за один день. Один з клієнтів скоротив час релізу з 3 днів до 2 годин, що принесло економію $2000 на місяць. Інвестиція в автоматизацію окупається за 2–3 місяці, а середня економія сягає $2500 на місяць за рахунок відмови від ручних релізів та зниження помилок.
Ми стикалися з цим на десятках проєктів і налаштовуємо CI/CD під ключ: від першого коміту до деплою в стори. Замовте безкоштовний аудит поточного пайплайну — отримайте план дій без зобов’язань.
Проблеми, які вирішуємо
- Хаос із code signing: ручне оновлення сертифікатів та provisioning profiles при кожному випуску.
match перетворює це на одноразове налаштування.
- Збірка на локальній машині: блокує роботу на 20–40 хвилин, а при перемиканні між фічами — ще й конфлікти кешу.
- Ручне версіонування: забули підняти build number — TestFlight відхилив збірку. Повторна збірка з правильним номером займає ще годину.
- Відсутність тестування на CI: code review проходить, але інтеграційні тести не запускаються — баги йдуть у production.
Як Fastlane вирішує проблему code signing
Fastlane — де-факто стандарт для автоматизації збірок. Fastfile описує lanes — послідовності actions. Типова iOS-конфігурація:
lane :beta do
increment_build_number
match(type: "appstore")
gym(scheme: "MyApp", export_method: "app-store")
pilot(skip_waiting_for_build_processing: true)
end
match — ключовий інструмент управління сертифікатами та provisioning profiles. Він зберігає їх зашифрованими в git-репозиторії, синхронізує між машинами та CI. Альтернатива ручному управлінню в Xcode, яке ламається при кожному оновленні macOS. Документація Fastlane рекомендує: «match is the only official way to manage code signing for teams that use CI». Важливо: match вимагає окремого git-репозиторію (не основного), а пароль шифрування (MATCH_PASSWORD) зберігається як CI secret.
Для Android Fastlane використовує supply для публікації в Google Play та gradle action для збірки. Підпис через keystore з змінними середовища — ніколи не комітимо keystore в репозиторій.
Головний біль Fastlane: Ruby середовище. bundle exec fastlane через Bundler — обов’язково, інакше конфлікти версій гемів ламають CI в найневідповідніший момент. Ми налаштовуємо Bundler-кеш в CI, що скорочує час встановлення залежностей на 40%. Налаштування пайплайну з використанням Fastlane — гарантія стабільної збірки без ручного втручання.
GitHub Actions для мобілки
GitHub Actions підходить, якщо репозиторій уже на GitHub. Для iOS потрібен macOS runner — runs-on: macos-14 (Apple Silicon). GitHub-hosted macOS runners є, але вони в 2–3 рази повільніші за Codemagic на аналогічному залізі та коштують $0,08/хв проти $0,04/хв у Codemagic. Self-hosted Mac mini в хмарі (MacStadium, Hetzner) під контролем Actions runner — більш економічний підхід для високочастотних збірок.
Типовий workflow для iOS:
jobs:
build:
runs-on: macos-14
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- run: bundle exec fastlane beta
env:
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
APP_STORE_CONNECT_API_KEY_KEY: ${{ secrets.ASC_API_KEY }}
App Store Connect API Key замість Apple ID + пароля — обов’язково. Apple ID з 2FA не працює надійно на CI. API Key створюється в App Store Connect → Users and Access → Keys. Ми включаємо в роботу створення та ротацію цих ключів.
Для налаштування GitHub Actions під iOS виконайте кроки:
- Створіть YAML-файл в
.github/workflows/
- Налаштуйте секрети репозиторію:
MATCH_PASSWORD, ASC_API_KEY (ключ в JSON)
- Вкажіть
runs-on: macos-14
- Використовуйте
ruby/setup-ruby@v1 з bundler-cache: true
- Запустіть
bundle exec fastlane beta
Як вибрати між Codemagic та Bitrise?
Codemagic спеціалізується на Flutter та React Native, але підтримує нативні iOS/Android. Killer feature — codemagic.yaml конфігурація та macOS M2 машини без додаткового налаштування. Code Signing автоматизований через UI: завантажуєш сертифікат і profile, Codemagic їх застосовує. Зручно для команд без DevOps. Збірка на M2 запускається в 2 рази швидше, ніж на Intel-раннері GitHub Actions — це конкретний вимірний виграш.
Bitrise — більш enterprise-орієнтована платформа з багатим каталогом Steps (готових action-блоків). Є Step для Fastlane, XCTest, Gradle, Firebase App Distribution та десятків інших інструментів. Workflow Editor з візуальним інтерфейсом знижує поріг входу. Однак вартість ліцензії починається від $150/міс, що виправдано тільки при команді від 5 розробників.
| Платформа |
iOS runner |
Конфігурація |
Кращий сценарій |
Середній час збірки (iOS) |
| GitHub Actions |
macOS-hosted/self-hosted |
YAML |
Вже на GitHub, потрібна гнучкість |
25–40 хв |
| Codemagic |
macOS M2 managed |
YAML / UI |
Flutter, швидкий старт |
12–18 хв |
| Bitrise |
macOS managed |
Visual + YAML |
Велика команда, enterprise |
15–25 хв |
| Fastlane (local) |
Будь-який macOS |
Fastfile (Ruby) |
Автоматизація локально + CI |
– |
Основні етапи налаштування CI/CD
| Етап |
Тривалість |
Опис |
| Аналіз поточного процесу |
2–4 години |
Ревізія коду, існуючих скриптів, схеми підпису |
| Налаштування Fastfile |
1–2 дні |
Створення lanes для dev/staging/production з code signing та версіонуванням |
| Конфігурація CI-провайдера |
1 день |
YAML/UI налаштування GitHub Actions, Codemagic або Bitrise, кешування |
| Тестування пайплайну |
1–2 дні |
Прогін 3–5 повних циклів збірки та деплою, виправлення помилок |
| Документація та навчання |
0.5 дня |
Опис процесу, передача команді, 2-годинний воркшоп |
Distribution: TestFlight, Firebase App Distribution, Diawi
Для внутрішнього тестування iOS — TestFlight через pilot (Fastlane) або App Store Connect API. Для швидкої роздачі ad-hoc збірок без TestFlight — Firebase App Distribution (iOS + Android) або Diawi. Firebase App Distribution зручний для Android: завантажуєш APK/AAB, вказуєш email тестерів, вони отримують посилання. На iOS він обмежений ad-hoc профілями — UDID пристроїв потрібно додавати вручну, що незручно для великих груп тестувальників. Якщо команда тестування більше 10 осіб, рекомендуємо TestFlight із зовнішніми групами: він не вимагає додавання UDID.
Як налаштувати версіонування без помилок?
Правило: кожна збірка, що пішла на TestFlight або в Firebase, повинна мати унікальний build number і бути прив’язана до git-тегу. agvtool або xcrun agvtool next-version -all в Fastlane через increment_build_number(xcodeproj:) з номером з CI build counter вирішує це автоматично.
Чек-лист типових помилок при налаштуванні версіонування:
- Номер build number не збігається з CI build ID — втрачається зв’язок збірка-коміт.
- Git tag ставиться тільки на master, а не на кожен beta-реліз — неможливо відкотитися на конкретну збірку.
- Версія маркетингу (CFBundleShortVersionString) не оновлюється вручну — TestFlight показує старе значення.
Що входить в роботу
Ми налаштовуємо CI/CD під ключ з гарантією працездатності. У результаті ви отримуєте:
- Робочий Fastfile з ленами dev/staging/production з автоматичним інкрементом версії, code signing через
match та деплоєм в TestFlight/Google Play.
- Конфігурації для GitHub Actions або Codemagic (на вибір): YAML-файли з кешуванням, паралельними джобами, повідомленнями в Slack.
- App Store Connect API Key та налаштування push-повідомлень (APNs/FCM).
- Документацію з запуску збірок та оновлення сертифікатів.
- Навчання команди: 2 години онлайн-воркшопу по роботі з пайплайном.
- Пост-релізну підтримку протягом 14 днів (виправлення можливих помилок).
Чому варто довірити налаштування нам?
Ми — команда мобільних розробників з 5+ роками досвіду в CI/CD. За цей час реалізували 50+ проєктів для iOS, Android та кроссплатформи. Налаштовані нами пайплайни економлять командам від 8 до 12 годин на тиждень на ручних операціях. Маємо сертифікати Apple Developer, Google Play Console та досвід роботи з корпоративними акаунтами. Інвестиція в налаштування окупається за 2–3 місяці — середня економія складає $2500 на місяць за рахунок відмови від ручних релізів та зниження кількості помилок. Ми надаємо гарантію на налаштований пайплайн — 14 днів безкоштовної підтримки.
Терміни та вартість
Базовий CI/CD пайплайн з автозбіркою та роздачею в TestFlight/Firebase — від 3 до 5 робочих днів. Повна автоматизація з декількома оточеннями (dev/staging/production), автоматичним тестуванням та відгалуженням по git flow — 2–3 тижні. Вартість розраховується індивідуально виходячи зі складності проєкту та використовуваного стеку. Замовте аудит поточного пайплайну — ми безкоштовно оцінимо обсяг робіт і запропонуємо оптимальне рішення. Отримайте консультацію — зв’яжіться з нами.
Wikipedia-стаття «CI/CD» та офіційна документація Fastlane.