It’s really useful.

Imagine your team is working on a project. Everyone is working on different parts, and they need to be combined to make the app work. Now try to imagine the combination process needs to be done manually, every file combined into a folder, not to mention changes within the same file. Sounds like hell, right?

Now your code is ready to be deployed. You do the process manually, possibly wasting precious time that you can use to do something else (not to mention possible errors when deploying). All of this sounds like a pain, right?

Now imagine doing this daily.

That is why we have CI/CD, and I will try to explain as concisely as possible about this thing.

Continuous Development (CI)

Continuous Integration (CI) is a development practice that requires developers to integrate code into a shared repository several times a day. Each check-in is then verified by an automated build, allowing teams to detect problems early.

By integrating regularly, you can detect errors quickly, and locate them more easily. — ThoughtWorks

I think that definition already explains quite well what CI is. CI can help us in combining our works into one repository automatically. CI can also help us check if our code is working by running the tests created by the team.

Continuous Development (CD)

Continuous Delivery is the ability to get changes of all types — including new features, configuration changes, bug fixes and experiments — into production, or into the hands of users, safely and quickly in a sustainable way.

Our goal is to make deployments — whether of a large-scale distributed system, a complex production environment, an embedded system, or an app — predictable, routine affairs that can be performed on demand.

We achieve all this by ensuring our code is always in a deployable state, even in the face of teams of thousands of developers making changes on a daily basis. — Jez Humble

The main goal of CD is so your working code can be immediately deployed into a working application, no matter the size of the changes (preferably small).

Benefits of CI/CD

There are some excellent incentives to implement CI/CD, such as:

Smaller changes

As the process of integrations is done automatically, it’s now feasible for developers to push small blocks of code one at a time rather than one big block. This makes it easier to know which code makes what changes, and in case of errors, one can immediately know the source of the problem.

Easier to find errors

CI/CD can highlight if there are any faults, errors, or regressions in codes, so developers can immediately check the part that creates the error.

Lower costs

The process of combining the codes and deploying them is already automated by the CI/CD, so developers can focus on other things to do and also avoiding the cost of error-fixing in case of errors in integration or deployment.

CI/CD in our project

In our project, we use GitLab as our code repository and also uses GitLab CI as our CI/CD tool. Gitlab CI utilizes a script called .gitlab-ci.yml, and the good thing is you can modify this file as you like, depending on what you need. I would share our CI file, but it seems that you need to log in to GitLab CSUI to view the file.


Our three main stages for our CI.

There are three stages in our CI. The first one is test, where it will run all provided unit and functional tests and also checks for code smells with pylint. The second stage is sonarqube, where the code is integrated into SonarQube. Lastly, there is deploy, where the code will be deployed into Heroku, where the app can be accessed.

Unit Test

the code for the UnitTest job.
  • image: Consists of what version of python we are using. In this case, it’s Python 3.9.1.
  • stage: Specifies which stage this job belongs to.
  • before_script: Consists of commands to run before the job, such as collecting requirements and dependencies, collecting files in the app such as static files and migrations.
  • when: on_success means this job will only be done if the previous job is successful.
  • scripts: Consists of the commands for the job.
  • artifacts: Specify files and paths that are attached to the job.
  • only: specifies which branch this job should be added to.


The code for our Pylint job.
  • allow_failure: If the job isn’t successful, subsequent jobs will still be executed. In this case, if the pylint score isn’t perfect, then the pipeline is still allowed to continue. We do this because having a clean code shouldn’t affect whether an application can be deployed or not.


  • except: Works the opposite of only, branches listed here won’t have the job be executed on those branches.


  • environment: creates an environment with the name and URL provided.

If all things go well, this is what you should see when you check the pipeline:



CI/CD is a very powerful tool to use in your project, as it can save a lot of time doing things that you would usually do manually in an automatic and safer way. Not only to save time, but using this may also save you from going insane from all the repetitive and prone-to-failure tasks that you need to do every time.




Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store