How to set up SonarQube locally on a React TypeScript Project

Introduction

SonarQube is a tool that helps you catch bugs and vulnerabilities in your app. Working together with ESLint and Unit tests, it provides a great code quality scan.

On this tutorial, I will show you how to set up SonarQube and run locally over a React TypeScript project. Then, we will improve SonarQube analysis by adding ESLint and Jest reports.

The topics are organized as follow:

  • Step 1: Create a React Project with TypeScript
  • Step 2: Install SonarQube
  • Step 3: Configuring SonarQube over our React + TypeScript project
  • Configure Jest to send information to SonarQube
  • Configure ESLint to send information to SonarQube
  • Useful Tips

So, let's start!

Prerequisites

You need to have already installed on your computer:
Node.js (version >= 10). — DockerDocker Compose

Step 1. Create a React Project with TypeScript

The following command will create a project inside a folder 'my-app'.
On terminal, run:

npx create-react-app my-app --template typescript

Step 2. Install SonarQube

We will use an official Docker Compose file to install it.

Download Docker Compose file

On the SonarSource Github, download the following docker compose file (SonarQube with Postgres):
https://github.com/SonarSource/docker-sonarqube/blob/master/example-compose-files/sq-with-postgres/docker-compose.yml

Run Docker Compose file

It is time to run our Docker Compose 'docker-compose.yml' file.

Before running it, we need to increase the memory dedicated for Docker, otherwise, when we try to run it, we will get the following error:

image

To solve this problem, execute the follow command.
On terminal:

sudo sysctl -w vm.max_map_count=262144

(Reference: https://stackoverflow.com/questions/51445846/elasticsearch-max-virtual-memory-areas-vm-max-map-count-65530-is-too-low-inc)

Now, let's run 'docker-compose.yml' file. Inside the same directory where the file is located, run:

On terminal:

docker-compose up

image

PS: To keep SonarQube running you will need to let this terminal window open. Whenever you want to stop SonarQube from running, just press Ctrl+C on the terminal (or close it).

Open another terminal window to execute other commands when needed.

Check installation

Check if installation succeeded by opening SonarQube at localhost. SonarQube will be available on port 9000.

http://localhost:9000/

SonarQube UI:

image

Log in

Click on Login and enter with the follow credentials:
Login: admin
Password: admin

Step 3. Configuring SonarQube over our React + TypeScript project

At this moment we have:

  • React + TypeScript project created
  • SonarQube running

It is time to configure SonarQube on our React + TypeScript project.

Install SonarQube Scanner package

sonarqube-scanner: https://www.npmjs.com/package/sonarqube-scanner
It runs sonarQube analysis over our project and sends the information to SonarQube application.

Inside the React project directory 'my-app/', run on terminal:

npm install --save-dev sonarqube-scanner

SonarQube Configuration File

On the root of the project, create a 'sonarqube-scanner.js' file.

'sonarqube-scanner.js' file content:

const scanner = require("sonarqube-scanner");
scanner(
  {
    serverUrl: "http://localhost:9000",
    login: "admin",
    password: "admin",
    options: {
      "sonar.sources": "./src",
    },
  },
  () => process.exit()
);

Note: Using login and password is not safe and we are doing it just to simplify the configuration process.

You can see the best solution for this security problem at the end of this article, on '_Useful Tips' Section_

Running SonarQube

SonarQube is already set up! To see its analysis over our code, we need to run SonarQube Scanner.

Before running it, let's add a code smell to our code! (to see it on SonarQube analysis)

On 'App.tsx' file:

// ...
function App() {
//'Empty block statement' code smell
try{
}
catch(e){
}
return (
// ...
)
}

Running SonarQube Scanner Now, let's call SonarQube Scanner to send the report to SonarQube.
On terminal:

node sonarqube-scanner.js

After some time, it will print the message below:

image

SonarQube Scanner analysis finished.

Let's check the results on http://localhost:9000

image

Cool!

To see a detailed list of problems pointed out, just click on 'Issues' tab.

Issues detailed list:

image

And if you click over the issue, it'll show you all the lines related to the problem.

Detailed Issue:

image

Cool, right?

Configure Jest to send information to SonarQube

We've seen SonarQube power by itself. Now, let's improve it by sending our Unit Test report to it.

Install Jest-Sonar-Reporter package

jest-sonar-reporter: https://www.npmjs.com/package/jest-sonar-reporter
It converts Jest's report output to SonarQube report format.

On terminal:

npm install --save-dev jest-sonar-reporter

Add some Test configurations to Sonar Configuration File

On 'sonarqube-scanner.js' file, add over “options”:

"sonar.exclusions": "**/*.test.tsx",
"sonar.tests": "./src",
"sonar.test.inclusions": "**/*.test.tsx,**/*.test.ts",
"sonar.typescript.lcov.reportPaths": "coverage/lcov.info",
"sonar.testExecutionReportPaths": "test-report.xml"

Test files organized in subfolders: It is not our case, but If your React tests are under a folder ,like 'src/myTests' and sub-folders, you will need to change the follow settings:

"sonar.exclusions": "**/myTests/**",
"sonar.tests": "./src/myTests",
"sonar.test.inclusions": "./src/myTests/**/*.test.tsx,./src/myTests/**/*.test.ts"

Now, we need to tell Jest that on every time that the Unit Tests run, it has to create a report in a format that SonarQube will understand.

So, on package.json, let's change our “test” script:

{
...,
"test": "react-scripts test --watchAll=false --coverage --testResultsProcessor jest-sonar-reporter",
...
}

Let me explain some command options that we've added:

--watchAll=false: It is because when executing 'test' script, React will start a watch-mode menu, so you can select if you want to run all files, specific ones, just the modified ones, etc. In our case, we don't want it to ask anything, but just run all the tests. So we turn off this watch-mode by adding '--watchAll=false' to it.

--coverage: It just tells Jest that the test coverage information should be collected and reported in the output.

--testResultsProcessor jest-sonar-reporter: tells to generate the output in a SonarQube expected format.

SonarQube is ready to receive Jest report data. So let 's do it!.

Running Jest + SonarQube

**Running Jest
**First, run Jest to generate a report output:

On terminal:

npm run test

See that a report called 'test-report.xml' will appear on the root of your project.

Running SonarQube Scanner Now, let's call SonarQube Scanner to send the report to SonarQube.
On terminal:

node sonarqube-scanner.js

After some time, it will print the message below:

image

Let's check the results on http://localhost:9000

image

Our Jest report is now showing on SonarQube report! Cool!

Configure ESLint to send information to SonarQube

We can also execute ESLint over our project files, generate a report and send it to SonarQube.

So, let's do this!

Add Eslint report path to SonarQube Configuration File

On 'sonarqube-scanner.js' file, add over “options”:

"sonar.eslint.reportPaths":"eslint-report.json"

Running ESLint + SonarQube

Running ESLint Before running ESLint, let's add another code smell to our 'App.tsx' file, so we can see the ESLint analysis on our SonarQube Report. An easy code smell to add is to create a variable and not use it on our code.

On 'App.tsx' file:

...
//'Unused variable' code smell
const unusedVar = "";
function App() {
//'Empty block statement' code smell
try{
}
catch(e){
}
return (
// ...
)
}

Code smell added! Now let's run ESLint to generate a report output:

On terminal:

npx eslint -f json -o eslint-report.json .

See that a report called 'eslint-report.json' will appear on the root of your project.

Running SonarQube Scanner Now, let's call SonarQube Scanner to send the report to SonarQube.

On terminal, run:

node sonarqube-scanner.js

After some time, it will print the message below:

image

Let's check the results on http://localhost:9000

image

Cool! Another Code Smell appeared in our report!

Let's see the detailed list of problems pointed by SonarQube analysis on 'Issues' tab.

image

The code smell 'unusedVar' is pointed out as we expected! Cool, right?

Useful Tips

We have finished! But let me give you some very useful tips!

Update .gitignore

Some files such as the reports generated are not useful to push into the repository. I suggest to add the following to your .gitignore file:

#SonarQubetest-report.xml
eslint-report.json
/.scannerwork

Generate user Token to use on SonarQube Configuration File

Expose your login and password on ''sonarqube-scanner.js'' is not safe. To solve this security issue let me show you how to generate and use a token instead:

  1. Open http://localhost:9000 and log in.
  2. Click on Administrator icon then click at 'My Account'

image

  1. On the Administrator screen, select 'Security' tab. Enter a Token Name and click on 'Generate' button.

image

  1. A token will show on the screen. Copy it and store it in a safe place.

image

user token generated

  1. On ''sonarqube-scanner.js”:
  • Add the following line with the generated Token:
token: "3aa403f1ad2065ea2b4b837262ca2cad96e3cd7a"
  • Remove the following lines:
login:"admin",
password:"admin"
  • Resulting in the follow:
const scanner = require('sonarqube-scanner');
scanner(
{
serverUrl: "http://localhost:9000",
token: "3aa403f1ad2065ea2b4b837262ca2cad96e3cd7a",
options: {
// ...

And it's done!

Organize all of your scripts over 'package.json' file

To better organize your project, let all the scripts on “package.json” file.

"scripts": {
// ...
"test": "react-scripts test",
"test:noWatch":"npm run test -- --watchAll=false",
"test:report": "npm run test:noWatch -- --coverage --testResultsProcessor jest-sonar-reporter",
"lint": "eslint --fix",
"lint:report":"npm run lint -- -f json -o eslint-report.json",
"sonar": "node sonarqube-scanner.js"
},

And then you can use it like:

  • To run Jest over all the project in watch-mode:
npm run test
  • To run Jest over all the project without watch-mode:
npm run test:noWatch
  • To run Jest over all the project without watch-mode and generate a report:
npm run test:report
  • To run ESLint over all the project
npm run lint -- .
  • To run ESLint over all the project and generate a report:
npm run lint:report -- .
  • To run SonarQube Scanner
npm run sonar

Configure these validations also on your CI pipeline:

SonarQube was built to run over a CI pipeline and guarantee that no bad code will be deployed. So, I strongly recommend setting it up on your CI (Continuous Integration) pipeline process.

PS: We can discuss about this CI configuration on another time. The main goal here was to run and use SonarQube locally.

Thanks!

Many thanks! Hope you enjoyed!

References:

Jest CLI Options · Jest

sonarqube-scanner

jest-sonar-reporter

JavaScript / TypeScript

Configuring Sonar with a Create React App in TypeScript

Enjoyed this article?

Share it with your network to help others discover it

Continue Learning

Discover more articles on similar topics