Simple setup for Gitlab CI with Sonarqube

Thanh Polimi
5 min readSep 22, 2022

--

I. Prerequisite

Install Sonarqube is very simple using Docker technology, so I suggested that you just install docker and run the following command

$ docker run -d --name sonarqube -p 9000:9000 -p 9092:9092 sonarqube

If everything goes smoothly then we will have sonarqube server listening on port 9000.

II. Project setup

The next step is to create your project docker images and push it to our Gitlab Registry Container so that everytime we run, we can just pull the image to save our time rather than start building from scratch.

There is a very useful post that I found on the internet which helped me on setting up the multi-stage Dockerfile for my NestJS project.

FROM node:current-alpine3.16 as development
RUN apk --update add postgresql-client python3 make g++

WORKDIR /usr/src/app
COPY --chown=node:node package*.json ./

RUN npm ci

RUN npm install glob rimraf

RUN npm i -g @nestjs/cli

COPY --chown=node:node . .

RUN npm run build

USER node

###################
# BUILD FOR PRODUCTION
###################

FROM node:current-alpine3.16 As build

WORKDIR /usr/src/app

COPY --chown=node:node package*.json ./

COPY --chown=node:node --from=development /usr/src/app/node_modules ./node_modules

COPY --chown=node:node . .

RUN npm run build

ENV NODE_ENV production

RUN npm ci --only=production && npm cache clean --force

USER node

###################
# PRODUCTION
###################

FROM node:current-alpine3.16 As production

COPY --chown=node:node --from=build /usr/src/app/node_modules ./node_modules
COPY --chown=node:node --from=build /usr/src/app/dist ./dist

CMD [ "node", "dist/main.js" ]

At the end of this step, we should be able to create the docker image for our project by using following command

$ docker build -t <your-project-gitlab-container-registry-path>:latest --target production .

Please noted that <your-project-gitlab-container-registry-path> can be easily found by visiting your project gitlab page > Packages & Registry > Container Registry.

※ Note : For MacOS user please note that if your laptop using M1/2 chip then we need to specify the target platform for our images otherwise the images will be built on ARM platform and it might not be able to run on the machine with other platform ( linux/amd64 for example )which later run Gitlab Runner.

docker build -t <your-project-gitlab-container-registry-path>:latest --target production  --platform linux/amd64  .

Finally, we can follow above guidline to login and push our built images to gitlab container registry :

$docker push <your-project-gitlab-container-registry-path>

III. gitlab-ci.yaml

It is time for our core steps to setup gitlab-ci to use Sonarqube to check our source-code.

Here I defined 4 basic stages

  • Install
  • Build
  • Test
  • Deploy

Auto-deploy is not supported at the moment but I defined this step for near future tutorial. All stage will use our built images to save our build time.

stages:
- install
- build
- test
- deploy

image: <your-project-gitlab-container-registry-path>:latest

yarn:
stage: install
# Cache the `node_modules` folder
# using the `CI_JOB_NAME` suffix on the key.
cache:
key: $CI_JOB_NAME-$CI_COMMIT_REF_SLUG
paths:
- node_modules/
# Install and compile.
script:
- yarn --version
- yarn --install --pure-lockfile
# Provide the other jobs of the pipeline with
# the node dependencies and the compiled assets.
artifacts:
expire_in: 1 days
paths:
- node_modules/
tags:
- default

build-yarn:
stage: build
dependencies:
- yarn
script:
- yarn --version
- yarn run build
artifacts:
paths:
- dist/
expire_in: 1 days
when: always
tags:
- default

linter:
stage: test
script:
- yarn --version
- yarn run eslint
tags:
- default

sonarqube:
stage: test
image:
name: sonarsource/sonar-scanner-cli:latest
entrypoint: [""]
variables:
SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar" # Defines the location of the analysis task cache
GIT_DEPTH: "0" # Tells git to fetch all the branches of the project, required by the analysis task
cache:
key: "${CI_JOB_NAME}"
paths:
- .sonar/cache
script:
- sonar-scanner
allow_failure: true
only:
- main # or the name of your main branch
tags:
- default

ssh:
stage: deploy
script:
- echo "This job deploys something from the $CI_COMMIT_BRANCH branch."
tags:
- default

You might ask, how can gitlab know the Sonarqube server and invoke the test. The answer is while setup new project on Sonarquebe using web interface, system will provide the value and ask us to define 2 variables on gitlab

  • SONAR_HOST_URL
  • SONAR_TOKEN

Runner will use those information to request Sonarqube.

Finally, we need sonar-project.properties file

sonar.projectKey=<your-project-key>
sonar.qualitygate.wait=true
sonar.sources=./src

Your project key is also provided during setup steps.

VI. Gitlab Runner

We can think of gitlab runner as worker who pull the jobs from gitlab ci pipeline and perform them. Gitlab runner can be easily deploy on any machine using docker

docker run -d --name gitlab-runner --restart always \
-v /srv/gitlab-runner/config:/etc/gitlab-runner \
-v /var/run/docker.sock:/var/run/docker.sock \
gitlab/gitlab-runner:latest

We then need to register the runner with our project by running following command

docker run --rm -it -v gitlab-runner-config:/etc/gitlab-runner gitlab/gitlab-runner:latest register

Runner will ask us about registration token which can be easily be found as above.

※ Please note that we must define TAGS as default to match our gitlab-ci.yaml definition. This runner will only run job in gitlab-ci.yaml which match its defined tag.

V. The end

If everything goes well then everytime we push to the main branch, sonarqube will be trigger to perform verify on our code

※Please note that the community version of Sonarqube support only 1 branch.

--

--

Thanh Polimi

I am represented by the lion(leo), and these spirited fire signs are the kings of the celestial jungle. Leo is delighted to embrace his royal status.