Ade Dyas
Staffinc Tech
Published in
8 min readJan 19, 2022


Have you ever felt bored doing repetitive work or were insecure about data leaks?

An android developer, for example, does things like building AAB to upload to the Playstore. And, always remember to store passwords, alias names, and key passwords that absolutely must not be forgotten for life if you don’t want to deal with all the complications that will occur.

We might think to write it down in a document. But can it guarantee that the document will always be there? Will the document not fall into the hands of irresponsible people? Will we always remember where we put the document? If you’re in a team, would you be willing to give your app’s keystore file and password to someone else? Of course, it’s risky.

Some developers may be okay with all that stuff, but it won’t solve the first problem: doing tedious things like building AABs and then uploading them via the Play Console. Wait, did you guys upgrade the version code earlier? We sometimes forget about it, then repeat it. So dull, isn’t it?

Have you ever heard of Fastlane?

Fastlane is an open-source platform that aims to simplify the distribution of mobile applications. Fastlane automates our workflows quickly and inexpensively. We combine automation in Fastlane with automation in our repositories like Gitlab CI, Github Actions, etc. For more details, read about CI/CD.

I will share how to apply the automation to an android application project that has not implemented any automation, either Fastlane or CI/CD in the repository.

Here I have an application that only displays the version of the application:

We need to have an app already deployed in the Playstore to do this. Our next step will be to add automation to our repository. In this case, I use GitLab, so I will use GitLab CI. Read how to make a GitLab CI/CD here.

Here are a few sections, let’s go one by one.

image: jangrewe/gitlab-ci-android

The image here shows that the Docker image that we use is of jangrewe/gitlab-ci-android.

- .gradle/

The cache is used to store pipeline results from jobs so they don’t need to be worked on again, they can be reused.

- chmod +x ./gradlew

before_script contains commands to be executed each time jobs are running.

- build
- inspection

stages contain jobs to be executed in order from top to bottom. If you want to run jobs simultaneously, it can be done by matching the stage name on the job as in the script above, stage inspection is found in 3 jobs, namely linter, linterFormat, and unitTest.

stage: build
- ./gradlew assembleDebug
- app/build/outputs/
- merge_requests
- dev

The above script shows one job named build. The stage contains the name of the stage to be executed in the stages section. The script has the commands to be executed. artifacts indicate that the script will save the results at the specified path. Only, is used to specify where the job will be performed. The example above will only run on the dev branch and when making a merge request.

In addition to the commands above, we can learn more at the link here.

After adding the above code to our project. We will do a push to GitLab, after that we can look in the CI/CD tab -> pipeline to see if the automation is running or not. When it is successful, we can download the APK build available on the job artifact. The build problem to be shared with the QA team is also resolved.

By implementing Gitlab CI, we don’t need to do a manual build for distribution; just download the artifact. But not everyone has access rights to the repository, so we will implement Fastlane so that people can download our application on the Playstore.

The way to implement Fastlane already exists here. First, we will create a service account as an identity to run an API from Google. In this case, it is deploying through a third party (Fastlane) in the form of the JSON format.

Once we get it (we call it service_account.json), we are trying to deploy it through our local machines first then place it in our project’s root directory. After that, it’s time for us to install Fastlane.

sudo gem install fastlane

This command is used to install Fastlane on our device.

fastlane init

This command is used to initialize Fastlane in our project. Here we will be asked to enter the package name of our application, then enter the service_account path JSON, which we have placed in our project’s root directory before.

After that, we will be asked to confirm whether to import metadata from Google Play. Choose y if we feel it’s safe. But don’t worry, we can change it next time. After completion, it will generate several files as shown in the image below.

We can confirm whether our service_account.json is valid or not with the command:

bundle exec fastlane run validate_play_store_json_key json_key:service_account.json

If it is confirmed to be valid, we will modify the Fastfile and Appfile files. The result generated from the previous Fastlane in command is depicted here:

After that, we are going to make changes in our application, such as adding a changelog feature like this:

The change already exists. the QA team needs to get this change. We can try Fastlane on our local machine first to execute the internal deployment with the Fastlane command that we have set up in our Fastfile.

fastlane internal

A message will have been sent to Slack via Fastlane with the APK internal URL address. we don’t need to open the artifact on GitLab to give it to the QA team.

They can get it directly on the Slack channel!

We have successfully deployed internal applications without needing to open the Play Console. It’s time we combine the two automation that we have made to be more automated.

Imagine that we have finished developing a sprint. We only need to make an MR to our GitLab. After merging, the application will be built automatically by GitLab using Fastlane, and then distributed to the Playstore. We need to modify ourgitlab-ci file so that we can execute the existing Fastlane commands like this:

Enter the environment we need to deploy to the GitLab variable as above, we can also include our .jks file if needed, otherwise, put the .jks file in the app directory. Uncheck FlagProtect variable if we work in an unprotected branch.

Before pushing to GitLab, let’s prepare the metadata for deployment with the command:

fastlane supply init

Then we will get our previous metadata file on Playstore in the Fastlane directory:

In the changelogs directory, there is a .txt file with a name based on the version code. Because we will be deploying version 1.2 with version code 2, we need to create a new file with the name 2.txt and fill in the changes we made.

After that, we can delete the service_account.json file because it’s for security reasons and it’s not needed because we already save it in GitLab variables. If so, do commit and push.

When we push to the dev branch, the uploadPlayStoreInternal job of the deploy stage will be executed and will run the internal Fastlane as we did before on our local machine.

Upon success, a success message along with the URL internal app sharing will be sent to the Slack channel, after safe we can make a merge request to the branch master.

Once the pipeline is completed, perform merge and then see the process on the tab CI / CD -> pipeline

An incoming message in Slack, it’s time to take a look at the Play Console. The app is being reviewed! We’ve done the automation, no more manual work for our app distribution!


By using CI/CD and Fastlane, we can implement automation to make it faster, cheaper, and hassle-free. We also don’t need to memorize all the sensitive stuff to avoid data leakage.