Skip to content

Build Android App

Build Android App #26

Workflow file for this run

name: Build Android App
on:
workflow_dispatch:
# Inputs the workflow accepts.
inputs:
tar-url:
description: 'URL for Kolibri tar file'
required: true
signed:
description: 'Should this be signed with the development key? (mutually exclusive with release)'
required: false
type: boolean
default: false
release:
description: 'Is this a release asset?'
required: false
type: boolean
default: false
workflow_call:
inputs:
tar-file-name:
required: false
type: string
tar-url:
required: false
type: string
ref:
description: 'A ref for this workflow to check out its own repo'
required: false
type: string
signed:
description: 'Should this be signed with the development key? (mutually exclusive with release)'
required: false
type: boolean
default: false
release:
description: 'Is this a release asset?'
required: false
type: boolean
default: false
secrets:
# A base64-encoded keystore that contains the key used to sign the app
# for development builds.
KOLIBRI_ANDROID_APP_DEVELOPER_KEYSTORE:
required: false
# The password for the keystore.
KOLIBRI_ANDROID_APP_DEVELOPER_KEYSTORE_PASSWORD:
required: false
# The password for the key in the keystore.
KOLIBRI_ANDROID_APP_DEVELOPER_KEYALIAS_PASSWORD:
required: false
# A base64-encoded keystore that contains the key used to sign the app
# for production builds.
KOLIBRI_ANDROID_APP_PRODUCTION_KEYSTORE:
required: false
# The password for the keystore.
KOLIBRI_ANDROID_APP_PRODUCTION_KEYSTORE_PASSWORD:
required: false
# The password for the key in the keystore.
KOLIBRI_ANDROID_APP_PRODUCTION_KEYALIAS_PASSWORD:
required: false
KOLIBRI_ANDROID_PLAY_STORE_API_SERVICE_ACCOUNT_JSON:
required: false
outputs:
apk-file-name:
description: "APK file name"
value: ${{ jobs.build_apk.outputs.apk-file-name }}
version-code:
description: "Version code"
value: ${{ jobs.build_apk.outputs.version-code }}
jobs:
build_apk:
runs-on: ubuntu-latest
env:
SERVICE_ACCOUNT_JSON: '${{ secrets.KOLIBRI_ANDROID_PLAY_STORE_API_SERVICE_ACCOUNT_JSON }}'
outputs:
apk-file-name: ${{ steps.get-apk-filename.outputs.apk-file-name }}
version-code: ${{ steps.get-version-code.outputs.version-code}}
steps:
- name: Validate release flag inputs
if: ${{ (inputs.release == true || github.event.inputs.release == 'true') && (inputs.signed == true || github.event.inputs.signed == 'true') }}
run: |
echo "Cannot build a release and signed development APK at the same time."
exit 1
- name: Validate tar reference inputs
if: ${{ !github.event.inputs.tar-file-name && ( (inputs.tar-file-name && inputs.tar-url) || (!inputs.tar-file-name && !inputs.tar-url) ) }}
run: |
echo "Must specify only one reference for the tar file to build the APK with."
exit 1
- uses: actions/checkout@v4
if: ${{ !inputs.ref }}
- uses: actions/checkout@v4
if: ${{ inputs.ref }}
with:
repository: learningequality/kolibri-installer-android
ref: ${{ inputs.ref }}
- name: Get SHA of current commit
id: get-commit
# Note that we do this, so that we get the same commit regardless
# of whether this is being run from the local repository with workflow_dispatch
# or from another repository with workflow_call.
run: echo "sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
- name: Set up Python 3.9
uses: actions/setup-python@v5
with:
python-version: 3.9
- name: Install Apt Dependencies
# Dependencies installed here are taken from the buildozer Dockerfile:
# https://github.com/kivy/buildozer/blob/master/Dockerfile#L45
# with items that are already installed on the Ubuntu 22.04 image removed:
# https://github.com/actions/runner-images/blob/main/images/linux/Ubuntu2204-Readme.md#installed-apt-packages
run: |
sudo apt update -qq > /dev/null \
&& DEBIAN_FRONTEND=noninteractive sudo apt install -qq --yes --no-install-recommends \
build-essential \
ccache \
cmake \
gettext \
libffi-dev \
libltdl-dev \
patch \
zlib1g-dev
- uses: actions/cache@v4
with:
# This is where python for android puts its intermediary build
# files - we cache this to improve build performance, but be
# aggressive in clearing the cache whenever any file changes
# in the repository, especially as we commit files to this folder
# too, so we don't want the cache to override these files.
# We achieve this by just caching on the currently checked out commit.
# Every time we update this repository, this commit will change,
# but repeated workflow calls for this commit will use the cache.
path: ./python-for-android
key: ${{ runner.os }}-python-for-android-${{ steps.get-commit.outputs.sha }}
- uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Download the tarfile from URL for workflow_dispatch
if: ${{ github.event.inputs.tar-url }}
run: make get-tar tar=${{ github.event.inputs.tar-url }}
- name: Download the tarfile from URL for workflow_call
if: ${{ inputs.tar-url }}
run: make get-tar tar=${{ inputs.tar-url }}
- name: Download the tarfile from artifacts
if: ${{ inputs.tar-file-name }}
uses: actions/download-artifact@v4
with:
name: ${{ inputs.tar-file-name }}
path: tar
- name: Install dependencies
run: pip install -r requirements.txt
- name: Ensure that Android SDK dependencies are installed
run: make setup
- name: Build the aab
if: ${{ inputs.release == true || github.event.inputs.release == 'true' }}
env:
RELEASE_KEYALIAS: LE_RELEASE_KEY
RELEASE_KEYSTORE_PASSWD: ${{ secrets.KOLIBRI_ANDROID_APP_PRODUCTION_KEYSTORE_PASSWORD }}
RELEASE_KEYALIAS_PASSWD: ${{ secrets.KOLIBRI_ANDROID_APP_PRODUCTION_KEYALIAS_PASSWORD }}
run: |
echo -n "${{ secrets.KOLIBRI_ANDROID_APP_PRODUCTION_KEYSTORE }}" | base64 --decode > production.keystore
export RELEASE_KEYSTORE=$(realpath production.keystore)
make kolibri.aab
- name: Get AAB filename
if: ${{ inputs.release == true || github.event.inputs.release == 'true' }}
id: get-aab-filename
run: echo "aab-file-name=$(ls dist | grep .aab | cat)" >> $GITHUB_OUTPUT
- uses: actions/upload-artifact@v4
if: ${{ inputs.release == true || github.event.inputs.release == 'true' }}
with:
name: ${{ steps.get-aab-filename.outputs.aab-file-name }}
path: dist/${{ steps.get-aab-filename.outputs.aab-file-name }}
- name: Upload the AAB to the Play Store and download the signed Universal APK
if: ${{ inputs.release == true || github.event.inputs.release == 'true' }}
run: make playstore-upload
- name: Build the apk
if: ${{ inputs.signed == true || github.event.inputs.signed == 'true' }}
env:
RELEASE_KEYALIAS: LE_DEV_KEY
RELEASE_KEYSTORE_PASSWD: ${{ secrets.KOLIBRI_ANDROID_APP_DEVELOPER_KEYSTORE_PASSWORD }}
RELEASE_KEYALIAS_PASSWD: ${{ secrets.KOLIBRI_ANDROID_APP_DEVELOPER_KEYALIAS_PASSWORD }}
run: |
echo -n "${{ secrets.KOLIBRI_ANDROID_APP_DEVELOPER_KEYSTORE }}" | base64 --decode > development.keystore
export RELEASE_KEYSTORE=$(realpath development.keystore)
make kolibri.apk
- name: Build the debug apk
if: ${{ inputs.signed != true && github.event.inputs.signed != 'true' && inputs.release != true && github.event.inputs.release != 'true'}}
run: make kolibri.apk.unsigned
- name: Get APK filename
id: get-apk-filename
run: echo "apk-file-name=$(ls dist | grep .apk | cat)" >> $GITHUB_OUTPUT
- name: Get versionCode
id: get-version-code
run: echo "version-code=$(cat .version-code)" >> $GITHUB_OUTPUT
- uses: actions/upload-artifact@v4
with:
name: ${{ steps.get-apk-filename.outputs.apk-file-name }}
path: dist/${{ steps.get-apk-filename.outputs.apk-file-name }}