Configure SonarQube quality gates and automated project analysis with multi-language support

Intermediate 45 min Apr 14, 2026 932 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Set up custom SonarQube quality gates with automated project analysis for multiple programming languages. Configure SonarScanner integration, webhook notifications, and CI/CD pipeline automation for continuous code quality monitoring.

Prerequisites

  • Running SonarQube server
  • PostgreSQL database
  • Root or sudo access
  • Internet connectivity for plugin downloads

What this solves

SonarQube quality gates provide automated code quality control by setting thresholds for metrics like code coverage, duplicated lines, and security vulnerabilities. This tutorial configures custom quality gates with multi-language project scanning, automated analysis workflows, and CI/CD integration to maintain consistent code quality across your development pipeline.

Prerequisites

You need a running SonarQube server and database. If you haven't set this up yet, follow our SonarQube installation guide first.

Verify SonarQube installation

Check that SonarQube is running and accessible before configuring quality gates.

sudo systemctl status sonarqube
curl -I http://localhost:9000

Step-by-step configuration

Install SonarScanner CLI

Download and install the SonarScanner command-line interface for automated project analysis.

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 mv sonar-scanner-5.0.1.3006-linux sonar-scanner
sudo chown -R root:root sonar-scanner
sudo chmod +x sonar-scanner/bin/sonar-scanner

Configure SonarScanner environment

Set up environment variables and PATH for system-wide SonarScanner access.

SONAR_SCANNER_HOME="/opt/sonar-scanner"
PATH="$PATH:/opt/sonar-scanner/bin"
source /etc/environment
sonar-scanner --version

Create authentication token

Generate a user token in SonarQube for secure scanner authentication.

curl -u admin:admin -X POST "http://localhost:9000/api/user_tokens/generate" \
  -d "name=scanner-token" \
  -d "type=USER_TOKEN"
Note: Replace admin:admin with your actual SonarQube credentials. Save the generated token securely.

Configure global SonarScanner properties

Set up default configuration for SonarScanner to connect to your SonarQube server.

# SonarQube server configuration
sonar.host.url=http://localhost:9000
sonar.login=your-generated-token-here

# Default project settings
sonar.sourceEncoding=UTF-8
sonar.scm.provider=git

# Multi-language analysis settings
sonar.java.binaries=target/classes
sonar.javascript.lcov.reportPaths=coverage/lcov.info
sonar.python.coverage.reportPaths=coverage.xml
sonar.php.coverage.reportPaths=coverage.xml

Create custom quality gate

Define a quality gate with specific thresholds for code quality metrics using the SonarQube API.

# Create new quality gate
curl -u admin:admin -X POST "http://localhost:9000/api/qualitygates/create" \
  -d "name=Production Quality Gate"

# Get quality gate ID (replace with actual ID from response)
QG_ID="1"

# Add coverage condition
curl -u admin:admin -X POST "http://localhost:9000/api/qualitygates/create_condition" \
  -d "gateId=${QG_ID}" \
  -d "metric=coverage" \
  -d "op=LT" \
  -d "error=80"

# Add duplicated lines condition
curl -u admin:admin -X POST "http://localhost:9000/api/qualitygates/create_condition" \
  -d "gateId=${QG_ID}" \
  -d "metric=duplicated_lines_density" \
  -d "op=GT" \
  -d "error=3"

# Add security hotspots condition
curl -u admin:admin -X POST "http://localhost:9000/api/qualitygates/create_condition" \
  -d "gateId=${QG_ID}" \
  -d "metric=security_hotspots_reviewed" \
  -d "op=LT" \
  -d "error=100"

Configure webhook for CI/CD integration

Set up webhooks to notify external systems when quality gate status changes.

# Create webhook for Jenkins integration
curl -u admin:admin -X POST "http://localhost:9000/api/webhooks/create" \
  -d "name=Jenkins Webhook" \
  -d "url=http://jenkins.example.com:8080/sonarqube-webhook/" \
  -d "secret=webhook-secret-key"

# Create webhook for Slack notifications
curl -u admin:admin -X POST "http://localhost:9000/api/webhooks/create" \
  -d "name=Slack Webhook" \
  -d "url=https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK"

Create project-specific analysis configuration

Set up analysis properties for different programming languages and project types.

# Java project configuration
sonar.projectKey=java-app
sonar.projectName=Java Application
sonar.projectVersion=1.0

# Source and test directories
sonar.sources=src/main/java
sonar.tests=src/test/java
sonar.java.binaries=target/classes
sonar.java.test.binaries=target/test-classes
sonar.java.libraries=target/dependency/*.jar

# Coverage reports
sonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xml
sonar.junit.reportPaths=target/surefire-reports

Configure JavaScript/Node.js project analysis

Create configuration for JavaScript and Node.js projects with ESLint and test coverage.

# Node.js project configuration
sonar.projectKey=nodejs-app
sonar.projectName=Node.js Application
sonar.projectVersion=1.0

# Source and test directories
sonar.sources=src
sonar.tests=test
sonar.exclusions=node_modules/**,coverage/**,dist/**

# ESLint reports
sonar.eslint.reportPaths=reports/eslint-report.json

# Test coverage
sonar.javascript.lcov.reportPaths=coverage/lcov.info
sonar.testExecutionReportPaths=reports/test-report.xml

Configure Python project analysis

Set up analysis configuration for Python projects with pytest and coverage reports.

# Python project configuration
sonar.projectKey=python-app
sonar.projectName=Python Application
sonar.projectVersion=1.0

# Source and test directories
sonar.sources=src
sonar.tests=tests
sonar.exclusions=venv/**,__pycache__/**,*.pyc

# Python coverage
sonar.python.coverage.reportPaths=coverage.xml
sonar.python.xunit.reportPath=test-results.xml

# Pylint reports
sonar.python.pylint.reportPaths=pylint-report.txt

Create automated analysis script

Build a shell script to automate project analysis with quality gate validation.

#!/bin/bash
set -e

# Configuration
PROJECT_DIR="${1:-.}"
SONAR_HOST="${SONAR_HOST:-http://localhost:9000}"
SONAR_TOKEN="${SONAR_TOKEN}"

if [ -z "$SONAR_TOKEN" ]; then
    echo "Error: SONAR_TOKEN environment variable is required"
    exit 1
fi

echo "Starting SonarQube analysis for project in: $PROJECT_DIR"

# Change to project directory
cd "$PROJECT_DIR"

# Run SonarScanner
sonar-scanner \
    -Dsonar.host.url="$SONAR_HOST" \
    -Dsonar.login="$SONAR_TOKEN"

# Extract project key from sonar-project.properties
PROJECT_KEY=$(grep "sonar.projectKey" sonar-project.properties | cut -d'=' -f2)

echo "Analysis complete. Checking quality gate status..."

# Wait for analysis to complete and get quality gate status
sleep 10
QG_STATUS=$(curl -s -u "$SONAR_TOKEN:" "$SONAR_HOST/api/qualitygates/project_status?projectKey=$PROJECT_KEY" | jq -r '.projectStatus.status')

echo "Quality Gate Status: $QG_STATUS"

if [ "$QG_STATUS" = "OK" ]; then
    echo "✓ Quality gate passed!"
    exit 0
else
    echo "✗ Quality gate failed!"
    exit 1
fi
sudo chmod +x /usr/local/bin/sonar-analyze.sh

Set up CI/CD integration script

Create a comprehensive script for CI/CD pipeline integration with multiple language support.

#!/bin/bash
set -e

# Detect project type and configure analysis
detect_project_type() {
    if [ -f "pom.xml" ] || [ -f "build.gradle" ]; then
        echo "java"
    elif [ -f "package.json" ]; then
        echo "javascript"
    elif [ -f "requirements.txt" ] || [ -f "setup.py" ]; then
        echo "python"
    elif [ -f "composer.json" ]; then
        echo "php"
    else
        echo "generic"
    fi
}

# Generate coverage reports based on project type
generate_coverage() {
    PROJECT_TYPE=$(detect_project_type)
    
    case $PROJECT_TYPE in
        "java")
            echo "Running Maven tests with JaCoCo coverage"
            mvn clean test jacoco:report
            ;;
        "javascript")
            echo "Running Jest tests with coverage"
            npm test -- --coverage --coverageReporters=lcov
            ;;
        "python")
            echo "Running pytest with coverage"
            python -m pytest --cov=. --cov-report=xml
            ;;
        "php")
            echo "Running PHPUnit with coverage"
            ./vendor/bin/phpunit --coverage-clover coverage.xml
            ;;
    esac
}

# Main execution
echo "Detected project type: $(detect_project_type)"

# Generate coverage if requested
if [ "$1" = "--with-coverage" ]; then
    generate_coverage
fi

# Run SonarQube analysis
export SONAR_TOKEN="$SONAR_TOKEN"
/usr/local/bin/sonar-analyze.sh
sudo chmod +x /usr/local/bin/ci-sonar-analysis.sh

Install additional language analyzers

Install plugins for comprehensive multi-language support in SonarQube.

# Install Node.js and npm for JavaScript analysis
sudo apt update
sudo apt install -y nodejs npm
npm install -g eslint jshint

# Install Python analysis tools
sudo apt install -y python3-pip
pip3 install pylint pytest pytest-cov

# Install PHP analysis tools
sudo apt install -y php-cli composer
composer global require squizlabs/php_codesniffer
# Install Node.js and npm for JavaScript analysis
sudo dnf install -y nodejs npm
npm install -g eslint jshint

# Install Python analysis tools
sudo dnf install -y python3-pip
pip3 install pylint pytest pytest-cov

# Install PHP analysis tools
sudo dnf install -y php-cli composer
composer global require squizlabs/php_codesniffer

Configure systemd service for automated scanning

Create a systemd service to run scheduled project analysis automatically.

[Unit]
Description=SonarQube Scanner for %i
After=network.target

[Service]
Type=oneshot
User=sonarqube
Group=sonarqube
WorkingDirectory=/var/lib/sonarqube/projects/%i
Environment=SONAR_TOKEN=your-token-here
ExecStart=/usr/local/bin/ci-sonar-analysis.sh --with-coverage
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload

Set up automated timer for periodic analysis

Configure systemd timer to run analysis on a schedule for continuous monitoring.

[Unit]
Description=Daily SonarQube Analysis Timer
Requires=sonar-scanner@.service

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target
sudo systemctl enable sonar-scanner-timer.timer
sudo systemctl start sonar-scanner-timer.timer

Verify your setup

Test the complete analysis workflow with a sample project.

# Check SonarScanner installation
sonar-scanner --version

# Verify SonarQube connectivity
curl -u admin:admin "http://localhost:9000/api/system/status"

# List quality gates
curl -u admin:admin "http://localhost:9000/api/qualitygates/list"

# Check webhook configuration
curl -u admin:admin "http://localhost:9000/api/webhooks/list"

# Test analysis script
export SONAR_TOKEN="your-token-here"
/usr/local/bin/sonar-analyze.sh /path/to/test/project

Common issues

Symptom Cause Fix
Authentication failed Invalid or expired token Generate new token: curl -u admin:admin -X POST "http://localhost:9000/api/user_tokens/generate"
Quality gate not found Incorrect quality gate ID List gates: curl -u admin:admin "http://localhost:9000/api/qualitygates/list"
Coverage not reported Missing coverage report files Check coverage paths in sonar-project.properties and ensure tests run first
Scanner out of memory Large project analysis Set SONAR_SCANNER_OPTS="-Xmx2048m" environment variable
Webhook delivery failed Network connectivity issues Check webhook URL accessibility and firewall rules

Quality gate best practices

Configure different quality gates for different environments and project types.

Create development quality gate

Set up a more lenient quality gate for development branches with lower thresholds.

# Create development quality gate
curl -u admin:admin -X POST "http://localhost:9000/api/qualitygates/create" \
  -d "name=Development Quality Gate"

# Add relaxed coverage condition (60% instead of 80%)
DEV_QG_ID="2"
curl -u admin:admin -X POST "http://localhost:9000/api/qualitygates/create_condition" \
  -d "gateId=${DEV_QG_ID}" \
  -d "metric=coverage" \
  -d "op=LT" \
  -d "error=60"

# Add duplicated lines condition (5% instead of 3%)
curl -u admin:admin -X POST "http://localhost:9000/api/qualitygates/create_condition" \
  -d "gateId=${DEV_QG_ID}" \
  -d "metric=duplicated_lines_density" \
  -d "op=GT" \
  -d "error=5"
Note: Consider integrating this setup with your monitoring infrastructure using Prometheus and Grafana for comprehensive code quality metrics.

Next steps

Automated install script

Run this to automate the entire setup

Don't want to manage this yourself?

We handle infrastructure for businesses that depend on uptime. Fully managed, with one fixed contact who knows your setup.

You get one fixed contact who knows your setup

Rotterdam 03:14 · reachable in a message, no ticket form