## Setup SonarQube for Node JS Typescript Project ## What is SonarQube? SonarQube is an open source quality management platform, dedicated to continuously analyze and measure technical quality, from project portfolio to method. [https://www.sonarqube.org/](https://www.sonarqube.org/) ### Basic of SonarQube - SonarQube (formerly just "Sonar") is a server-based system. Of course you can install it on your local machine (the hardware requirements are minimal). But it is a central server with a database. - SonarQube is an open-source platform developed by SonarSource for continuous inspection of code quality. Sonar does static code analysis, which provides a detailed report of bugs, code smells, vulnerabilities, code duplications. - SonarQube also highlights the complex areas of code that are less covered by unit tests. ### Highlights - Release Quality Code : Catch tricky bugs to prevent undefined behaviour from impacting end-users. - Application Security : Fix vulnerabilities that compromise your app, and learn AppSec along the way with Security Hotspots. - Technical Debt : Make sure your codebase is clean and maintainable, to increase developer velocity! ### Setup Sonarqube on local machine We are going to use bitnami-docker-sonarqube image to setup Sonarqube on our local machine. For more details you can check [bitnami-docker-sonarqube](https://github.com/bitnami/bitnami-docker-sonarqube) respository. #### Run the application using Docker Compose ``` $ curl -sSL https://raw.githubusercontent.com/bitnami/bitnami-docker-sonarqube/master/docker-compose.yml > docker-compose.yml $ docker-compose up -d ``` Or else you can create `docker-compose.yml` file and use the following configuartion to run Sonarqube using `docker-compose up -d` command. ``` version: '2' services: postgresql: image: docker.io/bitnami/postgresql:10 environment: - ALLOW_EMPTY_PASSWORD=yes volumes: - 'postgresql_data:/bitnami/postgresql' sonarqube: image: docker.io/bitnami/sonarqube:8 ports: - '80:9000' environment: - POSTGRESQL_HOST=postgresql - POSTGRESQL_ROOT_USER=postgres - POSTGRESQL_CLIENT_CREATE_DATABASE_NAME=bitnami_sonarqube - POSTGRESQL_CLIENT_CREATE_DATABASE_USERNAME=bn_sonarqube - POSTGRESQL_CLIENT_CREATE_DATABASE_PASSWORD=bitnami1234 - SONARQUBE_DATABASE_NAME=bitnami_sonarqube - SONARQUBE_DATABASE_USER=bn_sonarqube - SONARQUBE_DATABASE_PASSWORD=bitnami1234 volumes: - sonarqube_data:/bitnami volumes: sonarqube_data: driver: local postgresql_data: driver: local ``` Access your application at [http://127.0.0.1](http://127.0.0.1) and use below credentials to login into the application. - USERNAME - admin - PASSWORD - bitnami ### Analyzing a Project - Click the **Create new project** button. - Give your project a **Project key** and a **Display name** and click the **Set Up** button. - Under **Provide a token**, select **Generate a token**. Give your token a name, click the **Generate** button, and click **Continue**. - Copy the generated token and paste into our `.env` file with corresponding to varaible `SONARQUBE_TOKEN`. - Example : `SONARQUBE_TOKEN=generated-token` - Make sure to set environment variable in `.env` file. ``` SONARQUBE_URL=http://127.0.0.1 SONARQUBE_PROJECTKEY=sonarqube-node-tpescript-demo SONARQUBE_TOKEN=43b915a482ba1dce4b36c215718e56e37ad9e910 ``` ### `sonarqube-scanner` - NPM module to run SonarQube/SonarCloud analyses To add code analysis to your build files, simply add the package to your project dev dependencies: `npm install --save-dev sonarqube-scanner` ### SonarQube Configuration File On the root of the project, we are going to create `sonar-scanner.ts` file which contains the source code for SonarQube scanner configuration. ``` import * as scanner from 'sonarqube-scanner' import { config as configDotenv } from 'dotenv'; // config the environment configDotenv(); // The URL of the SonarQube server. Defaults to http://localhost:9000 const serverUrl = process.env.SONARQUBE_URL; // The token used to connect to the SonarQube/SonarCloud server. Empty by default. const token = process.env.SONARQUBE_TOKEN; // projectKey must be unique in a given SonarQube instance const projectKey = process.env.SONARQUBE_PROJECTKEY // options Map (optional) Used to pass extra parameters for the analysis. // See the [official documentation](https://docs.sonarqube.org/latest/analysis/analysis-parameters/) for more details. const options = { 'sonar.projectKey': projectKey, // projectName - defaults to project key 'sonar.projectName': 'node-typescript-boilerplate', // Path is relative to the sonar-project.properties file. Defaults to . 'sonar.sources': 'src', // source language 'sonar.language': 'ts', 'sonar.javascript.lcov.reportPaths' : 'coverage/lcov.info', // Encoding of the source code. Default is default system encoding 'sonar.sourceEncoding': 'UTF-8' }; // parameters for sonarqube-scanner const params = { serverUrl, token, options } const sonarScanner = async () => { console.log(serverUrl); if (!serverUrl) { console.log('SonarQube url not set. Nothing to do...'); return; } // Function Callback (the execution of the analysis is asynchronous). const callback = (result) => { console.log('Sonarqube scanner result:', result); } scanner(params, callback); } sonarScanner() .catch(err => console.error('Error during sonar scan', err)); ``` ### How to fix `“parserOptions.project” has been set for @typescript-eslint/parser` ? Simply instruct `eslint` to ignore them by adding the `ignorePatterns` option to your `.eslintrc`: `"ignorePatterns": ["sonar.js"]` ``` { "parser": "@typescript-eslint/parser", "extends": [ "airbnb/base", "plugin:@typescript-eslint/recommended", "plugin:import/errors", "plugin:import/warnings", "plugin:import/typescript", "prettier" ], "parserOptions": { "ecmaVersion": 2018, "project": "./tsconfig.json" }, "ignorePatterns": ["sonar-scanner.ts"], // This line should be add in configuration "plugins": ["prettier"], "rules": {} } ``` ### How to Run SonarQube Scanner Please add below script in `package.json` to run SonarQube Scanner, make sure you already installed `ts-node` locally or globally. `"sonar": "ts-node sonar-scanner.ts"` Start the SonarQube Scanner by using command on terminal ``` npm run sonar ``` **Output** ``` ➜ node-boilerplate git:(master) ✗ npm run sonar > sonarqube-node-tpescript-demo@1.0.0 sonar > ts-node sonar-scanner.ts http://127.0.0.1:80 [23:30:35] Starting analysis... [23:30:35] Getting info from "package.json" file [23:30:35] Checking if executable exists: /Users/macbook/.sonar/native-sonar-scanner/sonar-scanner-4.5.0.2216-macosx/bin/sonar-scanner [23:30:35] Platform binaries for SonarScanner found. Using it. INFO: Scanner configuration file: /Users/macbook/.sonar/native-sonar-scanner/sonar-scanner-4.5.0.2216-macosx/conf/sonar-scanner.properties INFO: Project root configuration file: NONE INFO: SonarScanner 4.5.0.2216 INFO: Java 11.0.3 AdoptOpenJDK (64-bit) INFO: Mac OS X 10.16 x86_64 INFO: User cache: /Users/macbook/.sonar/cache INFO: Scanner configuration file: /Users/macbook/.sonar/native-sonar-scanner/sonar-scanner-4.5.0.2216-macosx/conf/sonar-scanner.properties INFO: Project root configuration file: NONE INFO: Analyzing on SonarQube server 8.9.1 INFO: Default locale: "en_IN", source code encoding: "UTF-8" INFO: Load global settings INFO: Load global settings (done) | time=150ms INFO: Server id: FD2E0B99-AXqmE06gm3W0APi1RPSm INFO: User cache: /Users/macbook/.sonar/cache INFO: Load/download plugins INFO: Load plugins index INFO: Load plugins index (done) | time=71ms INFO: Load/download plugins (done) | time=4641ms INFO: Process project properties INFO: Process project properties (done) | time=6ms INFO: Execute project builders INFO: Execute project builders (done) | time=3ms INFO: Project key: sonarqube-node-tpescript-demo INFO: Base dir: /Users/macbook/Documents/workspace/node-boilerplate INFO: Working dir: /Users/macbook/Documents/workspace/node-boilerplate/.scannerwork INFO: Load project settings for component key: 'sonarqube-node-tpescript-demo' INFO: Load project settings for component key: 'sonarqube-node-tpescript-demo' (done) | time=101ms INFO: Load quality profiles INFO: Load quality profiles (done) | time=100ms INFO: Load active rules INFO: Load active rules (done) | time=4058ms INFO: Indexing files... INFO: Project configuration: INFO: Excluded sources: node_modules/**, bower_components/**, jspm_packages/**, typings/**, lib-cov/** INFO: 12 files indexed INFO: 0 files ignored because of inclusion/exclusion patterns INFO: 0 files ignored because of scm ignore settings INFO: Quality profile for ts: Sonar way INFO: ------------- Run sensors on module node-typescript-boilerplate INFO: Load metrics repository INFO: Load metrics repository (done) | time=81ms INFO: Sensor CSS Rules [cssfamily] INFO: No CSS, PHP, HTML or VueJS files are found in the project. CSS analysis is skipped. INFO: Sensor CSS Rules [cssfamily] (done) | time=1ms INFO: Sensor JaCoCo XML Report Importer [jacoco] INFO: 'sonar.coverage.jacoco.xmlReportPaths' is not defined. Using default locations: target/site/jacoco/jacoco.xml,target/site/jacoco-it/jacoco.xml,build/reports/jacoco/test/jacocoTestReport.xml INFO: No report imported, no coverage information will be imported by JaCoCo XML Report Importer INFO: Sensor JaCoCo XML Report Importer [jacoco] (done) | time=3ms INFO: Sensor TypeScript analysis [javascript] INFO: Found 1 tsconfig.json file(s): [/Users/macbook/Documents/workspace/node-boilerplate/tsconfig.json] INFO: Analyzing 12 files using tsconfig: /Users/macbook/Documents/workspace/node-boilerplate/tsconfig.json INFO: 12 source files to be analyzed INFO: Load project repositories INFO: Load project repositories (done) | time=105ms INFO: 12/12 source files have been analyzed INFO: Sensor TypeScript analysis [javascript] (done) | time=11441ms INFO: Sensor JavaScript/TypeScript Coverage [javascript] WARN: No coverage information will be saved because LCOV file cannot be found. WARN: Provided LCOV file path: coverage/lcov.info. Seek file with path: /Users/macbook/Documents/workspace/node-boilerplate/coverage/lcov.info WARN: No coverage information will be saved because all LCOV files cannot be found. INFO: Sensor JavaScript/TypeScript Coverage [javascript] (done) | time=1ms INFO: Sensor C# Project Type Information [csharp] INFO: Sensor C# Project Type Information [csharp] (done) | time=1ms INFO: Sensor C# Properties [csharp] INFO: Sensor C# Properties [csharp] (done) | time=1ms INFO: Sensor JavaXmlSensor [java] INFO: Sensor JavaXmlSensor [java] (done) | time=1ms INFO: Sensor HTML [web] INFO: Sensor HTML [web] (done) | time=3ms INFO: Sensor VB.NET Project Type Information [vbnet] INFO: Sensor VB.NET Project Type Information [vbnet] (done) | time=1ms INFO: Sensor VB.NET Properties [vbnet] INFO: Sensor VB.NET Properties [vbnet] (done) | time=0ms INFO: ------------- Run sensors on project INFO: Sensor Zero Coverage Sensor INFO: Sensor Zero Coverage Sensor (done) | time=13ms INFO: SCM Publisher SCM provider for this project is: git INFO: SCM Publisher 12 source files to be analyzed INFO: SCM Publisher 0/12 source files have been analyzed (done) | time=66ms WARN: Missing blame information for the following files: WARN: * src/server.ts WARN: * src/environments/environment.constant.ts WARN: * src/lib/logger.ts WARN: * src/abstractions/ApiResponses.ts WARN: * src/middleware/error-handler.ts WARN: * src/components/system-status/system-status.controller.ts WARN: * src/components/system-status/system-status.types.ts WARN: * src/routes.ts WARN: * src/environments/environment.ts WARN: * src/components/BaseApi.ts WARN: * src/abstractions/ApiError.ts WARN: * src/App.ts WARN: This may lead to missing/broken features in SonarQube INFO: CPD Executor 3 files had no CPD blocks INFO: CPD Executor Calculating CPD for 9 files INFO: CPD Executor CPD calculation finished (done) | time=13ms INFO: Analysis report generated in 68ms, dir size=124 KB INFO: Analysis report compressed in 51ms, zip size=35 KB INFO: Analysis report uploaded in 159ms INFO: ANALYSIS SUCCESSFUL, you can browse http://127.0.0.1/dashboard?id=sonarqube-node-tpescript-demo INFO: Note that you will be able to access the updated dashboard once the server has processed the submitted analysis report INFO: More about the report processing at http://127.0.0.1/api/ce/task?id=AXqmLdoG21WQGzQaFi7o INFO: Analysis total time: 25.450 s INFO: ------------------------------------------------------------------------ INFO: EXECUTION SUCCESS INFO: ------------------------------------------------------------------------ INFO: Total time: 32.270s INFO: Final Memory: 12M/50M INFO: ------------------------------------------------------------------------ [23:31:08] Analysis finished. Sonarqube scanner result: undefined ➜ node-boilerplate git:(master) ✗ ``` ### Refrences - [bitnami-docker-sonarqube](https://github.com/bitnami/bitnami-docker-sonarqube) - [sonarqube-node-tpescript-demo](https://github.com/santoshshinde2012/sonarqube-node-tpescript-demo) <hr/> # Please connect with me on Twitter [@shindesan2012](https://twitter.com/shindesan2012) & [https://blog.santoshshinde.com](https://blog.santoshshinde.com/)