Fight Technical Debt With SonarQube

The longer a project continues, the more apparently innocent smells are added to the source code. Eventually, you will be in a swamp which is very hard to get out of. Technical debt is a devious thing that sneaks up on you.

How would you like it if check-ins with smelly code are rejected automatically? That might be an efficient way to battle some of the technical debt anyway.

For a while now, Team Foundation Server (TFS) provides gated check-in builds. Such builds are triggered just before code is checked in. If the build fails, the check-in is rejected.

To be honest, I have never been a huge fan of gated check-ins. Most people remember to compile and run the tests before they check-in, so in my opinion, gated check-in builds were just something that were in the way.

However, with the more intelligent analysis of SonarQube, I think it is time to reevaluate that opinion and make use of gated check-in builds again.

Introduction to SonarQube

SonarQube is a service that can perform different forms of analysis of your project. It can run code analysis for you, such as FxCop and their own SonarLint. If you need to, you can write custom rules (in XPath format for C#) for any special validation you need to make.

Information that is produced by a build, such as code coverage and unit test execution results, can be reported to SonarQube. Analysis of that can be made on the entire code base or just on new code. Either from last analysis, or from the last version of the software.

SonarQube Nemo Instance

A great feature of SonarQube is that it can perform trend analysis of these project metrics. Metrics can be used both to visualize how the project has evolved over time, or to set a quality gate that code must pass before it is submitted. For example, SonarQube can be configured so that it is not ok if code coverage is lower than a certain value. It is wise to configure that threshold to be based on metrics from new or changed code since last analysis. This makes it easier to introduce such a rule midway in a project.

Another nice feature is that it is possible to see the project code with coverage highlighting. Not everyone care to run tests with coverage when they develop, and what is worse, not all have coverage software to begin with. Code coverage included in Visual Studio Enterprise, or can be added with third party add-ons such as dotCover, but typically cost money.

(There are exceptions though. For example, nCover that comes bundled with TestDriven.Net is free for personal and open source development.)

Anyhow, it is really great to have one place where all can see and reason about the current code coverage!

Here are some links to posts from the SonarQube blog:

How to Get Started

SonarQube is hosted as a Java application that is run inside a windows service. If you like, you can use the following powershell script to set up SonarQube on a fresh Windows Server 2012 R2.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Install Java Runtime
iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))
cinst jre8 -y
# Get latest version
$tmpFilename = [System.IO.Path]::GetTempFileName()
$latestVersionUrl = wget -Uri "http://www.sonarqube.org/downloads/" -UseBasicParsing |
select -ExpandProperty Links | select -ExpandProperty href |
?{ $_ -match "distribution(.*)sonarqube-(.*).zip$" } | sort -Descending | select -First 1
wget $latestVersionUrl -UseBasicParsing -OutFile $tmpFilename
Add-Type -AssemblyName System.IO.Compression.FileSystem
[System.IO.Compression.ZipFile]::ExtractToDirectory($tmpFilename, 'c:\SonarQube')
rm $tmpFilename
# Install SonarQube service
$installerPath = Resolve-Path "C:\SonarQube\sonarqube-*\bin\windows-x86-64\InstallNTService.bat" |
select -ExpandProperty Path
& $installerPath
# Setup firewall rule
New-NetFirewallRule -DisplayName "SonarQube:9000" -Profile Any -LocalPort 9000 -Protocol tcp

Then, you have to manually configure SonarQube with the following steps.

  • Change the service logon to a local administrator account.
  • Consider connecting a real database to SonarQube, since migration of data is only supported if you have.
  • Start service.
    • Wait for Java(TM) Platform SE binary-processes to stop using 100% CPU.
  • Browse to http://localhost:9000.
  • Login with username admin and password admin.
    • Consider to change the admin password
  • Install the C# plugin under Administration - System - Update Center - Available.
  • Restart SonarQube service.
    • Wait for Java(TM) Platform SE binary-processes to stop using 100% CPU.
  • Create a new project under Administration - Projects - Management.

How to configure VSTS/TFS

Team Foundation Server (TFS) 2015 and Visual Studio Team Services (VSTS) comes with two build tasks for retrieving and sending data to a SonarQube service. In you have not got these tasks installed, you can get them at vso-agent-tasks.

If you use Team Foundation Version Control (TFVC), you can use gated builds to prevent bad quality check-ins.

Gated builds are not available if you use Git. In that case, use SonarQube to analyse your pull requests instead. There are plugins for GutHub and BitBucket that will do this for you. If you use VSTS/TFS there is no problem setting up the analysis as part of a pull request build.

If you have an old version of TFS, or have on-premise build agents, you need to install the SonarScanner manually. See the ALM Ranger Guidance pp 18-21 for instructions.