SonarQube Integration with GitHub Actions
GitHub Actions is a CI/CD platform built directly into GitHub. Connecting SonarQube to GitHub Actions means every push and pull request automatically triggers a code scan. This topic explains the complete setup using GitHub Actions workflows.
Two Options for GitHub and Sonar
OPTION A: SonarCloud (hosted by Sonarsource) Pros: Zero server setup, free for public repos Cons: Cloud-based, paid for private repos OPTION B: Self-hosted SonarQube + GitHub Actions Pros: Full control, works with private repos Cons: You manage the SonarQube server
This topic covers Option B — a self-hosted SonarQube server integrated with GitHub Actions.
Step 1: Store Secrets in GitHub
Never put your SonarQube token or server URL directly in your workflow file. Store them as encrypted secrets in GitHub:
- Go to your GitHub repository
- Click Settings > Secrets and variables > Actions
- Click New repository secret
- Add these two secrets:
Secret name: SONAR_TOKEN Value: sqp_abc123your_token_here Secret name: SONAR_HOST_URL Value: http://your-sonarqube-server:9000
Step 2: Create the Workflow File
Create the file .github/workflows/sonarqube.yml in your repository:
name: SonarQube Analysis
on:
push:
branches:
- main
- develop
pull_request:
types: [opened, synchronize, reopened]
jobs:
sonarqube:
name: SonarQube Scan
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0 # Required: full git history for blame info
- name: Set up Java 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- name: Build and run tests
run: mvn clean verify
- name: Run SonarQube analysis
uses: SonarSource/sonarqube-scan-action@master
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
with:
args: >
-Dsonar.projectKey=com.acme:customer-portal
-Dsonar.projectName=Customer Portal
- name: Check Quality Gate
uses: SonarSource/sonarqube-quality-gate-action@master
timeout-minutes: 5
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
Understanding fetch-depth: 0
By default, GitHub Actions checks out only the latest commit (a shallow clone). SonarQube needs the full git history to calculate which code is "new" and to annotate issues with the correct author information from git blame. Setting fetch-depth: 0 fetches the complete history.
WITHOUT fetch-depth: 0 WITH fetch-depth: 0 Shallow clone Full clone Only last commit All commits SonarQube cannot blame Author info works correctly New code detection may fail New code detected properly
The sonarqube-scan-action
The official SonarSource/sonarqube-scan-action action handles downloading and running the SonarScanner CLI automatically. You pass project parameters via the args field. The action reads the SONAR_TOKEN and SONAR_HOST_URL environment variables to authenticate with your server.
The sonarqube-quality-gate-action
This action polls the SonarQube server for the Quality Gate result. It waits for the server to finish analysis and then returns success or failure to GitHub Actions. If the gate fails, the workflow step shows a red X and the GitHub check on your commit or pull request shows as failed.
Pull Request Decoration
When a pull request is opened, SonarQube can add comments directly to the pull request showing new issues found in the changed code. To enable this:
- In SonarQube, go to Administration > Configuration > GitHub
- Create a GitHub App with the required permissions (read/write on pull requests)
- Install the GitHub App on your repository
- Enter the App ID and private key in SonarQube settings
PULL REQUEST WITH SONARQUBE DECORATION +--------------------------------------------------+ | PR: Add user authentication feature | | | | Checks: [SonarQube Quality Gate: FAILED] ✗ | | | | SonarQube comment on PR: | | "Found 2 issues in this pull request: | | - Line 47: SQL injection vulnerability (Blocker)| | - Line 89: Null pointer dereference (Critical)" | +--------------------------------------------------+
Workflow for Non-Maven Projects
For projects not using Maven, run the scanner with explicit properties:
- name: Run SonarQube analysis
uses: SonarSource/sonarqube-scan-action@master
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
with:
args: >
-Dsonar.projectKey=my-node-app
-Dsonar.sources=src
-Dsonar.tests=tests
-Dsonar.javascript.lcov.reportPaths=coverage/lcov.info
Handling Firewall Issues
If your SonarQube server is on a private network not accessible from GitHub's hosted runners, you have two options:
- Self-hosted GitHub Actions runner: Run the GitHub Actions runner on a machine inside your network that can reach the SonarQube server
- Expose SonarQube: Make the SonarQube server accessible via a public URL with proper authentication
SELF-HOSTED RUNNER SOLUTION
GitHub Server
|
v
[GitHub Actions Job] runs on your machine inside the network
|
v
[SonarQube Server] on the same private network
-- No firewall issue --
Branch Analysis in GitHub Actions
The Community Edition of SonarQube only analyzes the main branch. The Developer Edition supports multiple branch analysis. When using the Community Edition, configure your workflow to only run the full scan on the main branch, and run a lightweight check (without Quality Gate blocking) on other branches:
on:
push:
branches: [main] # Full scan + Quality Gate on main
pull_request: # Scan on PR for visibility only
branches: [main]
