Continuous Integration for Android

Learn how to use Continuous Integration for Android to be sure you have fully-verified and battle-tested code on the master branch. By Prashant Barahi.

4.8 (11) · 1 Review

Download materials
Save for later
Share
You are currently viewing page 2 of 4 of this article. Click here to view the first page.

GitHub Actions

GitHub recently started providing a workflow automation feature named GitHub Actions. You’ll find it under the Actions tab of your repository.

You’ll require a GitHub account to be able to use GitHub Actions. Open GitHub and sign in to your account.

Then create a new repository – name it SimpleCalculator and follow the instructions provided by GitHub to push the starter project to the newly created GitHub repository.

GitHub Instructions

Great! You have your GitHub repository ready.

There should be several tabs at the top of your repo, the Actions tab is where the progress of workflow for the current repository is displayed. If you click on it you will see that it’s empty right now as you haven’t defined any workflows yet. You’ll learn to do so in the upcoming sections.

But before you can dive into using GitHub Actions, here are some important terms you should know:

For example, you might have a rule that says: Before running a job to generate an APK file, first run the job that runs test cases.

Unit tests and instrumentation tests can run in parallel.

  • Events are specific activities that trigger the workflow. Define them using the on key.
  • Jobs are a set of steps that execute on a fresh instance of a virtual environment. You can have multiple jobs and run them sequentially or in parallel by defining their dependency rules.

    For example, you might have a rule that says: Before running a job to generate an APK file, first run the job that runs test cases.

    Unit tests and instrumentation tests can run in parallel.

  • Runners are machines that execute jobs defined in the workflow file. GitHub hosts Linux, Windows and macOS runners with commonly-used software pre-installed, but you can create custom runners as well. Basically, these are equivalent to the containers or virtual machines mentioned in the section above.
  • Actions are the smallest portable building blocks of a workflow, which you include as a step. The popular one is actions/checkout@v2, which you use to check out the current repository into the runner’s file system. Use actions/setup-java@v1 to set up a specified version of Java in the runner.
  • Artifacts are files like APKs, screenshots, test reports, logs and so on, which the workflow generates. You can upload and download artifacts to the current workflow using actions/upload-artifact@v2 and actions/download-artifact@v2 respectively.

These terms should be enough to get you through this tutorial. If you’d like to learn more important concepts, visit the GitHub Actions official documentation.

Understanding the GitHub Actions Workflow

As mentioned earlier, you’re limited to CLI when working with any automated tools — otherwise, they wouldn’t be “automated”.

In GitHub Actions, you specify these CLI commands using a YAML file. YAML is a human-friendly data serialization language like JSON, but cleaner, more readable and more expressive.

Here’s an example of a GitHub Actions workflow configuration file:

# 1
name: Simple Workflow Example
# 2
on: [push]

# 3
jobs:
  build:
    # 4
    name: Greet
    # 5
    runs-on: ubuntu-latest
    # 6
    steps:
      - name: Hello world step
        run: echo Hello, World!

  time:
    name: Print date
    # 7
    needs: 
     - build
    runs-on: ubuntu-latest
    steps:
     - run: echo "It is $(date)"

So, what does this YAML snippet do? Let’s go over this step by step.

  1. Here you give Simple Workflow Example as a name to the workflow using the name key.
  2. Using the on key, list all the events that will trigger the workflow. Current workflow is triggered only on push events i.e. whenever you push the changes to GitHub repository.
  3. Define jobs using the jobs key. build and time are the two jobs in this workflow.
  4. Inside a job, give it a name using the name key.
  5. Define the runners on which the current job will be executed on. The greet and the time jobs both run in different instance of ubuntu-latest runner.
  6. In previous section, you learned that commands are only way to instruct the runners what they need to do. These are defined in steps key using the run key. Optionally, you can use name key to give a name or a description to the step.
  7. The needs key specifies that the time job will run only after the build job completes. By default, the independent jobs run in parallel to each other.

Create a directory .github in the root of the Git repository. Inside it, create another directory called workflows. This is where all the GitHub Actions configuration files go.

Now, save the YAML file mentioned above as simple-workflow.yaml and put it inside .github/workflows and add, commit, then push it to GitHub. GitHub Actions will then start this workflow. Go to GitHub and navigate to current project’s Actions tab to see the workflow in action.

Simple Workflow Example executing in GitHub Actions

As you can see, the jobs both executed successfully. Click on one of the jobs to see the logs of its execution. Take your time to understand how workflows, jobs and steps are laid out by GitHub Actions.

Simple Workflow Example's logs

Setting up GitHub Actions for Android

As mentioned in above section, GitHub Actions requires that you must have the workflow YAML files in .github/workflows. You can have multiple workflow files that are triggered by events defined in those files.

For Android development, you’ll need to set up a JDK in the runner, then check out your source code in the runner’s file system. As for Gradle, Android Studio projects, by default, has a Gradle wrapper shell script gradlew and a Windows batch script gradlew.bat – which can be invoked using ./gradlew and ./gradlew.bat respectively.

Next, you’ll see how to design the workflows for your project.

Defining Workflows and Jobs

To define a workflow, start by creating android-workflow.yaml inside .github/workflows. Add the following code to the file:

name: CI Workflow
on: [push]

Here, you name the workflow CI Workflow and make it trigger when a user pushes a commit to this repository.

Next, you’ll define the jobs you need in the current workflow. Remember that the runner’s file system doesn’t have the code yet. So, you need to check out the code from the current repository and set up the Java environment in the runner. You’ll use actions to accomplish this. Recall that the actions are written as a part of job’s steps. After the on key, add the following lines:

jobs:
  build-and-test:
    name: Build and run tests
    runs-on: ubuntu-latest
    steps:
      - name: Checkout current repository in ubuntu's file system 
        uses: actions/checkout@v1
      - name: Setup JDK 1.8
        uses: actions/setup-java@v1
        with:
          java-version: 1.8
      - name: Print contents in current directory
        run: ls -la

Here you’ve used actions/checkout@v1 and actions/setup-java@v1 to checkout the current GitHub repository and setup Java Development Kit in your runner respectively. The third step, as its name says, prints the contents of current working directory.

Add, commit and push the changes to trigger the workflow. The current runner contains the following files:

File structure inside the current runner