SonarCloud with MSBuild (+ Build Wrapper) on GitHub Actions


I’m happy to report that we were able to use SonarCloud with GitHub Actions for Windows and MSBuild.

It was a tad tricky but I wanted to share with the community since the official GitHub Action for Sonar points users to Travis CI which is not necessary.

I’m sharing a simplified version of our .github/workflows/ci.yml file:

name: CI Checks
    branches: [ main ]
    branches: [ main ]
    # Allow manual trigger for debugging the workflow.
    runs-on: windows-latest
    - name: Checkout branch
      uses: actions/checkout@master
        # Disabling shallow clone is required to report the correct blame information.
        fetch-depth: 0
    - name: Add msbuild to PATH
      uses: microsoft/setup-msbuild@v1.0.2
    - name: Environment
      shell: bash
      run: |
        mkdir -p build
        org="$(cut -d/ -f1 <<< "$GITHUB_REPOSITORY")"
        repo="$(cut -d/ -f2 <<< "$GITHUB_REPOSITORY")"
        echo "SONAR_ORGANIZATION=${org}" >> "$GITHUB_ENV"
        echo "SONAR_PROJECT_KEY=${org}_${repo}" >> "$GITHUB_ENV"
    - name: Install Sonar Scanner
      run: |
        Invoke-WebRequest -Uri "${{ env.SONAR_WRAPPER_URL }}" -OutFile build/
        Invoke-WebRequest -Uri "${{ env.SONAR_SCANNER_URL }}" -OutFile build/
        Expand-Archive -LiteralPath build/ -DestinationPath build
        Expand-Archive -LiteralPath build/ -DestinationPath build
    - name: Build with Sonar Wrapper
      shell: cmd
      run: |
        SET PATH=%PATH%;%cd%\build\build-wrapper-win-x86
        build-wrapper-win-x86-64 --out-dir build\bw_output build-all.bat
    - name: Prepare Sonar Scanner
      shell: bash
      run: |
        set -x
        cd build
        ls -la bw_output
        mv sonar-scanner-*-windows sonar-scanner
    - name: Sonar Scanner
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
      shell: cmd
      run: |
        SET PATH=%PATH%;%cd%\build\sonar-scanner\bin
        ECHO PATH=%PATH%
        ECHO DIR %cd%\build\bw_output\
        DIR %cd%\build\bw_output\

Note that we have a build-all.bat script that calls multiple msbuild commands for our various binaries. This was necessary since calling build-wrapper msbuild multiple times overwrites the output json.
Our sonar property files then uses the SONAR_ORGANIZATION and SONAR_PROJECT_KEY environment variables.

Note that when using Windows targets the default shell is Powershell, which makes it a bit more verbose to execute some commands, but it can download and extract zip archives. The cmd shell is the classic Windows shell, with the classic limitations. There is cygwin with bash available but it is very limited to basics (no wget or curl), however it makes it easier to perform some file and environment variables manipulations. An other thing to consider is how backslashes are escaped, or not, in YAML. This gave us quite a bit of trouble.

I’m sure the yaml could be simplified with pure PowerShell, but I personally never use Windows and the PowerShell that is available for Docker does not behave exactly the same way than on Windows (echo is slightly different for example).

The repository is private so I cannot share more details. We have not integrated the unittest coverage reports yet but that should not be too complicated.

You will have to configure SONAR_TOKEN as a repository secret obviously. The GITHUB_TOKEN secret is always available and managed by GitHub directly, it might not be required but I have not tested that yet.


Hi @sodul

Thanks for that, much appreciated !


1 Like

Further details. We tried to use the official sonarsource/sonarcloud-github-action but it requires linux, which means that the paths in the json reports will not match.

We ended up with this error:
java.lang.IllegalStateException: The "build-wrapper-dump.json" file was found but 0 C/C++/Objective-C files were analyzed.

I guess it might be possible to massage the json report to remap the paths, but that’s not worth it.

Using sonarsource/sonarcloud-github-action would probably make sense for macOS builds on private repositories since macOS minutes are charged at 10x the rate, and the paths might be compatible by using a neutral build path such as something under /tmp.

1 Like

Hey @sodul

Would it be okay if I move your post to the Guides section?

(I know the description makes the category sound a bit exclusive, but we’ve done it before :smiley:)

Let me know!


Sure thing Colin!