Deploy our App at Ease with Gitlab CI

Muhfathurh
6 min readMay 25, 2021

--

As you have (maybe) noticed in my other writings already, I’ll start this with a narrative about ci/cd use case. Imagine that you’re in a team, developing a web app that surely, upon analysis by your team will be a big hit. However, midway in development period, you encounter an annoying repetitive problem. Building your app in its environment, testing it through unit/functional test or manually from your “prototype” web app, and deploy it in your “prototype ”web app is a pain that must be done every time you add something to our code. Considering that, we seek to automate those steps and allowing us to make changes in code without fear of repeating those repetitive steps. That’s where Gitlab CI and CI/CD concept coming to the rescue!

Continous Integration & Continous Development

cicd-tools.jpg (850×450) (onecg.cc)

CI/CD is a concept that is used to frequently delivering your apps through automated steps. An analogy to this can be seen in car manufacture, although its is not an apple to apple analogy. First, we need to design parts of car, build it, and integrate it with already finished part. Then, we need to test it to check any possible error or mistakes that we had made, we can also check how its behavior with another component that already finished too. After that, we took it into our testing environment (such as wind tunnel or the others in this analogy), and check its behavior again. After we finish those steps, we can release our new car to the public and repeating those procedures to create a new car. Those build, design, and testing phase before testing environment can be called as continuous integration, while moving our car into testing environment and release it to public are what we called continuous development.

In short, CI involved in integrating our code changes with ease by build, packaging, and test it every time we make changes in our code. Meanwhile CD is about how we deliver our app into selected environments. Of course, both of them are automated, delegating repetitive process to machine will certainly help us a lot :D!

There are several examples of CI/CD tools that we can use, such as Jenkins, Circle CI, Travis CI, and Gitlab CI. For this writing, I will demonstrate how to deploy your app with Gitlab CI, mainly due to most of project are located in Gitlab that integrates directly with gitlab CI. Gitlab CI is also easy to learn and had interesting features such as code reviews and merge request that help us, developers, a lot.

Environment

Environment can be defined as a place where we build our application. We separate our development environment to avoid any major error/bugs that potentially appeared in our development from being published public. In general, there are 3 environment that we use in application development:

  1. Development Environment: Environment where developers develop their code and used to build our application. It is not accessible to public because of being developed locally and synchronized with Git repository.
  2. Staging Environment: Place where we test our application and see if our app is working in this realistic environment. We call that realistic because of it has similarities with production environment with the only different staging environment’s url kept hidden from public and used of mock data. We can also use this environment to test user’s feedback and present our newest changes to stakeholders.
  3. Production Environment: Place where our real-known application located. Changes will only made it into this place only if they had passed 2 previous environment before. This environment use real live data and actively engaged with end to end users.

One things to be noted in this environment, especially staging and production environment, developers usually use container-based deployment. Container-based deployment means that we use container to build our application before releasing it to targeted environment. Why we use container? Well, that is because containers are has significantly smaller image size than virtual machines and we can isolate our app environment for better testing and development. You can read my writing about docker for further discussion about it.

Example of Gitlab CI Usage

Now we have done with basic theories about it, let’s move on into its implementation! After all, knowledges without practices are useless, isn’t it?

Finally we have finished build our scripts and it will look like this:

Some things to be noted in this scripts:

  1. To determine stages of our application pipeline, we use stages. You can use build stage to build your application if you use docker or other containers, otherwise, Gitlab already provided images/container that you can use and you can skip this stage. The rest of our stages are test, sonar, and deploy. Test stage is the place where we test & lint our code and check any errors that occur. We send our project to be analyzed by sonarqube (static code analyzer) in sonar stages and deploy our apps in deploy stages.
  2. Then, we need to specify jobs for each stages. For test stages, I will pull python3.6 image because I use Django framework and to create similar environment with staging and production environment (Heroku’s default python image is python3.6). We can also specify additional services that we can use by using services. In this case, I will use postgres as my test database with its variables being defined in variables. before_script will run all command that is written inside that block before it run this job. When will specify any condition that needs to be fulfilled before we run our jobs. All of our job command will be located in script. We store and save required file that needs to be passed in our pipeline, such as code coverage, in artifacts.
  3. Our next stage, sonar, consists of 2 possible jobs. SonarScanner will only executed in master and staging branch, while SonarScanner Dev will be executed in all branches except master and staging. To specify where we will run or not run this jobs, we use only and except respectively. Because we use sonarqube, this stages will pull sonar-scanner image.
  4. Our last job is deploy. One thing to notice, because we use heroku for both production and staging environment, it has similar command with different arguments. To prevent copy and paste in our script, I create a skeleton of Gitlab CI job, by using . before the name of the job (in this case .deploy) and use extend to create a new job that used .deploy as its skeleton. Major advantage of this is I can create a new environment, with its own name and specify each variables based on our environment scope.

Now that we have finished our script, let’s setup our environment variables. To setup our environment variables, we need to navigate to Variables setting through Settings > CI/CD > Variables, then we can add variables based on what we need, in my case all variables about Heroku. As a result, in variables setting you will show detail like this

Example of Gitlab CI Variables

If you encounter any problem, such as no environment scope available, I suggest you to push .gitlab-ci.yml scripts into Gitlab repository first and do it again. At the very least, that’s what I had done previously. Now, let your script running in Gitlab CI/CD pipeline, pray that no red marks available, and your pipeline should look like this:

Successful Gitlab Pipeline

Finally, we arrived at the end of our article, hopefully, with this you can understand what is CI/CD and how to implement it with Gitlab CI. Now you can say good bye to annoying repetitive task and let our scripts do the job, Cheers!

--

--