Issue setting up SonarCloud in Azure DevOps pipelines when multiple repos need to be checked out

I’m trying to set up SonarCloud with our Azure DevOps pipelines. I was able to do it just fine if the pipeline involved checking out only one repository, but if more than 1 needs checking out, it throws an error. I’m encountering a similar issue as the one described in this article:
Sonar not working with multiple Azure DevOps projects - SonarCloud - Sonar Community (sonarsource.com)

I’m using a Microsoft hosted agent to analyze a C# repository using Azure DevOps YAML pipelines. Here’s the error I’m getting when running the analyzer:

2023-06-05T13:59:06.9804285Z ##[section]Starting: Run Code Analysis using SonarCloud
2023-06-05T13:59:06.9915599Z ==============================================================================
2023-06-05T13:59:06.9915732Z Task         : Run Code Analysis
2023-06-05T13:59:06.9915800Z Description  : Run scanner and upload the results to the SonarCloud server.
2023-06-05T13:59:06.9915911Z Version      : 1.38.0
2023-06-05T13:59:06.9915967Z Author       : sonarsource
2023-06-05T13:59:06.9916029Z Help         : Version: 1.38.0. This task is not needed for Maven and Gradle projects since the scanner should be run as part of the build.

[More Information](https://docs.sonarcloud.io/advanced-setup/ci-based-analysis/sonarcloud-extension-for-azure-devops/)
2023-06-05T13:59:06.9916284Z ==============================================================================
2023-06-05T13:59:07.2498576Z [command]D:\a\_tasks\SonarCloudPrepare_14d9cde6-c1da-4d55-aa01-2965cd301255\1.35.0\classic-sonar-scanner-msbuild\SonarScanner.MSBuild.exe end
2023-06-05T13:59:07.2822477Z SonarScanner for MSBuild 5.13
2023-06-05T13:59:07.2823118Z Using the .NET Framework version of the Scanner for MSBuild
2023-06-05T13:59:07.3253068Z Post-processing started.
2023-06-05T13:59:07.4455236Z 13:59:07.436  13:59:07.436  WARNING: File 'D:\a\1\current\Xrm\Code\Plugins\***.cs' is not located under the base directory 'D:\a\1\s' and will not be analyzed.
2023-06-05T13:59:07.4459748Z 13:59:07.436  13:59:07.436  WARNING: File 'D:\a\1\current\Xrm\Code\Plugins\***.cs' is not located under the base directory 'D:\a\1\s' and will not be analyzed.
...
...
2023-06-05T13:59:08.0581191Z ##[error]13:59:08.045  No analysable projects were found. SonarCloud analysis will not be performed. Check the build summary report for details.
13:59:08.045  Post-processing failed. Exit code: 1
2023-06-05T13:59:08.0581988Z 13:59:08.045  No analysable projects were found. SonarCloud analysis will not be performed. Check the build summary report for details.
2023-06-05T13:59:08.0582369Z 13:59:08.045  Post-processing failed. Exit code: 1
2023-06-05T13:59:08.0582936Z 13:59:08.029  13:59:08.029  WARNING: File 'D:\a\1\current\Xrm\Code\Plugins\Model\OptionSets\***_statuscode.cs' is not located under the base directory 'D:\a\1\s' and will not be analyzed.
2023-06-05T13:59:08.0583692Z 13:59:08.029  13:59:08.029  WARNING: File 'D:\a\1\current\Xrm\Code\Plugins\Model\OptionSets\***.cs' is not located under the base directory 'D:\a\1\s' and will not be analyzed.
...
...
2023-06-05T13:59:08.0778611Z 13:59:08.045  Generation of the sonar-properties file failed. Unable to complete the analysis.
2023-06-05T13:59:08.0816844Z ##[error]The process 'D:\a\_tasks\SonarCloudPrepare_14d9cde6-c1da-4d55-aa01-2965cd301255\1.35.0\classic-sonar-scanner-msbuild\SonarScanner.MSBuild.exe' failed with exit code 1
2023-06-05T13:59:08.0885326Z ##[section]Finishing: Run Code Analysis using SonarCloud

Based on my investigations, SonarScanner is picking up the wrong base directory (D:\a\1\s), instead of D:\a\1\current.

Here is scenario 1, of a pipeline that works:

jobs:
- job: build_plugin_assemblies
  displayName: Build and Test Plugin Assemblies
  variables:
    solution: ${{ parameters.slnPattern }}
    buildPlatform: 'Any CPU'
    buildConfiguration: 'Release'
  steps:
  - checkout: self
    path: current
    submodules: recursive
    fetchDepth: 0
    
  - task: NuGetToolInstaller@1

  - task: NuGetCommand@2
    retryCountOnTaskFailure: 3
    inputs:
      restoreSolution: '$(Pipeline.Workspace)/current/$(solution)'
      vstsFeed: '#{COMPANY_NAME}#-shared'

  - task: SonarCloudPrepare@1
    displayName: 'Prepare analysis on SonarCloud'
    inputs:
      SonarCloud: 'SonarCloud-ADO'
      organization: '#{COMPANY_NAME}#-retail'
      projectKey: '#{COMPANY_NAME}#-retail_$(Build.Repository.Name)'
      projectName: $(Build.Repository.Name)

  - task: VSBuild@1
    displayName: Build plugin assemblies
    inputs:
      solution: '$(Pipeline.Workspace)/current/$(solution)'
      platform: '$(buildPlatform)'
      configuration: '$(buildConfiguration)'

  - task: SonarCloudAnalyze@1
    displayName: 'Run Code Analysis using SonarCloud'

Here is scenario 2, of a pipeline that doesn’t work because I’m checking out the extra repo at the end:

jobs:
- job: build_plugin_assemblies
  displayName: Build and Test Plugin Assemblies
  variables:
    solution: ${{ parameters.slnPattern }}
    buildPlatform: 'Any CPU'
    buildConfiguration: 'Release'
  steps:
  - checkout: self
    path: current
    submodules: recursive
    fetchDepth: 0
    
  - task: NuGetToolInstaller@1

  - task: NuGetCommand@2
    retryCountOnTaskFailure: 3
    inputs:
      restoreSolution: '$(Pipeline.Workspace)/current/$(solution)'
      vstsFeed: '#{COMPANY_NAME}#-shared'

  - task: SonarCloudPrepare@1
    displayName: 'Prepare analysis on SonarCloud'
    inputs:
      SonarCloud: 'SonarCloud-ADO'
      organization: '#{COMPANY_NAME}#-retail'
      projectKey: '#{COMPANY_NAME}#-retail_$(Build.Repository.Name)'
      projectName: $(Build.Repository.Name)

  - task: VSBuild@1
    displayName: Build plugin assemblies
    inputs:
      solution: '$(Pipeline.Workspace)/current/$(solution)'
      platform: '$(buildPlatform)'
      configuration: '$(buildConfiguration)'

  - task: SonarCloudAnalyze@1
    displayName: 'Run Code Analysis using SonarCloud'

  - checkout: utils
    path: utils
    fetchDepth: 1

Here is scenario 3, of a pipeline that still doesn’t work, even though I’m setting the project base dir in the SonarCloudPrepare step:

jobs:
- job: build_plugin_assemblies
  displayName: Build and Test Plugin Assemblies
  variables:
    solution: ${{ parameters.slnPattern }}
    buildPlatform: 'Any CPU'
    buildConfiguration: 'Release'
  steps:
  - checkout: self
    path: current
    submodules: recursive
    fetchDepth: 0
    
  - task: NuGetToolInstaller@1

  - task: NuGetCommand@2
    retryCountOnTaskFailure: 3
    inputs:
      restoreSolution: '$(Pipeline.Workspace)/current/$(solution)'
      vstsFeed: '#{COMPANY_NAME}#-shared'

  - task: SonarCloudPrepare@1
    displayName: 'Prepare analysis on SonarCloud'
    inputs:
      SonarCloud: 'SonarCloud-ADO'
      organization: '#{COMPANY_NAME}#-retail'
      projectKey: '#{COMPANY_NAME}#-retail_$(Build.Repository.Name)'
      projectName: $(Build.Repository.Name)
      extraProperties: |
        sonar.projectBaseDir=$(Pipeline.Workspace)/current
        sonar.working.directory=$(Pipeline.Workspace)/current

  - task: VSBuild@1
    displayName: Build plugin assemblies
    inputs:
      solution: '$(Pipeline.Workspace)/current/$(solution)'
      platform: '$(buildPlatform)'
      configuration: '$(buildConfiguration)'

  - task: SonarCloudAnalyze@1
    displayName: 'Run Code Analysis using SonarCloud'

  - checkout: utils
    path: utils
    fetchDepth: 1

Both scenarios 2 & 3 are throwing the same error as described at the beginning of the thread.

Could you please offer some support so that I can achieve checking out multiple repositories within the same pipeline (scenarios 2 &3)?

Hi,

Could you provide the full job log from a failing analysis, please?

 
Thx,
Ann

Hi Ann,

Thanks for responding. I can provide the full job log, but it contains some company sensitive logs. Is there a secure way to provide you with the logs?

Thanks,
Vladimir

Hi Vladimir,

Feel free to redact the logs as necessary.

 
Ann

Please find the redacted logs attached.
ado logs.zip (87.1 KB)

Hi,

Thanks for the logs. Unfortunately it’s not clear to me where analysis starts from. I suppose your structure looks something like this?

workspace
| - project1
| - project2
| - project3

With each project built in order and then analysis kicked off from within the project3 directory? Or from the workspace directory?

At any rate, it’s not surprising to me that you have problems with this. Analysis should be kicked off from the project root/checkout directory, i.e. the one with the SCM files in it. Reading a sister project during analysis (so reading project2 during analysis from the project3 directory) is going to be problematic.

You may be thinking this means that you should kick off analysis from the workspace directory. Unfortunately that would mean that none of the SCM data would be read (since it wasn’t present there in the analysis root directory) and things like issue assignment and - more importantly - new code detection would fail.

Your best bet is to analyze each project separately.

 
HTH,
Ann

After checking out the 2 repositories, my workspace will look something like this:

workspace
| - current
| - utils

The code that I need analyzed is in the workspace/current directory. The workspace/utils is only used to call some shared scripts inside the pipeline run. I don’t need SonarCloud to analyze workspace/utils.

However, SonarCloud base directory defaults to workspace, or more specifically D:\a\1\s, instead of using the directory from which the build was run - workspace/current (D:\a\1\current). It also ignores any extraParameters I give it to set the projectBaseDir.

Hi,

Is analysis kicked off from within the current directory, or from workspace?

 
Ann

The analysis is kicked off from the default directory, which is workspace. There is no setting on the Analysis ADO task to set the current working directory. Please do let me know if there actually is one.

Hi,

It looks like SO can help.

 
Ann

Ann, have you tested this on your side? The Sonar tasks for ADO don’t support the workingDirectory parameter.

Here’s the code change I attempted to make based on your suggestion:

  - task: SonarCloudPrepare@1
    displayName: 'Prepare analysis on SonarCloud'
    workingDirectory: $(Pipeline.Workspace)/current
    inputs:
      SonarCloud: 'SonarCloud-ADO'
      organization: '***'
      projectKey: '***_$(Build.Repository.Name)'
      projectName: $(Build.Repository.Name)

Hi,

No, I didn’t test.

I’ve flagged this for the team.

 
Ann

Hi Ann, do you have any update from your team on this?

Hi @vnega,

Apologies for the delay in getting back to. you. Could you try omitting the path: current and path: utils in the pipeline definition?

Thank you for the suggestion, @TomVanBraband. Removing the path from the checkout steps indeed worked.

However, I see this as a workaround - having to adapt my entire pipeline because of a limitation in the SonarCloud ADO tasks. As you can imagine, not supplying a path to the checkout steps means that I have to do additional work to figure out the path generated by ADO’s checkout logic.

It would be good if SonarCloud added a baseDirectory parameter to its ADO task.

@vnega Your feedback makes sense, we don’t want to add friction to pipelines. We will consider adding the baseDirectory parameter to the task.

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.