In the previous section, we registered a group runner. In this lesson, we will implement a simple CI/CD process.
To make the shell script execution more secure, for each project group, we will create a user in the Instance with the same name and only grant execution permission to the build folder for that user. In this case, we need to create a user named ecommerce
.
Run with root privileges and create the user ecommerce
with the corresponding information:
exit
adduser ecommerce
We will grant sudo privileges to both gitlab-runner
and ecommerce
users so that when a user uses sudo, they won’t need to enter a password.
Type visudo
:
visudo
Add the following lines below root ALL=(ALL:ALL) ALL
:
gitlab-runner ALL=(ALL) NOPASSWD:ALL
ecommerce ALL=(ALL) NOPASSWD:ALL
Press Ctrl+X → Y → Enter to save.
We need to install the net-tools
utility.
apt install net-tools
We can verify by using the command:
netstat -tlpun
We should see two projects running on port 3000 (frontend) and port 5214 (backend).
net-tools
will check if a process for the backend or frontend is running and will kill it during the CI/CD process. If it’s not killed, the application won’t be able to run with the new source code!
Before running CI/CD, we need to check if the gitlab-runner
user has the required tools: node
, dotnet
, pm2
by running:
su gitlab-runner
cd
dotnet --version
node -v
npm -v
pm2 -v
In the backend project, select build
→ Pipelines Editor
→ Configure pipeline
.
We will add the .gitlab-ci.yml
file to the main branch to simulate running the CI/CD pipeline when deploying to production. You can customize it according to your strategy!
In the .gitlab-ci.yml
file, we will enter the following:
variables:
USER_PROJECT: "ecommerce"
PATH_PROJECT: "/home/${USER_PROJECT}/${CI_PROJECT_NAME}"
stages:
- build
- deploy
before_script:
- sudo mkdir -p $PATH_PROJECT
build:
stage: build
variables:
GIT_STRATEGY: clone
script:
- dotnet restore
tags:
- group-ecommerce-shell-runner
only:
- tags
deploy:
stage: deploy
variables:
GIT_STRATEGY: none
script:
- sudo cp -rf * ${PATH_PROJECT}
- sudo chown -R ${USER_PROJECT}. ${PATH_PROJECT}
- pid=$(sudo netstat -tulnp | grep :5214 | awk '{print $7}' | cut -d'/' -f1) || true
- if [ -n "$pid" ]; then sudo kill -9 $pid; fi
- sudo su ${USER_PROJECT} -c "cd ${PATH_PROJECT};nohup dotnet run > log_be.txt 2>&1 &"
tags:
- group-ecommerce-shell-runner
only:
- tags
Explanation of the file above:
Variables
Before Running Stages
Stages
clone
means the source code will be cloned from the repository.pid
variable. If not found, pid
will be empty (true prevents an error from occurring).pid
variable is not empty (i.e., there’s a process listening on port 5214), that process will be forcefully terminated using the kill -9
command.nohup
. The output will be logged to log_be.txt
.In the Visualize
tab, we can see two stages: build
and deploy
, with two jobs: build backend
and deploy backend
.
Commit the changes.
We will see the pipeline has failed.
Click view pipeline
.
You see that it says 0 jobs
, meaning that when it read the .gitlab-ci.yml
file, no jobs were executed. This is because we have an only: tags
attribute in the script. It means that jobs will only run when a tag is created.
Now, I want to ensure that when committing to the main branch, no pipeline is executed unless a tag is created. Go to Settings
→ CI/CD
→ Runners
→ Expand
→ Disable Instance Runner
.
Let’s enter the Pipeline Editor and add a line to check, then commit the changes.
There is nothing added beyond the initial pipeline.
Now let’s test the CI/CD pipeline by creating tags.
Select Code
→ Tags
.
Create a new tag.
Enter the name, create from main
, and click Create Tag
.
Check the pipeline, and you’ll see a new pipeline running. Click to view details.
To see the detailed logs of each command, click on the corresponding stage.
Click on the build backend job
.
Then click on the deploy backend job
.
Check if the website is still running normally.
The website is still running smoothly.
Go to Pipelines
→ Pipeline editor
→ Main
→ Enter the file → Commit Changes
.
In the .gitlab-ci.yml
file, enter the following line:
variables:
USER_PROJECT: "ecommerce"
PATH_PROJECT: "/home/${USER_PROJECT}/${CI_PROJECT_NAME}"
stages:
- build
- deploy
before_script:
- sudo mkdir -p $PATH_PROJECT
build:
stage: build
variables:
GIT_STRATEGY: clone
script:
- npm install
tags:
- group-ecommerce-shell-runner
only:
- tags
deploy:
stage: deploy
variables:
GIT_STRATEGY: none
script:
- sudo cp -rf * ${PATH_PROJECT}
- sudo chown -R ${USER_PROJECT}. ${PATH_PROJECT}
- pid=$(sudo netstat -tulnp | grep :3000 | awk '{print $7}' | cut -d'/' -f1) || true
- if [ -n "$pid" ]; then sudo kill -9 $pid; fi
- sudo su ${USER_PROJECT} -c "cd ${PATH_PROJECT}; pm2 start npm --name '${CI_PROJECT_NAME}' -- run 'start'"
tags:
- group-ecommerce-shell-runner
only:
- tags
Then create tags and see the pipeline run successfully.
Then check if the backend is still running normally.