how-to

SonarQube GitHub Actions: Automated Code Analysis Workflow

Set up SonarQube in GitHub Actions with workflow YAML for PR analysis, quality gates, caching, monorepos, and troubleshooting common issues.

Published:

SonarQube is one of the most widely adopted static analysis platforms, used by millions of developers to catch bugs, vulnerabilities, and code smells before they reach production. Integrating SonarQube with GitHub Actions lets you run automated code analysis on every push and pull request - catching issues early in the development cycle without requiring developers to manually trigger scans or check a separate dashboard.

This guide walks through every step of setting up SonarQube in GitHub Actions. You will learn how to configure basic scanning, enable pull request analysis, enforce quality gates, cache scanner data for faster builds, handle monorepo setups, and troubleshoot the most common issues teams encounter. Every YAML workflow and configuration file shown here is production-ready and can be copied directly into your repository.

If you are new to SonarQube entirely, start with our complete SonarQube setup guide first, then come back here for the GitHub Actions integration.

SonarQube static analysis tool homepage screenshot
SonarQube homepage

Prerequisites

Before setting up SonarQube in GitHub Actions, make sure you have the following in place:

  • A running SonarQube instance - either a self-hosted server (Community, Developer, or Enterprise Edition) or a SonarQube Cloud account. If you need to set one up, follow our SonarQube Docker installation guide.
  • A GitHub repository with at least one branch you want to analyze.
  • A SonarQube authentication token - generate this from your SonarQube instance under My Account, then Security, then Tokens.
  • A SonarQube project - create a project in SonarQube and note the project key.
  • Repository admin access - you need permissions to add GitHub Actions secrets and workflow files.

You should also decide whether to use SonarQube Cloud or self-hosted SonarQube, since the workflow configuration differs slightly between the two. We cover both approaches below.

Basic SonarQube GitHub Actions workflow

The simplest SonarQube integration scans your code on every push to the main branch and on every pull request. Start by adding your SonarQube credentials as GitHub repository secrets.

Add GitHub secrets

Navigate to your repository in GitHub, go to Settings, then Secrets and variables, then Actions. Add the following secrets:

  • SONAR_TOKEN - the authentication token you generated in SonarQube
  • SONAR_HOST_URL - your SonarQube server URL (for example, https://sonarqube.yourcompany.com). Skip this if you are using SonarQube Cloud.

Create the sonar-project.properties file

Add a sonar-project.properties file to the root of your repository. This tells the scanner which project to report to and which directories to analyze:

# SonarQube project configuration
sonar.projectKey=my-org_my-project
sonar.projectName=My Project

# Source code directories
sonar.sources=src
sonar.tests=tests

# Encoding
sonar.sourceEncoding=UTF-8

# Exclusions - skip generated and vendor code
sonar.exclusions=**/node_modules/**,**/vendor/**,**/dist/**,**/*.min.js,**/coverage/**

# Test file patterns
sonar.test.inclusions=**/*.test.ts,**/*.spec.ts,**/*.test.js,**/*.spec.js

# Coverage report path (if using Jest or similar)
sonar.javascript.lcov.reportPaths=coverage/lcov.info

Create the workflow file

Create the workflow file at .github/workflows/sonarqube.yml:

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 # Full history needed for accurate blame data

      - name: SonarQube Scan
        uses: SonarSource/sonarqube-scan-action@v4
        env:
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
          SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}

The fetch-depth: 0 parameter is critical. SonarQube uses git blame data to attribute issues to specific commits and developers. Without full history, blame information will be incomplete and the “New Code” period analysis may produce inaccurate results.

Commit and push these files. The workflow will trigger automatically on your next push or pull request.

SonarQube Cloud vs self-hosted setup

The GitHub Actions configuration differs depending on whether you use SonarQube Cloud (the SaaS product) or a self-hosted SonarQube server. Here is how each option works.

SonarQube Cloud setup

SonarQube Cloud (formerly SonarCloud) requires no server management. It connects directly to your GitHub organization and provides built-in PR decoration on all plans. The workflow uses a different action:

name: SonarQube Cloud Analysis

on:
  push:
    branches:
      - main
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  sonarcloud:
    name: SonarQube Cloud Scan
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: SonarQube Cloud Scan
        uses: SonarSource/sonarcloud-action@v4
        env:
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

For SonarQube Cloud, update your sonar-project.properties to include the organization key:

sonar.organization=my-github-org
sonar.projectKey=my-github-org_my-project

sonar.sources=src
sonar.tests=tests
sonar.sourceEncoding=UTF-8

SonarQube Cloud automatically detects PR context from GitHub Actions environment variables, so you do not need to pass additional parameters for PR decoration. It also uses the GITHUB_TOKEN secret (provided automatically by GitHub Actions) to post inline comments on pull requests.

For a deeper comparison between the cloud and self-hosted options, see our SonarQube vs SonarCloud analysis.

Self-hosted SonarQube setup

Self-hosted SonarQube gives you full control over your infrastructure and data. The basic workflow shown earlier in this guide uses the self-hosted approach with SonarSource/sonarqube-scan-action. The key difference is that you must provide the SONAR_HOST_URL secret pointing to your server.

For self-hosted setups, keep these considerations in mind:

  • Network access - your GitHub Actions runners must be able to reach your SonarQube server. If the server is behind a corporate firewall, you will need to use self-hosted GitHub runners or configure VPN access in your workflow.
  • HTTPS - SonarQube should be served over HTTPS in production. Use a reverse proxy like Nginx or Caddy in front of the SonarQube server.
  • Version compatibility - the scan action version should be compatible with your SonarQube server version. Check the SonarSource action documentation for compatibility matrices.
  • PR analysis - pull request analysis and decoration require Developer Edition ($490/year) or higher. Community Edition only supports main branch analysis.

Pull request analysis workflow

PR-level analysis is where SonarQube provides the most value in a GitHub Actions workflow. Instead of waiting until code is merged to find issues, you catch them during review. This requires SonarQube Developer Edition or higher for self-hosted, or any SonarQube Cloud plan.

When PR analysis is enabled, SonarQube posts inline comments directly on the pull request, showing exactly which lines introduced new bugs, vulnerabilities, or code smells. It also reports a quality gate status check that can block the merge if standards are not met.

Here is a complete PR analysis workflow for self-hosted SonarQube Developer Edition:

name: SonarQube PR Analysis

on:
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  sonarqube-pr:
    name: SonarQube PR Scan
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20

      - name: Install dependencies and run tests
        run: |
          npm ci
          npm run test -- --coverage

      - name: SonarQube Scan
        uses: SonarSource/sonarqube-scan-action@v4
        env:
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
          SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}

The scan action automatically detects that it is running in a pull request context and passes the appropriate parameters (sonar.pullrequest.key, sonar.pullrequest.branch, sonar.pullrequest.base) to SonarQube. You do not need to configure these manually.

For projects that require a build step before scanning - such as Java with Maven or Gradle - add the build step before the scan:

      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          java-version: 17
          distribution: temurin

      - name: Build with Maven
        run: mvn clean verify -DskipTests=false

      - name: SonarQube Scan
        uses: SonarSource/sonarqube-scan-action@v4
        env:
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
          SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}

Quality gate check

A SonarQube quality gate defines the minimum standards your code must meet before it can be merged. The default “Sonar Way” quality gate requires zero new bugs, zero new vulnerabilities, at least 80% coverage on new code, and less than 3% duplication on new code.

To enforce quality gates in GitHub Actions, add the quality gate check action after the scan:

name: SonarQube Analysis with Quality Gate

on:
  push:
    branches: [main]
  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

      - name: SonarQube Scan
        uses: SonarSource/sonarqube-scan-action@v4
        env:
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
          SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}

      - name: SonarQube Quality Gate check
        id: sonarqube-quality-gate-check
        uses: SonarSource/sonarqube-quality-gate-action@v1
        timeout-minutes: 5
        env:
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
          SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}

The quality gate action polls the SonarQube server until the analysis report is processed and the gate status is available. The timeout-minutes: 5 setting prevents the workflow from hanging indefinitely if the server is slow or unreachable.

To make the quality gate a required check for merging, go to your GitHub repository settings, then Branches, then Branch protection rules. Add a rule for your main branch and enable “Require status checks to pass before merging.” Search for the SonarQube quality gate job name and add it as a required check.

Custom quality gate configuration

If the default Sonar Way quality gate is too strict or too lenient for your team, create a custom gate in SonarQube. Navigate to Quality Gates in the SonarQube web interface, click Create, and add your conditions. Common customizations include:

  • Lowering the coverage threshold from 80% to 60% for legacy projects
  • Adding a maximum code complexity condition
  • Requiring zero new security hotspots (not just vulnerabilities)
  • Setting a maximum new technical debt ratio

Apply the custom gate to your project under Project Settings, then Quality Gate.

Caching for faster builds

SonarQube scanner downloads plugin data and builds a local cache on every run. Without caching, this adds 30 to 60 seconds to each workflow execution. GitHub Actions’ built-in caching eliminates this overhead on subsequent runs.

Add a cache step before the scan:

name: SonarQube with Cache

on:
  push:
    branches: [main]
  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

      - name: Cache SonarQube scanner
        uses: actions/cache@v4
        with:
          path: ~/.sonar/cache
          key: ${{ runner.os }}-sonar-cache-${{ hashFiles('sonar-project.properties') }}
          restore-keys: |
            ${{ runner.os }}-sonar-cache-

      - name: SonarQube Scan
        uses: SonarSource/sonarqube-scan-action@v4
        env:
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
          SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}

      - name: SonarQube Quality Gate check
        uses: SonarSource/sonarqube-quality-gate-action@v1
        timeout-minutes: 5
        env:
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
          SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}

The cache key includes a hash of sonar-project.properties so that the cache is invalidated when you change project configuration. The restore-keys fallback ensures a partial cache hit even when the properties file changes.

For Java projects using Maven or Gradle, also cache the build tool’s local repository to avoid downloading dependencies on every run:

      - name: Cache Maven dependencies
        uses: actions/cache@v4
        with:
          path: ~/.m2/repository
          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
          restore-keys: |
            ${{ runner.os }}-maven-

Multi-language projects

SonarQube automatically detects languages based on file extensions, so multi-language projects usually work without special configuration. However, some languages require build steps or additional configuration for accurate analysis.

Here is a workflow for a project with both a Java backend and a TypeScript frontend:

name: SonarQube Multi-Language

on:
  push:
    branches: [main]
  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

      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          java-version: 17
          distribution: temurin

      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20

      - name: Build Java backend
        run: mvn clean verify -f backend/pom.xml

      - name: Install and test frontend
        run: |
          cd frontend
          npm ci
          npm run test -- --coverage

      - name: SonarQube Scan
        uses: SonarSource/sonarqube-scan-action@v4
        env:
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
          SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}

The corresponding sonar-project.properties for this setup:

sonar.projectKey=my-org_fullstack-project
sonar.projectName=Fullstack Project

# Multiple source directories
sonar.sources=backend/src/main,frontend/src
sonar.tests=backend/src/test,frontend/src/__tests__

# Java-specific settings
sonar.java.binaries=backend/target/classes
sonar.java.libraries=backend/target/dependency/*.jar

# TypeScript coverage
sonar.javascript.lcov.reportPaths=frontend/coverage/lcov.info

# Exclusions
sonar.exclusions=**/node_modules/**,**/target/**,**/*.min.js

The key detail for Java projects is sonar.java.binaries - SonarQube needs compiled class files for deep analysis. Without this path, you will get incomplete results or errors. Make sure the Maven build step runs before the scan.

Monorepo setup

Monorepos present a unique challenge for SonarQube in GitHub Actions because scanning the entire repository on every commit is wasteful when only one service changed. The recommended approach is to create separate SonarQube projects per service and use path filters to trigger scans selectively.

Here is a workflow that scans only the services that changed:

name: SonarQube Monorepo

on:
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  detect-changes:
    name: Detect changed services
    runs-on: ubuntu-latest
    outputs:
      api: ${{ steps.changes.outputs.api }}
      web: ${{ steps.changes.outputs.web }}
      shared: ${{ steps.changes.outputs.shared }}
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Detect changes
        uses: dorny/paths-filter@v3
        id: changes
        with:
          filters: |
            api:
              - 'services/api/**'
            web:
              - 'services/web/**'
            shared:
              - 'packages/shared/**'

  scan-api:
    name: Scan API Service
    needs: detect-changes
    if: needs.detect-changes.outputs.api == 'true'
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: SonarQube Scan - API
        uses: SonarSource/sonarqube-scan-action@v4
        with:
          projectBaseDir: services/api
        env:
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
          SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}

  scan-web:
    name: Scan Web Service
    needs: detect-changes
    if: needs.detect-changes.outputs.web == 'true'
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: SonarQube Scan - Web
        uses: SonarSource/sonarqube-scan-action@v4
        with:
          projectBaseDir: services/web
        env:
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
          SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}

Each service directory needs its own sonar-project.properties:

# services/api/sonar-project.properties
sonar.projectKey=my-org_monorepo-api
sonar.projectName=Monorepo - API Service
sonar.sources=src
sonar.tests=tests
# services/web/sonar-project.properties
sonar.projectKey=my-org_monorepo-web
sonar.projectName=Monorepo - Web Service
sonar.sources=src
sonar.tests=src/__tests__
sonar.javascript.lcov.reportPaths=coverage/lcov.info

The projectBaseDir parameter in the scan action tells the scanner to use the service directory as the project root. Combined with path filters, this setup ensures each service is only scanned when its code actually changes, keeping CI times fast even in large monorepos.

Troubleshooting common issues

Even with a correct configuration, SonarQube in GitHub Actions can hit several common issues. Here are the most frequent problems and their solutions.

”Not authorized” or 401 errors

This means your SONAR_TOKEN is invalid, expired, or does not have permissions for the project. Generate a new token in SonarQube under My Account, then Security, then Tokens. Make sure the token type matches your use case - a “project analysis” token is sufficient for scanning. Update the GitHub secret with the new token value.

”Project not found” errors

The sonar.projectKey in your sonar-project.properties does not match any project in SonarQube. Log in to SonarQube, check the exact project key under Project Information, and update your properties file to match. For SonarQube Cloud, project keys follow the format organization_repository-name.

Quality gate timeout

The quality gate action polls the SonarQube server until the analysis report is processed. If your server is under heavy load, processing can take several minutes. Increase the timeout-minutes value on the quality gate step. For self-hosted servers, check that the SonarQube Compute Engine has enough resources to process reports in a timely manner.

Scanner cannot reach the SonarQube server

If your SonarQube server is behind a corporate firewall, GitHub-hosted runners will not be able to reach it. Options include using self-hosted GitHub Actions runners inside your network, configuring a VPN connection in the workflow, or switching to SonarQube Cloud which does not require inbound network access.

Missing coverage data

SonarQube does not generate coverage reports - it only reads them. You must run your test suite with coverage enabled before the scan step. Make sure the coverage report format matches what SonarQube expects (LCOV for JavaScript/TypeScript, JaCoCo XML for Java, coverage.xml for Python) and that the sonar.*.reportPaths property points to the correct file path.

Java “sonar.java.binaries” error

SonarQube requires compiled class files for Java analysis. If you see an error about missing binaries, add a build step before the scan and set sonar.java.binaries in your properties file to point to the output directory (typically target/classes for Maven or build/classes for Gradle).

For a comprehensive troubleshooting guide covering installation and configuration issues beyond GitHub Actions, see our SonarQube review.

Alternatives to SonarQube for GitHub Actions

SonarQube is a strong choice for static analysis in GitHub Actions, but it is not the only option. Depending on your needs, these alternatives may be a better fit.

SonarQube Cloud (SonarCloud)

If you want SonarQube’s analysis capabilities without managing infrastructure, SonarQube Cloud is the SaaS version. It is free for public repositories, includes PR decoration on all plans, and requires no server setup. The tradeoff is that you send your code to SonarSource’s infrastructure for analysis. Paid plans start at $14/month for private repositories.

CodeAnt AI

CodeAnt AI takes a different approach by combining static analysis with AI-powered code review. Priced at $24 to $40 per user per month, it integrates directly with GitHub and provides automated PR reviews that go beyond rule-based scanning. CodeAnt AI detects code quality issues, security vulnerabilities, and logic errors using AI models trained on code patterns. It supports over 30 languages and provides actionable fix suggestions directly in pull request comments.

Where SonarQube excels at established rule-based detection with thousands of predefined rules, CodeAnt AI adds contextual understanding - catching issues like missing edge cases, incorrect business logic, and architectural problems that rule-based tools cannot detect. For teams that want both static analysis depth and AI-powered code understanding, CodeAnt AI can replace or complement SonarQube in a GitHub Actions pipeline.

For a broader comparison of all available tools, see our guide on AI code review tools for GitHub Actions.

Other options

Several other tools integrate well with GitHub Actions for code analysis:

  • Semgrep - lightweight, fast SAST scanner with a generous free tier. Excellent for security-focused scanning.
  • CodeQL - GitHub’s own static analysis engine, free for public repositories and included with GitHub Advanced Security for private repos.
  • Codacy - code quality platform that works as a GitHub App with no YAML configuration needed.
  • DeepSource - automated code review with sub-5% false positive rate and autofix capabilities.

Conclusion

Setting up SonarQube in GitHub Actions gives your team automated code analysis on every push and pull request. The key steps are straightforward: add your credentials as GitHub secrets, create a sonar-project.properties file, and write a workflow YAML that runs the scan action.

For most teams, the recommended setup includes PR analysis with quality gate enforcement, caching to keep build times fast, and branch protection rules that prevent merging when the quality gate fails. If you are working with a monorepo, use path filters to scan only the services that changed.

Start with the basic workflow from this guide, confirm it runs successfully on a few pull requests, and then layer on the quality gate check and caching. Once the foundation is working, customize the quality gate thresholds and exclusion patterns to match your team’s standards.

For the complete guide to getting SonarQube running from scratch, including Docker installation and server configuration, see our how to setup SonarQube guide. If you are evaluating whether to self-host or use the cloud version, our SonarQube vs SonarCloud comparison breaks down the tradeoffs in detail.

Frequently Asked Questions

How do I integrate SonarQube with GitHub Actions?

Add the SonarSource/sonarqube-scan-action to a GitHub Actions workflow file triggered on push and pull_request events. Store your SonarQube token as a GitHub secret named SONAR_TOKEN and your server URL as SONAR_HOST_URL. Create a sonar-project.properties file in your repository root with your project key and source directories. The action runs the scanner and sends results to your SonarQube instance.

What is the difference between SonarQube Cloud and self-hosted SonarQube in GitHub Actions?

SonarQube Cloud (formerly SonarCloud) is a SaaS service that requires no infrastructure management - you use the SonarSource/sonarcloud-action and connect through sonarcloud.io. Self-hosted SonarQube requires running your own server and uses SonarSource/sonarqube-scan-action with your server URL. Cloud is simpler to configure but self-hosted gives full control over data and infrastructure.

How do I set up SonarQube quality gate checks in GitHub Actions?

Add the SonarSource/sonarqube-quality-gate-action as a step after the scan action in your workflow. It polls SonarQube for the quality gate status and fails the GitHub Actions job if the gate does not pass. Configure branch protection rules in GitHub to require this status check before merging, which blocks PRs that do not meet your quality standards.

Why is my SonarQube GitHub Actions scan failing with a timeout?

Timeout failures usually happen because the quality gate action cannot reach your SonarQube server or because the server has not finished processing the analysis report. Increase the timeout using the waitForQualityGate parameter. For self-hosted servers behind a firewall, ensure the GitHub Actions runner can reach the server URL. Also check that the SONAR_TOKEN secret has not expired.

How do I cache SonarQube scanner data in GitHub Actions?

Use the actions/cache action to cache the .sonar/cache directory between workflow runs. Set the cache key to include your operating system and a hash of the sonar-project.properties file. This avoids re-downloading plugin data on every run and can reduce scan times by 30 to 60 seconds depending on project size.

Can SonarQube analyze pull requests in GitHub Actions?

Yes, but PR analysis requires SonarQube Developer Edition or higher for self-hosted, or SonarQube Cloud. Community Edition only supports main branch analysis. When using Developer Edition, the scan action automatically detects PR context from GitHub Actions environment variables and reports results as PR decoration with inline comments on the pull request.

How do I configure SonarQube for a monorepo in GitHub Actions?

Create a separate SonarQube project for each service or module. Use GitHub Actions path filters to trigger scans only when files in a specific module change. Each module needs its own sonar-project.properties file with a unique sonar.projectKey and sonar.sources path pointing to its directory. Use a matrix strategy to scan multiple modules in parallel.

What languages does SonarQube support in GitHub Actions?

SonarQube supports over 30 languages including Java, JavaScript, TypeScript, Python, C#, Go, PHP, Ruby, Kotlin, Swift, C, C++, and Scala. The GitHub Actions integration supports all of them. Some languages like Java and C# require a build step before scanning, while interpreted languages like Python and JavaScript can be scanned directly without compilation.

How do I fix the SonarQube error 'Project not found' in GitHub Actions?

This error means the sonar.projectKey in your sonar-project.properties does not match any project in your SonarQube instance. Log in to SonarQube, create the project manually or through the API, and copy the exact project key into your properties file. For SonarQube Cloud, the project key format is usually organization_repository-name.

How long does a SonarQube scan take in GitHub Actions?

Scan time depends on project size and language complexity. Small projects under 10,000 lines typically scan in 30 to 90 seconds. Medium projects around 100,000 lines take 2 to 5 minutes. Large projects over 500,000 lines can take 10 to 30 minutes. Caching the .sonar/cache directory and excluding generated code reduces scan times significantly.

Can I run SonarQube alongside other code review tools in GitHub Actions?

Yes, and many teams do. A common setup pairs SonarQube for rule-based static analysis with an AI review tool like CodeRabbit or CodeAnt AI for logic and context-aware feedback. Run them as separate jobs in your workflow for parallel execution. Each tool catches different categories of issues, so combining them provides broader coverage.

Is SonarQube free for GitHub Actions?

SonarQube Community Edition is free and open source for self-hosted use, but it only supports main branch analysis without PR decoration. SonarQube Cloud is free for public repositories. For private repositories with PR analysis and quality gate enforcement in GitHub Actions, you need SonarQube Developer Edition (starts at $490 per year) or a paid SonarQube Cloud plan.

Explore More

Free Newsletter

Stay ahead with AI dev tools

Weekly insights on AI code review, static analysis, and developer productivity. No spam, unsubscribe anytime.

Join developers getting weekly AI tool insights.

Related Articles