Automate Publishing your Android app to Google Play Store with Fastlane and Github Actions
by Tifani Dermendzhieva
Developers need fast and efficient way to deliver apps to the users, ensuring continuous integration and clear versioning of their apps. Manual publishing of an app can be time-consuming and involves a lot of repetitive steps that could easily be automated, such as building and signing a new apk/aab file, logging in to the Google Play Console and uploading the file. Therefore, the most efficient way to achieve this is automating the process of publishing the app to Google Play Store or AppStore.
In this tutorial, I will show you how you can use Fastlane and Gihtub Actions to automatically upload an android app bundle (.aab) to Google Play Store.
Prerequisites
Before we proceed with the tutorial, you will need to have done the following:
- Create a Google Play Developer Account
- Setup an app in your account
- Enable Google Play Android Developer API
- Enroll on Play App Signing: if you are not sure how to enroll, check out this super concise tutorial on jmango360
- Configure your app to use the correct upload key for signing the app: it must be the one used to enroll for Play App Signing and for the purposes of this tutorial it will be called
myKeystore.keystore
1. Create a service account and JSON key
To automate the process of publishing your app to Google Play Store you will have to provide a JSON key, which will be used for authentication against Google Play Developer API. In order to obtain this key, you have to setup a service account first.
Create a new service account
Step 1: Login to Google Cloud Console
Step 2: Navigate to IAM & Admin and select Service Accounts
Step 3: Create a new service account and assign the role of Basic Editor to it.
Generate a new json key
Step 4: Navigate to the service account you have just created, click on create new key and select type JSON.
Download the key and store it securely. For the purposes of this tutorial rename the file to service-account.json
.
Invite the service account user to the app project
Step 5: Login to Google Play Console and navigate to Setup -> API access
Step 6: Find the service account name (email) and grant admin access to it. If you want to keep the permissions to the minimum required, make sure that you have selected everything under the release section.
Note: Be aware that granting access to the service account can only be performed by the owner of the google developer account.
2. Setting up Fastlane
Step 1: Make sure that you have installed Ruby on your machine:
ruby -v
Step 2: Install fastlane:
gem install fastlane -NV
Step 3: At the root of the project (i.e. android/
) run the following command to initialise fastlane:
fastlane init
This will prompt you to enter the name of the package, e.g. "io.appname.app".
You can press enter to skip the rest of the questions, as they can be configured later.
When asked "Download existing metadata and setup metadata management?" respond with no (i.e. n
).
After the command has been executed you will notice that a new folder fastlane
has been created.
Inside this folder there will be two files - Appfile
and Fastfile
.
Place the service-account.json
in the fastlane/
folder, but do NOT commit it to github.
Step 4: In the fastlane/Appfile
define the path to the service account json key (relative to where the fastlane actions will be called) and the package name.
Assuming that the fastlane actions will be called at the root of the project, the Appfile
content looks like this:
json_key_file("fastlane/service-account.json")
package_name("io.appname.app")
Important: When you use github actions make sure to restore the json key in the correct directory (i.e. fastlane/
).
Step 5: The fastlane/Fastfile
is where all methods (a.k.a lanes) must be defined.
Let's take a look at the following Fastfile
.
There are two lanes (methods), the first of which is :internal
. It uses the gradle
action to build an app bundle (.aab) and the upload_to_play_store
action to upload the bundle to the internal track on the play store (the other track options are 'alpha', 'beta' and 'production').
To find out more about the google play tracks click here.
The second lane is :production
and uses the same actions to build and publish the bundle to the production track on Google Play.
default_platform(:android)
platform :android do
# LANE 1
desc "Publish a new version to the Google Play (INTERNAL)"
lane :internal do
# Generate AAB file
gradle(
task: "bundle",
build_type: "Release"
)
# Upload the AAB to play store (internal track)
upload_to_play_store(track: 'internal')
end
# LANE 2
desc "Publish a new version to the Google Play (PROD)"
lane :production do
# Generate AAB file
gradle(
task: "bundle",
build_type: "Release"
)
# Upload the AAB to play store (production track)
upload_to_play_store(track: 'production')
end
end
If you want to make sure everything works as expected before you publish your app, you could pass the validate_only: true
argument to the upload_to_play_store
action.
It will only verify that everything is correct without actually publishing the app on the selected track.
# Validate upload the AAB to play store (production track)
upload_to_play_store(track: 'production', validate_only: true)
Note: You can find all available arguments for upload_to_play_store
here
If you want to run the :production
lane locally, execute the following command in your terminal (note: make sure you are working in the root dir):
bundle exec fastlane production
3. Create a workflow with Github Actions
Create new repository secrets for the JSON key and upload key (myKeystore.keystore
)
Both the upload key and the service account json key contain sensitive information which should be stored securely and hence, should not be pushed to the github repository. In order to be able to access them from within the workflow, you have to obtain them from the repository secrets. To achieve this, let's first ecrypt/encode them:
Step 1: Encrypt the .keystore file, in the terminal run the following command:
gpg -c -armor myKeystore.keystore
This command will prompt you to enter a passphrase. Important: Make note of the passphrase.
After successful exection you will be able to see a myKeystore.keystore.asc
file in the current directory.
Step 2: Create a new repository secret (ENCRYPTED_KEYSTORE), containing the content of myKeystore.keystore.asc
Step 3: Create a new repository secret (ENCRYPTED_KEYSTORE_PASSPHRASE), containing the passphrase, used to encrypt the keystore (ref. Step 1)
Step 4: Encode the JSON key
base64 -it service-account.json -o encoded.base64.txt
Step 5: Create new repository secret (SERVICE_ACCOUNT_JSON) and place the content of the encoded.base64.txt
Create a new github workflow
Now, that Fastlane and the secrets have been setup, let's create the workflow .github/workflows/publish_play_store.yml
, containing the following:
name: Publish to Play Store ( Internal track )
on:
workflow_disptach:
jobs:
upload-play-store-internal:
name: Upload app to Play Store (Internal track)
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v3
- name: Setup ruby
uses: actions/setup-ruby@v1
with:
ruby-version: "3.x"
- name: Setup fastlane
run: |
cd android
bundle install
cd ..
- name: Restore json key # make sure that you restore the key in the correct directory (ref. fastlane/Appfile)
run: |
cd android/fastlane
echo "${{ secrets.SERVICE_ACCOUNT_JSON }}" | base64 --decode > service-account.json
cd ../..
- name: Restore keystore # make sure that you restore the key in the correct directory (same as app/gradle.properties)
run: |
cd android/app
echo "${{ secrets.ENCRYPTED_KEYSTORE }}" > myKeystore.keystore.asc
gpg -d --passphrase ${{ secrets.ENCRYPTED_KEYSTORE_PASSPHRASE }} --batch myKeystore.keystore.asc > myKeystore.keystore
cd ../..
- name: Set up JDK environment
uses: actions/setup-java@v3
with:
distribution: "zulu"
java-version: 11
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Make Gradlew Executable
run: cd android && chmod +x ./gradlew
- name: Upload app to Play Store (Internal track)
run: |
cd android
bundle exec fastlane internal
Congratulations, you have automated your app publishing process. All you have to do is run the workflow and your app will be available to testers on the internal track. To publish the app on the production track instead, simply switch the lane in the final step to poduction and you are good to go.
Conclusion
Automating your app deployment can save you hours of building, testing, and releasing your app on a regular basis. In this tutorial I have walked you through the steps of automating the process of building and publishing an android app to Google Play Store. If you are interested in reading other tutorials related to play store automation with Gihtub Actions, I recommend these amazing articles by Tomer Ben Rachel on freecodecamp.org and by Shreyas Patil on medium.com.