С появлением 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.
Много полезных примеров можно посмотреть тут и тут.
Надеюсь, статья кому-нибудь будет полезна. Удачи и меньше крашей на продакшене!
ссылка на оригинал статьи https://habr.com/ru/post/488134/
Добавить комментарий