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 проект где пошагово описана каждая итерация из данной статьи.

Only registered users can participate in poll. Log in, please.

Раскрыть тему для более сложных примеров?

  • +9
  • 10.3k
  • 7
Share post

Comments 7

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

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

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

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

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

        Only users with full accounts can post comments. Log in, please.