Integrate NDepend with SonarQube

IMPORTANT:
  • The communication from NDepend to SonarQube occurs through XML files: hence the NDepend plugin must run on a Windows machine but the SonarQube server can run on any OS.
  • To run the NDepend SonarQube plugin on a machine NDepend must be activated on it first.

    To do so, once NDepend files are unzipped on the machine, just run from a command window NDepend.Console.exe /RegEval to start evaluation or NDepend.Console.exe /RegLic XYZ to register a seat of the Build-Machine license with key XYZ.

    If the machine is not connected to internet, a simple offline activation procedure will be proposed instead, and must be fulfilled in order to run the SonarQube NDepend plugin.

  • The NDepend SonarQube plugin supports SonarQube version 5.6 and higher.
  • If you are using NDepend v6, see the SonarQube integration here.

Introduction: NDepend and SonarQube rule-sets are complimentary

Both NDepend and SonarQube are static analyzers that offer a rule-based system to detect problems in C# and VB.NET code. However the NDepend default Rules-Set has very few overlap with the SonarQube rules and also with the Roslyn analyzers.

Basically the Roslyn analyzers and SonarQube rules are good at analyzing what is happening inside a method, the code flow while the NDepend code model, on which the NDepend rules are based, is optimized for a 360 view of particular higher-scale areas including OOP, dependencies, metrics, breaking changes, mutability, naming...

Concretely Roslyn analyzers and SonarQube rules can warn about problems like a reference that doesn't need to be tested for nullity because in the actual scope it cannot be null, while NDepend can warn you about too complex classes or components, and offer advices about how to refactor to make the code cleaner and more maintainable.

Another point that makes the NDepend ruling system unique is how easy it makes to write custom rules. With NDepend a rule is a C# LINQ query, that queries a code model dedicated to code quality, edited live in Visual Studio, compiled and executed live at edition time.

Concretely, this piece of code below is a fully functional rule, could it be simpler?

// <Name>Interfaces must start with an I</Name>
warnif count > 0 
Application.Types.Where(t => t.IsInterface && !t.SimpleName.StartsWith("I"))

When defining a custom rule with NDepend, the user doesn't need to create a Visual Studio project, create a source file, step into the edit/compile/debug cycle, maintain a binary assembly that requires effort to be shared, versioned and integrated.

With NDepend custom rules are raw texts, embedded as XML CDATA into the NDepend project or rule files. Also, the documentation and how-to-fix guidelines can be embedded in the rule source code as comments.

Editing a custom code rule with NDepend in Visual Studio

Also each NDepend rule can present its issues with extra data that will help understanding the problem and fix it.

Moreover each rule can embed two C# formulas that attempt to estimate both the cost to fix the issue and the annual cost to let the issue unfixed, also called the technical-debt and the annual interest of the issue. Since these formulas rely on what really matter at fix time, this makes the debt estimations smart.

For example, below, in a rule that attempts to detect wrong dependencies based on getting rid of dependency cycles between namespaces, cost to fix estimations are estimated in terms of the amount of coupling to get rid of. The team can rely on realistics estimations to take the right decisions.

Architecture Rule with NDepend

Finally, with NDepend each rule is run in a few milli-seconds even on a large code base. As a consequence all rules can be passed in a few seconds (typically 2 or 3 seconds on a real-world code base), both in Visual Studio and in the Continuous-Integration system.

As a benefit, after each compilation and also at check-in time, the developer instantly knows about the new and fixed issues since the baseline, and the impact in terms of technical debt fixed or created.

Now let's explain how to integrate NDepend rule results into the SonarQube system to cumulate the strength of both products.

Plugin Prerequisites

Install the NDepend Plugin

    Copy the sonar-ndepend-plugin-VERSION.jar

    • from the $NDependInstallDir$\Integration\SonarQube directory
    • to the $SonarQubeInstallDir$\extensions\plugins directory
    • Restart the SonarQube server for it to take account of the NDepend plugin.

    Notice that this plugin is open sourced at: https://github.com/SonarCommunity/sonar-ndepend

NOTE:

If you are not using the NDepend plugin on SonarQube install, make sure to remove its sonar-ndepend-plugin-VERSION.jar file from the $SonarQubeInstallDir$\extensions\plugins directory and then restart the SonarQube server.

Else the NDepend plugin will check for certain pathes and parameters, and if not found, it will break the SonarQube analysis with an error.

Define the NDepend Rules-set that will be configured into the Sonar server

  • In the SonarQube user interface, go to Administration. You need to be logged with the appropriate administrator privileges for that.
  • NDepend plugin SonarQube UI settings
  • MANDATORY Specify the path to NDepend.SonarQube.RuleRunner.exe. This path is $NDependInstallPath$\Integration\SonarQube\NDepend.SonarQube.RuleRunner.exe. Don't prefix the path with an environnement variable path, write the entire absolute path (follow this advice for all paths writing you'll find in this documentation).
  • OPTIONAL Specify the NDepend project file path (.ndproj extension) to fetch the rules from. If it's not specified the default NDepend rule set will be used.

    If you specify the NDepend project file path, the rules taken account are activated rules defined in:

    • The NDepend project file,
    • Rules defined in the NDepend Rules Files referenced by the NDepend project file
    • and NDepend rules defined in source code

Activate the NDepend Rules in the Sonar server

The NDepend rules are now loaded in the SonarQube repository but not activated yet.

To activate them, you have to:

  • Log as admin in the SonarQube UI
  • Go to the Quality Profiles tab
  • Create a custom Quality Profile. If you already have a custom Quality Profile you can skip this step.
ndepend sonarqube extension create a custom quality profile

Make sure that you choose the Sonar way profile as parent of your new Quality Profile:

ndepend sonarqube extension sonar way built-in profile

After the creation of the custom Quality Profile, you have to add the NDepend rules. For that click on the Activate More button:

ndepend sonarqube extension activate more button

Choose the NDepend repository, and click on the Bulk Change button and activate all the NDepend rules in your new Quality Profile.

ndepend sonarqube extension bulk change button

Finally go back to the Quality Profile tab and set the new Quality Profile as Default:

ndepend sonarqube extension set the new quality profile as default

Activate the NDepend Rules in the Sonar server (before SonarQube v7.X)

Before SonarQube 7.X it was possible to activate new rules in the standard profile and the creation of a new custom Quality Profile was not mandatory

Once the step Define the NDepend Rules-set that will be configured into the Sonar server done, the NDepend rules are now loaded in the SonarQube repository but not activated yet. To activate them, you have to:

  • Log as admin in the SonarQube UI:
  • Go to the Rules tab:
  • Choose Language C# and Repository: NDepend
  • Activate the NDepend Rules in the SonarQube repository
  • Activate these rules in the profile you want by clicking on Bulk Change - Activate In:
  • Activate the NDepend Rules in the SonarQube repository : Bulk Changes
IMPORTANT:
  • Notice that the handle of a rule is the rule name with also the parent group(s) names and the rule source code. This remark is important in this situation when:

    - The NDepend project used for analysis contains a custom rule-set

    - The NDepend project specified in the SonarQube configuration to define the rules in the SonarQube system (parameter NDepend rules from ndproj, see the previous section) is different from the NDepend project used for analysis.

    In such situation if the two rules-set don't correspond exactly, the rules won't be resolved in the SonarQube system and the issues won't be computed.

    This is why we strongly recommend to rely on shared rule files when you have to deal with several NDepend projects with a custom rule-set. Doing so will prevent any custom rule resolving mistmatch.

  • If some rules have been added or removed in your custom rule-set:

    1) Restart the SonarQube server to let it parse the NDepend project specified in the SonarQube configuration to define the rules

    2) go again in the Rules tab logged as administrator, to activate/deactivate these new/removed rules through eventually a Bulk Change action.

Run MSBuild Sonar-Runner

Here is the SonarQube documentation concerning runnig MSBuild Sonar-Runner from the command line argument.

To let SonarQube.Scanner.MSBuild.exe also runs NDepend analysis and rules, you need to append the mandatory parameter /d:sonar.cs.ndepend.projectPath={the path of ndproj}.

Take note that you need to run the 3 commands below, you can eventually embed them in a batch file.

>SonarQube.Scanner.MSBuild.exe begin /key:{SonarQube project key} /name:{SQ project name} /version:{SQ project version}  /d:sonar.cs.ndepend.projectPath={the path of ndproj}
>MSBuild
>SonarQube.Scanner.MSBuild.exe end

Don't use any environment variable in paths and if the path contains a space character, surround it with double quotes /d:sonar.cs.ndepend.projectPath="C:\work with space\project.ndproj"

Notice you can use /d:sonar.cs.ndepend.skip=true to avoid triggering NDepend analysis (option introduced with NDepend v2019.2.5).


IMPORTANT:
  • Make sure that all your assemblies analyzed by NDepend PDB files are available at analysis time, because without PDB, NDepend rules issues won't have source file declaration available.
  • For this reason, if a single PDB file is missing, the executable NDepend.SonarQube.RuleRunner.exe, invoked through sonar-runner.bat, will fail. In such situation no NDepend rule issues will be shown in the Sonar UI. NDepend.SonarQube.RuleRunner.exe exit-code will be 1 (while 0 means success) and an explicit message will be shown on the console (but not in the SonarQube UI).
  • Related link: Understanding NDepend Analysis Inputs
  • Notice that if your code is not commited under an SCM, make sure to disable the run of SCM blame, else MSBuild Sonar-Runner will fail. https://docs.sonarqube.org/latest/extend/adding-scm/
What if I run Sonar on a Linux machine and NDepend on a Windows machine?
  • The Sonar scanner on Windows will take care of starting NDepend.SonarQube.RuleRunner.exe.
  • Hence the path to NDepend.SonarQube.RuleRunner.exe you provide is the absolute path in the windows machine where the sonar msbuild scanner is executed.
REMARKS
  • According to the SonarQube documentation: "MSBuild SonarQube Runner is the only official way to launch a SonarQube analysis on .NET projects."

Tips in case of Analysis Error

If the NDepend analysis fails, you can have a look at Sonar scanner logs and you'll see the error cause in the NDepend exception report.

Activate the NDepend Rules in the SonarQube repository

Most of the times a NDepend analysis error comes from:

  • NDepend project file path specified in not found (we remind this path is specified in SonarQube.Scanner.MSBuild.exe begin ... /d:sonar.cs.ndepend.projectPath={the path of ndproj})
  • NDepend fails to find any assembly to analysis, referenced by the NDepend project (more on NDepend assemblies resolution here)
  • One or several assemblies PDB missing (see expanations above in the IMPORTANT section)
  • NDepend output directory locked, or cannot be created, because of unauthorized Windows privileges

Browse NDepend Rules Issues in the SonarQube UI

    NDepend Rules Issues are now reported as any issues in the SonarQube UI.

    You can browse it, go to source code declaration (in the UI), assign it, change its status...

NDepend Issues in the SonarQube interface
NOTES:
  • In the SonarQube UI, issues on fields and on abstract methods will be located at the source file declaration of their parent type. We are commited to fix this limitation within this year 2017.
  • The same way most of issues on VB.NET code won't be properly reported in the SonarQube UI and we are commited to fix this limitation within this year 2017.
  • If some issues are missing in the SonarQube UI:

    - Check that you followed all rules activation steps explained in this document.

    - Then double check that the concerned rule is indeed activated by checking if it emits at least one issue.

    - In such case, if some issues are missing, this is because the source file declaration of their parent types hasen't been found.

    Typically this happens with types and their members generated by the compiler.