Как устроен процесс деплоя мобильных приложений
Что проверяют
Понимаете ли вы главное отличие мобильного релиза от серверного: выкаченную версию нельзя откатить, она уже стоит у пользователей. Следом спрашивают, как вы снижаете риск: поэтапная раскатка, фича-флаги, принудительное обновление.
Как отвечать
Пройдите путь от сборки до пользователя:
- сборка: CI (GitHub Actions, GitLab CI) запускает
./gradlew bundleReleaseс R8. Для Google Play нужен AAB, APK остаётся для внутренних раздач и альтернативных сторов; - версии:
versionCodeэто целое число, которое обязано расти с каждой загрузкой,versionNameвидит пользователь. Их выставляет CI, а не человек руками; - подпись: Play App Signing. Вы подписываете сборку upload-ключом, а ключ подписи приложения хранит Google. Потерянный upload-ключ сбрасывается через поддержку, а потеря ключа подписи без Play App Signing означала бы, что обновить приложение больше нельзя;
- тестовые раздачи: Firebase App Distribution для QA, затем треки Play Console: internal, closed, open;
- публикация: загрузка через Play Developer API, обычно с помощью fastlane или плагина Gradle Play Publisher, ревью, заполненные описание и раздел о безопасности данных;
- раскатка: staged rollout на небольшой процент пользователей с ростом, пока держатся метрики. Раскатку можно остановить, но обновившиеся останутся на новой версии.
После выхода смотрят Crashlytics и Android vitals (частота падений и ANR), не забыв загрузить mapping-файл R8, иначе стектрейсы останутся обфусцированными. Для российского рынка сборку часто параллельно публикуют в RuStore.
Где спотыкаются
Говорят «если что, откатимся». Откат в мобайле это новая сборка с большим versionCode, поэтому рискованное прячут за удалённым флагом, например в Firebase Remote Config.
Забывают, что старые версии живут месяцами. Бэкенд обязан держать совместимость API, а для критичных случаев есть In-App Updates с принудительным режимом.
Путают семантическую версию с versionCode и не знают, что загрузка с уже использованным кодом просто не пройдёт.