You need to integrate SonarQube into your CI/CD pipeline to provide PR decoration (inline comments on pull requests) and branch analysis. How do you set this up for GitHub with branch-aware analysis?
Quick Answer
Configure the SonarQube GitHub integration with a GitHub App, enable branch analysis in SonarQube (Developer Edition+), set `sonar.pullrequest.key/branch/base` parameters in PR builds, and SonarQube will post inline comments on the PR showing new issues introduced in the branch.
Detailed Answer
Branch Analysis
SonarQube Developer Edition and above support branch analysis, where each Git branch gets its own analysis in SonarQube. The main branch serves as the reference; feature branches are compared against it to identify NEW issues. Short-lived branches (PRs) are automatically cleaned up after merge. This gives developers feedback on their specific changes without noise from existing issues on main.
PR Decoration
When configured, SonarQube posts analysis results directly on pull requests as: (1) a summary check/status that shows pass/fail based on Quality Gate, (2) inline comments on specific lines where new issues were introduced, and (3) a link to the full analysis in SonarQube. This provides immediate feedback in the developer's workflow without requiring them to visit the SonarQube UI.
GitHub App Configuration
Create a GitHub App (not OAuth app) with permissions to read/write checks and pull requests. Install it on your organization. In SonarQube, configure the GitHub integration with the App ID, private key, and webhook secret. SonarQube uses the App to post PR comments and check statuses. The App approach is preferred over personal tokens because it doesn't tie to an individual user account.
Pipeline Configuration
In your CI pipeline, pass PR-specific parameters to the scanner: sonar.pullrequest.key (PR number), sonar.pullrequest.branch (source branch), sonar.pullrequest.base (target branch). For branch builds (not PRs), pass sonar.branch.name. The scanner detects changed files and only sends those for analysis, making PR analysis faster than full branch analysis.
Code Example
# GitHub Actions workflow for SonarQube PR decoration
# .github/workflows/sonarqube.yml
name: SonarQube Analysis
on:
push:
branches: [main, develop]
pull_request:
types: [opened, synchronize, reopened]
jobs:
sonarqube:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Full clone for accurate blame/history
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- name: Build and Test with Coverage
run: ./gradlew build jacocoTestReport
- name: SonarQube Scan
uses: sonarsource/sonarqube-scan-action@v2
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
with:
args: >
-Dsonar.projectKey=order-service
-Dsonar.sources=src/main/java
-Dsonar.tests=src/test/java
-Dsonar.java.binaries=build/classes
-Dsonar.coverage.jacoco.xmlReportPaths=build/reports/jacoco/test/jacocoTestReport.xml
- name: SonarQube Quality Gate
uses: sonarsource/sonarqube-quality-gate-action@v1
timeout-minutes: 5
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
# sonar-project.properties
sonar.projectKey=order-service
sonar.projectName=Order Service
sonar.sources=src/main/java
sonar.tests=src/test/java
sonar.java.binaries=build/classes/java/main
sonar.coverage.jacoco.xmlReportPaths=build/reports/jacoco/test/jacocoTestReport.xml
sonar.qualitygate.wait=true
# SonarQube server configuration for GitHub integration
# Administration > Configuration > General > ALM Integrations > GitHub
# - GitHub API URL: https://api.github.com
# - GitHub App ID: 12345
# - Client ID: Iv1.abc123
# - Client Secret: (from GitHub App)
# - Private Key: (PEM from GitHub App)
# - Webhook Secret: (configured in GitHub App)
# Jenkins pipeline with branch-aware analysis
pipeline {
agent any
stages {
stage('Analysis') {
steps {
withSonarQubeEnv('sonar-prod') {
script {
def scannerParams = "-Dsonar.projectKey=order-service"
if (env.CHANGE_ID) {
// PR build
scannerParams += " -Dsonar.pullrequest.key=${env.CHANGE_ID}"
scannerParams += " -Dsonar.pullrequest.branch=${env.CHANGE_BRANCH}"
scannerParams += " -Dsonar.pullrequest.base=${env.CHANGE_TARGET}"
} else {
// Branch build
scannerParams += " -Dsonar.branch.name=${env.BRANCH_NAME}"
}
sh "sonar-scanner ${scannerParams}"
}
}
}
}
stage('Quality Gate') {
steps {
timeout(time: 5, unit: 'MINUTES') {
waitForQualityGate abortPipeline: true
}
}
}
}
}Interview Tip
Emphasize fetch-depth: 0 in the checkout step - without full Git history, SonarQube cannot perform accurate blame detection to identify new vs. existing issues. Also mention that PR analysis is faster because it only analyzes changed files, while branch analysis covers everything.