Привет!
С появлением Github Actions проявил инициативу и интегрировал простенький (но вполне эффективный) CI/CD в наш небольшой, но уже как 2 года живой проект Flowwow.
Зачем?

Возможно, есть такие разработчики, которые не совершают ошибок, но вот я — не из таких, поэтому изредка, но случаются вот такие небольшие всплески крашей и приходится в срочном порядке выпускать новую версию с правкой либо откатом к предыдущей версии. Но те часы-дни, в которые пользователи натыкаются на вылеты приложения, без следов не остаются как у клиентов, так и в настроении ответственного разработчика.
Как минимизировать факапы на продакшене, расскажу ниже.
Отчего же лично у меня бывают такие факапы?
С 1 пунктом нам помогут code review, Unit тесты, статический анализ кода, UI тесты, ручное тестирование.
Со 2-3 пунктами — только UI тесты и ручное тестирование.
Остается только это автоматизировать. На этом этапе выбор пал на тогда еще только появившийся Github Actions, благо и код проекта находится на Github. Сразу скажу, для free аккаунта github дается бесплатных 2,000 Action минут в месяц.
Здесь полно готовых примеров для различных языков и фреймворков. Настраивается эта штука через конфигурационный файлик YAML, который находится в репозитории проекта.

Минимальный пример для Android:
Описание: на каждый push в любую ветку запускается задача (job) на виртуальной машине github с ОС ubuntu. Шаги задачи: checkout нашего кода, настройка jdk, запуск gradle задачи для сборки.
В случае неуспешного прохождения какого либо шага увидим такую картину

там же можно посмотреть логи.
Удобно, что при Pull Request нам сразу покажут, что наша проверочная последовательность зафейлилась

А если у вас есть интеграция github со Slack, то еще и так

1. Unit tests
Вы написали Unit тесты используя junit, mockito, etc.
Теперь ваши тесты включаются в последовательность проверки добавлением соответствующей gradle задачи.
2. Статический анализ кода
Вы можете использовать простые линтеры (detekt — для kotlin, pmd — для java).
Или же более сложный вариант — sonarqube.
В случае простых линтеров (например, у нас и java, и kotlin):
в случае sonarqube — подробнее про настройку — здесь
3. UI тесты
Написание UI теста — плод вашей фантазии, мой подход — один «Smoke» тест, имитирующий стандартные действия пользователя в приложении — зайти, выбрать товар, сделать заказ, отследить заказ. Вы можете использовать UIAutomator, Espresso, Kaspresso.
Для запуска здесь тоже 2 варианта — эмулятор на виртуальной машине github или облачные сервисы, такие как Firebase Test Lab
Для использования эмулятора внутри github есть готовые реализации: раз и два.
В случае с Firebase Test Lab, необходимо работать с Google Cloud Platform через gcloud CLI
Чтобы это работало, необходимо создать проект в Firebase, создать в Google Cloud Сonsole сервисный аккаунт с админ правами и полученный ключ json загрузить в base64 в github secrets для авторизации в gcloud.
Общий конфиг в моем случае выглядел так. Задача запускается по событию PR в master
Вроде, просто. Эффективность зависит от написанных тестов и выбранных правил код-анализа. Можно писать несколько независимых задач (job) для их параллельного запуска. В моем случае все проходит последовательно. Процесс проверки занимает примерно 15 минут на нашем проекте (виртуальная машина github 2-core CPU, 7 GB RAM, 14 GB of SSD), но на самом деле не критично, тк пока «кодревьюишь» глазами, подъезжают результаты и этих тестов.
Больше всего выручают UI тесты — бывает, что во время их прохождения крашится аналитика после обновления библиотеки и ты просто понимаешь, что не стоит её обновлять.
Через gcloud также можно доставлять билды в Firebase App Distribution, релизить в Google Play, etc.
Много полезных примеров можно посмотреть тут и тут.
Надеюсь, статья кому-нибудь будет полезна. Удачи и меньше крашей на продакшене!
С появлением Github Actions проявил инициативу и интегрировал простенький (но вполне эффективный) CI/CD в наш небольшой, но уже как 2 года живой проект Flowwow.
Зачем?

Возможно, есть такие разработчики, которые не совершают ошибок, но вот я — не из таких, поэтому изредка, но случаются вот такие небольшие всплески крашей и приходится в срочном порядке выпускать новую версию с правкой либо откатом к предыдущей версии. Но те часы-дни, в которые пользователи натыкаются на вылеты приложения, без следов не остаются как у клиентов, так и в настроении ответственного разработчика.
Как минимизировать факапы на продакшене, расскажу ниже.
Отчего же лично у меня бывают такие факапы?
- Ненадежный участок кода
- Завезли какую-то библиотеку и она ситуативно крашит
- Обновили какую-то библиотеку (обычно, это аналитика) на нестабильную версию
С 1 пунктом нам помогут code review, Unit тесты, статический анализ кода, UI тесты, ручное тестирование.
Со 2-3 пунктами — только UI тесты и ручное тестирование.
Остается только это автоматизировать. На этом этапе выбор пал на тогда еще только появившийся Github Actions, благо и код проекта находится на Github. Сразу скажу, для free аккаунта github дается бесплатных 2,000 Action минут в месяц.
C чего начать?
Здесь полно готовых примеров для различных языков и фреймворков. Настраивается эта штука через конфигурационный файлик YAML, который находится в репозитории проекта.

Минимальный пример для Android:
name: Android CI
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Build with Gradle
run: ./gradlew assembleDebug
Описание: на каждый push в любую ветку запускается задача (job) на виртуальной машине github с ОС ubuntu. Шаги задачи: checkout нашего кода, настройка jdk, запуск gradle задачи для сборки.
В случае неуспешного прохождения какого либо шага увидим такую картину

там же можно посмотреть логи.
Удобно, что при Pull Request нам сразу покажут, что наша проверочная последовательность зафейлилась

А если у вас есть интеграция github со Slack, то еще и так

А теперь по пунктам
1. Unit tests
Вы написали Unit тесты используя junit, mockito, etc.
Теперь ваши тесты включаются в последовательность проверки добавлением соответствующей gradle задачи.
- name: Run some unit tests
run: ./gradlew testStageDebugUnitTest
2. Статический анализ кода
Вы можете использовать простые линтеры (detekt — для kotlin, pmd — для java).
Или же более сложный вариант — sonarqube.
В случае простых линтеров (например, у нас и java, и kotlin):
task("checkAll") {
group "Verify"
description "Runs all static checks on the build"
dependsOn "pmd", "detekt"
}
- name: Run some unit tests
run: ./gradlew checkAll
в случае sonarqube — подробнее про настройку — здесь
- uses: actions/checkout@v1
- name: SonarCloud Scan
run: ./gradlew jacocoUnitTestReport sonarqube -Dsonar.login=${{ secrets.SONAR_TOKEN }} --stacktrace
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Link to SonarCloud Report
run: echo "https://sonarcloud.io/dashboard?id=.."
3. UI тесты
Написание UI теста — плод вашей фантазии, мой подход — один «Smoke» тест, имитирующий стандартные действия пользователя в приложении — зайти, выбрать товар, сделать заказ, отследить заказ. Вы можете использовать UIAutomator, Espresso, Kaspresso.
Для запуска здесь тоже 2 варианта — эмулятор на виртуальной машине github или облачные сервисы, такие как Firebase Test Lab
Для использования эмулятора внутри github есть готовые реализации: раз и два.
В случае с Firebase Test Lab, необходимо работать с Google Cloud Platform через gcloud CLI
- name: prepare gcloud
uses: GoogleCloudPlatform/github-actions/setup-gcloud@master
with:
version: latest
service_account_email: ${{ secrets.SA_EMAIL }}
service_account_key: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS }}
- name: gcloud Set up project
run: |
gcloud config set project ${{ secrets.PROJECT_ID }}
- name: Assemble apks for smoke test
run: ./gradlew Smoke
- name: Run tests in test lab
run: |
gcloud firebase test android run \
--app app/build/outputs/apk/production/debug/app.apk \
--test app/build/outputs/apk/androidTest/production/debug/appTest.apk \
--device model=Nexus6P,version=25,orientation=portrait,locale=en_US \
--device model=athene,version=23,orientation=portrait,locale=en_US \
--device model=sailfish,version=26,orientation=portrait,locale=en_US
Чтобы это работало, необходимо создать проект в Firebase, создать в Google Cloud Сonsole сервисный аккаунт с админ правами и полученный ключ json загрузить в base64 в github secrets для авторизации в gcloud.
Общий конфиг в моем случае выглядел так. Задача запускается по событию PR в master
name: Android CI
on:
pull_request:
branches:
- 'master'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Run static checks
run: ./gradlew checkAll
- name: Run some unit tests
run: ./gradlew testStageDebugUnitTest
- name: prepare gcloud
uses: GoogleCloudPlatform/github-actions/setup-gcloud@master
with:
version: latest
service_account_email: ${{ secrets.SA_EMAIL }}
service_account_key: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS }}
- name: gcloud Set up project
run: |
gcloud config set project ${{ secrets.PROJECT_ID }}
- name: Assemble apks for smoke test
run: ./gradlew Smoke
- name: Run tests in test lab
run: |
gcloud firebase test android run \
--app app/build/outputs/apk/production/debug/app.apk \
--test app/build/outputs/apk/androidTest/production/debug/appTest.apk \
--device model=Nexus6P,version=25,orientation=portrait,locale=en_US \
--device model=athene,version=23,orientation=portrait,locale=en_US \
--device model=sailfish,version=26,orientation=portrait,locale=en_US
Вроде, просто. Эффективность зависит от написанных тестов и выбранных правил код-анализа. Можно писать несколько независимых задач (job) для их параллельного запуска. В моем случае все проходит последовательно. Процесс проверки занимает примерно 15 минут на нашем проекте (виртуальная машина github 2-core CPU, 7 GB RAM, 14 GB of SSD), но на самом деле не критично, тк пока «кодревьюишь» глазами, подъезжают результаты и этих тестов.
Больше всего выручают UI тесты — бывает, что во время их прохождения крашится аналитика после обновления библиотеки и ты просто понимаешь, что не стоит её обновлять.
Через gcloud также можно доставлять билды в Firebase App Distribution, релизить в Google Play, etc.
Много полезных примеров можно посмотреть тут и тут.
Надеюсь, статья кому-нибудь будет полезна. Удачи и меньше крашей на продакшене!