Continuous Delivery for Android Using GitHub Actions

Learn how to create a continuous delivery pipeline in Android to deploy your apps to the Google Play Store. By Subhrajyoti Sen.

4.7 (7) · 1 Review

Download materials
Save for later
Share

One of the principles behind the Agile Manifesto states:

“Our highest priority is to satisfy the customer through early and continuous delivery of valuable software.”

But what does this mean in software engineering terms? Well, picture having a repository where you regularly push code. That code doesn’t directly provide value to the customer. Instead, the value comes when you use the code to build software that you can deliver to your customer.

To deliver software confidently, you need tests to ensure your changes haven’t introduced any issues. When you bring these steps together, you get continuous delivery.

Continuous delivery is the practice of:

  1. Regularly merging code.
  2. Running tests on the codebase.
  3. If those tests pass, building a release version of the software.
  4. Delivering the software to the customer, preferably in a staged manner.

In this chapter, you’ll learn how to use GitHub Actions to set up a continuous delivery pipeline that:

  1. Runs tests when you are ready to send a build.
  2. Generates a release build, if those tests pass.
  3. Pushes the build to Firebase App Distribution to deliver to your Quality Assurance (QA) team.
  4. Pushes the build to the Play Store with a rollout percentage after QA approves the changes.

You’ll do this while working with the RW Quotes app.

Note: This tutorial assumes you’re familiar with Git, Android development and releasing android apps. If these topics are new to you, read the Beginning Git, Beginning Android Development and Android App Distribution: From Zero to Google Play Store tutorials first.

Getting Started

Download the project by clicking the Download Materials button at the top or bottom of the tutorial. Open the starter project using Android Studio. Build and run and you’ll see a screen like the one below:

Screenshot of RW Quotes final UI

The app lets you add quotes from different people, then displays those quotes in a list. It also has the option to edit the quotes.

The project contains some unit and instrumentation tests too, as shown in the image below:

RW Quotes unit and instrumentation tests

For this tutorial, you won’t be making any changes to the actual application code, since the app is already finished. Instead, you’ll make the changes in an additional file that will control the continuous delivery process.

Using GitHub Actions

GitHub Actions is GitHub’s platform for automation workflows. A workflow is a sequence of jobs that can run either in series or in parallel. A job usually contains more than one step, where each step is a self-contained function. To learn more about GitHub Actions, go through the tutorial on Continuous Integration for Android.

In this tutorial, you’ll use multiple first-party as well as third-party actions. To explore the different actions available, visit the GitHub Marketplace.

Uploading the Project to GitHub

The next part of the tutorial will take place mostly on GitHub’s website. Therefore, you need to have a GitHub account and to upload the sample project to a repository under your account.

To upload your project from Android Studio, go to VCS ▸ Import into Version Control ▸ Share Project on Github:

Menu for uploading the project to github

Once you’ve set that up, you can create your first workflow.

Creating a Workflow

To add a new workflow, first, create a new directory with the path .github/workflows in the root of your project, either directly in your OS file system or by switching to the Project view in Android Studio. Then, create a file named check_and_deploy.yml in the workflows directory, as shown in the image below:

Screenshot of menu to create a new file in Android Studio

All workflows are written in YAML, which is a serialization format commonly used in configuration files. One thing to keep in mind is that that proper indentation is extremely important in the YAML format, so make sure to follow the indentation presented in the tutorial exactly for your workflows to work.

Running the Tests

There are two ways you can run tests in your projects:

  1. Use the Run tests option inside Android Studio.
  2. Run the Gradle task for the tests from the command line.

To run tests on a remote machine, you have to go with the second option.

Run the following command from the command line to run the unit tests:

./gradlew test

After the tests run, you’ll see a screen like the one below:

Unit tests passing

For the instrumentation tests, you need to either start an emulator or connect a physical device. Once you’ve done that, run the following command to run the instrumentation tests:

./gradlew connectedAndroidTest

Once all the tests run, you’ll see the following results:

Instrumentation tests passing

Now that you know how to run the tests from the command line, add the following code to check_and_deploy.yml:

## 1
name: Test and deploy

## Actions that will be executed when you push code currently none
on:
  push:

## 2
jobs:
  ## 3
  unit_tests:
    runs-on: [ubuntu-latest]
    steps:
      - uses: actions/checkout@v2

      - name: Unit tests
        run: ./gradlew test
  ## 4
  android_tests:
    runs-on: [ macos-latest ]
    steps:
      - uses: actions/checkout@v2

      - name: Instrumentation Tests
        uses: reactivecircus/android-emulator-runner@v2
        with:
          api-level: 29
          script: ./gradlew connectedAndroidTest

The code above does a few things. It:

  1. Creates a workflow named Test and deploy.
  2. Creates two parallel jobs named unit_tests and android_tests.
  3. The unit_tests job runs on an ubuntu runner, which checks out the code and runs the unit tests.
  4. The android_tests job runs on a macOS runner. This job also checks out the code, but runs the instrumentation tests instead. To do this, it uses the reactivecircus/android-emulator-runner action. The emulator can use hardware acceleration only on the macOS emulator. Therefore, this job needs to run on a macOS runner while others can run on Ubuntu runners.

Next, you’ll see how to generate a secure release build on a remote system.

Generating a Signed Release Build

Generating a release build on a remote system is quite different from doing it locally. One of the main aspects is to make sure that the signing secrets remain secret.

Creating a Keystore

To sign your release build, you first need a keystore. If you haven’t generated a keystore for your apps yet, follow the tutorial on Android App Distribution: From Zero to Google Play Store. This guides you through the process of creating a new keystore.