Настройка Jenkins для сборки Android-проекта

Основано на статьях: How To Build Android Apps with Jenkins и Continuous Integration для Android с использованием Jenkins + Gradle.

Для примера возьмем стандартный «Hello World», который генерирует Android Studio. В этом проекте есть также и простой unit-тест.

Это руководство подразумевает, что сам Jenkins уже установлен и работает.

Идем на страницу скачивания Android SDK и качаем .tgz архив для Linux.
Screenshot from 2016-05-20 23-47-14
Затем идем на страницу скачивания Gradle и скачиваем «Binary only distribution».
Screenshot from 2016-05-20 23-54-38
Распаковываем скаченные архивы:

tar xzf android-sdk_r24.4.1-linux.tgz
unzip gradle-2.13-bin.zip

Создаем файлы /etc/profile.d/android.sh и /etc/profile.d/gradle.sh с содержимым:

export ANDROID_HOME="/home/imposibrus/android-sdk-linux"
export PATH="$PATH:$ANDROID_HOME/tools:$ANDROID_HOME/platform-tools"
export GRADLE_HOME="/home/imposibrus/gradle-2.13"
export PATH="$PATH:$GRADLE_HOME/bin"

Где /home/imposibrus/android-sdk-linux и /home/imposibrus/gradle-2.13 пути к распакованным ранее архивам.
Теперь нужно пере-логинится или выполнить:

source /etc/profile

Обновляем Android-SDK:

android update sdk -u --filter platform-tools,android-23

Замените android-23 на нужную версию SDK.
Теперь устанавливаем нужные Build tools. выводим список всех доступный пакетов:

android list sdk --all

Ищем в выводе «Android SDK Build-tools, version xx.xx.xx», где «xx.xx.xx» — самая последняя доступная версия, запоминаем номер этого пакета (порядковый номер слева). Устанавливаем пакет:

android update sdk -u --all --filter 

Где — номер, который вы запомнили.
Повторяем тоже самое для Android Support Repository и Android Support Library.

Если используется 64-битная версия ОС, то устанавливаем пакеты:

sudo apt-get install lib32stdc++6 lib32z1

Настраиваем Jenkins

Устанавливаем плагины:

  • Gradle Plugin
  • Git Plugin (если используем Git)
  • Android Emulator Plugin (если будем использовать эмулятор)

Создаем проект «свободной конфигурации» и создаем шаг сборки:
Screenshot from 2016-05-21 00-16-37
И создаем 2 шага «после сборки»:
Screenshot from 2016-05-21 00-17-55

Пробуем запустить сборку. Если все ОК — поздравляю.

Автоматическая подпись .apk-файлов после сборки

Настройка Android Studio:

  • Добавляем в `app/build.gradle` в секцию `android` следующее:
    signingConfigs {
      ciRelease {
        storeFile file(KEYSTORE)
        storePassword System.getenv("KEYSTORE_PASSWORD")
        keyAlias System.getenv("KEY_ALIAS")
        keyPassword System.getenv("KEY_PASSWORD")
      }
    }

    А в `buildTypes` внутри секции `android` добавляем:

    ciRelease {
      signingConfig signingConfigs.ciRelease
    }
  • В `gradle.properties` в корне проекта добавляем строчку `KEYSTORE=release.keystore`
  • Генерируем `keystore`:
    keytool -genkey -v -alias appAlias -keyalg RSA -keysize 2048 -keystore release.keystore -validity 10000

    Где `appAlias` заменяем на свой.

Настройка Jenkins:

  • Копируем на сервер с Jenkins сгенерированный ранее файл `release.keystore`
  • Создаем на сервере с Jenkins папку, где будут храниться переменные окружения и файл `release.keystore`. Перемещаем в нее файл `release.keystore` и создаем в ней файл `environment.properties` с содержимым:
    ORG_GRADLE_PROJECT_KEYSTORE=/path/to/createdFolder/release.keystore
    KEYSTORE_PASSWORD=pass
    KEY_ALIAS=appAlias
    KEY_PASSWORD=pass

    Где `/path/to/createdFolder` — путь к созданной ранее папке. Остальные значения понятны, их нужно заменить на свои.

  • Устанавливаем плагин EnvInject
  • В настройка Jenkins ставим галочку «Prepare jobs environment»
  • В настройках проекта в пункте «Среда сборки» ставим галочку «Inject environment variables to the build process» и в поле ввода «Properties File Path» указываем полный путь к созданному ранее `environment.properties`

Запускаем сборку. В итоге в артефактах сборки должен появиться еще один файл — app-ciRelease.apk.

Включаем красивые графики ошибок, найденных с помощью `gradle lint`

  • Устанавливаем плагин Android Lint
  • Добавляем в «Шаги после сборки» «Publish Android Lint results». По-умолчанию он ищет файлы по маске «**/build/test-results/*/*.xml»

Варианты ошибок или что может пойти не так

Если при сборке возникает ошибка

[Gradle] - Launching build.
[workspace] $ gradle clean build
FATAL: command execution failed
java.io.IOException: Cannot run program "gradle" (in directory "/var/lib/jenkins/jobs/android-test/workspace"): error=2, No such file or directory

То, нужно проверить «Переменные окружения» в разделе «Системной информации» в Настройках Jenkins.
Screenshot from 2016-05-21 00-23-19
Тут должна быть переменная «GRADLE_HOME», указывающая в папку с разархивированным Gradle и в переменной «PATH» должен быть путь к папке «bin» внутри «GRADLE_HOME». Если их нет, можно попробовать перезапустить Jenkins и сервер.

Если возникает ошибка в стиле gradle Unsupported major.minor version 52.0, то, скорее всего, версия Java, установленная на сервере, не совпадает с версией, необходимой для сборки проекта. В случае версии 52.0 скорее всего на сервере установлена Java 7, а необходима Java 8. Чтобы установить Java 8 и установить ее по-умолчанию:

sudo add-apt-repository ppa:webupd8team/java -y
sudo apt-get update
sudo apt-get install oracle-java8-installer
sudo apt-get install oracle-java8-set-default

После этого нужно перезапустить Jenkins и проверить вывод «Переменные окружения» в разделе «Системной информации» в Настройках. «JAVA_HOME» должна вести к Java 8.