Automate Your Android Development Workflow with GitHub Actions

As an Android developer, you‘re all too familiar with the tedious, repetitive tasks that are part of the job – running tests, ensuring the app builds successfully when merging pull requests, and going through the process of building and publishing an updated version to the Play Store.

Wouldn‘t it be nice if you could automate these chores so you can focus your time and energy on more important and interesting things? That‘s where GitHub Actions come to the rescue!

In this article, I‘ll show you how to leverage the power of GitHub Actions to put common Android development tasks on autopilot. You‘ll learn what GitHub Actions are, how to configure them, and see examples of automating builds, tests, and app publishing. Let‘s jump in!

What are GitHub Actions?

In a nutshell, GitHub Actions allow you to automate tasks by executing code in response to events that occur in your GitHub repository. An action is essentially a custom application that performs a complex but frequently repeated task.

Some common use cases for GitHub Actions relevant to Android development include:

  • Automatically running unit tests when a pull request is opened to check if the changes break anything
  • Building your app when changes are pushed to ensure there are no compilation errors
  • Generating a signed release build of your app and publishing it to the Play Store

The great thing about Actions is that you can use pre-built ones shared by the community, or easily create your own. Under the hood, an Action is just a Docker container, so you can use any language to implement the custom functionality you need.

Anatomy of a GitHub Actions Configuration File

To use GitHub Actions, you define one or more workflows in your repository. A workflow is an automated process that you set up to run one or more jobs. It‘s defined in a YAML file checked into your repo in the .github/workflows directory.

Here‘s a simple example:

name: Android CI

on:
  pull_request:
    branches: [ main ]

jobs:

  build:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2

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

    - name: Grant execute permission for gradlew
      run: chmod +x gradlew

    - name: Build with Gradle
      run: ./gradlew build

Let‘s break this down:

  • name specifies a name for the workflow that will appear in the "Actions" tab of your repo
  • on defines the event that triggers the workflow to run. In this case, it will run when a pull request targeting the main branch is opened or synchronized
  • jobs is where you define the steps that make up the workflow
  • build is the ID of the first (and only) job in this workflow. You can give it any name you want
  • runs-on specifies the type of machine to run the job on. This example uses the latest version of Ubuntu
  • steps contains an ordered list of tasks to perform as part of the job
  • uses specifies an action to run as part of a step, typically selecting one from the marketplace. actions/checkout@v2 is a standard action that checks out your repo so the workflow can access it
  • with specifies input parameters for an action. In this case, we‘re telling the setup-java action to use JDK 11
  • run specifies a command to run on the runner machine. Here we grant execute permissions to the Gradle wrapper script, then use it to build the app

With this configuration, GitHub will automatically build your app every time a pull request is opened. If the build fails, you‘ll be notified so you can fix it before merging. This helps maintain a stable main branch and minimizes the risk of breaking changes sneaking in.

Of course, this just scratches the surface of what‘s possible with GitHub Actions! Let‘s look at a few more examples specific to Android development.

Automating Your Android Test and Build Process

Building on the previous example, here‘s a more sophisticated workflow that runs your unit tests, then builds your debug and release variants and generates an APK artifact:

name: Android CI

on:
  pull_request:
    branches: [ main ]

jobs:

  test:
    name: Run Unit Tests
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2
      - name: Set up JDK 11
        uses: actions/setup-java@v2
        with:
          java-version: ‘11‘
          distribution: ‘adopt‘

      - name: Grant execute permission for gradlew
        run: chmod +x gradlew

      - name: Run Tests
        run: ./gradlew test

  apk:
    name: Generate APK
    needs: test

    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2
      - name: Set up JDK 11
        uses: actions/setup-java@v2
        with:
          java-version: ‘11‘
          distribution: ‘adopt‘

      - name: Grant execute permission for gradlew
        run: chmod +x gradlew

      - name: Build debug APK
        run: ./gradlew assembleDebug

      - name: Build release APK
        run: ./gradlew assembleRelease

      - name: Upload APK
        uses: actions/upload-artifact@v2
        with:
          name: apk
          path: app/build/outputs/apk/debug/app-debug.apk

This workflow has two jobs:

  1. test – This runs your unit tests to ensure no breaking changes.

  2. apk – Generates a debug and release APK. It depends on the test job, so it will only run if the tests pass. The upload-artifact action at the end uploads the generated debug APK so you can download and test it.

The ability to break up your workflow into separate jobs is a powerful feature of GitHub Actions. You can define dependencies between them to create sophisticated build pipelines.

Publishing to the Play Store

Now for the ultimate automation – publishing your app to the Google Play Store! To do this, we‘ll create a new workflow that triggers when you create a new GitHub release:

name: Android Release

on:
  release:
    types: [published]

jobs:

  publish:
    name: Publish to Play Store
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2

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

      - name: Grant execute permission for gradlew
        run: chmod +x gradlew

      - name: Build release AAB
        run: ./gradlew bundleRelease

      - name: Sign AAB
        uses: r0adkll/sign-android-release@v1
        with:
          releaseDirectory: app/build/outputs/bundle/release
          signingKeyBase64: ${{ secrets.SIGNING_KEY }}
          alias: ${{ secrets.KEY_ALIAS }}
          keyStorePassword: ${{ secrets.KEYSTORE_PASSWORD }}
          keyPassword: ${{ secrets.KEY_PASSWORD }}

      - name: Deploy to Play Store
        uses: r0adkll/upload-google-play@v1
        with:
          serviceAccountJsonPlainText: ${{ secrets.SERVICE_ACCOUNT_JSON }}
          packageName: com.yourcompany.yourapp
          releaseFiles: app/build/outputs/bundle/release/app-release.aab
          track: production
          whatsNewDirectory: distribution/whatsnew

There are a few prerequisites needed for this to work:

  1. Create a new service account for publishing in the Google Play Console, and download the JSON key file. Add this as a secret in your GitHub repo named SERVICE_ACCOUNT_JSON.

  2. In the Google Play Console, grant the service account permission to manage app releases.

  3. Generate an upload key for signing your app and add it to your GitHub repo as secrets named SIGNING_KEY, KEY_ALIAS, KEYSTORE_PASSWORD and KEY_PASSWORD respectively.

With those pieces in place, the workflow can now automatically build your app in release mode, sign the bundle, and publish it to the Play Store!

A few notes on this workflow:

  • This workflow isn‘t triggered by a pull request event, but when you publish a new release in your GitHub repo. This ensures you only publish a new version of your app when you‘re ready, not after every change.

  • The whatsNewDirectory parameter allows you to automatically populate your app‘s release notes from a dedicated directory in your project. This is optional, but a nice touch!

That covers the key points! With these workflows in place, you can focus on building great features while letting GitHub handle the repetitive tasks of building, testing, and publishing.

Monitoring Your Workflows

You can keep an eye on your workflows from the "Actions" tab in your GitHub repo. Here you can view the status of builds, inspect logs if something goes wrong, and even manually trigger workflows to run.

A status indicator next to each commit also shows at a glance whether changes broke the build. This is a great way to catch problems early before they snowball.

Learn More

GitHub Actions is an incredibly flexible tool for automating all kinds of tasks in your development workflow. While this article focused on Android development, Actions can help automate everything from building web apps to deploying infrastructure.

To dive deeper into GitHub Actions, check out the following resources:

Happy automating!

Similar Posts