Integrating SonarQube into a Gradle project is straightforward once you know where the configuration lives. Unlike Maven, where the plugin runs as part of the build lifecycle automatically, Gradle uses an explicit sonar task that you trigger on demand. A single ./gradlew sonar command analyzes your Java or Kotlin code, collects test coverage data, and uploads everything to your SonarQube server.
This guide covers the complete sonarqube gradle setup - from adding the plugin to build.gradle or build.gradle.kts through sonar properties configuration, multi-module project handling, JaCoCo code coverage integration, quality gate enforcement, and CI/CD pipeline examples for GitHub Actions and Jenkins. Both Groovy DSL and Kotlin DSL configurations are covered side by side throughout.
If you need a SonarQube instance to connect to first, see our guide on SonarQube alternatives to understand your hosting options, or jump straight to the SonarQube tool page for an overview of features and pricing.
Prerequisites
Before setting up the SonarQube Gradle plugin, have the following ready:
- Gradle 7.0 or later - SonarQube Gradle plugin 5.x requires at least Gradle 7
- Java 17 or later - required as the runtime JDK for Gradle itself (your project can still target Java 8, 11, or other versions)
- A running SonarQube instance - self-hosted or SonarQube Cloud
- A SonarQube authentication token - generated from My Account, then Security, then Generate Tokens in your SonarQube instance
-
A Gradle-based Java or Kotlin project - with a valid
build.gradleorbuild.gradle.kts
If you are using the Gradle wrapper (which you should be), replace all gradle commands in this guide with ./gradlew on Linux/macOS or gradlew.bat on Windows.
Adding the SonarQube Plugin
The SonarQube Gradle plugin is published to the Gradle Plugin Portal. Adding it to your project takes a few lines in the plugins block of your root build.gradle or build.gradle.kts.
Groovy DSL (build.gradle)
plugins {
id 'java'
id 'org.sonarqube' version '5.1.0.4882'
}
Kotlin DSL (build.gradle.kts)
plugins {
java
id("org.sonarqube") version "5.1.0.4882"
}
That is all you need to make the sonar task available. Check the Gradle Plugin Portal for the latest version number - the plugin is updated frequently alongside SonarQube server releases.
Note on the task name: SonarQube renamed the task from sonarqube to sonar in plugin version 3.4. If you are on a current version, use ./gradlew sonar. You may see both names in older documentation - they refer to the same operation on different plugin versions.
Running Your First Analysis
Once the plugin is applied, trigger the analysis from your project root:
./gradlew sonar \
-Dsonar.host.url=http://localhost:9000 \
-Dsonar.token=YOUR_TOKEN \
-Dsonar.projectKey=my-project-key
This connects to your SonarQube server, analyzes the source code in src/main/java (or src/main/kotlin), and uploads the results. After the task completes, the terminal prints a link to your project dashboard on the SonarQube server.
The analysis output looks similar to this:
> Task :sonar
SonarQube version: 10.7
Indexing files...
56 files indexed
Quality profile for java: Sonar way
Sensor JavaSensor [java]
Sensor JaCoCo XML Report Importer [jacoco]
ANALYSIS SUCCESSFUL, you can browse http://localhost:9000/dashboard?id=my-project-key
Configuring Sonar Properties in build.gradle
Passing every property on the command line gets unwieldy quickly. Instead, declare persistent project-level properties inside the sonar extension block in your build.gradle.
Groovy DSL Configuration
sonar {
properties {
property 'sonar.projectKey', 'com.example:my-project'
property 'sonar.projectName', 'My Project'
property 'sonar.host.url', 'http://localhost:9000'
property 'sonar.java.source', '17'
property 'sonar.sourceEncoding', 'UTF-8'
}
}
Kotlin DSL Configuration
sonar {
properties {
property("sonar.projectKey", "com.example:my-project")
property("sonar.projectName", "My Project")
property("sonar.host.url", "http://localhost:9000")
property("sonar.java.source", "17")
property("sonar.sourceEncoding", "UTF-8")
}
}
With these properties declared in build.gradle, you only need to pass the token at runtime:
./gradlew sonar -Dsonar.token=YOUR_TOKEN
Keeping the Token Secure
Never put your SonarQube token inside build.gradle - it would end up in version control. There are two safe approaches:
Option 1 - System property at runtime:
./gradlew sonar -Dsonar.token=$SONAR_TOKEN
Option 2 - Gradle properties file (local only):
Add to ~/.gradle/gradle.properties (user-level, not in the project directory):
systemProp.sonar.token=your-token-here
This keeps the token in a file that is never committed to your repository and is available on every Gradle invocation on that machine.
Exclusion Properties
Control what SonarQube analyzes by setting exclusion patterns:
sonar {
properties {
property 'sonar.exclusions', 'src/main/java/**/generated/**, **/dto/**'
property 'sonar.coverage.exclusions', 'src/main/java/**/config/**, **/dto/**'
property 'sonar.cpd.exclusions', 'src/main/java/**/migrations/**'
}
}
All patterns follow Ant-style glob syntax. ** matches any number of directory levels. Separate multiple patterns with commas. The sonar.exclusions property removes files from all analysis. sonar.coverage.exclusions keeps the file in analysis but excludes it from coverage calculations. sonar.cpd.exclusions skips the copy-paste detection sensor for matched files.
Kotlin DSL vs Groovy DSL - A Practical Comparison
Many teams are migrating from Groovy DSL (build.gradle) to Kotlin DSL (build.gradle.kts) to get better IDE support, type safety, and refactoring capabilities. The SonarQube plugin works equally well with both, but the syntax differences catch people off-guard.
Side-by-Side Comparison
Groovy DSL (build.gradle)
plugins {
id 'org.sonarqube' version '5.1.0.4882'
id 'java'
id 'jacoco'
}
sonar {
properties {
property 'sonar.projectKey', 'my-project'
property 'sonar.projectName', 'My Project'
property 'sonar.coverage.jacoco.xmlReportPaths',
'build/reports/jacoco/test/jacocoTestReport.xml'
}
}
jacoco {
toolVersion = '0.8.12'
}
jacocoTestReport {
dependsOn test
reports {
xml.required = true
html.required = true
}
}
Kotlin DSL (build.gradle.kts)
plugins {
id("org.sonarqube") version "5.1.0.4882"
java
jacoco
}
sonar {
properties {
property("sonar.projectKey", "my-project")
property("sonar.projectName", "My Project")
property(
"sonar.coverage.jacoco.xmlReportPaths",
"build/reports/jacoco/test/jacocoTestReport.xml"
)
}
}
jacoco {
toolVersion = "0.8.12"
}
tasks.jacocoTestReport {
dependsOn(tasks.test)
reports {
xml.required.set(true)
html.required.set(true)
}
}
The key differences: Kotlin DSL requires parentheses on all function calls, uses double-quoted strings, and accesses tasks through tasks.taskName rather than directly by name. IDE tooling like IntelliJ IDEA provides autocomplete for Kotlin DSL, which significantly reduces configuration errors.
JaCoCo Code Coverage Integration
Code coverage is the metric teams care about most in SonarQube, and JaCoCo is the standard tool for measuring it in JVM projects. Getting sonarqube jacoco gradle integration right requires the correct task ordering and XML report configuration.
Applying the JaCoCo Plugin
Add jacoco to your plugins block alongside the SonarQube plugin:
Groovy DSL:
plugins {
id 'java'
id 'jacoco'
id 'org.sonarqube' version '5.1.0.4882'
}
Kotlin DSL:
plugins {
java
jacoco
id("org.sonarqube") version "5.1.0.4882"
}
Configuring the JaCoCo Report Task
By default, the jacocoTestReport task generates an HTML report. SonarQube needs the XML report. Enable it explicitly:
Groovy DSL:
jacocoTestReport {
dependsOn test
reports {
xml.required = true
html.required = true
}
}
sonar {
properties {
property 'sonar.coverage.jacoco.xmlReportPaths',
"${buildDir}/reports/jacoco/test/jacocoTestReport.xml"
}
}
Kotlin DSL:
tasks.jacocoTestReport {
dependsOn(tasks.test)
reports {
xml.required.set(true)
html.required.set(true)
}
}
sonar {
properties {
property(
"sonar.coverage.jacoco.xmlReportPaths",
"${buildDir}/reports/jacoco/test/jacocoTestReport.xml"
)
}
}
Running Tests, Coverage, and Analysis Together
Always run these tasks in sequence:
./gradlew test jacocoTestReport sonar -Dsonar.token=YOUR_TOKEN
The order matters. test compiles and runs your tests. jacocoTestReport reads the JaCoCo execution data (.exec file) and produces the XML report. sonar reads that XML report and uploads coverage data to SonarQube.
If you run ./gradlew sonar without jacocoTestReport, SonarQube will show 0% coverage because the XML report does not exist yet.
Making the Dependency Automatic
To avoid remembering the task order, add an explicit dependency on jacocoTestReport to the sonar task:
Groovy DSL:
tasks['sonar'].dependsOn jacocoTestReport
Kotlin DSL:
tasks.sonar {
dependsOn(tasks.jacocoTestReport)
}
Now ./gradlew sonar automatically runs tests and generates the coverage report first.
Multi-Module Gradle Projects
Enterprise Gradle projects commonly use multi-module structures with a root project and several subprojects such as :api, :service, :domain, and :persistence. The SonarQube Gradle plugin handles this natively, with configuration centralized in the root project.
Root Project Configuration
Apply the plugin only in the root build.gradle or build.gradle.kts. Subprojects do not need the plugin applied individually:
Groovy DSL (build.gradle in root):
plugins {
id 'org.sonarqube' version '5.1.0.4882'
}
sonar {
properties {
property 'sonar.projectKey', 'com.example:my-application'
property 'sonar.projectName', 'My Application'
property 'sonar.host.url', 'http://localhost:9000'
property 'sonar.java.source', '17'
}
}
Kotlin DSL (build.gradle.kts in root):
plugins {
id("org.sonarqube") version "5.1.0.4882"
}
sonar {
properties {
property("sonar.projectKey", "com.example:my-application")
property("sonar.projectName", "My Application")
property("sonar.host.url", "http://localhost:9000")
property("sonar.java.source", "17")
}
}
Subproject-Level Overrides
Apply JaCoCo and per-module SonarQube properties in a subprojects or allprojects block in the root build file, or in individual subproject build files:
Groovy DSL - applying JaCoCo to all subprojects:
subprojects {
apply plugin: 'java'
apply plugin: 'jacoco'
jacocoTestReport {
dependsOn test
reports {
xml.required = true
}
}
}
Kotlin DSL - applying JaCoCo to all subprojects:
subprojects {
apply(plugin = "java")
apply(plugin = "jacoco")
tasks.withType<JacocoReport> {
dependsOn(tasks.withType<Test>())
reports {
xml.required.set(true)
}
}
}
Excluding a Subproject from Analysis
To skip a specific subproject entirely, add this to the subproject's build.gradle:
// Groovy DSL
sonar {
isSkipProject = true
}
// Kotlin DSL
sonar {
isSkipProject = true
}
This is useful for subprojects that contain only test utilities, generated code, or configuration files that should not appear in the SonarQube dashboard.
Aggregated Coverage for Multi-Module Projects
When integration tests in one subproject test classes from other subprojects, individual per-module JaCoCo reports miss coverage that crosses module boundaries. Use JaCoCo's aggregation plugin to produce a single unified report:
Groovy DSL (in a dedicated coverage subproject):
// coverage/build.gradle
plugins {
id 'java'
id 'jacoco-report-aggregation'
}
dependencies {
jacocoAggregation project(':api')
jacocoAggregation project(':service')
jacocoAggregation project(':domain')
jacocoAggregation project(':persistence')
}
reporting {
reports {
testCodeCoverageReport(JacocoCoverageReport) {
testType = TestSuiteType.UNIT_TEST
}
}
}
Then point SonarQube at the aggregate report from the root project:
sonar {
properties {
property 'sonar.coverage.jacoco.xmlReportPaths',
"${project(':coverage').buildDir}/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml"
}
}
Quality Gate Integration
A quality gate is a set of conditions SonarQube uses to determine whether a project passes or fails analysis. The default "Sonar way" gate requires no new bugs, no new vulnerabilities, coverage on new code above 80%, and duplication below 3%. If any condition fails, the quality gate status is "Failed."
Waiting for the Quality Gate Result
By default, ./gradlew sonar uploads the analysis and exits without waiting to know if the quality gate passed. For CI pipelines where you want to fail the build on gate failures, set sonar.qualitygate.wait:
./gradlew sonar \
-Dsonar.token=YOUR_TOKEN \
-Dsonar.qualitygate.wait=true
Or declare it in build.gradle only for CI environments:
Groovy DSL:
sonar {
properties {
if (System.getenv('CI')) {
property 'sonar.qualitygate.wait', 'true'
property 'sonar.qualitygate.timeout', '300'
}
}
}
Kotlin DSL:
sonar {
properties {
if (System.getenv("CI") != null) {
property("sonar.qualitygate.wait", "true")
property("sonar.qualitygate.timeout", "300")
}
}
}
The sonar.qualitygate.timeout value is in seconds. The default is 300 seconds (5 minutes). For large projects that take longer to process on the server, increase this value.
Custom Quality Gates
You can create custom quality gates in the SonarQube interface under Quality Gates in the main navigation. Custom gates let you adjust thresholds for coverage, reliability, security, and maintainability ratings. Once defined, assign a custom gate to your project in the Project Settings page - the Gradle plugin will automatically use whatever gate is configured for that project on the server.
CI Pipeline Examples
GitHub Actions
Here is a production-ready GitHub Actions workflow for sonarqube gradle:
name: SonarQube Analysis
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
sonarqube:
name: Build and Analyze
runs-on: ubuntu-latest
steps:
- name: Checkout
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: Setup Gradle
uses: gradle/actions/setup-gradle@v3
with:
gradle-home-cache-cleanup: true
- name: Cache SonarQube packages
uses: actions/cache@v4
with:
path: ~/.sonar/cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar
- name: Build, Test, and Analyze
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
run: >
./gradlew test jacocoTestReport sonar
-Dsonar.host.url=$SONAR_HOST_URL
-Dsonar.token=$SONAR_TOKEN
-Dsonar.qualitygate.wait=true
The fetch-depth: 0 checkout is critical. SonarQube uses the full Git history to identify which code is "new" for the quality gate's "new code" conditions. A shallow clone causes SonarQube to treat all code as new, which can give misleading coverage metrics.
For a detailed walkthrough of SonarQube in GitHub Actions, see the SonarQube GitHub Actions guide.
Jenkins Pipeline
For Jenkins, use the SonarQube Scanner plugin and withSonarQubeEnv to inject server credentials securely:
pipeline {
agent any
tools {
jdk 'JDK-17'
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Test') {
steps {
sh './gradlew test jacocoTestReport'
}
post {
always {
junit 'build/test-results/test/*.xml'
jacoco(
execPattern: 'build/jacoco/*.exec',
classPattern: 'build/classes/java/main',
sourcePattern: 'src/main/java'
)
}
}
}
stage('SonarQube Analysis') {
steps {
withSonarQubeEnv('SonarQube') {
sh './gradlew sonar'
}
}
}
stage('Quality Gate') {
steps {
timeout(time: 5, unit: 'MINUTES') {
waitForQualityGate abortPipeline: true
}
}
}
}
}
The withSonarQubeEnv('SonarQube') block reads server URL and credentials from the Jenkins global configuration (Manage Jenkins, then Configure System, then SonarQube servers). The waitForQualityGate step uses a webhook that your SonarQube server sends back to Jenkins when analysis is complete. Set this webhook up in SonarQube under Administration, then Configuration, then Webhooks - point it at http://your-jenkins-url/sonarqube-webhook/.
See the SonarQube Jenkins integration guide for step-by-step webhook configuration and troubleshooting.
Troubleshooting Common Issues
0% Code Coverage
The most frequent problem with sonarqube gradle setups is the SonarQube dashboard showing 0% coverage. Work through this checklist:
-
Verify
jacocoTestReportran - check thatbuild/reports/jacoco/test/jacocoTestReport.xmlexists after your build -
Confirm XML output is enabled - the task's
reports.xml.requiredmust betrue -
Check the report path - if your Gradle version puts the report in a different location, set
sonar.coverage.jacoco.xmlReportPathsto the actual path -
Verify the
.execfile exists -build/jacoco/test.execshould exist beforejacocoTestReportruns; if it does not, thetesttask did not run or JaCoCo was not attached
To debug, print the path in your build script:
tasks.sonar.doFirst {
println "JaCoCo report: ${file('build/reports/jacoco/test/jacocoTestReport.xml').exists()}"
}
"Project Not Found" or Wrong Project Key
If SonarQube creates a new project on every analysis run instead of updating the existing one, the sonar.projectKey property is changing between runs. Ensure it is hardcoded in build.gradle rather than being derived from a variable that changes (such as the Git branch name or build number).
Memory Issues on Large Projects
Increase the Gradle JVM heap for large projects:
export GRADLE_OPTS="-Xmx4g -XX:+UseG1GC"
./gradlew test jacocoTestReport sonar -Dsonar.token=YOUR_TOKEN
Or set it persistently in gradle.properties:
org.gradle.jvmargs=-Xmx4g -XX:+UseG1GC
SSL Certificate Errors
When connecting to a self-hosted SonarQube instance over HTTPS with a self-signed certificate, the JVM may refuse the connection. Import the certificate into the JVM's truststore, or for testing purposes only, pass the truststore properties:
./gradlew sonar \
-Dsonar.token=YOUR_TOKEN \
-Djavax.net.ssl.trustStore=/path/to/truststore.jks \
-Djavax.net.ssl.trustStorePassword=changeit
Do not use -Djavax.net.ssl.trustAll=true in production - it disables all certificate validation.
SonarQube Cloud Configuration
If you are using SonarQube Cloud (hosted by SonarSource) instead of a self-hosted instance, change two properties:
Groovy DSL:
sonar {
properties {
property 'sonar.host.url', 'https://sonarcloud.io'
property 'sonar.organization', 'your-org-key'
property 'sonar.projectKey', 'your-org-key_your-project-name'
}
}
Kotlin DSL:
sonar {
properties {
property("sonar.host.url", "https://sonarcloud.io")
property("sonar.organization", "your-org-key")
property("sonar.projectKey", "your-org-key_your-project-name")
}
}
Generate your token from sonarcloud.io under My Account, then Security. The token format is the same as self-hosted. SonarQube Cloud includes PR decoration on GitHub, GitLab, Bitbucket, and Azure DevOps at no extra cost, which requires an additional plugin purchase or Developer Edition on self-hosted setups.
A Modern Alternative - CodeAnt AI
Setting up sonarqube gradle integration involves meaningful infrastructure overhead: a SonarQube server, a PostgreSQL database, regular updates, and Gradle plugin configuration across every project. Teams that want code quality analysis without this operational burden should look at CodeAnt AI.
CodeAnt AI is an AI-powered code review platform priced at $24 to $40 per user per month. There is no server to run, no Gradle plugin to configure, and no database to manage. Connect it to your GitHub, GitLab, or Bitbucket account and it begins analyzing pull requests automatically. It catches code quality issues, security vulnerabilities, and antipatterns using models trained on large volumes of real-world code reviews - going beyond the pattern-matching rules that SonarQube applies.
The comparison is not purely one-sided. SonarQube has a larger rule library, self-hosted data control, and better support for custom quality profiles. But for teams whose primary goal is "catch issues before they merge" rather than "maintain a comprehensive code quality platform," CodeAnt AI removes a significant amount of setup and maintenance friction.
See the full comparison in our SonarQube alternatives guide.
Summary
The SonarQube Gradle plugin makes static analysis a first-class part of your Gradle build. With a few lines in your build.gradle or build.gradle.kts, you get automated code quality analysis, security vulnerability detection, and code coverage tracking on every build.
Key takeaways from this guide:
- Apply the plugin in the root project only - use
id 'org.sonarqube' version '5.1.0.4882'in thepluginsblock - The task is named
sonar(notsonarqube) in plugin version 3.4 and later - Always run
./gradlew test jacocoTestReport sonarin sequence - never skip the test and coverage steps - Enable XML output on
jacocoTestReportwithxml.required = trueso SonarQube can read the coverage data - Use the
sonarextension block inbuild.gradlefor persistent project properties; pass the token at runtime only - Kotlin DSL and Groovy DSL configurations are structurally identical - the syntax differs in quotes and parentheses
- For multi-module projects, configure the root project and apply JaCoCo to subprojects via
subprojects {}block - Set
sonar.qualitygate.wait=truein CI to fail the build when the quality gate does not pass - Use
fetch-depth: 0in GitHub Actions checkouts to give SonarQube access to the full Git history
For build-system-specific comparisons, see the SonarQube Maven integration guide. For CI-specific workflows, see the SonarQube GitHub Actions guide and the SonarQube Jenkins guide.
Further Reading
- How to Set Up AI Code Review in GitHub Actions - Complete Guide
- How to Automate Code Reviews in 2026 - Complete Setup Guide
- How to Setup SonarQube - Complete Docker, Scanner, and CI/CD Guide
- How to Reduce Code Review Time by 50% - Proven Strategies and Tools
- SonarQube Docker Compose: Production-Ready Configuration
Frequently Asked Questions
How do I add the SonarQube plugin to a Gradle project?
Add the SonarQube plugin to your build.gradle using the plugins block: plugins { id 'org.sonarqube' version '5.1.0.4882' }. For Kotlin DSL, use plugins { id("org.sonarqube") version "5.1.0.4882" }. Then run './gradlew sonar -Dsonar.host.url=http://localhost:9000 -Dsonar.token=YOUR_TOKEN' to trigger the analysis.
What is the correct task name - sonarqube or sonar?
Starting with SonarQube Gradle plugin version 3.4, the task was renamed from 'sonarqube' to 'sonar'. If you are using plugin version 3.4 or later, run './gradlew sonar'. Older versions still use './gradlew sonarqube'. Both names work in some version ranges, but 'sonar' is the current standard.
How do I configure sonar properties in build.gradle?
Use the sonar extension block in your build.gradle. For Groovy DSL: sonar { properties { property 'sonar.projectKey', 'my-project' property 'sonar.host.url', 'http://localhost:9000' } }. For Kotlin DSL: sonar { properties { property("sonar.projectKey", "my-project") } }. You can also pass properties as system properties on the command line with -D flags.
How do I integrate JaCoCo code coverage with SonarQube in Gradle?
Apply the JaCoCo plugin in build.gradle with 'apply plugin: jacoco' or 'plugins { id 'jacoco' }'. Run './gradlew test jacocoTestReport sonar'. The jacocoTestReport task generates an XML report at build/reports/jacoco/test/jacocoTestReport.xml, which SonarQube detects automatically. If your report path differs, set sonar.coverage.jacoco.xmlReportPaths explicitly.
How do I set up SonarQube in a Gradle multi-module project?
Apply the SonarQube plugin only in the root project's build.gradle. Child modules do not need the plugin applied individually. Run './gradlew sonar' from the root directory. The plugin automatically discovers all subprojects, analyzes each one, and aggregates the results into a single SonarQube project. Each subproject appears as a component in the SonarQube dashboard.
What is the difference between Kotlin DSL and Groovy DSL for SonarQube Gradle configuration?
The configuration structure is identical - both use the sonar extension block with a properties closure. The syntax differs: Groovy DSL uses single-quoted strings and the property keyword without parentheses, while Kotlin DSL uses double-quoted strings and requires parentheses on function calls. Kotlin DSL files use the .kts extension (build.gradle.kts) and provide better IDE completion and type safety.
How do I exclude files from SonarQube analysis in Gradle?
Set the sonar.exclusions property inside the sonar properties block: property 'sonar.exclusions', 'src/main/java/com/example/generated/,/dto/*'. For coverage exclusions only, use sonar.coverage.exclusions. All exclusion patterns use Ant-style glob syntax where * matches any number of directories.
Why does SonarQube show 0% coverage in my Gradle project?
The most common cause is running './gradlew sonar' without running 'test' and 'jacocoTestReport' first. Always run './gradlew test jacocoTestReport sonar' in sequence. Also verify that the jacoco plugin is applied, the jacocoTestReport task is configured to generate XML output (xml.required = true), and that the report exists at the expected path before the sonar task runs.
Can I use SonarQube Gradle plugin with SonarQube Cloud?
Yes. Set sonar.host.url to https://sonarcloud.io and add sonar.organization with your SonarQube Cloud organization key in the sonar properties block. Pass your SonarQube Cloud token via -Dsonar.token on the command line or as an environment variable. Everything else works the same as with a self-hosted SonarQube instance.
How do I run SonarQube analysis only in CI without affecting local builds?
Define SonarQube properties as environment-specific command-line system properties rather than hardcoding them in build.gradle. Use -Dsonar.token and -Dsonar.host.url on the command line. In build.gradle, you can wrap properties in an if block checking for a CI environment variable: if (System.getenv('CI')) { property 'sonar.qualitygate.wait', 'true' }. Local developers can skip the sonar task by not running it.
How do I enforce a SonarQube quality gate in a Gradle CI pipeline?
Set the sonar.qualitygate.wait property to true in your sonar configuration block or pass -Dsonar.qualitygate.wait=true on the command line. This makes the Gradle sonar task poll the SonarQube server after uploading the analysis and fail the build if the quality gate does not pass. You can also set sonar.qualitygate.timeout to control how long the task waits before giving up.
Is there a simpler alternative to SonarQube for Gradle projects?
Yes. CodeAnt AI provides AI-powered code analysis at $24 to $40 per user per month with no Gradle plugin configuration or self-hosted server required. It connects directly to your GitHub, GitLab, or Bitbucket repository and analyzes pull requests automatically. For teams that want code quality enforcement without Gradle plugin setup or server maintenance, it is a practical alternative to consider.
Originally published at aicodereview.cc

Top comments (0)