Publishing code analysis results to AzureDevops from docker

Hi,

Is there a way to run a sonarscan and publish the results to the quality gate AzureDevops policy from a docker container running in an AzureDevops yml pipeline. We have the sonarscannercli begin and end tasks, but no equivalent to the “SonarCloudPublish” task that is available within a docker container.
We’ve tried a few workarounds. Like copying out the .sonarqube folder from the docker image, then using the publish task from the .yml file, but the paths don’t match. I’ve check the community topics for any solution, the closest I’ve found is these two topics:

In both of them, a solution using webhooks is suggested, but the linked docs is far away from being useful for this.
I’ve a lot of questions regarding this:

  • What is the URL, I configure the webhook to post?
  • How do I configure the authentication?
  • What does the request look like, the quality gate endpoint accepts to approve the pull request?
    • Is it the same as the webhook publishes, or do I need a service that transforms the request?
  • The sonarcloud webhook calls azure devops to tell it the quality gate is approved? Is this what we are supposed to do? I’m just guessing, because the documentation about this is pretty much non existent.

It is very common to have a build run in a docker container, yet we don’t have a sonarcli task, or any useful documentation about how to do this.

Hey there.

To be clear, SonarQubeAnalyze submits the report to SonarCloud – SonarCloudPublish tags the build with the Quality Gate, but this is purely visual, it does not block the merge of your Pull Request or interact with the build policy whatsoever. It is not particularly useful.

Do you currently have orchestrated analyses of your pull requests configured within the context of your Docker build?

That means the correct values are being passed to the sonar.pullrequest.* analysis parameters in the context of a pull request build (sonar.pullrequest.key, sonar.pullrequest.base, and sonar.pullrequest.branch).

This values are automatically configured when using the Azure DevOps Extension. You can get an idea of how they’re derived here.

After that, as long as you have a bound organization and project, you should be able to receieve Pull Request Analysis in SonarCloud, and Pull Request Decoration which allows you to add a status policy

Hello,

I’m using the branch / pull request policy in Azure Devops described here: SonarScanner for Azure DevOps | SonarCloud Docs.

The quality gate check stays stuck in waiting unless we use the publish task. We’ve configured the sonarscanner begin task the following way (only the relevant configs are shown here):

/d:sonar.pullrequest.key=2675 
/d:sonar.pullrequest.branch=refs/heads/{branchname}
/d:sonar.pullrequest.base=master 
/d:sonar.host.url=https://sonarcloud.io 
/d:sonar.login=***

When using the SonarQubePublish task, it means the Azure pipelines job won’t be complete until the Quality Gate is computed SonarCloud-side. It does not affect the actual status.

Is it possible that when running the build without SonarQubePublish, the status appears populated after you are able to view the PR in SonarCloud?

I’m sorry. I may have mislead you. The quality gate status is fine in sonarcloud. My problem is that the Azure pipelines job is not completed.

Can you expand on this? What part is not completed? A screenshot or snippet of logs would be great.

Sure. Sorry for the delay. I had to gather the required data.

I have an Azure Devops project with a git repo. The master branch has the following policy configured:

This is what I’m seeing after a successful pipeline run on the pull request:
image

This is the definition of the yml pipeline:

trigger:
- master

jobs:  

  - job: WebApp
    pool:
      vmImage: ubuntu-latest      
    steps:
    - task: Docker@2
      displayName: Build WebApp
      inputs:
        command: 'build'
        Dockerfile: '**/Dockerfile'
        arguments: '--build-arg SONAR_TOKEN=$(SONAR_TOKEN) --build-arg BUILD_REASON=$(Build.Reason) --build-arg PULLREQUEST_ID=$(System.PullRequest.PullRequestId) --build-arg TARGET_BRANCH_NAME=$(System.PullRequest.targetBranchName) --build-arg SOURCE_BRANCH_NAME=$(System.PullRequest.SourceBranch)'

This is the dockerfile:

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS webapp-ci

ARG SONAR_PROJECT_KEY=[---REDACTED---]
ARG SONAR_OGRANIZAION_KEY=[---REDACTED---]
ARG SONAR_HOST_URL=https://sonarcloud.io
ARG SONAR_TOKEN

# BUILD_REASON = PullRequest (need to run sonarscanner on pr) <- Build.Reason
ARG BUILD_REASON 
# System.PullRequest.PullRequestId	
ARG PULLREQUEST_ID 
# System.PullRequest.targetBranchName	
ARG TARGET_BRANCH_NAME
# System.PullRequest.SourceBranch	
ARG SOURCE_BRANCH_NAME


ENV NUGET_CERT_REVOCATION_MODE=offline
ENV NUGET.PLUGIN.HANDSHAKE.TIMEOUT.IN.SECONDS=20
ENV NUGET.PLUGIN.REQUEST.TIMEOUT.IN.SECONDS=20

RUN apt-get update && apt-get install -y openjdk-11-jdk
RUN dotnet tool install --global dotnet-sonarscanner
RUN dotnet tool install --global coverlet.console
ENV PATH="$PATH:/root/.dotnet/tools"
ENV LANG=C.UTF-8 LC_ALL=C.UTF-8

WORKDIR /app

RUN echo ${SONAR_TOKEN}
RUN echo ${BUILD_REASON}
RUN echo ${PULLREQUEST_ID}
RUN echo ${TARGET_BRANCH_NAME}
RUN echo ${SOURCE_BRANCH_NAME}

RUN if [ "${BUILD_REASON}" = "PullRequest" ] ; then dotnet sonarscanner begin \
  /k:${SONAR_PROJECT_KEY} \
  /o:${SONAR_OGRANIZAION_KEY} \
  /d:sonar.pullrequest.key=${PULLREQUEST_ID}\
  /d:sonar.pullrequest.branch=${SOURCE_BRANCH_NAME}\
  /d:sonar.pullrequest.base=${TARGET_BRANCH_NAME}\
  /d:sonar.host.url=${SONAR_HOST_URL} \
  /d:sonar.login=${SONAR_TOKEN} \
  /d:sonar.cs.opencover.reportsPaths=/coverage.opencover.xml \
  /d:sonar.exclusions=app/[---REDACTED---]/wwwroot/**/* ; else dotnet sonarscanner begin \
  /k:${SONAR_PROJECT_KEY} \
  /o:${SONAR_OGRANIZAION_KEY} \
  /d:sonar.host.url=${SONAR_HOST_URL} \
  /d:sonar.login=${SONAR_TOKEN} \
  /d:sonar.cs.opencover.reportsPaths=/coverage.opencover.xml \
  /d:sonar.exclusions=app/[---REDACTED---]/wwwroot/**/* ; fi

ARG FEED_URL

COPY . ./

RUN dotnet restore [---REDACTED---]/[---REDACTED---].csproj --runtime linux-x64

RUN dotnet build [---REDACTED---]/[---REDACTED---].csproj \
--no-restore \
--configuration Debug \
--runtime linux-x64 \
--no-self-contained \
/property:WarningLevel=0

RUN dotnet sonarscanner end /d:sonar.login=${SONAR_TOKEN}

Here are the logs: Build Logs - Pastebin.com

If I’m not using docker and build the whole thing in the azure pipelines runner with the built in tasks using the following .yml

trigger:
- master

jobs:  
  - job: Sonar
    displayName: Sonar
    pool:
      vmImage: 'ubuntu-latest'
    steps:
    - task: SonarCloudPrepare@1
      enabled: true
      inputs:
        SonarCloud: 'SonarCloud [---REDACTED---]-[---REDACTED---]'
        organization: '---REDACTED---'
        scannerMode: 'MSBuild'
        projectKey: '---REDACTED---_[---REDACTED---]'
        projectName: '[---REDACTED---]'
        extraProperties: |          
          sonar.exclusions=[---REDACTED---].App/wwwroot/**,**/Properties/**,[---REDACTED---].App/appsettings.json,[---REDACTED---].App/appsettings.*.json
    - task: DotNetCoreCLI@2
      inputs:
        command: 'build'
        projects: '[---REDACTED---].App/[---REDACTED---].App.csproj'
      displayName: 'Build app'
    - task: SonarCloudAnalyze@1
      enabled: true
      displayName: 'Run Code Analysis'
    - task: SonarCloudPublish@1
      enabled: true
      displayName: 'Publish Quality Gate Result'

The quality gate is going green:
image

I’d like to have the same functionality using docker.

Okay, I think I understand now. I’d like to return to this point:

Is the project bound?

Yes, I have these badges:

image
image

Okay. Thanks. I’ll reach out via a private message for some private details.

Hey @Plevi1337

Thanks for the details.

My understanding is that when the project is bound there should be data that’s always available to SonarCloud when decorating PRs. That data doesn’t seem to be there on the PR you shared with me.

This is data that is set also by the Extension for Azure DevOps (but only meant to be used when a project isn’t bound). That’s these analysis parameters and corresponding build variables:

sonar.pullrequest.vsts.instanceUrl - System.TeamFoundationCollectionUri
sonar.pullrequest.vsts.project - System.TeamProject
sonar.pullrequest.vsts.repository - Build.Repository.Name

Can you give it a go configuring these in your Docker build to see if it results in the PR being decorated? On my side, I’ll flag this for attention as the logs look really odd.

Wow, thank you very much. It seems to work.

Thanks. I will still flag this for attention as this shouldn’t be required (even if we wish all users were just using our Azure DevOps tasks that populate these values :smiley:)