avatarMatt H

Summary

This context provides a step-by-step guide on automating SonarQube scans with GitHub Actions.

Abstract

The guide begins by noting that this process is specific to SonarQube, as SonarCloud works out of the box with minimal adjustments. The first step involves creating a SonarQube project for the repository, which can be done through a simple process with a wizard. The guide then lists the prerequisites for the process, including admin access to SonarQube or the project and admin access to the GitHub repository. The configuration process is recommended to be done through a configuration file included within the repo for version control. The guide provides a sample config file with explanations for each property. The final step involves integrating with GitHub by adding a job to the PR Verification workflow for the SonarQube Scan and setting up an action to run a scan against the develop branch each time the code is updated.

Opinions

  • The guide notes that it is easier to configure the project through the SonarQube UI, but recommends doing it through a configuration file included within the repo for version control.
  • The guide provides a sample config file with explanations for each property, noting that each property is documented in the SonarSource documentation and the UI itself.
  • The guide notes that if everything is set up correctly, a SonarQube scan should be added to pull requests.
  • The guide recommends using a bot account to post the outcome to the pull request, which will need write access to the GitHub repo.
  • The guide notes that setting up an action to run a scan against the develop branch each time the code is updated is super simple.
  • The guide notes that this process will give an awesome view on the dashboard for the project.

Automate SonarQube Scans with GitHub Actions

Before you jump in I want to notate that this is specific to SonarQube as SonarCloud works out of the box with very little adjustments.

Graphic: Sonar Scan

Create SonarQube Project

First step would be to create a project for your repository in SonarQube. It’s a very simple process and there is a wizard that will walk you through it. Currently there are a few integration options for Azure DevOps, Bitbucket, GitHub, GitLab or manually. During this process you should also be taken to a screen to authenticate into your SCM of choice. Keep track of any tokens you create as you will need that later in the process.

Prerequisites

  • Admin access to SonarQube or the project
  • Admin access on your GitHub repository

Configuration

While it is easier to configure your project through the SonarQube UI, I recommend doing it through a configuration file included within your repo so that you’re able to have it version controlled.

The configuration file for SonarQube should live in the root directory and be named sonar-project.properties. I had a hard time finding a sample of what it should look like so I included one below. Please read through it and update all configurations to meet your projects needs. The configurations that I left uncommented are required in order to work.

Something worth mentioning here is each of these properties below are noted in the SonarSource documentation and the UI itself. If you aren’t sure what they are being used for, or what format they expect the data I suggest starting there.

Sample Config File

# suppress inspection "UnusedProperty" for whole file
## Project Configuration
sonar.organization=[YOUR ORG HERE]
sonar.projectKey=[YOUR PROJECT KEY HERE]
# If true, the quality gate is not checked. By default the build will break if the project does not pass the quality gate.
# sonar.buildbreaker.skip=true
# Encoding of the source files.
sonar.sourceEncoding=UTF-8
# Control the quantity/level of logs produced during an analysis
# sonar.log.level=DEBUG
# adds more detail to both client and server-side analysis logs
# sonar.verbose=true
# Set to true if this project belongs to a monorepo. This enables better support for pull requests. This setting is currently only working for Azure DevOps repositories.
# sonar.project.monorepo.enabled=true
# The issue tracker being used.
# sonar.links.issue=https://github.com/[YOUR REPO]/issues
# The project source code repository.
sonar.links.scm=https://github.com/[YOUR REPO]/
# Enable the summary comment in the Conversation tab when decorating Pull Requests
# sonar.pullrequest.github.summary_comment=true
# Comma-separated paths to directories containing main source files.
# sonar.sources=
# sonar.exclusions=
# Comma-separated paths to directories containing test source files.
# sonar.tests=
# sonar.test.inclusions=
## TypeScript
# Path (relative to project base or absolute) to the tsconfig JSON file
# sonar.typescript.tsconfigPath=
# List of suffixes for files to analyze.
# sonar.typescript.file.suffixes=.tsx,.ts
## JavaScript
# List of suffixes for files to analyze.
# sonar.javascript.file.suffixes=.jsx,.js
# JavaScript execution environments
# sonar.javascript.environments=jest,node
# True to not count file header comments in comment metrics.
# sonar.javascript.ignoreHeaderComments=true
## Test Coverage
# see https://sonarcloud.io/documentation/analysis/coverage/
# Comma-delimited list of paths to LCOV coverage report files. Paths may be absolute or relative to project
# sonar.javascript.lcov.reportPaths=
# Patterns used to exclude some files from coverage report.
# sonar.coverage.exclusions=
## Test Execution
# for test execution: You can use jest-sonar-reporter (https://www.npmjs.com/package/jest-sonar-reporter)
# or karma-sonarqube-unit-reporter (https://github.com/tornaia/karma-sonarqube-unit-reporter) to
# create reports in the Generic Execution Data format. Both packages are available on npm.
# sonar.testExecutionReportPaths=
# See https://github.com/3dmind/jest-sonar-reporter/issues/22
# Would love this too. We use nx (https://nx.dev/) as a monorepo with only one package.json but
# different jest.configs for every app and lib. A configuration with jest.config would make some things easier.
# The solution with the node environment variable works, but is not optimal for our use case.
# External issues:
# https://sonarcloud.io/documentation/analysis/external-issues/
# Comma-delimited list of paths to JSON ESLint reports (use -f json ESLint option)
# sonar.eslint.reportPaths
# Comma-delimited list of paths to TSLint reports in JSON format (use -t json TSLint option)
# sonar.typescript.tslint.reportPaths=
# Comma-delimited list of paths to StyleLint.io reports
# sonar.css.stylelint.reportPaths =

Integrate with GitHub

Once the project is setup and you have the configuration file in your repository there are a couple more steps to wrap up your automated scans. The two instances in which I want to run a SonarQube scan are regularly on our main branch, and on every pull request.

GitHub Actions

Since I already have a PR Verification workflow that runs on each pull request, I added another job to it for the SonarQube Scan. Notice I have a couple additional steps which installs my dependencies then runs a test-coverage command. That is needed to create the coverage report which can be displayed in SonarQube.

Note: If you want to use a bot account to post the outcome to your pull request, it will need write access to your GitHub repo

name: PR Verification
  on:
    pull_request:
jobs:
  ...A BUNCH OF OTHER JOBS HERE THAT AREN'T RELEVANT
  sonarqube:
    name: SonarQube Scan
    runs-on: ubuntu-latest
    steps:
      - name: Checkout source code
        uses: actions/checkout@v2
        with:
          fetch-depth: 0
      - name: Setup Node.js
        uses: actions/setup-node@v1
        with:
          node-version: 12
      - name: Install dependencies
        run: yarn install
      - name: Gather Test Coverage
        run: yarn test-coverage
      - name: SonarQube Scan
        uses: sonarsource/sonarqube-scan-action@master
        env:
          SONAR_TOKEN: ${{ secrets.SONARQUBE_TOKEN }}
          SONAR_HOST_URL: ${{ secrets.SONARQUBE_HOST_URL }}

If everything is setup correctly, then you should start to see something like this added to your pull requests.

Now that my PR Verification workflow was working now I just needed to setup an action which would run a scan against my develop branch each time the code was updated. Spoiler alert, it’s super simple. I created a new GitHub Action workflow called sonarqube.yml and copy/pasted the same configuration as above. The only difference was in the trigger mechanism.

name: SonarQube Scan
on:
  workflow_dispatch:
  push:
    branches:
      - develop

This will give you an awesome view on your dashboard for your project.

Resources

Github
Sonarqube
Automation Testing
Code Quality
Recommended from ReadMedium