November 16, 2022
November 1, 2022
CI/CD stands for continuous integration and continuous delivery/continuous deployment. In the software world, the CI/CD pipeline refers to the automation that enables incremental code changes from developers’ desktops to be delivered quickly and reliably to production. This article will guide you on how to create and run a CI/CD pipeline using GitLab.
GitLab CI/CD is a tool for software development using the continuous methodologies:
To put it simply, GitLab CI/CD can automatically build, test, deploy, and monitor your applications. It can help you catch bugs and errors early in the development cycle, while also ensuring that all the code deployed to production complies with the code standards established for the application.
First, create a repository for our project and push some sample files.
Create the CI/CD configuration file .gitlab-ci.yml and add a first test job. We can also view the .gitlab-ci.yml syntax reference here.
Once we pushed the .gitlab-ci.yml file, the Gitlab pipeline will be triggered and run the job. Now, we can see the pipeline is running and this job should be done.
All our jobs will be run by an application called Gitlab runner. So, to find out what the Gitlab runner is, let’s read on.
GitLab Runner is an application that works with GitLab CI/CD to run jobs in a pipeline. Written in Go, it’s open-source and can be run as a single binary; no language-specific requirements are needed.
GitLab Runner can be installed on several different supported operating systems. Other operating systems may also work, as long as a Go binary is compiled on them.
Here is the scope of runners:
If you use GitLab.com, you can run your CI jobs on Runner Cloud. These are runners managed by GitLab and fully integrated with GitLab.com. These runners are enabled for all projects, though you can disable them. If you don’t want to use runners managed by GitLab, you can install GitLab Runner and register your own runners on GitLab.com.
Shared runners are available to every project in a GitLab instance.
Use shared runners when you have multiple jobs with similar requirements. Rather than having multiple runners idling for many projects, you can have a few runners that handle multiple projects. As the example above, the jobs are run by shared runners because on GitLab.com, shared runners are enabled in all projects by default.
Use Group runners when you want all projects in a group to have access to a set of runners. Group runners process jobs by using a first in, first out (FIFO) queue.
Use Specific runners when you want to use runners for specific projects. For example, when you have:
You can set up a specific runner to be used by multiple projects. Specific runners must be enabled for each project explicitly. Specific runners also process jobs by using a first-in, first-out (FIFO) queue.
In the next part, we will learn how to deploy from GitLab to the server automatically.
We will set up the Gitlab CI/CD pipeline to create a react app build, test, and deploy to our server whenever code is merged to the main branch using shared runners.
We are going to use Gitlab CI/CD Variables to save a private SSH key, user, and host which Gitlab will use to authenticate with the server. These SSH keys are used to authenticate rather than using usernames and passwords, as it is more secure. This can be configured at a repository level or at a group level.
To view all the CI/CD variables of our repository:
To create a new variable, Select the Add Variable button and fill in the details:
Finally, Click Add Variable to add the variable:
Repeat the same as above steps to create SSH_USER and SSH_HOST variables:
Gitlab looks for .gitlab-ci.yml in the root folder of our repository for CI/CD pipeline configurations. Once we added the .gitlab-ci.yml file and push it to our GitLab repository, GitLab will detect this file and a GitLab runner will go through the file and run all the jobs that we specify there.
In this file we can define the scripts that we want to run, we can run commands in sequence or in parallel, we can define where we want to deploy our app and specify whether we want to run the scripts automatically or trigger any of them manually. We need to organize our scripts in a sequence that suits our application and in accordance with the test we want to perform.
Let's see the example below:
Explanation:
Let's include this code in our .gitlab-ci.yml file and commit those changes to our repo.
If we go to our repo we will see that our pipeline is running, let's take a look at our pipeline, we need to go to CI/CD and then to pipelines in our sidebar:
Then we will see the progress/status of our jobs here:
So, this was a very simple example to see how the pipeline works, we have two stages, and in the first one we just build the application and in the second one, we run our tests. You might be asking why are we running "yarn install" 2 times, surely there's a better way to do it.
This is because each job runs in a new empty instance and we don't have any data from previous jobs, in order to share data we need to use artifacts or cache, what's the difference?
Artifacts:
Cache:
So, let's improve our pipeline:
Now we don’t need to add ‘yarn install’ at the test stage because the node_module folder was shared from build stage, and that will improve the speed of the build.
Let's commit our code, and we'll see that everything still working, that's good!
Now we will add the deploy stage to our .gitlab-ci.yml file, our last version of this file will be this one:
In order to make this happens, we need to establish an SSH connection between our pipeline and our server, to do that we will need to use our SSH_PRIVATE_KEY, SSH_USER, and SSH_HOST variable that was created at step 1.
So, for this stage we will use ubuntu image and need to run this command:
Next, we need to save our SSH_PRIVATE_KEY value as a file and grant permissions so we can use that file for SSH.
Finally, we will open an ssh connection to the server with StrictHostKeyChecking to no, to ensure git doesn't show a manual prompt during the initial connection. Then we cd to the folder that our project is placed and run the script in deploy.sh.
Add a new file deploy.sh in the root folder.
Here’s the explanation:
We can also modify this to meet our app requirements.
Now that everything is ready, let's commit and push our code to see the result. We can check our pipeline status by going to CI/CD > Pipelines, then clicking the status button of our pipeline.
We can also click the individual job to see the command line output of our script. Once our pipeline passed we can verify that our server is running perfectly and should apply new code.
That's all, now every time that we push our code into our repo, our pipeline will build our app, then it will run our tests, and finally, it will deploy our app into our server!
I hope this tutorial helps you learn how to build, test and deploy your application using Gitlab CI/CD. Thank you for sticking with this article until the end. Follow us for more cool technical stuff from an Offshore Development team in Vietnam. If you are curious about our services, visit https://fabatechnology.com/ to get your questions answered.