Русский
Русский
English
Статистика
Реклама

Настраиваем GitHub Actions для Android с последующим деплоем в PlayMarket

Привет, Хаброжители! На днях начал изучать GitHub Actions для Android. Ранее у меня была удачная попытка настройки данного функционала для проекта на Flutter, но без деплоя, для которого полно информации и гайдов как на англоязычных ресурсах, так и на русскоязычных, а вот с нативным андроидом не всё так прозаично. И решил записать основные проблемы и их решение.

Этап первый: настройка для автоматической подписи готового apk


Первая проблема с которой я столкнулся, это сделать универсальную настройку, позволяющую собирать релизные варианты как локально, так и глобально.

Я использую вариант с использование файла keystore.properties, который позволяет нам добавить ключ разработчика в папку проекта, не светя при этом паролями от него, делается это так:

apply plugin: ...def keystorePropertiesFile = rootProject.file("keystore.properties")def keystoreProperties = new Properties()keystoreProperties.load(new FileInputStream(keystorePropertiesFile))android {  ...  signingConfigs {    release {        storeFile file("../MyKey.jks")        storePassword keystoreProperties['RELEASE_STORE_PASSWORD']        keyAlias keystoreProperties['RELEASE_KEY_ALIAS']        keyPassword keystoreProperties['RELEASE_KEY_PASSWORD']    }    debug {        storeFile file('../debug.keystore')    }  }  buildTypes {    release {        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'        minifyEnabled false        signingConfig signingConfigs.release        buildConfigField "String", "PIN_ALIAS", keystoreProperties['PIN_ALIAS']        buildConfigField "String", "DB_PASS_ALIAS", keystoreProperties['DB_PASS_ALIAS']    }    debug {        minifyEnabled false        signingConfig signingConfigs.debug        buildConfigField "String", "PIN_ALIAS", keystoreProperties['PIN_ALIAS']        buildConfigField "String", "DB_PASS_ALIAS", keystoreProperties['DB_PASS_ALIAS']    }  }}dependencies {  ...}

И тут возникла проблема, как сделать так, что бы мы могли взять ключи из ${{ secrets.MY_KEY }} и при этом градл понимал, если у нас есть keystore.properties, то берём из него, если нет то берём из секретов? Решение нашлось на одном из гайдов для флаттера, где для этого они использую окружения (Кстати, здесь классный подход, чтобы не светить нашим ключём разработчика), но проблему это не решило. Перепробовав несколько вариантов с введением дополнительных файлов и т.п., остановился на самом простом: мы вводим дополнительно несколько переменных(в зависимости от нужного нам количества), и проверяем наличие файла keystore.properties:

def release_store_passworddef release_key_passworddef release_key_aliasdef pin_aliasdef db_pass_aliasdef keystoreProperties = new Properties()if (rootProject.file("keystore.properties").exists()) {    keystoreProperties.load(new FileInputStream(rootProject.file("keystore.properties")))    release_store_password = keystoreProperties['RELEASE_STORE_PASSWORD']    release_key_password = keystoreProperties['RELEASE_KEY_PASSWORD']    release_key_alias = keystoreProperties['RELEASE_KEY_ALIAS']    pin_alias = keystoreProperties['PIN_ALIAS']    db_pass_alias = keystoreProperties['DB_PASS_ALIAS']} else {    release_store_password = System.env.RELEASE_STORE_PASSWORD    release_key_password = System.env.RELEASE_KEY_PASSWORD    release_key_alias = System.env.RELEASE_KEY_ALIAS    pin_alias = System.env.PIN_ALIAS    db_pass_alias = System.env.DB_PASS_ALIAS}android {   signingConfigs {        release {            storeFile file("../my_key.jks")            storePassword = release_store_password            keyAlias = release_key_alias            keyPassword = release_key_password        }    buildType{       release {          buildConfigField "String", "PIN_ALIAS", "\"$pin_alias\"" //если вам нужно ввести некоторые           buildConfigField "String", "DB_PASS_ALIAS", "\"$db_pass_alias\"" // дополнительные данны.      }    }}

Итак, теперь наш сборщик умеет собирать и сразу подписывать наш apk.

Этап второй: версия сборки.


Тут нет ничего сверх естественного, хотелось получить какой-то, достаточно универсальный вариант, минимальной сложности. Погуглив, присмотрелся, сколько разработчиков столько и вариантов и каждый извращается как может. Мне какие-то сверх сложные подходы не нужны и я уже хотел было использовать BUILD_NUMBER, но тут я наткнулся на параметр у для GitHub actions: ${{ github.run_number }}.

${{ github.run_number }}
Уникальный номер для каждого запуска определенного рабочего процесса в хранилище. Это число начинается с 1 для первого запуска рабочего процесса и увеличивается с каждым новым запуском. Это число не изменится, если вы повторно запустите рабочий процесс. (Запуском здесь подразумевается когда вы пушите в ветку).

По этому взвесив все за и против имеем следующее решение:

def versionPropsFile = rootProject.file('version.properties')Properties versionProps = new Properties()versionProps.load(new FileInputStream(versionPropsFile))def verCode = versionProps['VERSION_CODE'].toInteger()android {  defaultConfig {    versionCode verCode    versionName "1.1.$verCode"  }}//version.properties файлVERSION_CODE=1

В рабочем процессе делаем так:

- name: Output version code        run: echo VERSION_CODE=${{ github.run_number }} > ./version.properties

Этап третий: развертывание (deploy)


На данный момент я нашел два готовых решения: Gradle Play Publisher и Upload Android release to the Play Store

Первый вариант отпал по причине: использование гаубицы при стрельбе по воробьям. По этому я выбрал второй. Ничего вроде сложного в нём нет, а тут есть подробная инструкция: Тут.

- name: Upload to PlayMarket        uses: r0adkll/upload-google-play@v1        with:          serviceAccountJsonPlainText: ${{ secrets.SERVICE_ACCOUNT_JSON }}          packageName: com.guralnya.notification_tracker          releaseFile: app/build/outputs/apk/release/notification_tracker.release.apk          track: beta          userFraction: 0.33          whatsNewDirectory: distribution/whatsnew

Но некоторые моменты у меня всё же возникли:

  • serviceAccountJson и serviceAccountJsonPlainText с первым я так и не разобрался в каком виде его нужно положить в секреты, второй же просто берём содержимое файла и кладём в наш секрет.
  • releaseFile использовал самый простой подход, когда мы берём готовый файл из папки с проектом, но вариант со звёздочкой не прокатил: notification_tracker.release.*.apk, где у меня стоит время сборки. Хотя в другом экшене, который у меня используется для загрузки файла (actions/upload-artifact@v2), такой подход работал отлично.
  • whatsNewDirectory внимательнее к языковым кодам. Если английский я взял из гугл-консоли при добавлении новой версии (en-IN), а Русский как (ru-RU), то логично предположить что все языки работают по том же принципу, но нет Украинский я не доглядел, а он там помечен как (uk), потому если не хотите лишний раз комититься и видеть красный крестик, лучше свериться с той же консолью.

Есть ситуация, когда у вас может по какой-то причине не деплоиться, это когда вы ещё не опубликовали приложение (встречать не приходилось, но в одной статье было описано). Так что начинайте с того, что сначала опубликуйте приложение в ручную если вы ещё этого не сделали.

Итоговый рабочий процесс будет оптимизироваться и улучшаться вместе с файлом градла


Android CI.yaml:

name: Android_CIon:  push:    branches:      - beta_releasejobs:  build:    runs-on: ubuntu-latest    name: Build release-apk and deploy to PlayMarket    steps:      - uses: actions/checkout@v2      - name: set up JDK 1.8        uses: actions/setup-java@v1        with:          java-version: 1.8      # Without NDK not compile and not normal error message. NDK is required      - name: Install NDK        run: echo "y" | sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install "ndk;20.0.5594570" --sdk_root=${ANDROID_SDK_ROOT}      # Some times is have problems with permissions for ./gradle file. Then uncommit it code      #    - name: Make gradlew executable      #      run: chmod +x ./gradlew      - name: Output version code        run: echo VERSION_CODE=${{ github.run_number }} > ./version.properties      - name: Build with Gradle        run: ./gradlew assemble        env:          RELEASE_STORE_PASSWORD: ${{ secrets.RELEASE_STORE_PASSWORD }}          RELEASE_KEY_PASSWORD: ${{ secrets.RELEASE_KEY_PASSWORD }}          RELEASE_KEY_ALIAS: ${{ secrets.RELEASE_KEY_ALIAS }}          PIN_ALIAS: ${{ secrets.PIN_ALIAS }}          DB_PASS_ALIAS: ${{ secrets.DB_PASS_ALIAS }}      - name: Upload APK        uses: actions/upload-artifact@v2        with:          name: notification_tracker          path: app/build/outputs/apk/release/notification_tracker.release.apk      - name: Upload to PlayMarket        uses: r0adkll/upload-google-play@v1        with:          serviceAccountJsonPlainText: ${{ secrets.SERVICE_ACCOUNT_JSON }}          packageName: com.guralnya.notification_tracker          releaseFile: app/build/outputs/apk/release/notification_tracker.release.apk          track: beta          userFraction: 0.33          whatsNewDirectory: distribution/whatsnew

Важный момент


необходимость NDK. Без установленного NDK у вас не соберётся проект, по крайней мере релизный. Можно долго гадать в чём проблема и искать решение, так как нормального сообщения ошибки нет. Иногда можно отловить вот это: Task :app:stripDebugDebugSymbols FAILED. После гуглинга и экспериментов, оказалось что нет NDK. Делаем так:

- name: Install NDK        run: echo "y" | sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install "ndk;20.0.5594570" --sdk_root=${ANDROID_SDK_ROOT}

P.S. Для Gradle использовал подсветку кода от Kotlin. Для YAML от JSON. Конечно немного не то, но лучше мне найти не удалось, если есть лучшие варианты, сообщите мне пожалуйста и я исправлю.

P.S.S. Может быть у кого есть лучшее решение или предложения по улучшения, напишите их в комментариях, так как по первому этапу вопрос провисел на StackOverflow больше 10-ти дней, но ответа так и не последовало.
Источник: habr.com
К списку статей
Опубликовано: 15.06.2020 12:08:41
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Github

Gradle

Разработка под android

Github actions

Android

Категории

Последние комментарии

© 2006-2020, personeltest.ru