Automating Android App Play Store Publishing via Jenkins

Elroy Y. Setiabudi
MindOrks
Published in
9 min readJun 16, 2019

Software development lifecycle is very crucial in software engineering. It will be more challenging once the team grows because there will be engineers, quality assurances, product managers, UX researchers, UI designers, automation tester, and many other roles.

Every stage of software development must be communicated and distributed clearly. For instance, once the regression testing for Android app has been done by the QA, then they will talk to the Android engineers to upload and release the application to Play Store. So, the Android engineers must standby during QA’s regression test, right? And, seems like an effective way to kill the time, right? ‘LOL’

So by looking at these processes, we can define some problems:

  1. Android engineers are the bottleneck of the release on the software development lifecycle.
  2. Android engineers must wait for the compile and build process, before waiting for the upload process until it is released on Play Store.
  3. A non-scalable process as the engineering team grows.

The next question is how to solve these problems? One of the solutions is to build a more automated system and flow. And we can start by building Android automated uploader to Play Store. It will reduce communication dependency between QAs and engineers.

Thus, how to build an Android Play Store Automatic Uploader? Basically, it is as simple as building Production APK and then letting the CI server upload the APK to Play Store.

These are the detailed step-by-step on how to implement Automatic uploader:

1. Create Google Play Credential ID (P12 File)

1.1. Inside the Google Play Store Console of your project, navigate to Settings -> Developer account-> API Access :

1.2. Scroll down to Service Accounts section, then click Create Service Account button on the bottom.

1.3. There will be a popup for creating the Service Account. Click on Google API Console link on the first point.

1.4. Google API Console will be shown in Service Account menu, click on + Create Service Account.

1.5. Create service account screen will be shown. Fill the Service account name and also Service account description. The Service account description will be automatically generated. After that, click Create button on the bottom.

1.6. Service Account will be shown in the list, click overflow menu in Actions, then click Add Keys.

1.7. Click + Create Key to create private key. Make sure to also request the .p12 Key File instead of JSON:

1.8. You will be prompted to download .p12 file. Save it somewhere. Input a password for that .p12 file.

1.9. Once you are done, go back to the Google Play Developer Console and navigate to the Settings -> API Access. Make sure the checkboxes for Edit store listing, pricing & distribution, Manage Production APKs, and Manage Alpha & Beta APKs are checked for the Google Service account used.

That’s it, you have finished the first step of a system that will make your life so much easier! :)

2. Set Up Release Signing Configs in Gradle

The second step is to set up signing configs in the Gradle. It is used to let Gradle knows all the needed keystore configs to build production APK.

Note: If you don’t have any idea about what keystore is, you can read this article to help you first https://developer.android.com/studio/publish/app-signing

Add this configuration in your app build.gradle inside android { } branch:

android {
signingConfigs {
release {
storeFile file(RELEASE_STORE_FILE)
storePassword System.getenv("KEYSTORE_PASSWORD")
keyAlias System.getenv("KEYSTORE_ALIAS")
keyPassword System.getenv("KEYSTORE_PASSWORD")
}
}
}

storeFile, a path to your production keystore. You can define your path in your gradle.properties. You can define any path for the keystore file.

RELEASE_STORE_FILE=keystore.jks

storePassword, your production keystore password. This ‘KEYSTORE_PASSWORD’ will be defined and entered from CI Server, which will be explained later in the next section.

keyAlias, your production keystore alias. This ‘KEYSTORE_ALIAS’ will be defined and entered from CI Server, which will be explained later in the next section.

keyPassword, your production keystore password. This ‘This ‘KEYSTORE_PASSWORD’ will be defined and entered from CI Server, which will be explained later in the next section.

3. Create a CI Pipeline

For this Play Store Automatic uploader, we will use Jenkins as our CI Server. So the following steps will be about implementation in Jenkins.

Pre-requisite: Jenkins server has been set up previously!

3.1. Add your production keystore to Jenkins

Go to Credentials -> System -> Add Credentials

  • Select Secret file as credential kind
  • Select Global (Jenkins, nodes, items, all child items, etc) as credential scope. It will make this credential accessible from all nodes and pipeline.
  • Upload your keystore.jks.
  • Name any unique ID for this credential. This ID will be the alias used to call from the pipeline later. In this example, I named it as android_keystore.
  • Input any Description of this credential.

3.2. Add your Google Play Credential ID (P12 File) to Jenkins

Go to Credentials-> System -> Add Credentials

  • Select Google Service Account from private key as credential kind.
  • Google Play Key as your project name.
  • Select P12 key.
  • Input your generated P12 email address, and upload your P12 key file that you have generated in section 1.

Click OK, then your P12 file has been set up in your Jenkins! And your Jenkins is now eligible to upload APK to the Play Store.

3.3. Create Jenkins Pipeline

After you’re done with adding credential and authentication files, the next step is to make the Jenkins pipeline to build and upload production APK to Play Store.

Create a Pipeline by clicking in the sidebar on the left. A new screen for pipeline configuration will be opened.

Insert description for the pipeline, and checkingDo not allow concurrent builds.

Give parameters to this pipeline by checking the This project is parameterized. Give Password Parameter for ‘KEYWORD_ALIAS’ and also ‘KEYSTORE_PASSWORD’. These two parameters will be mandatory fields that need to be input by the user when running this pipeline. It will secure the production pipeline, and not be abused by users. These parameters will be used by Gradle in generating production APK, how to integrate it with Gradle has been discussed in section 2.

Another parameter is the String Parameter for the ‘SELECTED_RELEASE_BRANCH’, to let users input the GIT branch that they want to build.

3.4. Pipeline Script to Build and Upload Production APK to Play Store

After you’re done with the general configuration of the Pipeline, scroll to bottom on the pipeline configuration screen. You will see the `Pipeline script` text box for you to define all the needed processes to do the APK automation.

Now let’s fill that pipeline script!

A. Preparing SDK

        def home = sh(script: "echo $HOME",returnStdout: true).trim()
def SDKPath = "$home/Android/SDK"
stage("Preparing SDK"){
// Check SDK Downloaded
def isSDKDownloaded = sh(script: "test -e sdk-tools-linux-4333796.zip && echo true || echo false",returnStdout: true).trim()
if(isSDKDownloaded == "false"){
// Download SDK
sh "wget 'https://dl.google.com/android/repository/sdk-tools-linux-4333796.zip'"
}
// Check if SDK is Extracted
def isExtracted = sh(script: "test -e $SDKPath/tools && echo true || echo false",returnStdout: true).trim()
if(isExtracted == "false"){
sh "mkdir -p $SDKPath"
//Unzip SDK
sh "unzip sdk-tools-linux-4333796.zip -d $SDKPath"
}
// Install SDK Tools
sh "yes | $SDKPath/tools/bin/sdkmanager 'build-tools;28.0.3' 'platform-tools' 'platforms;android-27'"
sh "ls $SDKPath/licenses"
// See installed And Available SDK
sh "$SDKPath/tools/bin/sdkmanager --list"
// Accept All SDK Licences
sh "yes | $SDKPath/tools/bin/sdkmanager --licenses"
}

What really happens in the script above is about preparing the server computer environment to be ready to build Android SDK. Preparing SDK means download Android SDK, extract, and install it. The following are the steps:

  1. Define the path of the Android HOME, then use it to define the path of Android SDK.
  2. Check if the SDK has been downloaded in the slave’s computer, then if the SDK has not been downloaded yet, then we must download the SDK to the computers based on the computer’s OS.
  3. Extract the SDK in the SDK Path that has been defined previously.
  4. Install SDK tools that have been extracted, use the $SDKPath/tools/bin/sdkmanager path to install the SDK. See installed and available SDK, and accept all the SDK licenses by following the above script.

B. Build Production APK

         def selectedBranch = SELECTED_RELEASE_BRANCH
stage('Checkout') {
git branch: selectedBranch, url: 'git@bitbucket.org:styletheory/styletheory-android-dummy-app.git'
// Remove Existing local properties
sh 'rm local.properties ||:'
// Write sdk.dir Path into local properties file
sh "echo 'sdk.dir=$SDKPath' >> local.properties"
}

stage('Setup Tools') {
withCredentials([file(credentialsId: 'android_keystore', variable: 'KEYFILE')]) {
sh "cp \$KEYFILE app/keystore.jks"
}
}

stage('Build Release APK') {
sh "./gradlew clean assembleRelease"
}

This second step is about building the production APK through Gradle command:

  1. Set the selected GIT branch based on the input user from the parameter.
  2. Checkout to that branch, remove existing local.properties, and write new local.properties.
  3. Next step is to copy the android_keystore that we already saved in Jenkins to a variable called KEYFILE. Copy that file on app/keystore.jks. The path depends on where you defined it in Gradle, we discussed this in section 2 previously.
  4. Build Production APK, do it by running a command ./gradlew clean assembleRelease. It will use all the Keystore information that has inputted by the user and also the file that has been copied from Jenkins itself.

C. Upload to Production

         stage('Upload to Play Store') {
androidApkUpload googleCredentialsId: 'Google Play Key', apkFilesPattern: '**/*-release.apk', trackName: 'production'
}

stage('Cleanup Credential') {
sh "rm app/keystore.jks"
}

Allow me to explain the above script:

  1. Use Google Play Android Publisher plugin to upload the generated APK to Play Store. If you haven’t installed Google Play Android Publisher plugin, install it on Manage Jenkins -> Manage Plugins -> Available.
  2. After installing this plugin, run command androidApkUpload. Specify googleCredentialsId that we already store in Jenkins (P12 File), apkFilesPattern of the production APK pattern, and also trackName of the track: it can be alpha, beta, and also production.
  3. After successfully upload the APK to Play Store, don’t forget to Cleanup Credential by removing the keystore file itself from the computer.

That’s all! That’s how you build the automatic APK uploader to Play Store!

Weeks after implementing this automated process, we received many positive feedbacks!

  • It boosts up development time. QA doesn’t need to work with Android engineer only to upload the final app! No more bottleneck! Even the QA can compile, build, and upload by themselves.
  • It improves productivity! Since Android engineers are not required to wait for the green light from the QAs and upload process to Play Store, they have plenty of time to do something else. They can do tech-improvement, backlog’s stories, or even do unit test for features! It enhances quality in software as well!

It is not perfect yet. There are still improvements to be done in the future! We can connect with GIT flow as well to integrate all the processes of software development. Wait for it in the next article! ☺

--

--