
Если вы хоть раз тестировали SDK для Android, то знаете, сколько времени и нервов может уйти на подготовку окружения и сборку тестового приложения. Особенно если это делает не разработчик, а, например, тестировщик или менеджер — сначала нужно настроить окружение, скачать и обновить ветку до актуального состояния, открыть Android Studio, найти нужные параметры в build.gradle, внести правки вручную, запустить сборку. И каждый раз надеяться, что ничего не отвалится.
Меня зовут Алексей Чебанов, я старший инженер по тестированию в RuStore. В этой статье расскажу, как мы автоматизировали сборку нашего SampleApp — внутреннего Android‑приложения для тестирования SDK RuStore — и сделали процесс сборки максимально простым, быстрым и доступным для всей команды. Теперь любой участник проекта — даже без навыков Android‑разработки — может собрать актуальный APK с набором поставляемых SDK в пару кликов через CI/CD.
SampleApp — что это и зачем
Внутри RuStore мы поддерживаем несколько SDK: для обновлений, отзывов и комментариев, аналитики, удалённой конфигурации, встроенных покупок.

Чтобы оперативно и стабильно тестировать работу каждого SDK, мы создали SampleApp — внутреннее приложение, которое эмулирует поведение обычного пользовательского Android‑приложения. Оно вызывает необходимые методы из всех SDK и позволяет проверить их в связке, в условиях, близких к продакшену.
SampleApp используется не только командой тестирования — его запускают и инженеры, и менеджеры, и другие участники проекта, когда нужно быстро проверить ту или иную функциональность SDK в действии.
Старая сборка: долго, сложно, рискованно
Ранее каждый SampleApp собирался вручную. Но этот процесс был медленным, требовал знаний Android‑разработки и отнимал много ресурсов:
Получение актуального кода. Каждый тестировщик должен был иметь локальную копию мастер‑ветки из системы контроля версий.
Редактирование конфигурационных параметров. Параметры сборки и тестирования изменялись в Gradle‑файле. Необходимо было ручное редактирование конфигураций, что увеличивало риск ошибки.
Запуск сборки. Используя задачи Gradle, тестировщик собирал APK, что требовало знания Gradle и умения работать с Android Studio.
На словах — звучит терпимо. На практике — это был медленный и нервный процесс с кучей подводных камней:
Техническая сложность. Не все уверенно работают с Android Studio и Gradle.
Уязвимость к ошибкам. Ручное изменение кода увеличивало вероятность ошибок по невнимательности. Это могло привести к сбоям в сборке приложения или сборке с неправильными конфигурациями.
Затраты времени. Процесс занимал значительное количество времени, отвлекая ресурсы от более важных задач.
Мощность локальной машины. Процесс занимал значительное количество времени еще и потому, что сборка требовала определенных ресурсов железа локальной машины.
Порог входа. Для работы с Gradle‑файлами, обновлениями мастер ветки и сборки приложения требуются определенные знания. Поэтому менеджеру проекта или человеку смежного направления для сборки требовалось изучать инструкции или просить QA‑специалистов собрать актуальную сборку.
После очередной сборки с багом из‑за неправильных параметров мы поняли — пора кардинально менять подход. Так родилась идея выстроить полностью автоматизированную сборку через GitLab CI/CD, доступную каждому члену команды в один клик.
Конфигурация Gradle
Первым шагом в автоматизации стала переработка Gradle‑конфигурации. Мы хотели, чтобы сборка под разные нужды — окружения, версии, пакеты — происходила без ручного редактирования кода. Всё должно задаваться снаружи — через параметры CI/CD. Для этого мы внедрили простую, но эффективную функцию, которая читает переменные окружения и превращает их в сборочную конфигурацию:
static def getAppBuildConfig() {
def env = System.getenv()
return [
appID : env["appID"] ?: "AppIDNumber",
packageName: env["packageName"] ?: "Package Name",
versionCode: env["versionCode"] ?: "1",
appName : env["appName"] ?: "App-debug",
debuggable : env["debuggable"] ?: "true",
ci : env['CI'] ?: 'true'
]
}
Теперь сборка адаптируется на лету, без правок руками. Хотим собрать debug-версию под dev с уникальным packageName
и appID
? Просто передаём параметры в CI Job — и получаем нужный APK.
Такая параметризация позволила нам гибко управлять:
Package name,
Названием приложения,
Версией кода (versionCode),
Идентификатором приложения (appID),
Окружением (dev, stage, release),
Наличием/отсутствием debug-флагов.
Иными словами, вместо десятков захардкоженных значений — аккуратная обёртка, которая всё подтягивает автоматически.
Как это всё работает
Функция getAppBuildConfig()
делает простую, но полезную вещь: вытаскивает параметры сборки из переменных окружения (environment variables) и возвращает их в виде структуры данных, где каждая переменная соответствует одному из параметров сборки. Если что-то не передано — подставляется стандартное, заранее заданное значение. Это делает сборку предсказуемой и отказоустойчивой.
Помимо основной функции конфигурации, также были заменены дефолтные значения параметров сборки, которые были до этого, и которые приходилось менять руками в разных частях кода, подставив вместо них реальные значения из конфигурации. Например, вместо использования фиксированных значений в процессе сборки задействуются параметры из переменной config
, которая сама обращается к функции getAppBuildConfig()
для получения актуальных или дефолтных данных.
Внедрение CI/CD
Изначально у нас была настроена автоматическая сборка основного приложения, и в своей работе был упор на уже существующие параметры. Работа над файлом конфигурации CI (ci.yml) позволила не только сохранить эти параметры, но и внедрить задачи и переменные, необходимые для передачи данных в Gradle-файлы.
Пример конфигурации сборочного процесса в системе CI:
build_project:
extends: .android_pipeline
needs: []
cache: []
stage: build
script:
- ./gradlew :module-name:assembleDebug
when: manual
only:
- merge_requests
- web
artifacts:
when: always
expire_in: 1 day
paths:
- module/build/outputs/apk/**/*.apk
В этой конфигурации используются различные параметры, которые определяют, когда (only: - merge_requests
) и как (- ./gradlew :module-name:assembleDebug
) задача сборки должна выполняться. Указание на использование artifacts
позволяет сохранять результаты сборки, такие как APK-файлы, которые можно скачать и установить локально на эмулятор или физическое устройство. Чтобы не нагружать инфраструктуру, запуск сборки сделан вручную (when: manual
) и ошибка в сборке не блокирует merge request.
Что в итоге: меньше рутины, больше пользы
После внедрения автоматизации сборки SampleApp мы получили ощутимый прирост удобства и эффективности:
Доступность для всех. Теперь любой участник команды — от тестировщика до менеджера — может собрать нужную версию приложения без Android Studio и без знания Gradle. Всё работает через GitLab CI по кнопке.
Меньше ошибок. Мы устранили ручные правки конфигов и, как следствие, практически исключили человеческий фактор.
Экономия времени. Сборка больше не зависит от мощности локального железа. Всё происходит на CI‑сервере за пару минут.
Гибкий рабочий процесс. Тестировщики быстрее переключаются между задачами, не тратя время на настройку и пересборки. Команда разработки выпускает релизы быстрее и с меньшими рисками.
Вместо заключения
Этот кейс — ещё одно напоминание, что автоматизация даже самых незначительных процессов может радикально улучшить рабочие будни команды. Один раз настроив сборку как следует, мы избавили себя от регулярной боли, сэкономили часы времени и дали всей команде инструмент, который просто работает.
А как вы автоматизируете сборку тестовых приложений? Делитесь в комментариях — сравним подходы!