Introduction

This post will describe how to integrate SonarCloud for a Java (Maven-based) project in Azure DevOps CI.


Steps


1. Create java project in GitHub

Will be using https://start.spring.io and create a simple SpringBoot app.


2. Create basic Azure DevOps pipeline YAML config in your repo:

---
jobs:
  - job: Linux_with_Java11  
    pool:
      vmImage: 'Ubuntu-20.04'
  
    steps:
    - task: Maven@3
      inputs:
        mavenPomFile: '$(System.DefaultWorkingDirectory)/spring-boot-azure-devops-sonarcloud/pom.xml'
        javaHomeOption: 'JDKVersion'
        jdkVersionOption: '1.11'
        jdkArchitectureOption: 'x64'
        goals: 'verify'

The above pipline contains only one maven task which builds sample project.


3. Create Azure DevOps project

Create a new project in Azure DevOps, ex: https://dev.azure.com/mogikanensoftware/Maven%20Demos


4. Create Azure DevOps build pipeline

Configure Azure DevOps CI pipeline:

  • Use “New pipeleine” in “Pipilenes -> Builds” in Azure DevOps project.
  • Select GitHub(YAML) option
  • Select the repo and point to azure-pipelines.yml


5. SonarCloud setup

  • Create new project in SonarCloud
  • Grant access to GitHub
  • Select “With other CI tools” option on “Choose your Analysis Method” page
  • Select “Maven” when answering “What option best describes your build?” question

At this point SonarCloud page contains description of futher steps which can be executed manually on your machine and include:

  • Setting SONAR_TOKEN env var
  • Generated token
  • instructions on how to update pom.xml
  • instructions on how to run sonar in your local project folder:
 
 mvn verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=demo-java-sonar-cloud


6. Adjust pom.xml

  • Add recommended sonar props to pom.xml
  • Also add sonar.projectKey to pom.xml to shorten maven command and consolidate sonar props
...
<groupId>com.example</groupId>
	<artifactId>demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>demo-java-sonar-cloud</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>11</java.version>
		<sonar.organization>mogikanen9-github</sonar.organization>
    <sonar.host.url>https://sonarcloud.io</sonar.host.url>
		<sonar.projectKey>demo-java-sonar-cloud</sonar.projectKey>
	</properties>
  ...

7. Main detail - pass SONAR_TOKEN safely and secretly

The main idea is to execute sonar check using Sonar Maven plugin in Azure DevOps CI pipleine. The important details is that we need to provide SONAR_TOKEN env var to the pipeline and we also need to keep it secret - token value must not be inside our source code (including azure-pipelines.yml)

A simple solution is to use Azure DevOps CI secret variables which can be stored with your pipeline in AzureDevOps. Those secret vars are encrypted.

8. Define a variable with SONAR_TOKEN value

  • Edit created pipeline in AzureDevOps CI UI
  • Select “Variables” in top right coner
  • Create new var named MY_SONAR_TOKEN_VAR and save SONAR_TONE value in it
  • Important! Select Keep this value secret option

9. Add SONAR_TOKEN as env var to pom.xml

Each AzureDevOps CI pipeline task has env option. Two changes has to be done:

  • SONAR_TOKEN env has to be defined there
  • SONAR_TOKEN value must reference secret MY_SONAR_TOKEN_VAR variable to get its value
    - task: Maven@3
      inputs:
        mavenPomFile: '$(System.DefaultWorkingDirectory)/spring-boot-azure-devops-sonarcloud/pom.xml'
        javaHomeOption: 'JDKVersion'
        jdkVersionOption: '1.11'
        jdkArchitectureOption: 'x64'
        goals: 'verify'
      env: 
        SONAR_TOKEN: $(MY_SONAR_TOKEN_VAR)  

10. Add sonar execution to Maven Taks goals

goals: 'verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar'

Final pipeline should look like:

---
jobs:
  - job: Linux_with_Java11  
    pool:
      vmImage: 'Ubuntu-20.04'
  
    steps:
    - task: Maven@3
      inputs:
        mavenPomFile: '$(System.DefaultWorkingDirectory)/spring-boot-azure-devops-sonarcloud/pom.xml'
        javaHomeOption: 'JDKVersion'
        jdkVersionOption: '1.11'
        jdkArchitectureOption: 'x64'
        goals: 'verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar'
      env: 
        SONAR_TOKEN: $(MY_SONAR_TOKEN_VAR)  

Done

Once a pipeline build is triggered sonar plugin is executed. It will create update project in SonarCloud and will publish results there.

Alternative to Azure DevOps pipelines secret vars Azure Vault can be used to store and provide SONAR_TOKEN value - check Use Azure Key Vault secrets in Azure Pipelines.

References: