Автоматизация публикации приложения в Google Play при помощи Jenkins
Для этого нам понадобится
-
Действующий account Google Play Developer
-
Сервер Linux с предустановленным Docker, в моём случае это Ubuntu 16.04
-
Установленный Android SDK
-
Jenkins – в данном случае развернём его при помощи Docker
-
Gitea – Удобная служба для собственного Git-репозитория (это не обязательно можно использовать и GItHub) её мы подымем также на базе Docker контейнера
Настройка Google Play Account
Давайте предположим что вы уже действующий разработчик и осуществляли публикацию своих приложений в ручном режиме, что даёт основание полагать что вам известны основные моменты процесса и их озвучивать не стоит, коснёмся лишь того что нам понадобится для автоматического развёртывания
-
Авторизуйтесь в Google Cloud Platform, если еще не создан проект то создаём его
-
В разделе IAM и администрирование – Сервисные аккаунты жмём Создать сервисный аккаунт
-
После заполнения соответствующих полей он будет создан и появится в списке, жмём на три точки с права и выбираем создать ключ, выбираем JSON, сохраните его он нам понадобится для настройки Jenkins
-
Авторизуйтесь в Gooogle Play Developer Console
-
В разделе Пользователи и разрешения нажимаем пригласить пользователя сервисного аккаунта по сгенерированному email , выставляем ему роль Релиз менеджер (при необходимости можете настроить права этого пользователя более детально)
-
Я предполагаю что Сертификат для ключа подписи приложения, и Сертификат ключа загрузки у вас уже настроен и это не требует пояснений.
Установка Android SDK
# Install latest JDK
sudo apt install default-jdk
sudo apt install android-sdk
Добавьте Android SDK в свой PATH, откройте ~/.bashrc
в редакторе и скопируйте следующие строки
# Export the Android SDK path
export ANDROID_HOME=$HOME/android-sdk
export PATH=$PATH:$ANDROID_HOME/tools/bin
export PATH=$PATH:$ANDROID_HOME/platform-tools
# Fixes sdkmanager error with java versions higher than java 8
export JAVA_OPTS='-XX:+IgnoreUnrecognizedVMOptions --add-modules java.se.ee'
Для проверки запустите
source ~/.bashrc
Для того что бы просмотреть все доступные инструменты сборки выполните команду
sdkmanager --list
По аналогии с выполните установку интересующих вас версий инструментов для нужных платформ
sdkmanager "platform-tools" "platforms;android-28"
На этом установка Android SDK может считаться завершённой, и в дальнейшем нам понадобится лишь путь к установленным инструментам, в моём случае это выглядит как то так
Установка Gitea
Этот шаг является опциональным и совсем не обязательным если вы предпочитаете использовать git репозитарии такие как GitHub и им подобные и его можно пропустить, это малой степени повлияет на конечный результат. (На базе gitea в дальнейшем будет обсуждаться тема создания Telegram Bot`a для оповещения о публикациях)
Подробно по установке и настройке написано на оф сайте https://docs.gitea.io/en-us/install-with-docker/
По факту установка сводится к выполнению 2х действий
1) Перейдите на официальный репозитарий Gitea , на Docker HUB и скопируйте то что там написано в предварительно созданный файл
version: '2'
services:
web:
image: gitea/gitea:1.12.4
volumes:
- ./data:/data
ports:
- "3000:3000"
- "22:22"
depends_on:
- db
restart: always
db:
image: mariadb:10
restart: always
environment:
- MYSQL_ROOT_PASSWORD=changeme
- MYSQL_DATABASE=gitea
- MYSQL_USER=gitea
- MYSQL_PASSWORD=changeme
volumes:
- ./db/:/var/lib/mysql
2) Сохраните и запустите команду docker-compose you_filename
3) Gitea установлена и доступна по URL http://you_IP:3000/
4) Создайте пользователя, репозитарий, сделайте PUSH исходного кода вашего проекта, и в моём случае для упрощения процесса публикации приложения все необходимые ключи для его подписи и деплоя я храню в месте с исходным кодом в системе контроля версий (да знаю это не совсем верно и вы вольны делать так как считаете нужным, к примеру создать отдельный volume для ключей и пробрасывать их jenkins для дальнейшего их использования gradle при подписании приложения, описание этого лишь раздует статью и потому не будет рассматриваться)
Предварительная настройка проекта
Для подписания нашего apk файла в автоматическом режиме на стороне сервера, нам нужен файл нашего keystore и правильно настроенный скрипт gradle , для этого добавим в него несколько секций
// Load keystore
def keystorePropertiesFile = rootProject.file("keystore.properties")
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
// GenerateNameVersion
def getVersionNameTimestamp() {
return new Date().format('yy.MM.ddHHmm')
}
// GenerateVersionCode
def getVersionCodeTimestamp() {
def date = new Date()
def formattedDate = date.format('yyMMddHHmm')
def code = formattedDate.toInteger()
println sprintf("VersionCode: %d", code)
return code
}
......
android {
signingConfigs {
config {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
}
}
......
defaultConfig {
versionCode getVersionCodeTimestamp()
versionName "${getVersionNameTimestamp()}"
Содержимое файла keystore.properties
storePassword=you_password_keystore
keyPassword=you_password_key
keyAlias=you_key_name
storeFile=path_to_keystore_file
-
Я храню как файл с keystore.properties так и сам keystore в системе контроля версий, что не совсем правильно и не безопасно при публикации исходного кода в открытом виде к примеру на GitHub, по этому я не рекомендую использовать данный подход если у вас OpenSource проект , храните и подтягивайте их из отдельной папки.
-
Для публикации в Google Play требуется уникальная версия сборки, и я генерирую её скриптом Gradle на основании текущей даты и времени, и как вы понимаете это исключает использование каких либо вразумительных номеров версий и если вам это важно , то вам придётся придумать некий другой механизм автоматизации версионирования, я же остановился на этом варианте – потому как хотел что бы deploy происходил по нажатию одной лишь кнопки (PUSH)
Установка Jenkins
Его мы развернём используя Docker , я применяю уже настроенный образ с нужными мне инструментами из своего репозитария, вы же вольны использовать официальный, принципиально ни чего не измениться
docker run -it -d -v jenkins_home:/var/jenkins_home -v /usr/lib/android-sdk:/usr/lib/android-sdk -p 8080:8080 -p 50000:50000 --env JENKINS_OPTS="--prefix=/jenkins" --restart always leganas/ls_repository:jenkins
пробрасываем в качестве volumes в в наш контейнер папку с установленным Android SDK
Теперь он запущен и доступен по адресу http://you_IP:8080/jenkins/
После не хитрых манипуляций по заданию пароля Jenkins готов к работе, и теперь нам предстоит его настроить
1) Для начала нам нужно настроить окружение , заходим System Configuration – Глобальные настройки , и добавляем Environment variables (возможно ваши пути будут отличатся)
2) В разделе Настройки – Конфигурация глобальных инструментов проверяем настройки Git и Gradle (по факту обычно там всё уже настроено)
3) Заходим Настройки – Управление пользователями , выбираем пользователя и его настройки, ищем строку API Token , создаём новый и сохраняем его , он нам понадобится.
4) В разделе управления плагинами проверяем и если нужно устанавливаем плагины Git, Git client, Google OAuth Credentials plugin, Google Play Android Publisher
5) Заходим Настройки – Manage Credentials Configure credentials -Store – Jenkins – Global credentials (unrestricted)- и создаём там 2 ключа доступа |
-
для доступа к Git репозитарию
в моём случае т.к. я использую Gitea я создаю обычную пару login/password , для GitHub есть специальный плагин и инструмент для авторизации
-
для публикации приложения в Google Play Market
создаём ключ используя JSON файл который создали в первом разделе данной инструкции
6) Теперь создайте проект вашего приложения в Jenkins и настройте его
-
Управление исходным кодом – установите Git , укажите Repository URL и Credentials (которые создали на прошлом этапе)
-
Триггеры сборки – выставите Trigger builds remotely (e.g., from scripts), в поле ввода введите любой случайный текст (он нам понадобится для удалённой активизации процесса сборки) при помощи GIt huck
-
Добавьте шаг сборки Invoke Gradle script , и После сборочные операции – публикацию
Обратите внимание на поле Release traack , оно указывает то как будет опубликовано ваше приложение , в моём случае это “Внутреннее тестирование”
7) Запустите проект в ручную использую Web интерфейс Jenkins и посмотрите на результат в истории сборок – Вывод консоли Если вы всё сделали верно то ваше приложение должно быть подтянуто из Git репозитария до актуальной версии ветки /master , собрано , подписано и опубликовано на Google Play.
Автоматизация запуска сборки
Если мы всё сделали правильно и проект удачно был опубликован на Google Play , можно перейти к настройке его автоматического deploy по Git событию PUSH в /master ветку
1) Если вы используете Gitea как я то зайдите в репозитарий вашего проекта – Настройки – Git хуки, и в post-receive нажмите редактировать, и добавьте нечто этого рода
#!/bin/bash
while read oldrev newrev refname
do
branch=$(git rev-parse --symbolic --abbrev-ref $refname)
if [ "master" = "$branch" ]; then
curl --user you_user_name:you_user_token http://you_url_jenkins/job/you_project/build?token=you_tocken_build
fi
done
-
you_user_name – Имя пользователя от лица которого jenkins будет производить сборку
-
you_user_token – Токен который был сгенерирован в настройках пользователя
-
you_url_jenkins и вообще весь путь до хука можно посмотреть на странице настройки проекта Jenkins и будет выглядеть он примерно так :

После проведения такого рода манипуляций сборка проекта Jenkins будет начинаться автоматически после PUSH события в master вашего репозитария.
PS. Если же вы используете для хранения вашего кода другую Git систему то этот же код вы можете поместить руками в .githookspost-update
Заключение
В случае положительного фидбэка от статьи, в следующей части я расскажу как написать Telegram бота для оповещения ваших тестировщиков о наличии обновления приложения на Google Play.
Надеюсь эта информация была полезна и как то облегчит вам жизнь по настройки автоматической публикации.