Site icon AppTractor

GitHub Actions для Android-разработки

Если вы разрабатываете приложения для Android, скорее всего, в какой-то момент своей карьеры вы столкнетесь с тем или иным видом CI. Если вы знакомы с фрагментацией Android, то большой выбор систем CI будет вам знаком.

GitHub Actions был запущен в ноябре 2019 года, и с тех пор зарекомендовал себя как надежное для производственной среды решение (одно из наших требований перед переходом к любой программной системе). Как и многие другие системы CI/CD, GitHub Actions в конечном итоге позволяет нам определять рабочие процессы для приложений, чтобы автоматически создавать, тестировать и развертывать их.

Одним из самых ярких аспектов GitHub Actions является его интеграция с GitHub. Для репозиториев, которые уже размещены на GitHub, GitHub Actions позволяет автоматизировать процесс на одной единой платформе без необходимости полагаться на какие-либо внешние инструменты. Ваш код находится на GitHub, ваш CI/CD работает на GitHub, и вы также можете разместить свой дистрибутив на GitHub, если хотите.

Теперь GitHub Actions предоставляет подробные руководства и документацию, хотя первый переход к нему может быть несколько ошеломительным для людей, не имеющих опыта работы с платформой. В документации приведен пример базовой настройки для разработчиков Android, но вы можете спросить: «Где мне найти вдохновение в том, что я могу делать с помощью GitHub Actions?». Этот пост призван дать несколько ответов, основанных на моем личном опыте использования GitHub Actions. Я использую его для Android-проектов, поэтому мой опыт (и этот пост) ограничен этой платформой. Без дальнейших промедлений, начнем.

Структура нашего конфигурационного файла

Для GitHub Actions требуется файл .yml, в котором указаны все шаги для CI/CD. Файлы YAML неудобны, особенно когда они становятся большими (проблемы с отступами могут остаться незамеченными, а поддержка со стороны IDE встречается редко). Файлы хранятся в папке .github/workflows/file.yml. Вот минимальный пример того, как они выглядят:



Действия (Actions)

Действия — это особый тип шагов, которые помогают нам автоматизировать CI/CD. Кто угодно может опубликовать свои действия с открытым исходным кодом, и их можно просматривать через GitHub. Многие функции, которые мы могли бы реализовать, скорее всего, уже здесь есть, поэтому стоит сначала посмотреть, чтобы не изобретать велосипед заново. И, конечно же, можно форкнуть и изменить существующие действия или создать свои собственные.

Ниже список некоторых операций, которые мы можем выполнять в ходе Android-разработки. Исходя изназвания CI/CD, мы обычно хотим создавать и развертывать приложения, но есть некоторые полезности, которые мы можем применить (уведомить определенные каналы или платформы и т.д.). Давайте начнем.

Настройка нашего приложения для Android

Первоначально мы настроим нашу среду, и для этого нам нужно проверить наш проект и настроить наш JDK. Здесь мы будем использовать наше первое Действие, Checkout v2, чтобы выполнить git checkout нашего репозитория, и setup-java для подготовки нашей Java-среды .

## Checkout our repository ###
- name: Checkout
  uses: actions/checkout@v2.3.3

- name: Set up our JDK environment
  uses: actions/setup-java@v1.4.3
  with:
    java-version: 1.8

Создание наших артефактов

Фундаментом каждого проекта является компиляция всех наших артефактов для загрузки и/или распространения. Разные версии часто имеют свои особенности, и мы можем сгенерировать несколько APK на основе нашего Flavor или BuildTypes. Некоторые из них актуальны (наш артефакт для релиза, который может быть передан непосредственно нашей группе тестирования), некоторые из них менее актуальны (наши тестовые артефакты, предназначенные только для использования в разработке) — в зависимости от структуры вашей команды. К счастью, мы можем напрямую вызывать команды Gradle и генерировать необходимое количество артефактов. Мы будем использовать Действие gradle-command-action для выполнения нашей команды Gradle. Примером может послужить следующее:

## Build all our Build Types at once ##
- name: Build all artifacts
 id: buildAllApks
 uses: eskatos/gradle-command-action@v1.3.3
 with:
   gradle-version: current
   wrapper-cache-enabled: true
   dependencies-cache-enabled: true
   configuration-cache-enabled: true
   arguments: assembleRelease

Здесь интересна строка arguments: assembleRelease. Мы можем легко заменить в ней команду Gradle, которую хотим выполнить.

Тестирование

Есть несколько инструментов для тестирования или анализа, которые мы могли бы использовать в нашей среде CI/CD. К счастью, с помощью GitHub Actions мы можем напрямую запускать наши команды Gradle. Например, можно легко запустить наши тесты или Lint, напрямую вызвав соответствующую команду Gradle:

- name: Run Kotlin Linter
  run: ./gradlew ktlintStagingDebugCheck

- name: Run Unit Tests
  run: ./gradlew testStagingDebugUnitTest

Мы также можем запускать наши тесты Espresso через GitHub Actions. Есть несколько действий, которые позволяют нам запускать их, мы продемонстрируем android-emulator-runner от Reactive Circus:

uses: reactivecircus/android-emulator-runner@v2
  with:
     api-level: 23
     target: default
     arch: x86
     profile: Nexus 6
     script: ./gradlew connectedCheck --stacktrace

Подписание артефактов

Подписание артефактов — это следующий естественный шаг при создании нашего Android-проекта, чтобы их можно было установить на устройстве.

## Sign our artifact##
- name: Sign artifact
  id: signArtifact
  uses: r0adkll/sign-android-release@v1.0.1
  with:
     releaseDirectory: app/build/outputs/apk/ourbuildtype/release
     alias: ${{ secrets.KEYALIAS }}
     signingKeyBase64: ${{ secrets.KEYSTORE }}
     keyStorePassword: ${{ secrets.KEYSTORE_PASSWORD }}
     keyPassword: ${{ secrets.KEY_PASSWORD }}

- name: Upload our APK
  uses: actions/upload-artifact@v2.2.0
  with:
     name: Release artifact
     path: app/build/outputs/apk/ourbuildtype/release/app-artifact-*.apk

Некоторые дополнительные объяснения того, что здесь происходит:

С помощью Gradle мы можем настроить наш файл конфигурации, чтобы определить имя нашего результирующего APK. Это приводит к гораздо более читабельному выводу, вместо того, чтобы всегда использовать имя APK по умолчанию. Например, следующий блок кода изменяет имя нашего файла Gradle на более читаемый формат:

android.applicationVariants.all { variant ->
   variant.outputs.all {
      outputFileName = "app-${variant.productFlavors[0].name}-${variant.buildType.name}-${variant.versionName}.apk"
   }
}

Создание выпуска

Интересно, что GitHub сам может создавать внутри Release, который мы позже можем использовать для распространения наших артефактов. Например, посмотрите, как выглядит страница Release для версии 1.4.2 корутин Kotlin:

Каждый из этих релизов может содержать ряд артефактов, исходный код, документацию и т.д. Также можно опубликовать CHANGELOG или примечания для конкретного выпуска (подробнее об автоматическом создании этого позже). Конечно, полезно, чтобы это автоматически создавалось вместе со всем процессом. Соответствующий раздел, который создаст релиз в GitHub.

- name: Create Release
  id: create_release
  uses: actions/create-release@v1
  env:
     GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  with:
    tag_name: ${{ github.ref }}
    release_name: Release ${{ github.ref }}
    draft: false
    prerelease: false

Загрузка ассетов на GitHub

С созданием релиза пришло время загрузить наши собственные ресурсы. Мы собираемся использовать вспомогательную задачу, чтобы собрать наши имена APK и пути (предположим, что у нас есть собственные имена для них, как было сделано ранее).

- name: Save name of our Artifact
  id: set-result-artifact
  run: |
     ARTIFACT_PATHNAME_APK=$(ls app/build/outputs/apk/ourbuildtype/release/*.apk | head -n 1)
     ARTIFACT_NAME_APK=$(basename $ARTIFACT_PATHNAME_APK)
     echo "ARTIFACT_NAME_APK is " ${ARTIFACT_NAME_APK}
     echo "ARTIFACT_PATHNAME_APK=${ARTIFACT_PATHNAME_APK}" >> $GITHUB_ENV
     echo "ARTIFACT_NAME_APK=${ARTIFACT_NAME_APK}" >> $GITHUB_ENV

Обратите внимание на несколько важных моментов в этом блоке кода:

Поскольку имена и PATH уже сохранены в переменной среды, мы приступим к их загрузке на нашу страницу выпуска. Здесь используется действие upload-release-asset:

- name: Upload our Artifact Assets
  id: upload-release-asset
  uses: actions/upload-release-asset@v1
  env:
     GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  with:
     upload_url: ${{ steps.create_release.outputs.upload_url }}
     asset_path: ${{ env.ARTIFACT_PATHNAME_APK }}
     asset_name: ${{ env.ARTIFACT_NAME_APK }}
     asset_content_type: application/zip

Это создало наши артефакты на GitHub, и мы готовы их распространять. Мы можем использовать множество механизмов уведомления. Например, если у нас есть группа в Slack, мы можем уведомить определенный канал о том, что наш релиз готов, используя act10ns/slack:

- name: Notify on Slack
  uses: act10ns/slack@v1.0.9
  with:
     status: ${{ job.status }}
     steps: ${{ toJson(steps) }}
     if: always()

В Действиях GitHub уже доступно большое количество опций, включая уведомления в Telegram, по электронной почте или в Discord. Если вы можете придумать конкретную платформу, которая вам нужна, скорее всего, она уже есть в GitHub Actions.

Мы могли бы придать последний штрих релизу, автоматически заполнив CHANGELOG, используя некоторую информацию, которая уже доступна. Как вы понимаете, на GitHub уже есть Действие, которое решает эту проблему. Конкретно это берет информацию из файла CHANGELOG.md согласно keepchangelog.com, но не составит труда изменить это с помощью git log —pretty=oneline или аналогичного формата.

Резюме

GitHub Actions — еще один движок Continuous Integration/Continuous Delivery. Если вы уже используете GitHub, он обеспечивает очень приличную интеграцию с вашим кодом, задачами и рабочим процессом. Он обладает широкими возможностями настройки, предоставляя API-интерфейсы для создания ваших собственных действий по мере необходимости или доступ к ним из маркетплейса GitHub. Как и в случае с любым облачным решением (или любым техническим решением), есть несколько факторов, которые необходимо взвесить, прежде чем решить, имеет ли смысл его использовать или нет.

Я считаю, что это удобное решение, отвечающее широкому кругу требований.

Источник

Exit mobile version