We can use SonarQube to analyse all or only selected modules from our multi-module application built with Maven. Let’s configure an existing Angular module so that we can see a full SonarQube analysis for an example SpringBoot-Angular project.
As an example application, we’re going to use the efficient-mvp-example. The project consists of two modules: backend
and frontend
that are built together with Maven. To learn how to set up a similar application read the Integrate Angular with a Spring Boot project post.
I use SonarQube to analyse code and I run it in a docker container locally. To learn how to set up SonarQube on development environment read the Boost project quality with SonarQube – local code analysis post.
Furthermore, I use Maven to built the multi-module application and to run SonarQube analyses.
The starting point for this article is in the 6ed4becccd2e58200cfea3757455f07a04cd6d75 commit.
The work presented in this article is in the 6c7f7628d84ae401a5b3434ea4b901fc1788d29e commit.
We want to be able to run a SonarQube analysis with Maven for the module that uses Spring Boot, the module that uses Angular and for the project as a whole. You can see our objective on the image below:
We already have a SonarQube instance running in a docker container where it can perform a code analysis for the backend
module. Before we can achieve the same for the frontend
module we need to change the existing config.
To the parent pom.xml
file add the following properties:
<!--pom.xml-->
…
<properties>
<sonar.projectKey>little-pinecone_efficient-mvp-example</sonar.projectKey>
<sonar.projectName>Efficient MVP example</sonar.projectName>
<sonar.sourceEncoding>UTF-8</sonar.sourceEncoding>
</properties>
…
As a result, we’ll be able to see Efficient MVP example
on the list of SonarQube projects once we complete the remaining steps.
In the pom.xml
for the backend
module update the <sonar.projectKey>
value and add a property for the project name
:
<!--backend/pom.xml-->
…
<properties>
<sonar.projectKey>little-pinecone_efficient-mvp-example-backend</sonar.projectKey>
<sonar.projectName>Efficient MVP example (backend)</sonar.projectName>
…
</properties>
…
As a result, we’ll be able to see Efficient MVP example (backend)
on the list of SonarQube projects once we complete the remaining steps.
We’re going to specify properties, profiles and test configuration necessary to analyse our frontend
module.
In the pom.xml
for the frontend
module add the following properties:
<!--frontend/pom.xml-->
…
<properties>
<sonar.projectKey>little-pinecone_efficient-mvp-example-frontend</sonar.projectKey>
<sonar.projectName>Efficient MVP example (frontend)</sonar.projectName>
<sonar.sourceEncoding>UTF-8</sonar.sourceEncoding>
<sonar.sources>src/main/angular/src</sonar.sources>
<sonar.tests>src/main/angular/src</sonar.tests>
<sonar.javascript.lcov.reportPaths>src/main/angular/coverage/lcov.info</sonar.javascript.lcov.reportPaths>
<sonar.test.inclusions>src/main/angular/src/**/*.spec.ts</sonar.test.inclusions>
<sonar.coverage.exclusions>
src/main/angular/src/environments/environment*.ts,
src/main/angular/src/**/*.module.ts,
src/main/angular/src/**/*.stub.ts,
</sonar.coverage.exclusions>
<sonar.exclusions>
/node_modules/,
src/main/angular/src/polyfills.ts,
src/main/angular/src/test.ts,
src/main/angular/src/main.ts,
…
</sonar.exclusions>
…
</properties>
…
Below you’ll find a short explanation for some of the tags used in the presented Maven config:
<sonar.sources>
– in my application I generated the Angular project in the frontend/src/main
directory as you can see on the image below. As I want SonarQube to run an analysis on almost all Angular code, I’m giving the path to the main
folder. I also used this path to specify the value for the <sonar.tests>
tag.<sonar.javascript.lcov.reportPaths>
– we want to have a test coverage report in our SonarQube analysis for Angular. Therefore, as we can read in the SonarQube docs for test coverage, for typescript
/javascript
coverage we need to specify:Comma-delimited list of paths to LCOV coverage report files. Paths may be absolute or relative to project root.
https://docs.sonarqube.org/latest/analysis/coverage/
<sonar.coverage.exclusions>
– remember to put here paths to all parts of the Angular app that you don’t want to see in the Coverage Report.<sonar.exclusions>
– remember to put here paths to all parts of the Angular app that you don’t want to analyse at all.In order to have some flexibility with the frontend
analysis, we’re going to add two profiles to our frontend/pom.xml
file:
frontend-pre-sonar
– for building the Angular project with frontend-maven-plugin
and running tests;frontend-sonar
– for only running an analysis.Add the following profiles to the frontend/pom.xml
file:
<!--frontend/pom.xml-->
…
<profiles>
<profile>
<id>frontend-pre-sonar</id>
<build>
<plugins>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>${frontend.maven.plugin.version}</version>
<configuration>
<workingDirectory>src/main/angular</workingDirectory>
<nodeVersion>${node.version}</nodeVersion>
<npmVersion>${npm.version}</npmVersion>
</configuration>
<executions>
<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
</execution>
<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
</execution>
<execution>
<id>npm run sonar</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>run pre-sonar</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>frontend-sonar</id>
<build>
<plugins>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>${frontend.maven.plugin.version}</version>
<configuration>
<workingDirectory>src/main/angular</workingDirectory>
<nodeVersion>${node.version}</nodeVersion>
<npmVersion>${npm.version}</npmVersion>
</configuration>
<executions>
<execution>
<id>npm run sonar</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>run sonar</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
…
In the frontend-pre-sonar
profile we are calling the pre-sonar
script:
<!--frontend/pom.xml-->
…
<profiles>
<profile>
<id>frontend-pre-sonar</id>
…
<configuration>
<arguments>run pre-sonar</arguments>
</configuration>
…
Therefore, we need to actually provide this script in the package.json
file:
//frontend/src/main/angular/package.json
{
"name": "angular",
…
"scripts": {
…
"pre-sonar": "ng test --code-coverage --no-watch --source-map=false --browsers=ChromeHeadless"
},
As a result, Maven will not only build the Angular project but also execute all tests for it (if you call it with the frontend-pre-sonar
profile).
Building the Angular module and running tests for it is not enough to produce a complete SonarQube analysis. To see the actual test coverage we need a test report saved in the location that we gave in the <sonar.javascript.lcov.reportPaths>
property.
Frist, install the karma-sonarqube-unit-reporter dependency (remember to execute this command in the folder with the package.json
file):
npm install --save-dev karma-sonarqube-unit-reporter
Next, edit the karma.conf.js file to:
coverageReporter
(src/main/angular/coverage/lcov.info
given in the pom.xml
file corresponds to ./coverage
in karma.cong.js
)Given these points, you can see the changes I made in my config file on the snippet below:
// frontend/src/main/angular/karma.conf.js
module.exports = function (config) {
config.set({
…
plugins: [
…
require('karma-sonarqube-unit-reporter')
],
…
coverageReporter: {
dir: require('path').join(__dirname, './coverage'),
…
reporters: [
…
{ type: 'lcovonly' }
]
},
…
The commands below contain credentials required for my SonarQube instance. Remember to adjust them when running the mvn
commands on your machine.
In this case, we’re going to use the frontend-pre-sonar
profile to build and test the Angular project and the code-coverage
profile to test the Spring Boot project:
mvn clean verify sonar:sonar -Pfrontend-pre-sonar -Pcode-coverage -Dsonar.login=your_login -Dsonar.password=your_password
In order to analyze solely the frontend
module, we’re going to use only the frontend-pre-sonar
profile to build and test the Angular project:
mvn clean verify sonar:sonar -Pfrontend-pre-sonar -Dsonar.login=your_login -Dsonar.password=your_password
For analyzing the backend
module, we’re going to use only the code-coverage
profile to test the Spring Boot project:
mvn clean verify sonar:sonar -Pcode-coverage -Dsonar.login=your_login -Dsonar.password=your_password
Below you’ll find my convenience shell script that I find useful in calling just the analysis I need. I called it run-sonar.sh
. Remember to adjust the credentials for SonarQube if you want to use it:
#!/bin/bash
set -e
all=false
backend=false
frontend=false
while getopts abfh option; do
case "${option}" in
a)
all=true
;;
b)
backend=true
;;
f)
frontend=true
;;
h)
echo "Options:
- a all: run sonar for all available modules
- b backend: run sonar for the backend module
- f frontend: run sonar for the frontend module
- h help: show help
"
exit 0
;;
*)
echo "Unknown option used. Run with -h option to see all available options"
exit 1
;;
esac
done
shift "$((OPTIND - 1))"
if [ "$all" == true ]; then
echo "Analyzing all available modules"
mvn clean verify sonar:sonar -Pfrontend-pre-sonar -Pcode-coverage -Dsonar.login=your_username -Dsonar.password=your_password
fi
if [ "$backend" == true ]; then
echo "Analyzing the backend module"
cd backend
mvn clean verify sonar:sonar -Pcode-coverage -Dsonar.login=your_username -Dsonar.password=your_password
fi
if [ "$frontend" == true ]; then
echo "Analyzing the frontend module"
cd frontend
mvn clean verify sonar:sonar -Pfrontend-pre-sonar -Dsonar.login=your_username -Dsonar.password=your_password
fi
Make sure that the file is executable and you can run analysis with the following options:
./run-sonar.sh -a
– for all modules./run-sonar.sh -b
– for the backend
module./run-sonar.sh -f
– for the frontend
moduleMake sure that when you run the mvn
command, you:
clean
build phase to remove old reports,frontend
module (calling the verify
build phase),fronted-pre-sonar
profile to the frontend/pom
file and the pre-sonar
script to the package.json
file,-Pfrontend-pre-sonar
argument,lconf.info
file is created in the coverage
directory:Spring Security allows us to use role-based control to restrict access to API resources. However,…
A custom annotation in Spring Boot tests is an easy and flexible way to provide…
Delegating user management to Keycloak allows us to better focus on meeting the business needs…
Swagger offers various methods to authorize requests to our Keycloak secured API. I'll show you…
Configuring our Spring Boot API to use Keycloak as an authentication and authorization server can…
Keycloak provides simple integration with Spring applications. As a result, we can easily configure our…