Skip to content

Analyze with SonarCloud #57

Analyze with SonarCloud

Analyze with SonarCloud #57

Workflow file for this run

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow helps you trigger a SonarCloud analysis of your code and populates
# GitHub Code Scanning alerts with the vulnerabilities found.
# Free for open source project.
# 1. Login to SonarCloud.io using your GitHub account
# 2. Import your project on SonarCloud
# * Add your GitHub organization first, then add your repository as a new project.
# * Please note that many languages are eligible for automatic analysis,
# which means that the analysis will start automatically without the need to set up GitHub Actions.
# * This behavior can be changed in Administration > Analysis Method.
#
# 3. Follow the SonarCloud in-product tutorial
# * a. Copy/paste the Project Key and the Organization Key into the args parameter below
# (You'll find this information in SonarCloud. Click on "Information" at the bottom left)
#
# * b. Generate a new token and add it to your Github repository's secrets using the name SONAR_TOKEN
# (On SonarCloud, click on your avatar on top-right > My account > Security
# or go directly to https://sonarcloud.io/account/security/)
# Feel free to take a look at our documentation (https://docs.sonarcloud.io/getting-started/github/)
# or reach out to our community forum if you need some help (https://community.sonarsource.com/c/help/sc/9)
# These are the arguments and Instructions for the SonarCloud scanner
# args: >
# # Unique keys of your project and organization. You can find them in SonarCloud > Information (bottom-left menu)
# # Mandatory
# -Dsonar.projectKey=${{ secrets.SONAR_PROJECT_KEY }}
# -Dsonar.organization=${{ secrets.SONAR_ORGANIZATION }}
# # Comma-separated paths to directories containing main source files.
# -Dsonar.sources=. # optional, default is project base directory
# # Comma-separated paths to directories containing test source files.
# -Dsonar.tests=. # optional. For more info about Code Coverage, please refer to https://docs.sonarcloud.io/enriching/test-coverage/overview/
# # Adds more detail to both client and server-side analysis logs, activating DEBUG mode for the scanner, and adding client-side environment variables and system properties to the server-side log of analysis report processing.
# -Dsonar.test.inclusions=**/tests/**,**/*_test.rs,**/*_tests.rs
# -Dsonar.exclusions=**/target/**,**/.cargo/**
# -Dsonar.rust.lcov.reportPaths=lcov.info
# #-Dsonar.verbose= # optional, default is false
# # When you need the analysis to take place in a directory other than the one from which it was launched, default is .
name: Analyze with SonarCloud
on:
# Manual trigger
workflow_dispatch:
# Run on PRs targeting main and develop
pull_request:
branches: [ main, develop ]
# Run on Pushes targeting main
push:
branches: [ main ]
# Weekly scheduled scan (Monday 03:00 UTC)
schedule:
- cron: '0 3 * * 1'
# ------------------------------------------------------------------------------
# Permissions
# ------------------------------------------------------------------------------
# contents: read → required to clone repository
# pull-requests: read → allows SonarCloud PR decoration
# NOTE: security-events: write is implicitly required for SARIF upload
# (GitHub enables it automatically for codeql-action/upload-sarif)
permissions:
contents: read
pull-requests: read # allows SonarCloud to decorate PRs with analysis results
security-events: write # Needed to upload SARIF results to GitHub
jobs:
sonarcloud:
runs-on: ubuntu-latest
# ----------------------------------------------------------------------------
# Environment variables (from repository secrets)
# ----------------------------------------------------------------------------
env:
SONAR_ORGANIZATION: ${{ secrets.SONAR_ORGANIZATION }}
SONAR_PROJECT_KEY: ${{ secrets.SONAR_PROJECT_KEY }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} # Generate a token on Sonarcloud.io, add it to the secrets of this repo with the name SONAR_TOKEN (Settings > Secrets > Actions > add new repository secret)
steps:
# --------------------------------------------------------------------------
# Verify required SonarCloud secrets are present (safe logging)
# --------------------------------------------------------------------------
- name: Check Sonar secrets (safe)
run: |
test -n "$SONAR_ORGANIZATION" && echo "SONAR_ORGANIZATION is set" || echo "SONAR_ORGANIZATION is NOT set"
test -n "$SONAR_PROJECT_KEY" && echo "SONAR_PROJECT_KEY is set" || echo "SONAR_PROJECT_KEY is NOT set"
test -n "$SONAR_TOKEN" && echo "SONAR_TOKEN is set" || echo "SONAR_TOKEN is NOT set"
# --------------------------------------------------------------------------
# Checkout repository source code
# fetch-depth: 0 ensures full git history for Sonar analysis
# --------------------------------------------------------------------------
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
# --------------------------------------------------------------------------
# Install Rust toolchain (from rust-toolchain.toml)
# Includes LLVM tools for coverage support
# ---------------------------------------------------------------------------
- name: Install Rust (rust-toolchain.toml)
uses: dtolnay/rust-toolchain@stable
with:
components: llvm-tools-preview
# --------------------------------------------------------------------------
# Install cargo-llvm-cov
# Used to generate LCOV coverage data for SonarCloud
# --------------------------------------------------------------------------
- name: Install cargo-llvm-cov
uses: taiki-e/install-action@v2
with:
tool: cargo-llvm-cov
# --------------------------------------------------------------------------
# Cache Cargo dependencies and build artifacts
# Speeds up subsequent workflow runs
# --------------------------------------------------------------------------
- name: Cache Cargo
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock', '**/rust-toolchain.toml', '**/rust-toolchain') }}
restore-keys: |
${{ runner.os }}-cargo-
# --------------------------------------------------------------------------
# Generate Rust code coverage in LCOV format
# Output file is consumed by SonarCloud
# --------------------------------------------------------------------------
- name: cargo llvm-cov
run: cargo llvm-cov --all-features --workspace --lcov --output-path lcov.info
# --------------------------------------------------------------------------
# Install SonarScanner CLI (runs on the runner, can access cargo/clippy)
# --------------------------------------------------------------------------
# Look for newer versions here https://binaries.sonarsource.com/?prefix=Distribution/sonar-scanner-cli/
- name: Install SonarScanner
if: ${{ env.SONAR_TOKEN != '' && env.SONAR_PROJECT_KEY != '' && env.SONAR_ORGANIZATION != '' }}
run: |
cd "$RUNNER_TEMP"
curl -sSLo sonar-scanner.zip https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-6.2.1.4610-linux-x64.zip
unzip -q sonar-scanner.zip
SCANNER_DIR=$(find . -maxdepth 1 -type d -name "sonar-scanner-*")
echo "$RUNNER_TEMP/$SCANNER_DIR/bin" >> $GITHUB_PATH
# --------------------------------------------------------------------------
# Verify SonarScanner has been installed correctly
# --------------------------------------------------------------------------
- name: Verify SonarScanner
run: sonar-scanner --version
# --------------------------------------------------------------------------
# Run SonarScanner (runner)
# Wait for SonarCloud Quality Gate if push to main (default branch)
# Uploads code, metrics, coverage, and issues to SonarCloud
# --------------------------------------------------------------------------
- name: Analyze with SonarCloud (runner)
if: ${{ env.SONAR_TOKEN != '' && env.SONAR_PROJECT_KEY != '' && env.SONAR_ORGANIZATION != '' }}
env:
SONAR_HOST_URL: https://sonarcloud.io
# Only wait on pushes to the repo default branch
SONAR_QG_WAIT: ${{ github.event_name == 'push' && github.ref_name == github.event.repository.default_branch }}
run: |
args=(
"-Dsonar.projectKey=${SONAR_PROJECT_KEY}"
"-Dsonar.organization=${SONAR_ORGANIZATION}"
"-Dsonar.sources=."
"-Dsonar.test.inclusions=**/tests/**,**/*_test.rs,**/*_tests.rs"
"-Dsonar.exclusions=**/target/**,**/.cargo/**,.github/workflows/**,sonar-scanner*.zip,sonar-scanner-*/**"
"-Dsonar.rust.lcov.reportPaths=lcov.info"
"-Dsonar.rust.clippy.enabled=false"
)
if [ "$SONAR_QG_WAIT" = "true" ]; then
echo "Default branch push (${GITHUB_REF_NAME}) - waiting for Quality Gate..."
args+=("-Dsonar.qualitygate.wait=true" "-Dsonar.qualitygate.timeout=600")
fi
sonar-scanner "${args[@]}"
# --------------------------------------------------------------------------
# Fallback message if SonarCloud is skipped due to missing secrets
# --------------------------------------------------------------------------
- name: SonarCloud skipped (missing secrets)
if: ${{ env.SONAR_TOKEN == '' || env.SONAR_PROJECT_KEY == '' || env.SONAR_ORGANIZATION == '' }}
run: echo "Skipping SonarCloud (missing SONAR_TOKEN / SONAR_PROJECT_KEY / SONAR_ORGANIZATION)."
# --------------------------------------------------------------------------
# Setup Python runtime for SARIF export tooling
# --------------------------------------------------------------------------
- name: Setup Python (for sonar-tools)
if: ${{ github.event_name == 'push'
&& github.ref_name == github.event.repository.default_branch
&& env.SONAR_TOKEN != ''
&& env.SONAR_PROJECT_KEY != ''
&& env.SONAR_ORGANIZATION != '' }}
uses: actions/setup-python@v5
with:
python-version: "3.x"
# --------------------------------------------------------------------------
# Install sonar-tools (community exporter)
# Used to pull findings from SonarCloud and emit SARIF
# --------------------------------------------------------------------------
- name: Install sonar-tools
if: ${{ github.event_name == 'push'
&& github.ref_name == github.event.repository.default_branch
&& env.SONAR_TOKEN != ''
&& env.SONAR_PROJECT_KEY != ''
&& env.SONAR_ORGANIZATION != '' }}
run: |
python -m pip install --upgrade pip
python -m pip install sonar-tools
# --------------------------------------------------------------------------
# Debug: Show sonar-findings-export help and supported options
# --------------------------------------------------------------------------
- name: Show sonar-findings-export help
if: ${{ github.event_name == 'push'
&& github.ref_name == github.event.repository.default_branch
&& env.SONAR_TOKEN != ''
&& env.SONAR_PROJECT_KEY != ''
&& env.SONAR_ORGANIZATION != '' }}
run: |
echo "sonar-findings-export help:"
sonar-findings-export -h || true
# --------------------------------------------------------------------------
# Export SonarCloud issues as SARIF (default branch only)
# Filters to BUG and VULNERABILITY only to reduce noise in GitHub Security tab
# --------------------------------------------------------------------------
- name: Export SonarCloud findings as SARIF
if: ${{ github.event_name == 'push'
&& github.ref_name == github.event.repository.default_branch
&& env.SONAR_TOKEN != ''
&& env.SONAR_PROJECT_KEY != ''
&& env.SONAR_ORGANIZATION != '' }}
env:
SONAR_HOST_URL: https://sonarcloud.io
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: |
# Export only bugs + vulnerabilities to keep GitHub Code Scanning noise down.
# Remove --sarifNoCustomProperties if you want extra Sonar metadata in SARIF.
sonar-findings-export \
-k "${SONAR_PROJECT_KEY}" \
-o "${SONAR_ORGANIZATION}" \
--branch "${GITHUB_REF_NAME}" \
--skipVersionCheck \
--types VULNERABILITY,BUG \
--statuses OPEN,CONFIRMED,REOPENED,TO_REVIEW,REVIEWED \
--resolutions "" \
--format sarif \
--sarifNoCustomProperties \
-f sonarcloud.sarif
# --------------------------------------------------------------------------
# Upload SARIF to GitHub Code Scanning
# Results appear under Security → Code scanning
# Skipped automatically for forked PRs
# --------------------------------------------------------------------------
- name: Upload SARIF to GitHub Code Scanning
# Uploading SARIF doesn’t work for PRs from forks because they won’t have security-events:write
if: ${{ github.event_name == 'push'
&& github.ref_name == github.event.repository.default_branch
&& env.SONAR_TOKEN != ''
&& env.SONAR_PROJECT_KEY != ''
&& env.SONAR_ORGANIZATION != '' }}
uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: sonarcloud.sarif
category: sonarcloud