Tag: SonarCloud

SonarQube for .NET Framework with GitHub Actions

If you haven't tried SonarQube or SonarCloud out then I suggest you do. The cloud version is quite straightforward to setup and from my experience the stuff it finds can be quite insightful. Like all these tools, at times you'll disagree with what they say, but there's always the option to change the rules.

What I particularly like with SonarQube is the examples you get with each bug that clearly explains why there's an issue and what you need to do in order to fix it.

What I didn't like however were the instructions for setting a project using .NET Framework. There are instructions labelled .NET, but this heavily assumes your using .NET Core, which while that might be our general preference, products like Sitecore could force your hand back to .NET Framework and all those legacy projects didn't just go away.

How to setup SonarQube using GitHub Actions for .NET Framework

The GitHub setup instructions (https://docs.sonarqube.org/latest/analysis/github-integration/) will give you the following code to create your GitHub Action with. This is also the same code you will get if you follow the wizard in SonarQube.

name: Build
on:
push:
  branches:
    - master # or the name of your main branch
pull_request:
  types: [opened, synchronize, reopened]
jobs:
build:
  name: Build
  runs-on: windows-latest
  steps:
    - name: Set up JDK 11
      uses: actions/setup-java@v1
      with:
        java-version: 1.11
    - uses: actions/checkout@v2
      with:
        fetch-depth: 0  # Shallow clones should be disabled for a better relevancy of analysis
    - name: Cache SonarQube packages
      uses: actions/cache@v1
      with:
        path: ~\sonar\cache
        key: ${{ runner.os }}-sonar
        restore-keys: ${{ runner.os }}-sonar
    - name: Cache SonarQube scanner
      id: cache-sonar-scanner
      uses: actions/cache@v1
      with:
        path: .\.sonar\scanner
        key: ${{ runner.os }}-sonar-scanner
        restore-keys: ${{ runner.os }}-sonar-scanner
    - name: Install SonarQube scanner
      if: steps.cache-sonar-scanner.outputs.cache-hit != 'true'
      shell: powershell
      run: |
        New-Item -Path .\.sonar\scanner -ItemType Directory
        dotnet tool update dotnet-sonarscanner --tool-path .\.sonar\scanner
    - name: Build and analyze
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}  # Needed to get PR information, if any
      shell: powershell
      run: |
        .\.sonar\scanner\dotnet-sonarscanner begin /k:"example" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="${{ secrets.SONAR_HOST_URL }}"
        dotnet build
        .\.sonar\scanner\dotnet-sonarscanner end /d:sonar.login="${{ secrets.SONAR_TOKEN }}"

There's two aspects to notice with this. Firstly the Build and analyze section is running a command dotnet build which is fine if your running .Net Core, but for .Net Framework it isn't going to work.

Secondly it's highly likely your solution will use NuGet packages and there's no step in here to restore them.

To setup and restore NuGet packages add in the following steps before the Build and analyze step. Be sure to put your solution filename in the restore command.

      - name: Setup Nuget
      uses: Nuget/setup-nuget@v1.0.5

    - name: Restore nuget packages
      run: nuget restore MySolution.sln

To do a build that will compile your .Net Framework code you will need to use MsBuild rather than dotnet. However if you just swap them over you'll get an invalid command error. First you need to add msbuild to PATH. Change your build steps as follows.

      - name: Add msbuild to PATH
      uses: microsoft/setup-msbuild@v1.0.2

    - name: Build and analyze
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}  # Needed to get PR information, if any
      shell: powershell
      run: |
        .\.sonar\scanner\dotnet-sonarscanner begin /k:"example" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="${{ secrets.SONAR_HOST_URL }}"
        dotnet build
        .\.sonar\scanner\dotnet-sonarscanner end /d:sonar.login="${{ secrets.SONAR_TOKEN }}"

With that now in place you can now compile some .Net Framework code and have the results sent back to your SonarQube instance.