Analyze with SonarCloud #57
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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 |