SonarCloud Guide: Cloud-Hosted Static Analysis for GitHub, GitLab, and Bitbucket

SonarCloud Guide: Cloud-Hosted Static Analysis for GitHub, GitLab, and Bitbucket

SonarCloud is the hosted version of SonarQube. You connect your GitHub/GitLab/Bitbucket account, import your repositories, and SonarCloud analyzes every push and PR — no server to run, no database to manage. Free for public repositories; paid for private. The tradeoff versus self-hosted: no admin control over rules or configuration, but zero infrastructure overhead.

SonarCloud vs Self-Hosted SonarQube

Aspect SonarCloud Self-Hosted SonarQube
Setup time Minutes Hours to days
Infrastructure None Server + database
Cost Free (public repos), ~$10/month per developer (private) Free Community Edition, paid for Enterprise features
Updates Automatic Manual
Branch analysis All editions Developer Edition+ only
Customization Limited Full admin control
Data residency Sonar's cloud Your infrastructure
Private network No Yes

For most teams with public repos or small private projects, SonarCloud is the right choice. For large organizations with compliance requirements (data residency, internal network) or who need deep customization, self-hosted is better.

Getting Started with SonarCloud

Step 1: Create an Account

Go to sonarcloud.io and sign in with GitHub, GitLab, or Bitbucket. SonarCloud uses OAuth — no separate account needed.

Step 2: Create an Organization

SonarCloud organizes projects under an Organization, which maps to your GitHub org or personal account.

  1. After login, click + → Create new organization
  2. Select Import from GitHub (or GitLab/Bitbucket)
  3. Authorize SonarCloud to access your repositories
  4. Choose which repositories to analyze (you can import all or select specific ones)
  5. Select a plan:
    • Free: public repositories only
    • Paid: private repositories (~$10/developer/month)

Step 3: Analyze a Project

After importing, SonarCloud shows you setup options:

Automatic analysis (recommended for simple projects):

  • SonarCloud runs analysis automatically on every push using GitHub Actions under the hood
  • No additional configuration needed
  • Supports JavaScript, TypeScript, Python, Java, C#, C/C++, Go, and more

CI-based analysis (required for coverage data):

  • You run the scanner in your CI pipeline
  • Required if you want to send coverage reports from your test runner

Choose CI-based analysis if you care about coverage metrics — automatic analysis can't run your tests.

GitHub Actions Integration

Click Set up project → With GitHub Actions. SonarCloud generates configuration for you, but here's the full pattern:

# .github/workflows/build.yml
name: Build and Analyze

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

jobs:
  sonarcloud:
    name: SonarCloud Analysis
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0  # Full history for better new code detection

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

      - name: Install dependencies
        run: npm ci

      - name: Run tests with coverage
        run: npm test -- --coverage --watchAll=false

      - name: SonarCloud Scan
        uses: SonarSource/sonarcloud-github-action@master
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}  # For PR decoration
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

SONAR_TOKEN — generate this in SonarCloud:

  1. Go to your SonarCloud account → Security → Generate Tokens
  2. Give it a name, set no expiry (or set a rotation schedule)
  3. Add it as a GitHub secret: repository → Settings → Secrets → SONAR_TOKEN

GITHUB_TOKEN — automatically provided by GitHub Actions. SonarCloud uses it to post PR comments.

sonar-project.properties

Create this file in your repository root:

sonar.projectKey=your-org_your-repo
sonar.organization=your-sonarcloud-org

# Source and test paths
sonar.sources=src
sonar.tests=src
sonar.test.inclusions=**/*.test.ts,**/*.spec.ts,**/*.test.js

# Coverage (adjust for your test runner)
sonar.javascript.lcov.reportPaths=coverage/lcov.info
sonar.typescript.lcov.reportPaths=coverage/lcov.info

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

The sonar.projectKey format for GitHub is github-org-name_repo-name. Find the exact key in SonarCloud → your project → Information.

PR Analysis and Decorations

SonarCloud's best feature: it analyzes every PR and posts inline comments on the changed lines:

  • New bugs → comment on the line introducing the bug
  • Security vulnerabilities → flagged with severity
  • Coverage gaps → which new lines aren't covered
  • Quality Gate status → pass/fail badge in the PR

To enable PR decoration:

  1. In SonarCloud: Administration → General Settings → Pull Request Decoration
  2. The GITHUB_TOKEN in your Actions workflow must have write permission to post comments

For GitHub, PR analysis works automatically when using sonarcloud-github-action. For self-hosted GitHub Enterprise or GitLab self-managed, you need to configure the webhook manually.

Configuring Quality Gates in SonarCloud

SonarCloud uses the same Quality Gate concept as SonarQube.

Go to Quality Gates in your SonarCloud organization:

  1. The built-in Sonar way gate covers the standard conditions
  2. Create a custom gate under Quality Gates → Create
  3. Assign it to specific projects or set it as the default

Example custom gate for TypeScript projects:

Coverage on New Code ≥ 80%
New Blocker Issues = 0
New Critical Issues = 0
Security Rating on New Code = A

Branch Analysis

SonarCloud supports branch analysis natively (this requires Developer Edition in self-hosted SonarQube). Every branch gets its own analysis page, tracking issues and coverage independently.

Configure which branches are "long-lived" (persistent analysis history) vs short-lived (PR branches):

# Force a specific branch to be treated as a long-lived branch
sonar.branch.name=develop

Or configure via SonarCloud UI: Project Settings → Branches and Pull Requests.

GitLab Integration

# .gitlab-ci.yml
sonarcloud-analysis:
  image: sonarsource/sonar-scanner-cli:latest
  stage: test
  variables:
    SONAR_TOKEN: $SONAR_TOKEN
    SONAR_HOST_URL: "https://sonarcloud.io"
  script:
    - sonar-scanner
      -Dsonar.projectKey=your-org_your-repo
      -Dsonar.organization=your-sonarcloud-org
      -Dsonar.qualitygate.wait=true
  only:
    - merge_requests
    - main

For GitLab MR decoration, add:

sonar.pullrequest.provider=GitLab
sonar.pullrequest.gitlab.repositorySlug=your-group/your-project

Bitbucket Integration

For Bitbucket Pipelines:

# bitbucket-pipelines.yml
pipelines:
  default:
    - step:
        name: SonarCloud Analysis
        image: sonarsource/sonar-scanner-cli:latest
        script:
          - sonar-scanner
            -Dsonar.projectKey=your-org_your-repo
            -Dsonar.organization=your-sonarcloud-org
            -Dsonar.host.url=https://sonarcloud.io
            -Dsonar.login=$SONAR_TOKEN

Monorepo Setup

For a monorepo with multiple services:

my-monorepo/
  packages/
    api/
    frontend/
    shared/
  sonar-project.properties

Option 1: One SonarCloud project, multiple source paths:

sonar.projectKey=org_my-monorepo
sonar.organization=org

sonar.sources=packages/api/src,packages/frontend/src,packages/shared/src
sonar.javascript.lcov.reportPaths=packages/api/coverage/lcov.info,packages/frontend/coverage/lcov.info

Option 2: Separate SonarCloud project per package (cleaner metrics, separate quality gates):

# GitHub Actions - analyze each package separately
- name: Analyze API
  uses: SonarSource/sonarcloud-github-action@master
  with:
    projectBaseDir: packages/api
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

- name: Analyze Frontend
  uses: SonarSource/sonarcloud-github-action@master
  with:
    projectBaseDir: packages/frontend
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

Automatic Analysis Limitations

If you use automatic analysis (no CI), be aware:

  • No coverage — SonarCloud can't run your tests
  • No custom rules — you can't add plugins or custom analyzers
  • Language limitations — C, C++, Obj-C, COBOL, and some others require CI-based analysis
  • Build-dependent analysis — Java bytecode analysis requires compiled output; automatic analysis uses source-level rules only

For any project where coverage matters, use CI-based analysis.

SonarCloud Pricing (2026)

  • Public repositories: Free, unlimited
  • Private repositories: ~$10/active committer/month
    • Active committer = someone who committed in the last 90 days
    • Billed monthly, scales automatically

For most small-to-medium teams (< 20 developers), SonarCloud costs less than running a dedicated SonarQube server even without paying for licenses.

Security Hotspots in SonarCloud

Security Hotspots are code patterns that might be security issues but require human review to confirm. SonarCloud marks them, but they don't fail the quality gate until reviewed.

Review hotspots: Project → Security Hotspots → mark each as:

  • Fixed — you've addressed the issue
  • Safe — reviewed, it's not a vulnerability in this context
  • Acknowledged — known risk you've accepted

The quality gate condition Security Hotspots Reviewed = 100% requires every hotspot to be reviewed before the gate passes.

Comparing SonarCloud to GitHub Code Scanning

GitHub Code Scanning (powered by CodeQL) overlaps with SonarCloud but focuses on security vulnerabilities. Key differences:

Aspect SonarCloud GitHub Code Scanning
Focus Quality + Security Security only
Languages 30+ 20+
Coverage tracking Yes No
Technical debt Yes No
False positives Moderate Low
Custom rules Limited Yes (CodeQL)
Price Paid for private Free (GitHub)

Many teams use both: SonarCloud for code quality and coverage, Code Scanning for deep security analysis. They complement each other rather than replacing each other.

Start now free