29/11/2024

Tech Guru

Trusted Source Technology

Android CI/CD pipeline with Github Actions: Demystifying Github Actions | by Ankur Anurag

Android CI/CD pipeline with Github Actions: Demystifying Github Actions | by Ankur Anurag

Android build generation and deployment have always been a pain point for Android developers. Hundreds of dev hours are wasted while gazing at the computer screen, waiting for our build to complete. That’s where CI/CD comes to our rescue. There are various tools to build CI/CD pipelines like Jenkins, CircleCI, Bitrise, TravisCI etc. Github Actions is a new addition to this list. It makes the whole process of building a pipeline very easy and is completely free for public repositories. You can find the pricing here.

In this article, I would demonstrate how to use Github Actions, to automate your android build and deployment process.

One can create the workflow file by going to Actions Tab > Setup workflow yourself.

This will take you to the YAML editor, where we will be defining our workflow according to our need. A basic workflow structure looks something like this:

# Name of your workflow
name: Android Build and Deployment Pipeline
# Define on which Github event, workflow will trigger
on:
push:
branches: [ master ]
pull_request:
branches: [ main ]
jobs:
job1:
name: Job 1
runs-on: ubuntu-latest
steps:
- name: 'Check Inputs'
run: echo 'Job 1'

Note that the YAML file is indentation sensitive

  1. Add a trigger for Github events
on:
push:
branches: [ master ]
pull_request:
branches: [ main ]

You can also add triggers for merging, pull request etc

2. Add support for manual trigger(if needed)

workflow_dispatch:
inputs:
app_id:
description: 'The application Id/package name'
required: true
branch:
description: 'The branch from which you want the build'
required: true
default: 'master'

3. Checkout code

Default branch:

- name: Checkout the code to specific branch
uses: actions/checkout@v2

Specific branch(branch name from Step 2 inputs, can be hardcoded too)

- name: Checkout the code to specific branch
uses: actions/checkout@v2
with:
ref: $ github.event.inputs.branch

4. Setup JDK

We have a predefined action in Github Actions Marketplace. It handles the task of downloading the JDK, unzipping it, setting the JAVA_HOME path etc.

- name: Set up JDK
uses: actions/setup-java@v2
with:
distribution: 'zulu'
java-version: '11'

5. Setup Android SDK

We have an action for this step also. Downloading SDK, unzipping, env variables, accepting licences everything is handled.

- name: Setup Android SDK
uses: android-actions/setup-android@v2

6. Gradle Caching(optional)

For this, we will use this action .

- uses: actions/cache@v2
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: $ runner.os -gradle-$ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties')
restore-keys: |
$ runner.os -gradle-

7. Make Gradle Executable

We will use bash command for this.

- name: Make gradlew executable
run: chmod +x ./gradlew

8. Generate the Artifact

For Bundle:

- name: Generate app bundle.
run: ./gradlew app:bundleRelease --stacktrace

For APK:

- name: Generate app APK.
run: ./gradlew assembleRelease --stacktrace

9. Sign the Artifact

If you have defined signing config in gradle file, then this step is not needed.

To sign the APK/Bundle you will need KeyStore Password, Alias, Key Password. You can define these as global variables in Github on organisation or repository level. These secrets are encrypted and safe to use in Github Actions. To create secrets you can visit this link

- name: Sign app bundle
run: |
jarsigner -keystore app/*.jks \
-storepass $ secrets.KEY_STORE_PASSWORD -keypass $ secrets.KEY_PASSWORD \
app/build/outputs/bundle/release/app-release.aab $ secrets.ALIAS

There is an action for the same. We can use it too.

- name: Sign app bundle
uses: r0adkll/sign-android-release@v1
id: sign_app
with:
releaseDirectory: app/build/outputs/bundle/release
signingKeyBase64: $ secrets.SIGNING_KEY
alias: $ secrets.ALIAS
keyStorePassword: $ secrets.KEY_STORE_PASSWORD
keyPassword: $ secrets.KEY_PASSWORD
env:
# override default build-tools version (29.0.3) -- optional
BUILD_TOOLS_VERSION: "30.0.2"

10. Upload the artifact to Github(optional)

Incase if you want to access the generated bundle/APK from previous steps, you can upload it to Github. It will be available to download inside the workflow.

- name: Upload Bundle
uses: actions/upload-artifact@v2
with:
name: signed_app_bundle
path: app/build/outputs/bundle/release/app-release.aab

11. Create release to Playstore

We will use a predefined action for this purpose.

For making a release to PlayStore, we need a service account json file, which is created from the playstore console. The steps involved are out of scope for this article. You can follow this link for creating the service account json file.

steps:
- name: Create service_account.json
run: echo '$ secrets.SERVICE_ACCOUNT_JSON ' > service_account.json
- name: Deploy to Play Store
uses: r0adkll/[email protected]
with:
serviceAccountJson: service_account.json
packageName: $ github.event.inputs.app_id
releaseFiles: app/build/outputs/bundle/release/*.aab
track: internal
whatsNewDirectory: whatsnew/
mappingFile: app/build/outputs/mapping/release/mapping.txt
inAppUpdatePriority: 5