Automate Building Android APKs 📱 with Google Cloud Build CI/CD 🔧 and a Gradle Docker Image ☁️
Google Cloud Build
Google Cloud Build(GCB) is a service that executes your builds on Google Cloud Platform infrastructure. Cloud Build can import source code from Google Cloud Storage, Cloud Source Repositories, GitHub, or Bitbucket, execute a build to your specifications, and produce artifacts.
You can write a build config to provide instructions to Cloud Build on what tasks to perform and can either use the build step/builders provided by Cloud Build , Cloud Build community or write your own custom build steps/builders.
You can also manually start builds in Cloud Build using the gcloud command-line tool or the Cloud Build API, or use Cloud Build's trigger feature to create an automated continuous integration/continuous delivery (CI/CD) workflow that starts new builds in response to code changes on your code repository.
In this tutorial, you would setup a Cloud Build trigger that builds your android application and uploads it to a Cloud Storage Bucket. The builds of new APK bundle would also be automatically triggered once code is pushed code to your code repository.
As at the time of this writing, GCB Builders supports Gradle 4.6 as it's latest Gradle Cloud Builder which is not compatible with the Android project. However, I created an updated Gradle Docker Image which we will use to perform gradle builds for our Android project.
Set up on Google Cloud Platform
- Create a new Google Cloud Platform (GCP) project, or use an existing one.
- Enable billing for your project..
- Enable the Cloud Build API
- Create a Bucket on Google Cloud Storage(GCS)
This is where your project APKs will be stored, you are expected to provide a unique Bucket name, I will be using fullstackgcp-apk-builds as my Bucket name.
Make Bucket Public (Optional)
If you would like to access your APKs from your bucket publicly ( click here for mine), then you can set Bucket-level permission to allow anyone on the internet access to your Bucket files.
To do so, click Add Members on the Permissions Tab of your Bucket and perform the following:
Note that: Your bucket is public and can be accessed by anyone on the internet
- Granting Cloud Build access to Cloud Storage (Optional - If your bucket is public)
Cloud Build service account's default permissions do not allow the account to manage a Cloud Storage bucket. To grant Cloud Storage IAM role to a Cloud Build service account, perform the following steps:
- Open the IAM page in GCP Console.
- Select your project and click Continue.
- In the list of members look for your Cloud Build service account named [PROJECT_NUMBER]@cloudbuild.gserviceaccount.com, where [PROJECT_NUMBER] is your GCP project number.
- Click the pencil icon in that row.
- Click Add another role, select Storage Object Admin under Storage and click Save.
Set up Cloud Build
Application Source Codes
You need to ensure your application codes and all necessary files needed for building an APK are available on a code repository. Cloud Build currently supports Cloud Source Repositories, GitHub, or Bitbucket.
The demo source codes for this tutorial is available on GitHub, you can access them here.
In your repository, create a build configuration file: cloudbuild.yaml, which contains instructions for Cloud Build. The configuration file for this tutorial is:
# cloudbuild.yaml
steps:
# Set a persistent volume according to https://cloud.google.com/cloud-build/docs/build-config (search for volumes)
- name: 'ubuntu'
volumes:
- name: 'vol1'
path: '/persistent_volume'
args: ['cp', '-a', '.', '/persistent_volume']
# Build APK with Gradle Image from mounted /persistent_volume using name: vol1
- name: 'gcr.io/cloud-builders/docker'
volumes:
- name: 'vol1'
path: '/persistent_volume'
args: ['run', '-v', 'vol1:/home/app', '--rm', 'gcr.io/fullstackgcp/gradle', '/bin/sh', '-c', 'cd /home/app && ./gradlew clean assembleDebug']
# Push the APK Output from vol1 to your GCS Bucket with Short Commit SHA.
- name: 'gcr.io/cloud-builders/gsutil'
volumes:
- name: 'vol1'
path: '/persistent_volume'
args: ['cp', '/persistent_volume/app/build/outputs/apk/debug/app-debug.apk', 'gs://fullstackgcp-apk-builds/app-debug-$SHORT_SHA.apk']
timeout: 1200s
In a nutshell, Cloud Build helps you run the docker command below:
docker run -v $(pwd):/home/app --rm gcr.io/fullstackgcp/gradle /bin/bash -c 'cd /home/app && ./gradlew clean assembleDebug'
In the command, we specify: -v which mounts our current directory as the volume, --rm which removes the container on exit.
You can change the -c command on your cloudbuild.yaml file if you would like to use other Gradle commands.
Cloud Build also copies the output: app-debug.apk into your GCS Bucket as app-debug-$SHORT_SHA.apk , where $SHORT_SHA is the first seven characters of COMMIT_SHA of the commit which triggered Cloud Build, it is meant to tag the APK builds on your GCS Bucket.
Cloud Build Trigger
Cloud Build trigger listens to changes in your code repository, follow the steps below to create a GCB trigger.
- Visit the Cloud Build Triggers Page and Click Create Trigger
- Select Code Repositroy Source
- Select Repository (Filter your search by inputting the repository name)
- Enter Description and Set Build Configuration : cloudbuild.yaml (You can also set a Branch Regex if you would like to limit the trigger to certain branches)
Cloud Build Costs
CPUs | Memory | Price per build-minute |
1 | 3.75 GB | $0.0034 / build-minute. First 120 build minutes per day are free. |
8 | 7.2 GB | $0.016 / build-minute |
32 | 28.8 GB | $0.064 / build-minute |
Cleaning up
To prevent unnecessary charges, clean up the resources created for this tutorial.
- Delete the project used (if you created a new project).
- Delete the Cloud Build Trigger and Cloud Storage Bucket. You might also choose to disable the Cloud Build Trigger.
Next steps
If you want to learn more about Cloud Build check out the following resources:
- Cloud Build Documentation
- Official Cloud Builder
- Community Cloud Builders
- Google Cloud Platform Awesome List
Thanks for reading through! Let me know if I missed any step, if something didn’t work out quite right for you or if this guide was helpful.