Build vNext and SonarQube Runner: Dynamic Version Script

teambuild
27038

SonarQube is a fantastic tool for tracking technical debt, and it’s starting to make some inroads into the .NET world as SonarSource collaborates with Microsoft. I’ve played around with it a little to start getting my hands dirty.

Install Guidance

If you’ve never installed SonarQube before, then I highly recommend this eGuide. Just one caveat that wasn’t too clear: you need to create the database manually before running SonarQube for the first time. Just create an empty database (with the required collation) and go from there.

Integrating into TeamBuild vNext – with Dynamic Versioning

Once you’ve got the server installed and configured, you’re ready to integrate with TeamBuild. It’s easy enough using build VNext Command Line task. However, one thing bugged me as I was setting this up – hard-coding the version number. I like to version my assemblies from the build number on the build using a PowerShell script. Here’s the 2015 version (since the environment variable names have changed):

Param(
  [string]$pathToSearch = $env:BUILD_SOURCESDIRECTORY,
  [string]$buildNumber = $env:BUILD_BUILDNUMBER,
  [string]$searchFilter = "AssemblyInfo.*",
  [regex]$pattern = "\d+\.\d+\.\d+\.\d+"
)
 
if ($buildNumber -match $pattern -ne $true) {
    Write-Error "Could not extract a version from [$buildNumber] using pattern [$pattern]"
    exit 1
} else {
    try {
        $extractedBuildNumber = $Matches[0]
        Write-Host "Using version $extractedBuildNumber in folder $pathToSearch"
 
        $files = gci -Path $pathToSearch -Filter $searchFilter -Recurse

        if ($files){
            $files | % {
                $fileToChange = $_.FullName  
                Write-Host "  -> Changing $($fileToChange)"
                
                # remove the read-only bit on the file
                sp $fileToChange IsReadOnly $false
 
                # run the regex replace
                (gc $fileToChange) | % { $_ -replace $pattern, $extractedBuildNumber } | sc $fileToChange
            }
        } else {
            Write-Warning "No files found"
        }
 
        Write-Host "Done!"
        exit 0
    } catch {
        Write-Error $_
        exit 1
    }
}

So now that I get dll’s versions matching my build number, why not SonarQube too? So I used the same idea to wrap the “begin” call into a PowerShell script which can get the build number too:

Param(
  [string]$buildNumber = $env:BUILD_BUILDNUMBER,
  [regex]$pattern = "\d+\.\d+\.\d+\.\d+",
  [string]$key,
  [string]$name
)
 
$version = "1.0"
if ($buildNumber -match $pattern -ne $true) {
    Write-Verbose "Could not extract a version from [$buildNumber] using pattern [$pattern]" -Verbose
} else {
    $version = $Matches[0]
}

Write-Verbose "Using args: begin /v:$version /k:$key /n:$name" -Verbose
$cmd = "MSBuild.SonarQube.Runner.exe"

& $cmd begin /v:$version /k:$key /n:$name

I drop this into the same folder as the MsBuild.SonarQube.Runner.exe so that I don’t have to fiddle with more paths. Here’s the task in my build:

image

The call to the SonarQube runner “end” doesn’t need any arguments, so I’ve left that as a plain command line call:

image

Now when the build runs, the version number passed to SonarQube matches the version number of my assemblies which I can tie back to my builds. Sweet!

image

One more change you could make is to specify the key and name arguments as variables. That way you can manage them as build variables instead of managing them in the call to the script on the task.

Finally, don’t forget to install the Roslyn SonarQube SonarLint extension. This will give you the same analysis that SonarQube uses inside VS.

Happy SonarQubing!