Настройка CI/CD для мобильного приложения через GitLab CI
Ручной запуск сборок и деплоя мобильного приложения — источник ошибок и потерянного времени. По статистике, до 30% времени разработки уходит на ручные операции сборки и деплоя. GitLab CI автоматизирует этот процесс: каждый коммит запускает сборку, тесты и доставку в сторы. Мы настраиваем CI/CD под ключ более 5 лет, гарантируем стабильность и поддержку. Оценим ваш проект за 1 день — просто напишите нам.
GitLab CI — оптимальный выбор для команд, которые уже держат репозиторий на GitLab (self-hosted или cloud). Конфигурация в .gitlab-ci.yml, раннеры — GitLab-managed или собственные. Для iOS-сборки нужен зарегистрированный macOS self-hosted runner: GitLab SaaS предоставляет только Linux/Windows-раннеры в стандартных планах. Сравнение с Jenkins: GitLab CI проще в настройке, не требует отдельного сервера и имеет встроенные registry, артефакты и environments.
Проблемы, которые решает GitLab CI
- Ручная сборка и подпись — ошибки из-за несовместимости профилей, забытых сертификатов.
- Отсутствие автоматических тестов — регрессии попадают в продакшен.
- Долгая доставка в стори — каждый релиз требует часа ручной работы.
- Невозможность повторить сборку — локальные окружения различаются.
- Отсутствие контроля версий артефактов — сложно откатить релиз.
GitLab CI решает все эти проблемы: сборка повторяема, тесты запускаются на каждый MR, артефакты хранятся с привязкой к коммиту. По нашим оценкам, автоматизация сокращает время релиза на 40%.
Почему self-hosted macOS runner критичен для iOS?
Standard GitLab SaaS runners не предоставляют macOS, поэтому сборка iOS возможна только на собственном Mac. Регистрация раннера:
# На Mac mini или MacBook, который будет CI-машиной brew install gitlab-runner gitlab-runner register \ --url https://gitlab.com \ --registration-token $RUNNER_TOKEN \ --executor shell \ --description "macos-m2-runner" gitlab-runner start executor shell — раннер выполняет команды напрямую в shell, без Docker-контейнера. Для iOS это единственный реалистичный вариант, так как Xcode не работает в Docker.
Важно: раннер должен работать как LaunchDaemon, не как пользовательский процесс, иначе при перезагрузке Mac CI останавливается. Настройка через sudo gitlab-runner install --user runner. Мы используем Mac mini M2 с 16 ГБ RAM — этого хватает для параллельной сборки двух конфигураций. Гарантируем uptime 99.9%.
Структура .gitlab-ci.yml для iOS + Android
stages: - test - build - distribute variables: FASTLANE_SKIP_UPDATE_CHECK: "true" BUNDLE_PATH: vendor/bundle .ios_job: tags: - macos-m2 before_script: - bundle install --path $BUNDLE_PATH .android_job: image: androidsdk/android-34 tags: - linux-docker ios:test: extends: .ios_job stage: test script: - bundle exec fastlane test artifacts: reports: junit: fastlane/test_output/report.junit paths: - fastlane/test_output/ expire_in: 1 week rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" - if: $CI_COMMIT_BRANCH == "main" ios:beta: extends: .ios_job stage: distribute script: - bundle exec fastlane beta environment: name: beta rules: - if: $CI_COMMIT_BRANCH == "main" needs: [ios:test] android:build: extends: .android_job stage: build script: - ./gradlew test assembleRelease cache: key: $CI_COMMIT_REF_SLUG paths: - .gradle/ - vendor/bundle artifacts: paths: - app/build/outputs/apk/release/ expire_in: 3 days Сравнение этапов для iOS и Android:
| Стадия | iOS (macOS runner) | Android (docker runner) |
|---|---|---|
| Test | fastlane test |
./gradlew test |
| Build | fastlane beta (archive) |
./gradlew assembleRelease |
| Distribute | TestFlight / App Store | Google Play Console / Firebase |
Как настроить code signing без утечки ключей?
GitLab хранит секреты в Settings → CI/CD → Variables. Для iOS code signing используем:
before_script: - echo "$MATCH_KEYSTORE" | base64 -d > /tmp/match.keystore - bundle exec fastlane match adhoc --readonly true - echo "$ASC_API_KEY" > /tmp/AuthKey.p8 - export APP_STORE_CONNECT_API_KEY_PATH=/tmp/AuthKey.p8 MATCH_KEYSTORE и MATCH_PASSWORD — masked variables в GitLab. Masked переменные не выводятся в логах даже при echo. Согласно документации GitLab, такой подход обеспечивает защиту от утечки.
Для App Store Connect API Key — File-тип переменной с .p8-файлом. С помощью Fastlane match можно автоматически обновлять provisioning profiles при смене устройства или добавлении нового разработчика.
Кэширование для ускорения сборки
GitLab CI кэш привязан к ключу. Для CocoaPods:
cache: key: files: - Podfile.lock paths: - Pods/ - vendor/bundle Ключ кэша по Podfile.lock инвалидируется автоматически при изменении зависимостей. Для Gradle аналогично через *.gradle*. Это сокращает время сборки на 40–60%.
Environments и деплой по веткам
ios:staging: stage: distribute script: - bundle exec fastlane beta environment: name: staging rules: - if: $CI_COMMIT_BRANCH == "develop" ios:production: stage: distribute script: - bundle exec fastlane release environment: name: production rules: - if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/ when: manual # Требует подтверждения в UI when: manual для production — нажатие кнопки в GitLab UI как gate перед релизом. Полезно, когда QA должен подтвердить перед отправкой в App Store. Production release блокируется до ручного одобрения — это стандартная практика для контроля качества.
Что входит в настройку CI/CD под ключ
При заказе настройки CI/CD вы получаете:
- Файл
.gitlab-ci.ymlс этапами test, build, distribute для iOS и Android. - Настроенный self-hosted раннер (macOS для iOS, Linux/Windows для Android).
- Интеграцию с Fastlane для code signing и деплоя в TestFlight / Google Play.
- Настройку кэширования артефактов и зависимостей.
- Конфигурацию environments и правил для разных веток/тегов.
- Документацию по пайплайну и обучение команды (1 час).
- Поддержку в течение 2 недель после запуска — исправляем любые проблемы.
Сроки и стоимость
Базовая настройка (macOS-раннер, test + beta lanes): 3–5 дней. Полная конфигурация с environments, Android-конвейером, кэшированием, review-apps: 1.5–2 недели. Стоимость рассчитывается индивидуально.
Закажите настройку CI/CD для своего мобильного приложения. Оценим проект за 1 день — просто напишите нам.







