Bridge the gap between SonarQube CE and GitHub. This GitHub Action brings PR decoration, inline annotations, and Security Tab integration to SonarQube Community Edition users.
|
|
| Feature | SonarQube CE | Developer+ Editions | CE + This Action |
|---|---|---|---|
| Code Analysis | β | β | β |
| PR Decoration | β | β | β |
| GitHub Security Tab | β | β | β |
| Inline Annotations | β | β | β |
| Check Run Summary | β | β | β |
name: SonarQube Analysis
on:
push:
branches: [main]
pull_request:
jobs:
analyze:
runs-on: ubuntu-latest
permissions:
security-events: write
checks: write
pull-requests: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
# Your SonarQube scan (use your preferred method)
- name: SonarQube Scan
uses: sonarsource/sonarqube-scan-action@v4
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
# Convert to SARIF and get all the features β¨
- name: SonarQube β GitHub Security
uses: vmvarela/sonarqube-ce-sarif-action@v1
with:
sonar-host-url: ${{ secrets.SONAR_HOST_URL }}
sonar-token: ${{ secrets.SONAR_TOKEN }}
# Upload to GitHub Security Tab (only on push to default branch)
- name: Upload SARIF
if: github.event_name != 'pull_request'
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: sonarqube.sarifThat's it! Your PRs get inline annotations and check summaries; the Security Tab reflects the state of your default branch.
Every PR gets a Check Run with:
- Summary table (issues by severity/type)
- Up to 50 inline code annotations
- Direct link to Security Tab
When issues are found, a summary comment is posted:
- Issue counts by severity
- Link to Security Tab (filtered by PR)
- Auto-updates (no duplicate comments)
In PR context, only shows issues from files you changed - not the entire project.
Optionally fail the check on specific severities:
- uses: vmvarela/sonarqube-ce-sarif-action@v1
with:
sonar-host-url: ${{ secrets.SONAR_HOST_URL }}
sonar-token: ${{ secrets.SONAR_TOKEN }}
fail-on-severity: CRITICAL # Fails if CRITICAL or BLOCKER issues exist| Input | Description |
|---|---|
sonar-host-url |
Your SonarQube server URL |
sonar-token |
Token with Browse permission |
| Input | Default | Description |
|---|---|---|
project-key |
Repo name | SonarQube project key |
output-file |
sonarqube.sarif |
Output file path |
min-severity |
INFO |
Filter: INFO, MINOR, MAJOR, CRITICAL, BLOCKER |
fail-on-severity |
- | Fail check at this severity |
pr-comment |
true* |
Post PR comment when issues found |
wait-for-processing |
true |
Wait for SonarQube analysis to complete |
processing-delay |
0 |
Fixed delay (seconds) as alternative to waiting |
* PR comments only appear in pull request context and when issues are found.
| Output | Description |
|---|---|
sarif-file |
Generated SARIF file path |
issues-count |
Total issues |
bugs-count |
Bug count |
vulnerabilities-count |
Vulnerability count |
code-smells-count |
Code smell count |
π All Outputs
| Output | Description |
|---|---|
sarif-file |
Path to the generated SARIF file |
issues-count |
Total number of issues converted |
rules-count |
Number of unique rules |
components-count |
Number of affected files |
blocker-count |
BLOCKER severity issues |
critical-count |
CRITICAL severity issues |
major-count |
MAJOR severity issues |
minor-count |
MINOR severity issues |
info-count |
INFO severity issues |
bugs-count |
BUG type issues |
vulnerabilities-count |
VULNERABILITY type issues |
code-smells-count |
CODE_SMELL type issues |
hotspots-count |
SECURITY_HOTSPOT type issues |
| Permission | Required For |
|---|---|
| Browse | β Required - fetching issues |
| Execute Analysis | Optional - for wait-for-processing |
The action uses GITHUB_TOKEN automatically. Add these permissions:
permissions:
security-events: write # Upload SARIF
checks: write # Create Check Run
pull-requests: write # Post PR commentsSonarQube CE doesn't support true PR analysisβit always analyzes the main branch. In PR context, this action filters issues to changed files, but cannot distinguish new issues from pre-existing ones.
Uploading SARIF on PRs can cause:
- False positives: Historical issues appearing as "new" in your PR
- Inconsistent state: Issues "fixed" in PR reappearing after merge
- Noise: Security Tab should reflect the default branch, not partial changes
Recommended approach: Use Check Run annotations and PR comments for PR feedback; upload SARIF only on push/schedule to the default branch (as shown in Quick Start).
Only include MAJOR and above:
- uses: vmvarela/sonarqube-ce-sarif-action@v1
with:
sonar-host-url: ${{ secrets.SONAR_HOST_URL }}
sonar-token: ${{ secrets.SONAR_TOKEN }}
min-severity: MAJORIf your token only has Browse permission:
- uses: vmvarela/sonarqube-ce-sarif-action@v1
with:
sonar-host-url: ${{ secrets.SONAR_HOST_URL }}
sonar-token: ${{ secrets.SONAR_TOKEN }}
wait-for-processing: false
processing-delay: 60 # Wait 60s for analysis- uses: vmvarela/sonarqube-ce-sarif-action@v1
with:
sonar-host-url: ${{ secrets.SONAR_HOST_URL }}
sonar-token: ${{ secrets.SONAR_TOKEN }}
pr-comment: false- name: Convert to SARIF
id: sarif
uses: vmvarela/sonarqube-ce-sarif-action@v1
with:
sonar-host-url: ${{ secrets.SONAR_HOST_URL }}
sonar-token: ${{ secrets.SONAR_TOKEN }}
- name: Check Results
run: |
echo "Found ${{ steps.sarif.outputs.issues-count }} issues"
echo "Vulnerabilities: ${{ steps.sarif.outputs.vulnerabilities-count }}"Why don't I see issues from my branch?
SonarQube CE doesn't support branch analysis. The action fetches all project issues and filters them to files changed in your PR. For branch-specific analysis, you need SonarQube Developer Edition.
How does severity mapping work?
| SonarQube | SARIF Level | GitHub Display |
|---|---|---|
| BLOCKER | error | π΄ Critical |
| CRITICAL | error | π΄ High |
| MAJOR | warning | π Medium |
| MINOR | note | π‘ Low |
| INFO | note | βͺ Info |
What if my token lacks Execute Analysis permission?
Use processing-delay instead of wait-for-processing:
wait-for-processing: false
processing-delay: 60 # secondsDo resolved issues disappear from GitHub?
Yes! When issues are fixed and no longer in the SARIF file, GitHub automatically marks them as Fixed in the Security tab.
What's the relationship with SonarQube Quality Gates?
This action does not consult SonarQube's Quality Gate. They operate independently:
| Feature | SonarQube Quality Gate | This Action (fail-on-severity) |
|---|---|---|
| Evaluates | Project metrics (coverage, duplications, ratings) | Issue count by severity |
| Defined in | SonarQube UI/config | Workflow YAML |
| Fails when | Metrics don't meet thresholds (e.g., coverage < 80%) | Issues exist at/above specified severity |
| Scope | Entire project | Issues (filtered to PR files if applicable) |
Using both together:
# Gate 1: Project health (SonarQube)
- name: Quality Gate
uses: sonarsource/sonarqube-quality-gate-action@master
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
# Gate 2: Security/issue gate (this action)
- name: Convert to SARIF
uses: vmvarela/sonarqube-ce-sarif-action@v1
with:
fail-on-severity: CRITICALThis separation allows you to enforce different quality criteria: project-wide metrics via SonarQube's gate, and PR-specific issue checks via this action.
| Error | Solution |
|---|---|
| "Permission denied" | Add Browse permission to your SonarQube token |
| "Project not found" | Verify project-key matches SonarQube exactly |
| Timeout | Increase max-wait-time or use processing-delay |
| No Check Run | Ensure checks: write permission in workflow |
| No PR Comment | Ensure pull-requests: write permission |
MIT Β© vmvarela
β Star this repo if you find it useful!