GitLab CI/CD Integration for Android Apps (Part1)
Many of us had already implemented or tried to implement the CI/CD pipelines in our mobile application development with little or no exposure to actual scripting languages.
One such integration I need to add in my recent projects where Jenkins is already being used as CI/CD to release builds but the project repository is already using Gitlab. So, now let's try to use the same for the release process.
In this post, I will tell you about the problems and technical issues I faced during the integration.
Prerequisite:
I am assuming you already have a runner set up in your local machine or server. A runner is an agent in the GitLab Runner application that runs jobs in a GitLab CI/CD pipeline
Steps to integrate :
- Go to your root Android project directory and create a file named .gitlab-ci.yml we need to use the same name for our file. This file uses yml format to write the script which contains the CI/CD configuration.
- Docker Image
Add the docker image we are using to execute our script.
Note: For docker images, we can use the already available images specifically for Android. You can use any of the images as per your requirements from the official docker images link
If you want to create a docker image of your own, I will help you in my next post from Scratch
The image
keyword is the name of the Docker image the Docker executor uses to run CI/CD jobs.
Let's assume we have used the image androidbuildimage : 1.0
this is the one I created so you cannot find this on the official site.
default:
image: androidbuildimage:1.0
3. Variables
If there are any variables
you need in the script to define constants or want the user to select from a list of options while running the pipeline, variables come into the picture.
CI/CD variables are a type of environment variable. You can use them to:
- Control the behavior of jobs and pipelines.
- Store values you want to reuse.
Variables can be global or local to a specific Job in the script.
There are many Predefined CI/CD variables available to any job for Ex.
CI_COMMIT_AUTHOR, CI_COMMIT_BRANCH, CI_COMMIT_SHA,CI_COMMIT_TITLE
These are specially used to get information about builds to publish the status of builds to Slack or any other tool.
variables:
TARGET_CLIENT:
value: custom
options:
- "ProdTest"
- "Staging"
- "qa"
- "dev"
description: "Select the variant from list of all variants"
Now this will give you an option to select the target env to build the app from the list of options while running the pipeline.
Note: There is a limitation on GitLab variables. We cannot use a list /array to populate the options. So we have to manually add all the options that we want to show on the build pipeline.
3. Stages
Stages, define when to run the jobs. For example, there are multiple stages in a pipeline
A typical pipeline might consist of four stages, executed in the following order:
- A
build
stage, with a job calledcompile
. - A
test
stage, with two jobs calledtest1
andtest2
. - A
staging
stage, with a job calleddeploy-to-stage
. - A
production
stage, with a job calleddeploy-to-prod
.
stages:
- test
- build
- staging
- production
4. Workflow
workflow
comes into the picture when you want to start your pipeline automatically. When a certain task is accomplished like an MR has merged the code in the default branch of the repo, it triggers the pipeline. This will ensure that the code being merged is not breaking anything.
In this, I am using the predefined global variables from the CI/CD pipeline that are available to every job. The job will only start when this condition is met.
workflow:
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
5. before_script
Use before_script
to define an array of commands that should run before each job’s script
commands.
We can use other script files to run in the.yml file to publish the status of builds eg. the build has been started, the build has been successfully created, successfully uploaded to Firebase, or other platforms.
before_script:
- source [..path to script in the root folder]/script/slackscript.sh; share_slack_build_start
6. script
Use script
to specify commands for the runner to execute.
This is the main area where you have to add all the steps you need to create the build, create release notes, and create files in the project directory.
For this, you can also include a separate bash file where all the steps are written to segregate.
Note: You can use loops, globally defined gitlab variables, custom variables, and if else statements in the script file for build creation.
I struggled a lot to use all these in the script file because it was something that I had never worked on before. So, I am adding it for your reference it will help you guys also.
if [[ "${TARGET_CLIENT}" == "ProdTest" ]]; then
DEPLOY_ENVIRONMENT="Prod"
for client in ${ProdTestBuilds[@]};
do
echo "targetVariants=${client}" >> $GRADLE_PROPERTIES
echo "Build create ${client}"
./gradlew assemble$client$DEPLOY_ENVIRONMENT$BUILD_TYPE
cp ${RELEASE_NOTES} ${RELEASE_NOTES_FINAL}
./gradlew appDistributionUpload$client$DEPLOY_ENVIRONMENT$BUILD_TYPE -PappDistribution-artifactType="apk"
done
7. artifacts
Use artifacts
to specify which files to save as job artifacts. Job artifacts are a list of files and directories that are attached to the job when it succeeds, fails, or always.
The artifacts are sent to GitLab after the job finishes. They are available for download in the GitLab UI.
Many people struggled with uploading the artifacts to Firebase as they did not have the actual path where they could get their artifacts.
So, basically output folder is the one that has all the artifacts that are created.
artifacts:
paths:
- /application/app/build/outputs/releasenotes.txt
- /application/app/build/outputs
So this is the basic syntax for the .yml file.
In the next post, I will explain how the docker image is created that has all the preinstalled Android SDK & Java that you need to create builds to make the build faster.
If this post helped you in any way please like and follow me for other informative posts.
Stay Tuned !!!