Code Quality, crucial for robust software, is upheld by tools like SonarQube. This article explores its significance, implementation, and management.
code quality
?Code quality measures the accuracy and reliability of code—but being bug-free and portable is not the only measure of code quality. It also includes how developer-friendly the code is. Code quality also describes how easy it is to understand, modify, and reuse the code if necessary.
source: Amazon: What is code quality?
Improving code quality involves addressing these factors to create code that is not only technically robust but also user-friendly and conducive to collaborative development.
“Clean Code” is code that’s easy to read, maintain, understand and change through structure and consistency yet remains robust and secure to withstand performance demands."
source: clean code](https://www.sonarsource.com/solutions/clean-code/))
🧹 Clean Code refers to the practice of writing code in a clear, readable and efficient manner, placing a strong emphasis on the understandability and maintainability of the code. The main premise is that the code must not only work correctly, but it must also be easy to understand for any developer who reads it so that it can be reused quickly. To achieve this, it is important to follow good programming practices and adopt conventions that promote clarity.
Aspects to consider:
📖 Readability: Code should be written in a way that is easily understandable. Descriptive names should be used for variables and functions, and confusing abbreviations should be avoided.
🚀 Simplicity: Simplicity is sought in the design and structure of the code. Avoiding unnecessary complexity and keeping functions and methods concise helps facilitate understanding.
🛠️ Maintainability: The code must be easy to maintain over time. This involves minimizing code duplication, following sound design principles, and documenting effectively.
🔄 Consistency: Consistent coding conventions should be followed throughout the project to improve consistency and make the code easier to read.
SonarQube
?SonarQube is a self-managed, automatic code review tool that systematically helps you deliver Clean Code. As a core element of our Sonar solution, SonarQube integrates into your existing workflow and detects issues in your code to help you perform continuous code inspections of your projects.
source: SonarQube
SonarLindt
?SonarLint is a free IDE extension that can be used in Visual Code, Visual studio or eclipse. This plugin allows you to identify coding problems in real time, in order to avoid errors, vulnerabilities and code smells while you write your code. SonarLint can perform code analysis in JS/TS, Python, PHP, Java, C, C++, Go and IaC.
The following is a comparative table in which we compare the functionality and the context in which each of these tools is applied
image source:sonarsource docs
Feature | SonarQube | SonarLint |
---|---|---|
Scope | Server-based code analysis for entire projects/repositories | IDE-based code analysis for individual developers |
Deployment | Requires a centralized server installation | Integrated directly into the developer’s IDE |
Real-time Feedback | Provides feedback during continuous integration | Offers real-time feedback within the developer’s IDE |
Code Analysis Depth | Offers in-depth static code analysis and metrics | Provides on-the-fly code analysis with immediate feedback |
Integration with CI/CD | Integrates with CI/CD pipelines for automated analysis | Supports local analysis as well as CI/CD integration |
Rule Configurability | Highly configurable rules for code quality and security | Limited rule configuration options within the IDE |
Collaboration | Facilitates collaboration among development teams | Focuses on individual developer experience and collaboration |
Use Case | Suitable for larger projects with centralized management | Ideal for individual developers or smaller development teams |
In SonarQube, “rules” are definitions that describe code patterns that indicate potential problems, security vulnerabilities, or areas for improvement in code quality. The SonarQube analysis engine uses these rules to scan the source code and highlight potential problems. Each rule has a definition that allows a specific pattern to be identified and covers aspects such as: good practices, errors, vulnerability, security, among others.
Quality profiles are a set of specific and organized rules that apply to specific projects. These profiles allow you to customize the rules you want to use to evaluate code quality based on your specific needs and standards. Therefore, profiles allow you to customize which rules apply to a project and provide predefined profiles for different programming languages.
Quality Gates are sets of conditions that are applied to a project after running a static analysis of the code and applying the rules defined in the quality profiles. These conditions allow you to quantify and evaluate whether a project meets specific quality criteria, helping to determine if the code is acceptable for implementation.
Metric | Description |
---|---|
Reliability Rating | This indicator evaluates the reliability of the code, which means how prone the code is to contain errors or defects. |
Security Rating | This indicator evaluates the security level of the code, which means how prone the code is to contain security vulnerabilities. |
Security Hotspots Reviewed | This indicator evaluates whether all security points identified in the code have been reviewed. |
Maintainability Rating | This indicator evaluates the ease with which the code can be maintained and improved in the future |
Coverage | This indicator examines the % of code that has been executed. |
Duplicated Lines (%) | This flag checks for duplicate lines in the code |
Ensure that Docker is installed on your machine. You can download and install Docker from the official website: Docker
Open a terminal and run the following command to pull the official SonarQube Docker image from Docker Hub:
docker pull sonarqube
Execute the following command in a terminal to run the sonarqube container.
docker run
-d --name sonarqube
-e SONAR_ES_BOOTSTRAP_CHECKS_DISABLE=true
-p 9000:9000
sonarqube:latest
Command | Description |
---|---|
docker run |
This is the command used to run a Docker container. |
-d |
This is a Docker run option that stands for “detached.” It runs the container in the background, which means you get your terminal prompt back immediately after starting the container. |
--name sonarqube |
This option allows you to specify a name for the container. In this case, the name “sonarqube” is given to the container, which makes it easier to reference the container later. |
-e SONAR_ES_BOOTSTRAP_CHECKS_DISABLE=true |
This option is used to set an environment variable within the container. It disables Elasticsearch bootstrap checks when starting SonarQube. |
-p 9000:9000 |
This option is used to map ports between the host and the container. It specifies that port 9000 on the host should be mapped to port 9000 inside the container, allowing access to SonarQube. |
sonarqube:latest |
This is the Docker image to run. It specifies the image named “sonarqube” and the “latest” tag, pulling the latest version from Docker Hub and creating a container from that image. |
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d8e576b6039e sonarqube:latest "/opt/sonarqube/dock…" 13 seconds ago Up 8 seconds 0.0.0.0:9000->9000/tcp, :::9000->9000/tcp sonarqube
🔐 Initial user and password login: admin password: admin
This Python🐍 code was created using chat-gpt intentionally includes some practices that may violate default SonarQube configurations.
In addition, we will duplicate this file in the same folder to be able to generate an alert for duplicate code by generating the same file with the name main_bk
main.py
# Code Smell: Unused variable
= 42
unused_variable
# Code Smell: Unused function
def unused_function():
pass
# Code Smell: Redundant parentheses
= (5 * 3)
result
# Code Smell: Unused import
import unused_module
# Code Smell: Print statement (considered a bad practice)
print("Hello, World!")
# Code Smell: Hardcoded values
= 42
magic_number
# Code Smell: Unused loop variable
for _ in range(5):
pass
# Code Smell: Assignment in a condition
if (result == 0): # Fix the equality check
pass
# Code Smell: Using a single underscore as a variable name
= "Unused variable"
_
# Code Smell: Using a mutable default argument in a function
def append_item(item, my_list=None):
if my_list is None:
= []
my_list
my_list.append(item)return my_list
# Code Smell: Unused variable in an exception block
try:
= int("text")
value except ValueError as e:
= e
unused_exception_variable
# Code Smell: Complex lambda function
= lambda x: x**2 + 2*x + 1 square
The following file contains the properties for execute the code quality processes in sonarqube. It is necesary to change the projectkey and the project name, in my case the both name is “test”, this parameters is config when you create the projects in SonarQube web application.
Filename: “sonar-project.properties”
# must be unique in a given SonarQube instance
sonar.projectKey=test
# --- optional properties ---
# defaults to project key
sonar.projectName=test
# defaults to 'not provided'
sonar.projectVersion=1.0
# Path is relative to the sonar-project.properties file. Defaults to .
sonar.sources=.
sonar.language=python
#----- Default SonarQube server
sonar.host.url=http://localhost:9000
# Encoding of the source code. Default is default system encoding
sonar.sourceEncoding=UTF-8
In summary, the folder that should contain the following files
main.py
main_bk.py
sonar-project.properties
The images below illustrate all the steps necessary to create the project and obtain the token for the scanner later.
"Create"
and define the name of the quality gate."Unlock Editing"
to update the condition metrics.default
To start the scanning process using the SonarQube CLI, execute the following command after replacing placeholders with your specific information. Ensure that this command is run in the terminal where the source path, containing the ‘sonar-project.properties’ file, is located.
It’s crucial to set your token as an environment variable using the following syntax: -e SONAR_LOGIN=“your_token_here”.
For example, if your token is “sqp_08ad32fcb385e8192b1a4e0aabdc54be3b1ad946” the corresponding command to be executed would be:
docker run --network=host
-e SONAR_HOST_URL=http://host.docker.internal:9000
-e SONAR_LOGIN="sqp_08ad32fcb385e8192b1a4e0aabdc54be3b1ad946"
-e SONAR_PROJECT_KEY=data-quality
-it -v "$(pwd):/usr/src"
sonarsource/sonar-scanner-cli
In the terminal you will see the following log
Digest: sha256:494ecc3b5b1ee1625bd377b3905c4284e4f0cc155cff397805a244dee1c7d575
Status: Downloaded newer image for sonarsource/sonar-scanner-cli:latest
INFO: Scanner configuration file: /opt/sonar-scanner/conf/sonar-scanner.properties
INFO: Project root configuration file: /usr/src/sonar-project.properties
INFO: SonarScanner 5.0.1.3006
INFO: Java 17.0.8 Alpine (64-bit)
INFO: Linux 5.10.25-linuxkit amd64
INFO: User cache: /opt/sonar-scanner/.sonar/cache
INFO: Analyzing on SonarQube server 10.3.0.82913
INFO: Default locale: "en_US", source code encoding: "UTF-8"
INFO: Load global settings
INFO: Load global settings (done) | time=624ms
INFO: Server id: 147B411E-AYxB7bsnEO8aoeQvN3oK
INFO: User cache: /opt/sonar-scanner/.sonar/cache
INFO: Load/download plugins
INFO: Load plugins index
INFO: Load plugins index (done) | time=453ms
INFO: Load/download plugins (done) | time=5843ms
INFO: Process project properties
INFO: Process project properties (done) | time=42ms
INFO: Execute project builders
INFO: Execute project builders (done) | time=10ms
INFO: Project key: data-quality
INFO: Base dir: /usr/src
INFO: Working dir: /usr/src/.scannerwork
INFO: Load project settings for component key: 'data-quality'
WARN: SCM provider autodetection failed. Please use "sonar.scm.provider" to define SCM of your project, or disable the SCM Sensor in the project settings.
INFO: Load quality profiles
INFO: Load quality profiles (done) | time=3356ms
INFO: Load active rules
when the process finish you can see the following log
INFO: ------------- Run sensors on project
INFO: Sensor Analysis Warnings import [csharp]
INFO: Sensor Analysis Warnings import [csharp] (done) | time=3ms
INFO: Sensor Zero Coverage Sensor
INFO: Sensor Zero Coverage Sensor (done) | time=14ms
INFO: SCM Publisher No SCM system was detected. You can use the 'sonar.scm.provider' property to explicitly specify it.
INFO: CPD Executor Calculating CPD for 0 files
INFO: CPD Executor CPD calculation finished (done) | time=0ms
INFO: Analysis report generated in 273ms, dir size=137.8 kB
INFO: Analysis report compressed in 306ms, zip size=17.4 kB
INFO: Analysis report uploaded in 412ms
INFO: ANALYSIS SUCCESSFUL, you can find the results at: http://localhost:9000/dashboard?id=test
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://localhost:9000/api/ce/task?id=AYxTnq5AFtsPP8-M5c1w
INFO: Analysis total time: 18.832 s
INFO: ------------------------------------------------------------------------
INFO: EXECUTION SUCCESS
INFO: ------------------------------------------------------------------------
INFO: Total time: 27.819s
INFO: Final Memory: 21M/80M
INFO: --------------------------------------------------------
Upon completion of the code scan, you can view the results of the code analysis on the web application at localhost:9000
The following table presents the metrics defined by SonarQube, which are objective indicators designed to evaluate the quality of the source code. These metrics allow a quantitative evaluation of various critical aspects of the code.
Metric | Description |
---|---|
Reliability | The “Reliability” metric refers to the reliability of the code. It measures the number of issues related to software reliability, such as errors and failures. |
Maintainability | The “Maintainability” metric in SonarQube assesses how easy it is to maintain and enhance the code over time. It measures code quality in terms of structure, readability, and ease of maintenance. |
New Code Smells | This metric indicates the number of new “code smells” introduced in the code recently. “Code smells” are design patterns or coding practices that may indicate issues with code quality. |
Security | The “Security” metric in SonarQube evaluates code security for potential vulnerabilities. It measures the code’s ability to resist attacks and protect data and systems. |
New Vulnerabilities | It indicates the number of new security vulnerabilities introduced in the code recently. Vulnerabilities are weaknesses that can be exploited by attackers. |
Security Review | This metric in SonarQube assesses the quality of security reviews conducted on the code. It measures the effectiveness of reviews in detecting and correcting security issues. |
New Security Hotspots | It signifies the number of new “security hotspots” introduced in the code recently. Security hotspots are areas of the code that require special attention due to potential security issues. |
Coverage | The “Coverage” metric in SonarQube refers to code coverage. It measures the proportion of code that has been tested through unit tests or automated tests. |
Duplications | This metric in SonarQube identifies sections of code that are duplicated in multiple places. Identifying and reducing duplications can improve code quality and maintainability. |
The result of the scan is the following
“SonarQube Issues” refer to issues identified by the SonarQube static code analysis process. Each issue provides:
📍 Location of the Issue: Enables identification of where the problem exists in the code.
🤔 Reason for the Issue: Offers a detailed explanation of why it is considered a problem.
💬 Activity: Facilitates collaboration by allowing the addition of comments and discussions about potential solutions.
👤 Assignment: Permits the assignment of the issue to a registered user in SonarQube for tracking and resolution.
📊 Status: Initiates with the “Open” status upon creation but may transition to other statuses such as:
🏷️ Tags: Allows the addition of tags to enhance the identification and categorization of issues.
The SonarQube API empowers users to interact with and extract information programmatically from a SonarQube instance. These APIs serve as a tool for developers, administrators, and integrators, enabling the automation of tasks, retrieval of project metrics, and seamless integration of SonarQube data into various workflows.
🤖 Automation: The SonarQube API allows for the automation of various tasks related to project analysis, configuration, and management. This includes triggering analyses, retrieving analysis results, and managing quality profiles.
📊 Data Retrieval: Users can extract a wide range of data from SonarQube, including project metrics, issues, code smells, duplications, and more. This information can be used for reporting, analytics, and custom dashboards.
🔗 Integration: The API facilitates integration with other development tools, continuous integration (CI) systems, and external applications. This enables seamless incorporation of SonarQube’s code quality and security analysis into existing development pipelines.
⚙️ Configuration Management: The API allows users to manage SonarQube configurations programmatically. This includes creating and updating quality profiles, setting project configurations, and managing global settings.
🤖 Automated Analysis: Integrate SonarQube analysis into your CI/CD pipeline by triggering analyses automatically after code commits or builds.
📊 Custom Reporting: Extract specific metrics and data from SonarQube to generate custom reports tailored to your team or organization’s needs.
🐛 Issue Tracking: Retrieve information about code issues, security vulnerabilities, and code smells to integrate SonarQube data into your issue tracking or project management system.
🚦 Quality Gate Status: Monitor and retrieve the status of Quality Gates for projects to ensure that code meets predefined quality criteria.
🛠️ Configuration as Code: Manage SonarQube configurations using scripts or code, making it easier to replicate configurations across different instances.
pip install python-sonarqube-api
sonarqube client
from sonarqube import SonarQubeClient
import pandas as pd
= SonarQubeClient(sonarqube_url="http://localhost:9000", username='admin', password='admin123') sonar
= sonar.projects.search_projects()
projects projects
{'paging': {'pageIndex': 1, 'pageSize': 100, 'total': 1},
'components': [
{'key': 'test',
'name': 'test',
'qualifier': 'TRK',
'visibility': 'public',
'lastAnalysisDate': '2023-12-10T13:47:32+0000',
'managed': False}]}
= sonar.project_analyses.search_project_analyses_and_events(project="test")
project_analyses_and_events = pd.json_normalize(project_analyses_and_events['analyses']) project_analyses_and_events
for item in project_analyses_and_events['events'] if item!=[]]```
[item
```bash'key': 'AYxT_AnVJaFOvYeUMXMa', 'category': 'VERSION', 'name': '1.0'}],
[[{'key': 'AYxT-xvhJaFOvYeUMXIe',
[{'category': 'QUALITY_GATE',
'name': 'Failed',
'description': 'Coverage on New Code < 80, New Code Smells > 0'}],
'key': 'AYxT-cgDJaFOvYeUMXFb',
[{'category': 'QUALITY_GATE',
'name': 'Passed',
'description': ''}],
'key': 'AYxT7MvDJaFOvYeUMW5W',
[{'category': 'QUALITY_GATE',
'name': 'Failed',
'description': 'Coverage on New Code < 80'}]]
If you want to learn…
Other references:
Text and figures are licensed under Creative Commons Attribution CC BY 4.0. The figures that have been reused from other sources don't fall under this license and can be recognized by a note in their caption: "Figure from ...".
For attribution, please cite this work as
Mendez (2023, Dec. 10). Romina Mendez: Code Quality - SonarQube. Retrieved from https://r0mymendez.github.io/posts_en/2023-12-10-code-quality-sonarqube/
BibTeX citation
@misc{mendez2023code, author = {Mendez, Romina}, title = {Romina Mendez: Code Quality - SonarQube}, url = {https://r0mymendez.github.io/posts_en/2023-12-10-code-quality-sonarqube/}, year = {2023} }