SonarScanner CLI integration tutorial

The SonarScanner CLI integration enables static code analysis of your projects using SonarQube or SonarCloud directly within your Buildkite pipelines.

SonarScanner analyzes your code for bugs, vulnerabilities, and code smells across 25+ programming languages. This integration is designed for self-hosted SonarQube instances, with optional support for SonarCloud as an alternative.

This page is a tutorial that covers both self-hosted SonarQube instances and SonarCloud integration.

Prerequisites

Before configuring SonarScanner in your Buildkite pipeline, ensure you have:

  1. SonarQube account or SonarCloud account
  2. Authentication token that is:
  3. Java Runtime Environment (JRE) 11 or higher
  4. Secrets management solutions - this tutorial demonstrates AWS Secrets Manager with the AWS Secrets Manager Buildkite Plugin.

Configuration strategy

SonarScanner supports two configuration methods:

  • Environment variables: Recommended for runtime settings and sensitive authentication data (tokens, URLs).
  • Properties files: Recommended for project-specific settings.

Configuration precedence

Environment variables take precedence over the settings in the properties file. This design allows you to keep project configuration in version control while securely managing authentication through Buildkite's secrets management.

Environment variables

Use environment variables in your pipeline for authentication and server configuration:

Environment Variable Description
SONAR_TOKEN Required. Authentication token for your SonarQube/SonarCloud server
SonarQube example: sqp_1234567890abcdef1234567890abcdef12345678
SonarCloud example: a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0
Security: Store using secrets management
SONAR_HOST_URL Required. URL of your SonarQube server
Example: https://sonarqube.mycompany.com or https://sonar.internal.mycompany.com

Properties file configuration

Create a sonar-project.properties file in your repository root to define project-specific settings:

# SonarQube configuration
sonar.host.url=https://sonarqube.mycompany.com
sonar.projectKey=sample-project
sonar.projectName=Multi-Language Sample Project
sonar.projectVersion=1.0
# Source configuration
sonar.sources=src,lib,scripts
sonar.sourceEncoding=UTF-8
# Working directory (adjust based on execution environment; default is root)
sonar.working.directory=./.scannerwork
# Exclusions
sonar.exclusions=**/.git/**,**/.buildkite/**,**/node_modules/**,**/target/**,**/*.jar,**/*.class
# Language-specific settings (optional)
sonar.javascript.lcov.reportPaths=coverage/lcov.info
sonar.python.coverage.reportPaths=coverage.xml
sonar.java.binaries=target/classes

Understanding key properties

  • sonar.sources: comma-separated list of directories containing source code, relative to project root.
  • sonar.working.directory: directory where SonarScanner stores temporary analysis files. Execution user must have write permissions to this directory.
  • sonar.exclusions: files and directories to exclude from analysis using Ant-style patterns (** = any subdirectories, * = any characters).
  • sonar.tests: directories containing test files, separate from the main source analysis.

Implementation approaches

Choose between two deployment approaches based on your infrastructure preferences and agent setup:

  • Pre-installed binary - install SonarScanner directly on your Buildkite agents for faster execution and reduced container overhead.
  • Docker image - use the official SonarScanner Docker image for consistent environments and simplified agent setup.

Pre-installed binary approach

This approach uses the SonarScanner CLI binary installed directly on your Buildkite Agents. Below is an example for Buildkite Elastic CI Stack for AWS.

Update launch template userdata

Add the following installation script to your Auto Scaling Group's launch template userdata:

#!/bin/bash -v

# Download and install SonarScanner CLI
echo "Installing SonarScanner CLI..."
cd /opt
sudo wget https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-5.0.1.3006-linux.zip
sudo unzip sonar-scanner-cli-5.0.1.3006-linux.zip
sudo ln -s sonar-scanner-5.0.1.3006-linux sonar-scanner

# Set proper permissions for buildkite-agent user
sudo chown -R root:root /opt/sonar-scanner-5.0.1.3006-linux
sudo chmod +x /opt/sonar-scanner/bin/sonar-scanner

# Add to system PATH
sudo tee /etc/profile.d/sonar-scanner.sh << 'EOF'
export PATH="/opt/sonar-scanner/bin:$PATH"
EOF
sudo chmod +x /etc/profile.d/sonar-scanner.sh

# Add to buildkite-agent user profile
sudo -u buildkite-agent tee -a /var/lib/buildkite-agent/.bashrc << 'EOF'
export PATH="/opt/sonar-scanner/bin:$PATH"
EOF

echo "SonarScanner installation completed"

Deploy launch template updates

Update your existing launch template with the new userdata script, create a new version, and configure your Auto Scaling Group to use the updated template. This ensures new agent instances will have SonarScanner pre-installed.

Pipeline configuration

Configure your pipeline configuration file to be able to run the sonar-scanner.

steps:
  - label: "📊 SonarQube Analysis"
    command: |
      # Wait for sonar-scanner availability
      echo "⏳ Ensuring sonar-scanner is ready..."
      timeout 30 bash -c 'while [[ ! -x "/opt/sonar-scanner/bin/sonar-scanner" ]]; do sleep 5; done' || {
        echo "❌ Error: SonarScanner binary not ready after 30 seconds"
        echo "Check that SonarScanner is properly installed on your agents"
        exit 1
      }

      # Run SonarScanner analysis
      /opt/sonar-scanner/bin/sonar-scanner
    env:
      SONAR_HOST_URL: "https://sonarqube.mycompany.com"
      SONAR_PROJECT_CONFIG: "./sonar-project.properties"
    plugins:
      - seek-oss/aws-sm#v2.3.3:
          env:
            SONAR_TOKEN: path/to/your/sonar-token

Docker image approach

This approach uses the official SonarScanner Docker image, eliminating the need for agent setup. This tutorial uses the Docker Buildkite plugin.

steps:
  - label: "📊 SonarQube Analysis"
    command: |
      # Run SonarScanner analysis in Docker container
      sonar-scanner
    env:
      SONAR_HOST_URL: "https://sonarqube.mycompany.com"
      SONAR_PROJECT_CONFIG: "./sonar-project.properties"
    plugins:
      - seek-oss/aws-sm#v2.3.3:
          env:
            SONAR_TOKEN: path/to/your/sonar-token
      - docker#v5.11.0:
          image: "sonarsource/sonar-scanner-cli:latest"
          environment:
            - "SONAR_TOKEN"
          propagate-environment: true

Configure your working directory

Adjust your sonar-project.properties working directory in Docker, for example:

# For Docker execution
sonar.working.directory=/usr/src/.scannerwork # Container runs as root
# For native binary execution (e.g., Elastic CI Stack for AWS)
sonar.working.directory=/tmp/.scannerwork # Runs as buildkite-agent user

Complete templated multi-language example

This example demonstrates a complete SonarScanner setup for analyzing a typical multi-language project using the pre-installed binary approach. You can adapt this configuration for your own projects by modifying the properties file.

Pipeline configuration

steps:
  - label: "📥 Setup"
    command: |
      echo "🏗️  Multi-Language SonarScanner Analysis"
      echo "🎯 Analyzing 20+ language samples..."
  - label: "🔍 SonarCloud Analysis"
    command: |
      # Wait for sonar-scanner availability (Elastic CI Stack for AWS)
      echo "⏳ Ensuring sonar-scanner is ready..."
      timeout 30 bash -c 'while [[ ! -x "/opt/sonar-scanner/bin/sonar-scanner" ]]; do sleep 5; done' || {
        echo "❌ Error: SonarScanner binary not ready after 30 seconds"
        echo "Check that SonarScanner is properly installed on your agents"
        exit 1
      }

      # Run analysis using properties file configuration
      /opt/sonar-scanner/bin/sonar-scanner
      echo "✅ Analysis completed successfully"
    plugins:
      - seek-oss/aws-sm#v2.3.3:
          env:
            SONAR_TOKEN: my-org/sonar-token
    # If using Docker
    #   - docker#v5.11.0:
    #       image: "sonarsource/sonar-scanner-cli:latest"
    #       environment:
    #         - "SONAR_TOKEN"
    #       propagate-environment: true

Properties file configuration

# SonarQube configuration
sonar.host.url=https://sonarqube.mycompany.com
sonar.projectKey=sample-project
sonar.projectName=Multi-Language Sample Project
sonar.projectVersion=1.0
# Comprehensive source analysis - scan all example projects
sonar.sources=examples/
sonar.sourceEncoding=UTF-8
# Working directory (Elastic CI Stack for AWS)
sonar.working.directory=/tmp/.scannerwork
# Working directory (Docker execution)
# sonar.working.directory=/usr/src/.scannerwork
# Exclusions for clean analysis
sonar.exclusions=**/.git/**,**/.buildkite/**,**/.scannerwork/**,**/images/**,**/target/**,**/build/**,**/gradle/**,**/node_modules/**,**/*.jar,**/*.class,**/vendor/**,**/__pycache__/**,**/*.pyc,**/dist/**,**/.terraform/**

Troubleshooting

This section covers some common issues and proposed mitigations for the SonarScanner integration for Buildkite.

Installation and path issues

SonarScanner binary not found (pre-installed binary approach)

# Check if binary exists
ls -la /opt/sonar-scanner/bin/sonar-scanner

# Verify permissions
sudo chmod +x /opt/sonar-scanner/bin/sonar-scanner

# Check PATH configuration
echo $PATH | grep sonar-scanner

# Test direct execution
/opt/sonar-scanner/bin/sonar-scanner --version

Authentication problems

Token authentication failures

  • Verify that the SonarQube/SonarCloud token is correctly stored in your secrets manager.
  • Check token permissions in SonarQube/SonarCloud (the token needs "Execute Analysis" permission).
  • Ensure token hasn't expired (check the expiration date in SonarQube/SonarCloud).
  • Test token's validity manually: curl -u YOUR_TOKEN: https://your-sonarqube-url/api/authentication/validate.

Analysis timeout or performance issues

Analysis timeout or memory issues

# Increase memory allocation for large projects
sonar.javascript.node.maxspace=8192

# Exclude large or unnecessary files and file types using `sonar.exclusions`
sonar.exclusions=**/*.min.js,**/vendor/**,**/third-party/**,**/*.pdf,**/*.jpg,**/*.png

Large project optimization

# Exclude test files from duplication analysis
sonar.cpd.exclusions=**/test/**,**/tests/**

# Skip binary files
sonar.exclusions=**/*.jar,**/*.zip

# Limit analysis scope
sonar.sources=src/main
sonar.tests=src/test

Docker permission issues

  • Check Docker image version compatibility.
  • Verify working directory permissions:
docker exec -it <container_name> ls -ld /path/to/workdir

Using SonarCloud instead of SonarQube

While this tutorial describes the implementation of self-hosted SonarQube, you can also use SonarCloud (the hosted SaaS version) by making a few changes.

Environment variables changes

  • SONAR_HOST_URL: Optional (defaults to https://sonarcloud.io)
  • SONAR_TOKEN: Required (also saved in your choice of Buildkite secrets management service)

Properties file changes

# SonarCloud configuration

# Optional (defaults to https://sonarcloud.io)
sonar.host.url=https://sonarcloud.io
# Required
sonar.projectKey=my-org_sample-project
# Required
sonar.organization=my-org

Token generation changes

Generate your SonarCloud token from My Account > Security > Generate Tokens in your SonarCloud dashboard.

Additional resources