If you’re still manually running ./gradlew assembleRelease on your local machine and uploading the APK to a shared folder, you’re wasting precious development time. Learning how to setup GitHub Actions for android is one of the highest-leverage moves you can make for your mobile workflow. In my experience, moving to a CI/CD pipeline doesn’t just save time; it eliminates the ‘it works on my machine’ syndrome that plagues many Android teams.

Whether you are building a side project or managing complex mobile application lifecycle management tools, GitHub Actions provides a native, powerful way to automate your testing and deployment without needing to manage your own build servers.

Prerequisites

Before we dive into the YAML configuration, ensure you have the following ready:

Step 1: Creating the Workflow File

GitHub Actions are defined in YAML files located in a specific directory of your repo. I recommend starting with a basic build check to ensure your environment is correct.

Create a file at .github/workflows/android.yml and add the following configuration:

name: Android CI

on:
  push:
    branches: [ "main", "develop" ]
  pull_request:
    branches: [ "main" ]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: set up JDK 17
        uses: actions/setup-java@v3
        with:
          java-version: '17'
          distribution: 'temurin'
          cache: 'gradle'

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

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

In this setup, I’m using ubuntu-latest because it’s faster and cheaper than macOS runners for standard Android builds. I also included the cache: 'gradle' option, which is critical. Without it, GitHub will redownload every single dependency on every run, adding minutes to your build time.

Step 2: Implementing Automated Testing

A build that compiles but crashes is useless. To make your pipeline truly effective, you need to run your unit tests. Add this step before your build step:

      - name: Run Unit Tests
        run: ./gradlew test

If you’re debating between different CI tools, you might be looking at Jenkins vs GitLab CI for mobile, but for most Android developers, the tight integration of GitHub Actions with the PR process makes it the superior choice for velocity.

Step 3: Handling Secrets for Signed Releases

To generate a production APK, you can’t check your .jks keystore file into version control. Here is how I handle this securely:

  1. Convert your keystore file to Base64: base64 -i upload-keystore.jks.
  2. Go to your GitHub Repo → Settings → Secrets and variables → Actions.
  3. Add the following secrets: KEYSTORE (the base64 string), KEYSTORE_PASSWORD, KEY_ALIAS, and KEY_PASSWORD.

Now, update your workflow to decode the keystore and sign the app. As shown in the image below, you’ll need to ensure the keystore is written to the filesystem before Gradle runs.

      - name: Decode Keystore
        run: echo "${{ secrets.KEYSTORE }}" | base64 --decode > app/release.keystore

      - name: Build Release
        run: ./gradlew assembleRelease
        env:
          SIGNING_KEY_STORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
          SIGNING_KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
          SIGNING_KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
GitHub Actions Secrets settings page showing the addition of Android keystore variables
GitHub Actions Secrets settings page showing the addition of Android keystore variables

Step 4: Uploading the Artifact

Once the build is complete, you want to be able to download the APK without digging through logs. Use the upload-artifact action:

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

Pro Tips for Android CI/CD

Troubleshooting Common Issues

Issue: Out of Memory (OOM) Errors
Android builds are memory-hungry. If your job fails with an OOM, add a gradle.properties file to your project or set an environment variable: org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=512m.

Issue: Permission Denied (gradlew)
This usually happens because the gradlew script lost its execution bit. Always include chmod +x gradlew in your workflow steps to be safe.

What’s Next?

Now that you know how to setup GitHub Actions for Android, the next step is automating your distribution. I recommend looking into Fastlane. You can integrate Fastlane into your GitHub Action to automatically push your build to the Google Play Console (Internal Testing track) as soon as a tag is pushed to the repository.