GitLab Node.js SonarQube Integration

Overview

Purpose

In the fast-evolving landscape of software development, ensuring code quality and security is paramount. To streamline this process, integrating a robust set of tools becomes imperative. In this blog, we embark on a journey to seamlessly integrate GitLab, SonarQube, pytest, coverage.py, and dependency-check into a unified ecosystem. By combining version control, code analysis, testing, code coverage evaluation, and dependency scanning, we aim to create a powerful and efficient pipeline that not only enhances the overall quality of the codebase but also fortifies it against potential vulnerabilities. Join us as we explore each tool's role in this integration, demonstrating how they collectively contribute to a more resilient and high-performing software development lifecycle.

Requirements

After the code is committed, these reports should be generated by CI/CD pipelines automatically.

  1. Test result and test coverage report by Jest.
  2. Dependency check report by Dependency-Check
  3. Code quality by SonarQube
  4. Sommarize these reports into GitLab & SonarQube.

Procedures

Test result and coverage

Test result and coverage in console and HTML reports (Jest)

  1. Test result (Console):

    I don't find a Jest feature to generate plain text test result on console, please let me know if you know how to do it.

  2. Test result (HTML):

  3. Test coverage (Console):

  4. Test coverage (HTML):

Test Result and coverage on GitLab

I don't try it, since GitLab only supports JUnit format, you can use jest-junit to generate JUnit format report and upload it into artifacts of GitLab.

Configuration files

package.json

  1. package.json

     1{
     2  "name": "test1",
     3  "version": "1.0.7",
     4  "main": "server.js",
     5  "dependencies": {
     6    "fastify": "^4.24.2",
     7    "fastify-plugin": "^4.5.1",
     8    "mysql2": "^3.6.2",
     9    "winston": "^3.11.0",
    10    "winston-daily-rotate-file": "^4.7.1"
    11  },
    12  "devDependencies": {
    13    "chai": "^4.3.10",
    14    "chai-http": "^4.4.0",
    15    "jest": "29.7.0",
    16    "jest-html-reporters": "^3.1.4"
    17  },
    18  "scripts": {
    19    "start": "node server",
    20    "testonly": "jest",
    21    "test": "jest --coverage "
    22  }
    23}
    

jest.config.json

  1. jest.config.json

     1{
     2  "reporters": [
     3    "default",
     4    [
     5      "jest-html-reporters",
     6      {
     7        "publicPath": "test-report",
     8        "pageTitle": "Test1 Test Report"
     9      }
    10    ]
    11  ]
    12}
    

Dockerfile

  1. Dockerfile

    1FROM node:20.6.1-bookworm-slim
    2
    3WORKDIR /app
    4ADD . /app
    5RUN ls
    6EXPOSE 8001
    7CMD ["npm", "start"]
    

.gitlab-ci.yml

  1. .gitlab-ci.yml

     1variables:
     2    PROJECT_NAME: "test_1"
     3    VER: 1.0.7
     4    DOCKER_FILE_NAME: test_1
     5    SONARQUBE_URL: http://example.com.
     6    SONARQUBE_TOKEN: squ_****************************************
     7    SONARQUBE_PROJECT_KEY: test_1
     8
     9image: node:20.6.1-bookworm-slim
    10
    11stages:
    12    - setup
    13    - test
    14    - dependency_check
    15    - quality_check
    16    - build_docker
    17
    18cache:
    19    paths:
    20        - node_modules/
    21
    22setup:
    23    stage: setup
    24    script:
    25        - npm install
    26
    27test:
    28    stage: test
    29    script:
    30        - npm test
    31    artifacts:
    32        paths:
    33            - ./test-report
    34            - ./coverage
    35
    36dependency_check:
    37    allow_failure: true
    38    stage: dependency_check
    39    image:
    40        #name: registry.gitlab.com/gitlab-ci-utils/docker-dependency-check:latest
    41        #name: owasp/dependency-check:latest
    42        name: owasp/dependency-check-action:latest
    43        entrypoint: [""]
    44    script:
    45        - - /usr/share/dependency-check/bin/dependency-check.sh --scan "./" --format ALL --project "$PROJECT_NAME" --failOnCVSS 0
    46    artifacts:
    47        when: always
    48        paths:
    49            - "./dependency-check-report.html"
    50            - "./dependency-check-report.json"
    51
    52quality_check:
    53    stage: quality_check
    54    image:
    55        name: sonarsource/sonar-scanner-cli:5.0.1
    56    script:
    57        - sonar-scanner -D"sonar.host.url=$SONARQUBE_URL"
    58        -D"sonar.token=$SONARQUBE_TOKEN"
    59        -D"sonar.projectKey=$SONARQUBE_PROJECT_KEY"
    60        -D"sonar.projectName=$PROJECT_NAME"
    61        -D"sonar.sourceEncoding=utf-8"
    62        -D"sonar.exclusions=test/**/*, coverage/**/*, test-report/**/*, dependency-check-report.html"
    63        -D"sonar.javascript.lcov.reportPaths=./coverage/lcov.info"
    64        -D"sonar.dependencyCheck.jsonReportPath=./dependency-check-report.json"
    65        -D"sonar.dependencyCheck.htmlReportPath=./dependency-check-report.html"
    66
    67build_docker:
    68    stage: build_docker
    69    image: docker
    70    services:
    71        - name: docker:dind
    72        alias: thedockerhost
    73    variables:
    74        # Tell docker CLI how to talk to Docker daemon; see
    75        # https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#use-docker-in-docker-executor
    76        DOCKER_HOST: tcp://thedockerhost:2375/
    77        # Use the overlayfs driver for improved performance:
    78        DOCKER_DRIVER: overlay2
    79        DOCKER_TLS_CERTDIR: ""
    80    script:
    81        - echo Buile Ver $VER
    82        - docker build --no-cache -t $DOCKER_FILE_NAME:$VER -f Dockerfile .
    83        - docker save $DOCKER_FILE_NAME:$VER -o $DOCKER_FILE_NAME-$VER.tar
    84    artifacts:
    85        paths:
    86            - ./$DOCKER_FILE_NAME-$VER.tar
    87    only:
    88        - master
    

Posts in this Series