Dietela: Quick Release Cycles with CI/CD

How we emphasize on maintained quality, risk reduction, and fast learning curve.

Wulan Mantiri
5 min readMay 2, 2021

This article is written as an individual review assignment for PPL CS UI 2021.

We, the Dietela developer team, have applied agile development and automated dirty code detection to deliver a product with speed and quality. Now, it leaves us one question. Where is the product?

It is almost useless if developers attempt to speed up their software development process, but end up with slow iteration of product release.

Here, we will cover the essence of fast iteration with CI/CD practice and the convenience of Gitlab CI/CD with Docker images.

The Essence

The Practice of CI/CD

First, CI stands for Continuous Integration. In the context of utilizing Git, CI is the practice where every commit fires off a process (or pipeline jobs) to rebuild the codebase, run entire test suites, and if deemed necessary, collect code coverage.

Second, CD stands for Continuous Deployment. As the name suggests, CD is the practice where new codes that are pushed to production, or any public branch, are automatically shipped and reflected into the product within minutes. Another variant of CD is Continuous Delivery, where developers will selectively determine which changes, bundled in versions, to deploy.

Combined, CI/CD is the practice of automated preparation and deployment for product release.

The Need for Fast Iteration

The conventional way of releasing software is per schedule basis (weekly, monthly, quarterly, etc.) with a manual mechanism that might take hours or days.

Compared to CI/CD that can release software up to 50 times a day in some companies like Quora, the conventional approach is rather very slow in comparison. Their concerns of “fast iteration” are usually around:

  1. the principle of “quality > quantity”,
  2. sacrifices of reliability, or
  3. simply the question, “Why would we even want to release software that often?”

However, CI/CD actually accommodates the answers to the concerns above while ensuring fast iteration.

  1. Deploying small, incremental changes facilitates debugging process.

When a bug surfaces or performance drops after release, developer teams with a longer release cycle have to search through hundreds of changes to figure out which change breaks the product.

On the other hand, since changes come in smaller batches for CI/CD, the code quality is more well-maintained. Teams that follow CI/CD practice can easily isolate the culprit of the identified problem into just a handful of changes. Not to mention, it is also relatively easier to reason about changes if it comes in small amounts.

2. Fixes can be implemented and delivered immediately.

If a bug is discovered, CI/CD makes it possible for the developers to implement a hot fix, deploy it, and verify if the fix solves the issue in one sitting.

With the conventional workflow, those three phases might take over multiple days or even weeks. The developers have to wait for their fixes to be packaged up with other changes for the next release, and then validate those fixes along with a bunch of other unrelated changes.

Sure, the chances of finding a bug in the release that has been checked by the quality assurance team are low, but never zero.

Therefore, I would say the conventional workflow sacrifices reliability more than CI/CD, as the longer the bug that linger in the product, the more users it affects.

3. Faster learning curve and more frequent feedback loops

Let’s bring back the question: “Why would we even want to release software that often?”

Well, it is a matter of priority. For our team, we focus on increasing impact rather than minimizing mistakes.

With fast iteration, we can learn a lot quicker on what works and what doesn’t. Every code change does not always produce positive impact as we would hope especially when the product grows bigger. Nonetheless, we can take all of that as lessons learnt to not repeat similar changes in the future.

The Convenience

Our CI/CD practice for fast iteration to release our Android app product are divided into four (4) stages.

The first three (lint, test, and sonar-scanner) are for CI purposes, showing lint warnings, calculating code coverage, and triggering SonarQube to conduct a clean code evaluation based on the code changes. These stages are always executed everytime there is a commit pushed to any branch in the repository.

Meanwhile, the final stage “build” is for the CD purpose of compiling and building the APK file, accessible in a downloadable artifact format. This stage is exclusive to changes in public branch (in our case, we have staging and master).

3 preparation stages for CI, and 1 final stage for CD
private branch only triggers CI (bottom) vs pushing to public branch triggers both CI/CD (top)

The Help of Docker Images

In case you are wondering, the (pipeline) stages above are actually scripts that will run on Docker container(s) based on the specified Docker image when executed. All of the pipeline scripts are written in .gitlab-ci.yml file.

In a nutshell, a Docker container is an isolated environment used to run codes (from a simple script to a whole application), while a Docker image is a read-only template used to build Docker containers.

  1. These are the scripts for the three stages in CI:
lint and test stages

Lint and test stages are comprised of simple scripts that only require one dependency, which is yarn from Node package manager. Our best choice is to use node Docker image with slim variant to save memory and time for the Gitlab pipeline runner.

sonar-scanner stages (different cases for private and public branch)

Fundamentally, the sonar-scanner stage only contain one line of command that only require sonar-scanner dependency from sonarsource.

2. Meanwhile, below is the script for our build stage for CD:

build stage (Android version)

Build stage for Android consists primarily of assembling APK release artifact with dependencies gradle and yarn coming from two different package managers. We use reactnativecommunity/react-native-android Docker image to accommodate both requirements.

In conclusion, if your priorities are either of these: (1) iteration speed with maintained quality, (2) risk reduction of lingering bugs, and (3) fast learning curve, follow the CI/CD practice like we do and enjoy the benefits!

References

  1. The Effective Engineer book
  2. https://docs.docker.com/get-started/overview/

--

--