10 мая в 16:38

Android + Gradle + CI + CD или Как настроить кормушку для котов tutorial



Здравстуй дорогой читатель. Если тебе незнакомы понятия Continuous integration (CI), Continuous delivery (CD) или же у тебя нет представления как и зачем их нужно использовать, то прошу под кат, где тебя ждет небольшое описание как настроить данные сервисы в своем Android проекте, а также какие бонусы будут получены в итоге.

Введение

Дорогой читатель, если ты думаешь, что в данной статье будет много кода — то ты ошибаешься. Кода как раз у нас будет самый минимум, но он позволит показать некоторые возможности CI. Основная часть статьи — как настроить связки сервисов. Надеюсь для разработчиков Junior/Middle данная статья будет весьма интересной и полезной.

Предыстория

Все началось со стартапа. У нас было достаточно хорошее финансирование и планы на ближайшие два года. Над android проектом работало два человека. Методология была у нас похожа на agile с использованием gitflow. Спустя два месяца разработки код был частично покрыт тестами, и вроде процесс для нашего небольшого проекта был отлаженный, но что то не давало покоя.

У меня есть предположение, что если вы не работаете в крупной компании, а трудитесь в стартапе (которых бесчисленное множество), то вы даже не задумываетесь о выгоде использования CI CD сервисов. Однако именно они помогут вам сэкономить время.

Я — разработчик, поэтому буду описывать происходящее от данной позиции.
Думаю ситуация, в которой к вам подходит кот (под данным словом я понимаю абсолютно любую позицию не-разработчиков в вашей команде, которые просят продукт для QA) и просит установить последнюю сборку на его телефон. По началу это не воспринимается как серьезная трудная задача. Однако, это создает следующие проблемы:

  • Пожалуй самое главное — вы отрываетесь от текущей задачи
  • Вы ищете последний скомпилированный apk
  • Ваш последний скомпилированный apk является вашей dev сборкой, и показывать ее ну никак нельзя
  • Вы подключаете мобильный телефон кота через кабель и устанавливаете сборку
  • А что если в нашей текущей ветке есть не закомиченные изменения? (commit -a \ stash в помощь, но все равно это время)
  • Вы тратите время на возврат к задаче которую вы выполняли

Это лишь вершина айсберга. А что если у вас много разных котов? Вы начинаете тратить все больше и больше времени для выполнения задач второстепенного характера.

Давайте же попробуем разобраться на небольшом примере, как сэкономить свое и чужое время.

Забегая немного вперед скажу, что сейчас, если разработка проекта у меня занимает больше одного месяца я все равно настраиваю Ci+Cd, что в дальнейшем приводит к вовлеченности заказчика и вы сразу же получаете фидбэк на разработку.

Цели

Мне было интересно построить данную статью на примере очереди из действий, которую нам необходимо проделать для получения результата. Причем каждую цель — выделить в отдельный коммит. Думаю так будет интереснее и проще понять, что происходит.

Пока мне видится три основные этапа ToDo:

  1. Создать проект
  2. Настроить CI
  3. Настроить CD

Преждевременная оптимизация — корень всех зол. (Premature optimization is the root of all evil. D. Knuth)

Создать проект

Думаю этот этап будет самым простым. Создаем новый репозиторий на VCS (Github/Bitbucket). Я лично выбираю GitHub — просто дело привычки. Все дальнейшие изменения вы можете отслеживать по коммитам.

Далее, делаем первый коммит

Даже если сейчас мы начнем делать разработку новой фитчи, и к нам подойдет кот и попросит последнюю сборку, то мы будет вынуждены откатиться до master head. В целом мы подошли к проблеме.

Настроить Ci

Чтобы что-то кому то отправить, надо это что-то где-то собрать. И желательно с минимальной отвлеченностью нас от основной задачи разработки.

В качестве Ci сервиса я предпочитаю CircleCI. Существуют также и альтернативы и никто не запрещает вам использовать более одного Ci сервиса в вашем проекте.

Наша цель — двигаться небольшими шагами, поэтому поставим себе цель просто запустить сборку репозитория на Ci

Начнем пошагово:

1. Авторизуемся на CiCircle через GitHub

2. В боковой плашке находим Project и переходим к нашему новому проекту (если вы нажмете на Build project то сборка завершится неудачей из за не настроенного проекта)



3. Заходим в настройки репозитория на GitHub в категорию Integrations & services и нажимаем Add Service

4. Забегая вперед, в настройках проекта на CiCircle рекомендую включить мониторинг Pull request(PR), это позволит вашим коллегам не мерджить в мастер нерабочий код. (Возможно это еще одна моя заморочка, но я считаю, что master ветка должна всегда собираться)



5. Пожалуй самая важная часть по настройке Ci — настройка в вашем проекте
Нам необходимо внести изменения в build.gradle, добавить cicircle.gradle (по сути шаблон) и некоторый circleci.yml (который несет в себе основную настройку по CI). Я сторонник проводить любые изменения master ветки только через PR, поэтому создаем branch с преднастройками Ci и делаем PR.
Если все было сделано правильно, то под PR мы увидим что-то похожее



А если зайдем в Ci то увидим как собирается наш проект
Спустя какое то время (обычно сборка занимает не более 5 минут мы увидим скорее всего положительный результат)



А значит можно продолжать, и смело нажимаем Merge! (И на Ci запустится сборка master ветки)

Какие плюсы для себя мы получаем?

  • Сборка происходит независимо от нас в облаке
  • Теперь каждый раз когда мы делаем PR то мы точно знаем, соберется ли у нас сборка. Это исключает возможность подкинуть себе проблем с нерабочими сборками из мастера
  • Есть возможность прогонять тесты

Отлично, работаем дальше!

Раз сборка происходит в облаке, логично предположить, что остаются какие то артифакты в виде apk.

Мне кажется, что хорошая цель на данную итерацию — получать apk, который можно было бы выложить в маркет. Таким образом мы получаем при каждой сборке master ветки (не PR) уже готовый продукт.

1. Чтобы сбирать release.apk — нам необходимо сгенерировать ключ подписи. Это делается единожды через Android Studio.

2. Далее вносятся изменения в build.gradle

 signingConfigs {
        release {
            def signFile = project.rootProject.file('./release.keystore')
            if (signFile.exists()) {
                storeFile signFile
                storePassword "qweqwe"
                keyAlias "habrcicdcat"
                keyPassword "qweqwe"
            }
        }
    }


    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.release
        }
    }


Файл release.keystore лежит в папке с проектом.

3. Создаем bash скрипт кторый будет отвечать за перенос собранного файла в директорию артефактов

#/bin/bash
GRADLE="./gradlew"
$GRADLE assembleRelease
RELEASEFILE="${CIRCLE_ARTIFACTS}/habrcicdcat-release-${CIRCLE_BUILD_NUM}-${CIRCLE_SHA1}.apk"
cp ./app/build/outputs/apk/app-release.apk ${RELEASEFILE}

Данные константы доступны по умолчанию
CIRCLE_BUILD_NUM — номер сборки
CIRCLE_SHA1 — ключ коммита

CIRCLE_ARTIFACTS — мы устанавливаем ее в cicircle.yml

general:
  artifacts:
    - /home/ubuntu/HabrCiCdCat/app/build/outputs/apk/

4. Добавляем в cicircle.yml часть, отвечающую за деплоймет


deployment:
  beta:
    branch: master
    commands:
      - cd scripts && ./build.sh

Всего лишь запускаем наш скрипт, при изменении мастер ветки

5. Делаем PR в мастер ветку, дожидаемся что все собирается успешно, выполняем слияние. Если перейти в консоль Ci то мы можем увидеть, как началась собираться master ветка.



Спустя какое то время, вы увидите, что сборка прошла успешно. Через консоль в Ci можно увидеть собранные APK



Фактически на этом можно закрывать создание apk. Мы можем скачать и сразу загрузить apk в маркет или отправить на почту нашим котам. Но чего то все таки не хватает. Главная цель статьи не была реализована, и нас все равно будут отрывать от выполнения текущей задачи. На помощь приходит CD.

Настройка Fabric Beta

В качестве CD сервиса я буду рассматривать Beta от Fabric. Опять же замечу, что существует множество альтернатив, но суть статьи не в холиварах а в описании процесса.

Итак. Когда корм для наших котов готов, осталось его до них донести. В этом нам помогают сервисы бета тестирования.

Начнем настройку:

1. Для начала наш проект должен зарегистрироваться в Fabric, существует несколько способов, включая добавление Fabric Plugin в Android Studio. Нужно внести изменения в build.gradle файлы. После выполнения этих операций в вашей консоли в crashlitics отобразится новое приложение.



2. В настройках аккаунта Fabric вам необходимо создать новую организацию, и получить от нее apiSecret и apiKey

3. Начнем настройку Beta сервиса от Fabric

Для начала нам нужно создать группу тестировщиков и добавить в нее хотя бы себя и
Тут главное запомнить Alias: habrcicdcat



и сделать связку организации и группы тестировщиков



Всем тестировщикам из группы придет уведомление на email, которое необходимо открыть с телефона, и перейти по ссылке внутри письма для скачивания или верификации приложения Beta.



Далее начнем настройку связки сервиса и приложения

Добавляем Alias в buildTypes

buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.release
            ext.betaDistributionGroupAliases = "habrcicdcat"
        }
    }

В папку app добавляем fabric.properties следующего содержания (константы из п.2)

apiSecret=23167a9cd00cb83f9dab952b47e7350e19dd7693071ceb2abe2d56dbfc6e1318
apiKey=3915c7e9ffe661c44a4db3935d34a5a8da525b9c


Далее, можно создавать PR и смотреть за сборкой master. Если все прошло успешно то вам придет нотификация в приложение Beta, и вы сможете его скачать и установить.



Конечная цель достигнута

Цели, поставленные в начале статьи выполнены. Теперь при любом изменении master ветки будет происходить сборка приложения, я отправка apk группе котов. И мы всегда имеем под рукой сборку, для публикации.

Теперь, когда вас будут отрывать от рабочего процесса, вы всегда можете ответить: «Последняя сборка всегда доступна в Beta» — а как побочный результат, вы можете спокойно продолжать работать над текущей задачей.

Что осталось за кадром:

  • Сборка flavors (чтобы показать пример, как кормить нескольких котов)
  • Возможные проблемы при создании сборок

В данной статье я хотел показать, что настройка CI и CD не такая страшная, однако крайне полезная вещь. Я не считаю проблемой, затратить час времени для настройки этой системы на фриланс проектах потому, что выгода от нее спустя 2 недели превысит этот час. Надеюсь, эта статья принесет в ваш проект CI и CD, ну или хотя бы вам было интересно.

Ссылка на GitHub проект где пошагово описана каждая итерация из данной статьи.
Раскрыть тему для более сложных примеров?

Проголосовало 43 человека. Воздержалось 8 человек.

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

Костянчик @Jukobob
карма
21,0
рейтинг 7,2
Написатель кода
Похожие публикации
Самое читаемое Разработка

Комментарии (7)

  • 0
    В нашей маленькой компании мы настроили практически такой же процесс, только ci используем от gitlab. Задумываюсь о переходе на старый-добрый jenkins)
    • 0
      Спора нет — альтернативных решений настроить подобную систему очень много. Специально приводил ссылки. Больше всего боюсь холиваров, кому что нравится. Хороший разработчик должен понимать подход, а инструментарий всегда добрать можно.
    • 0

      Не подскажите, а что не так с gitlab? Какие-то проблемы или ограничения?

      • 0
        Проблем нет, просто первым опытом с CI был именно дженкинс, по этому он мне больше и нравится)
  • 0

    А как там с настройкой автоматического тестирования в экосистеме андроид? Тесты на хосте не так интересны, а вот настройка прогона на реальных девайсах — это весело должно быть.

  • 0
    Отличная статья, спасибо. Как раз для небольшой подработки ок. А то я хотел дергать заказчика, что бы поднял jenkins и сделть ci на нем, но вот увидел Вашу статью, решил попроовать CircleCI :)

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.