Build your Capacitor Android app bundle using GitHub Actions
Looking for building iOS bundles with Capacitor? Check out this blog post instead!
This post has been updated on 2023-06-06 to work with Capacitor 5.
In this post we will set up a GitHub Actions workflow for a Capacitor app that will produce a signed app bundle, ready for upload to Google Play Console.
At a high level, we will:
- Set up our key store and signing keys
- Adding our key store and signing keys to GitHub Secrets
- Creating a GitHub Actions workflow
Let’s get started! π€©
Generating a key store
You probably already have a key store to sign your app releases, but in case you donβt hereβs how to create one:
keytool -genkey -v -keystore android/release.jks -keyalg RSA -keysize 2048 -validity 10000 -alias release
Follow the prompts until it asks you if the data is correct, enter yes to save your key. Don’t forget to also add it to .gitinore
so you don’t accidentally commit it to your repo, the keystore should be kept secret.
Adding the key store and password as GitHub Secrets
In GitHub we can add secrets for our repository under Settings > Secrets > Actions
We quickly run into a snag however, because secrets can only be strings, and the key store is actually binary data.
Thereβs a handy CLI utility called base64
, which should be preinstalled on most Linux distros. Using it we can convert our binary file into a string representation, letβs run:
base64 android/release.jks > android/release.jks.base64
If we now open android/release.jks.base64
we should see a normal text file.
Now we can add it as a secret named RELEASE_KEYSTORE
. It should look something like this:
βΉοΈ Don’t worry about the base64 representation – will convert it back to a file in our GitHub Action.
Letβs also add the key store password as RELEASE_KEYSTORE_PASSWORD
. Now it should look like this:
Adding our GitHub Action workflow
Itβs finally time to add our workflow! Add the following file to .github/workflows/android-build.yml
name: Build Android
on:
push:
branches:
- master
jobs:
build:
name: Build APK
runs-on: ubuntu-latest
steps:
- name: Checkout source
uses: actions/checkout@v3
- name: Setup java
uses: actions/setup-java@v3
with:
distribution: 'zulu'
java-version: '17'
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: 19.x
- name: Install app dependencies
run: npm install
- name: Build Svelte app
run: npm run build:static
- name: Capacitor update
run: npx cap update
- name: Capacitor copy
run: npx cap copy
- name: Build app bundle
run: cd android && ./gradlew bundle
- name: Extract Android signing key from env
run: |
echo "${{ secrets.RELEASE_KEYSTORE }}" > android/release.jks.base64
base64 -d android/release.jks.base64 > android/release.decrypted.jks
- name: Sign dev build
run: jarsigner -keystore android/release.decrypted.jks -storepass "${{ secrets.RELEASE_KEYSTORE_PASSWORD }}" -signedjar ./android/app/build/outputs/bundle/release/app-release-signed.aab ./android/app/build/outputs/bundle/release/app-release.aab release
- name: Upload release bundle
uses: actions/upload-artifact@v3
with:
name: app-release
path: android/app/build/outputs/bundle/release/app-release-signed.aab
retention-days: 60
βΉοΈ You might want to tweak a some things such as the branch to build on
, preferred Java version and how much retention you want for your output artifacts using the retention-days
configuration option.)
After pushing your change you can navigate to the Actions tab in your repo where you should see your build running.
β If your build does not finish, please try building locally using the workflow steps above, there might be something wrong with your Capacitor configuration.
Once your build has run successfully, you can download your bundle directly from the build run page!
From here you can directly upload the signed bundle in the Play Console! π
βΉοΈ Note that you have to bump the versionCode
in android/app/build.gradle
for every new version you intend to upload to the Play store.
Links and acknowledgements
A special thanks to the posts below, without which this post could not exist. π
- https://dico.duba.dev/building-a-vue-3-native-android-app-with-capacitor-on-wsl2-ubuntu-20-04
- https://gist.github.com/B45i/2afef964613f0698d881e0647a67fb43
- https://stefma.medium.com/how-to-store-a-android-keystore-safely-on-github-actions-f0cef9413784
Photo by Liam Briese on Unsplash
View Comments
Handling errors with Error Boundaries in Svelte
In this post you’ll learn how to create an Error Boundary in Svelte, similar to...