Setting up a Basic CI/CD Pipeline in GitLab
An all-inclusive DevOps solution for version control, continuous integration, continuous deployment, and project management is offered by the web-based platform GitLab. It makes it possible for teams and developers to work effectively together throughout the full software development lifecycle. GitLab offers a variety of tools to simplify development procedures and boost productivity, whether you’re working on a tiny personal project or a huge enterprise-level program.
Key Features and Components of Gitlab
- Version Control
- GitLab CI/CD (Continuous Integration/Continuous Deployment)
- Issue Tracking and Project Management
- Wiki and Documentation
- Code Review and Collaboration
- Integrations and Extensions
Setup basic pipeline using Gitlab
- Sign in to your Gitlab account.
- Then click the “Create blank project” button.
3. Then you can see the below screen.
Here, you need to give a project name, and you can enable static application security testing, which is helpful for you when you are using this with your actual project. Additionally, you can select project deployment targets. For example, if you wanted to deploy Kubernetes, you can select that, and it will set up some templates for you.
4. Now you can see the project is created.
5. Now you can navigate to “build” from the navigation menu. Then click pipelines.
6. Then you can there are so many templates available. For this, I use the “Bash” Template.
7. Now you can there is yml file that includes the configuration for our pipeline.
Here, you can find the line “image: busybox latest.” This line indicates a Docker container provided by GitLab.
Below that image, you’ll notice the `before_script` and `after_script` sections. The `before_script` contains scripts that run before the job, setting up the environment for that particular task. These scripts can be configured globally or on a per-job basis.
Similarly, the `after_script` section contains scripts that run after the job completes. This step is typically used for cleanup or for handling artifacts between different stages.
Moving further down, we have the main part of the pipeline. The first step is the `build` stage, as denoted by `stage: build`. The `script` section defines the commands that run during this stage of the pipeline.
In this example, the script merely echoes a string to the console. When you hover over it, you may get a tooltip providing more context.
Following the build stage, there are two `test` jobs, both belonging to the `tests` stage. GitLab pipelines are designed to run these jobs in parallel as part of the test stage, as mentioned in the comment.
Finally, there is a `deploy` stage at the end. For now, we don’t need to make any changes to this file. We’ll simply commit it to our repository. Feel free to add a more complex commit message if you like.
To commit the changes, place the file in the main branch and click on “commit changes.” As you do this, you’ll notice something happening at the top: “checking pipeline status.” GitLab will now run the newly created pipeline.
8. You can click View Pipeline now. You can see a pipeline like this.
Additionally, you’ll notice the “rerun” button available here. This feature allows you to restart a specific job within the pipeline.
9. If you click pipeline stages you can see a console like this:
10. If you click the pipeline editor button you can see yml file in there.
Then you can edit the pipeline.
11. And you can click visualize button to see how is your pipeline looks like.
12. You might have noticed that in our previous configuration, we haven’t explicitly defined the order in which our stages are supposed to run. They automatically ran in the sequence: build, test, deploy.
To make the pipeline stages more explicit, we’ll add a new top-level key-value pair in our YAML file.
Now, let’s delve into passing artifacts from one job to the next. To start, we’ll define the stages explicitly in our YAML file. We’ll use the following stages: build, test, and deploy. Do note that you can define any stages you prefer, as they are arbitrary strings. For simplicity, we’ll stick with the defaults.
Moving on to passing artifacts between jobs, let’s focus on the build stage first. We’ll add another line here to create an artifact. For instance, we can use the `echo` command to create a file, and then we’ll use the `tee` command with a pipe character to save its output to a text file called `file.txt`.
build:
stage: build
script:
- echo "This is a file" | tee file.txt
Now, to handle the created artifact in the test stage, we need to modify the `test1` job. To do this, we’ll use the `dependencies` command. Clicking on it will provide an array of strings, which represents the names of jobs that this specific job depends on.
The example we’ve explored here is indeed simple, but in real-world scenarios, GitLab pipelines can become much more complex and powerful. As I mentioned, tasks like compiling binaries, packaging code, and generating discrete artifacts for testing are common use cases in more sophisticated pipelines.
GitLab pipelines offer a wide range of possibilities for automating various stages of the development, testing, and deployment processes. You can incorporate multiple jobs, utilize different stages to organize the pipeline flow, and leverage various GitLab features like caching, environment variables, and integrations with external services.
Furthermore, GitLab CI/CD allows you to define custom scripts and commands, perform code quality checks, and deploy your application to different environments automatically based on your specific needs.
14. Now, if we open up the `test1` job, where we added our `cat` command to display the content of the file passed from the `build` job, you can see the result. The file we created in the `build` job was successfully passed along, and its content, which is simply “This is a file,” is output here.
However, we can enhance this test to offer more meaningful pass/fail functionality. Let’s make some modifications to the `test1` job. To keep things simpler, we’ll delete some of the example content and add a new line describing the test: “Echo testing for string GitLab.”
For the test, we’ll use a simple approach using Bash. We’ll employ the `grep` command, which allows us to use regular expressions to search within a file. In our case, we’ll look for a specific string. We’ll use `grep` with the pattern “GitLab” and the name of our file, and let’s run the test to see the results.
variables:
MY_WORD: "gitlab"
image: busybox:latest
stages:
- "build"
- "test"
- "deploy"
before_script:
- echo "Before script section"
- echo "For example you might run an update here or install a build dependency"
- echo "Or perhaps you might print out some debugging details"
after_script:
- echo "After script section"
- echo "For example you might do some cleanup here"
build1:
stage: build
script:
- echo "Do your build here"
- echo "This is a $MY_WORD"|tee file.txt
artifacts:
paths:
- "file.txt"
test1:
stage: test
script:
- echo "Testing for string 'gitlab'"
- grep "gitlab" file.txt
dependencies:
- "build1"
test2:
stage: test
script:
- echo "Do another parallel test here"
- echo "For example run a lint test"
deploy1:
stage: deploy
script:
- echo "Do your deploy here"
environment: production
If I go back to my pipeline view, which you can get to on the right here, you can see that test we just added actually passed. You can change the MY_WORD variable and see test passing and failing according to that.
15. Generate a static website
Let's add a markdown file to GitLab
Then paste the below yml configuration using the pipeline editor.
variables:
MY_WORD: "gitlab"
image: alpine:latest
stages:
- "build"
- "test"
- "deploy"
render_website:
stage: build
script:
- apk add markdown
- markdown website.md | tee index.html
artifacts:
paths:
- "index.html"
test_website:
stage: test
script:
- apk add libxml2-utils
- xmllint --html index.html
dependencies:
- "render_website"
deploy_website:
stage: deploy
script:
- echo "Do your deploy here"
environment: production
Alpine is a lightweight Linux container that provides more capabilities than Busybox, allowing us to install additional applications for rendering and testing. Let’s proceed with the modifications:
In the `build1` job, we’ll rename it to `render_website`. We can remove the existing scripts and replace them with the following commands:
render_website:
stage: build
script:
- apk add markdown
- markdown website.md | tee index.html
artifacts:
paths:
- index.html
In the `test` job, we’ll rename it to `test_website`. We’ll also add a command to test the validity of the HTML file using the `xmllint` tool from the `libxml2-utils` package:
test_website:
stage: test
script:
- apk add libxml2-utils
- xmllint --html index.html
dependencies:
- render_website
We can now delete the `test2` job.
Finally, let’s update the name of the `deploy` stage to `deploy_website`.
Once you commit these changes to GitLab, you can observe your pipeline running with your dummy website.