Полный разбор GitHub Actions Workflow для сборки, подписи и релиза Android-приложений.

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

Файл, представленный ниже, является YAML-скриптом для сборки, подписи и релиза Android-приложений.

Разберем по шагам!

1. Имя и триггеры

name: Create Release

on:
  push:
    tags:
      - 'v*.*.*'
  workflow_dispatch:
    inputs:
      release_tag:
        description: vx.y.z
        required: true
        type: string

  • name: Имя рабочего процесса (workflow)

  • on - триггеры:

    • push: Триггер срабатывает при публикации тега формата vX.Y.Z (например, v1.0.0).

    • workflow_dispatch: Позволяет вручную запустить workflow с возможностью указания версии релиза (тега) через ввод параметра release_tag.

2. Рабочие задания (jobs)

В workflow определено 2 задачи:

  • build: Сборка и подписание APK.

  • release: Генерация релиза и загрузка артефактов.

Job 1: build

Настройки

jobs:
  build:
    runs-on: ubuntu-latest

  • runs-on: Этот блок определяет виртуальную машину для запуска задачи: Ubuntu (последняя версия)

Шаги

1. Checkout Repo:

steps:
  - name: Checkout Repo
    uses: actions/checkout@v4

  • Это автоматическое Github action для клонирования репозитория на виртуальную машину.

2. Set up JDK 17:

  - name: Set up JDK 17
    uses: actions/setup-java@v4
    with:
      distribution: 'zulu'
      java-version: '17'
      java-package: 'jdk'
      cache: 'gradle'

  • Настраивает JDK 17 (распространение Zulu), необходимое для сборки Android-приложения.

  • Включает кэширование для инструментов Gradle

3. Build APK:

  - name: Build APK
    run: | 
      ./gradlew assembleRelease

  • Запускает Gradle-задачу assembleRelease для сборки APK в режиме release. Результирующий файл будет находиться в app/build/outputs/apk/release/

4. Set up Keystore:

  - name: Set up Keystore
    run: |
      sudo apt update -y || true
      sudo apt install -y --no-install-recommends coreutils
      mkdir -p $RUNNER_TEMP/keystores
      echo "${{ secrets.KEYSTORE_FILE }}" | base64 --decode > $RUNNER_TEMP/keystores/keystore.jks

  • Устанавливает необходимые инструменты для обработки файлов ключей: coreutils

  • Декодирует закодированный в Base64 файл хранилища ключей (keystore) из секрета KEYSTORE_FILE и сохраняет его в временной папке.

5. Sign APK:

  - name: Sign APK
    run: |
      ANDROID_SDK_PATH=$ANDROID_HOME/build-tools/35.0.0/apksigner
      $ANDROID_SDK_PATH sign \
        --ks $RUNNER_TEMP/keystores/keystore.jks \
        --ks-key-alias ${{ secrets.KEY_ALIAS }} \
        --ks-pass pass:${{ secrets.KEYSTORE_PASSWORD }} \
        --key-pass pass:${{ secrets.KEY_PASSWORD }} \
        --out app-release.apk \
        app/build/outputs/apk/release/app-release.apk

  • Использует инструмент apksigner для подписания собранного APK-файла. (Набор предустановленных инструментов можно найти здесь - ANDROID_HOME уже имеет предустановленные версии ANDROID)

  • Секреты ( KEY_ALIAS, KEYSTORE_PASSWORD, KEY_PASSWORD) обеспечивают безопасность конфиденциальной информации.

6. Upload APK Artifact:

  - name: Upload APK Artifact
    uses: actions/upload-artifact@v4
    with:
      name: apk-artifact
      path: app-release.apk
      compression-level: 5

  • Загружает подписанный APK ( app-release.apk ) в качестве артефакта. Он будет доступен для загрузки в интерфейсе GitHub Actions.

Job 2: release

Настройки

release:
  needs: [build]
  runs-on: ubuntu-latest
  permissions:
    contents: write

  • needs: Задание release выполняется только после успешного выполнения задания build.

  • permissions: Предоставляет разрешения для записи содержимого репозитория (необходимо для создания релиза).

Шаги

1. Checkout Changes:

steps:
  - name: Checkout Changes
    uses: actions/checkout@v4
    with:
      sparse-checkout: |
        CHANGE.md
      sparse-checkout-cone-mode: false

  • Загружает только файл CHANGE.md, который содержит список изменений для релиза (Впоследствии он будет телом релиза).

2. Download Build Artifacts

  - name: Download Build Artifacts
    uses: actions/download-artifact@v4
    with:
      name: apk-artifact

  • Загружает артефакт apk-artifact, созданный в предыдущем задании с использованием actions/download-artifact@v4.

3. Generate Changelog:

  - name: Generate Changelog
    run: |
      cat CHANGE.md > CHANGE.txt

  • Копирует содержимое CHANGE.md в файл CHANGE.txt. Этот файл будет использован в описании релиза.

4. Release:

  - name: Release 
    uses: softprops/action-gh-release@v2
    with:
      files: |
        app-release.apk
      body_path: CHANGE.txt

  • Использует действие softprops/action-gh-release для создания релиза в репозитории.

  • К релизу прикрепляется APK-файл и добавляется описание из CHANGE.txt.

Переменные и секреты

Секреты хранятся в разделе Settings → Secrets and variables репозитория. В этом workflow используются следующие секреты:

  • KEYSTORE_FILE: Закодированный в Base64 файл keystore.

  • KEY_ALIAS: Алиас ключа.

  • KEYSTORE_PASSWORD: Пароль хранилища ключей.

  • KEY_PASSWORD: Пароль ключа.

Summary

  1. Workflow запускается при создании тега (vX.Y.Z)

  2. Задание build:

    • Скачивает код.

    • Настраивает JDK и Gradle.

    • Собирает APK в режиме release.

    • Подписывает APK с использованием keystore.

    • Загружает подписанный APK в виде артефакта.

  3. Задание release:

    • Загружает список изменений и артефакт.

    • Генерирует changelog.

    • Создаёт релиз в GitHub с прикреплённым APK.

Полный код:

name: Create Release

on:
  push:
    tags:
      - 'v*.*.*'
  workflow_dispatch:
    inputs:
      release_tag:
        description: vx.y.z
        required: true
        type: string


jobs:
  build:
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v4

      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          distribution: 'zulu'
          java-version: '17'
          java-package: 'jdk'
          cache: 'gradle'

      - name: Build APK
        run: | 
          ./gradlew assembleRelease
      
      - name: Set up Keystore
        run: |
          sudo apt update -y || true
          sudo apt install -y --no-install-recommends coreutils
          mkdir -p $RUNNER_TEMP/keystores
          echo "${{ secrets.KEYSTORE_FILE }}" | base64 --decode > $RUNNER_TEMP/keystores/keystore.jks

      - name: Sign APK
        run: |
          ANDROID_SDK_PATH=$ANDROID_HOME/build-tools/35.0.0/apksigner
          $ANDROID_SDK_PATH sign \
            --ks $RUNNER_TEMP/keystores/keystore.jks \
            --ks-key-alias ${{ secrets.KEY_ALIAS }} \
            --ks-pass pass:${{ secrets.KEYSTORE_PASSWORD }} \
            --key-pass pass:${{ secrets.KEY_PASSWORD }} \
            --out app-release.apk \
            app/build/outputs/apk/release/app-release.apk

      - name: Upload APK Artifact
        uses: actions/upload-artifact@v4
        with:
          name: apk-artifact
          path: app-release.apk
          compression-level: 5

  release:
    needs: [build]
    runs-on: ubuntu-latest
    permissions:
      contents: write

    steps:
      - name: Checkout Changes
        uses: actions/checkout@v4
        with:
          sparse-checkout: |
            CHANGE.md
          sparse-checkout-cone-mode: false

      - name: Download Build Artifacts
        uses: actions/download-artifact@v4
        with:
          name: apk-artifact
      
      - name: Generate Changelog
        run: |
          cat CHANGE.md > CHANGE.txt
      
      - name: Release 
        uses: softprops/action-gh-release@v2
        with:
          files: |
            app-release.apk
          body_path: CHANGE.txt

Workflow был разработан при неоценимой поддержке моего уважаемого коллеги, Lead DevOps-инженера в одной из IT-компаний моего города, Алексея Алексеевича Н.

Данное руководство предназначено для пользователей с базовыми знаниями о работе в Linux.

No errors, no warnings, gentlemen and ledies!

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