Skip to content

SCANCLI-223 Experiment with the Gradle Tooling API#278

Draft
Seppli11 wants to merge 3 commits into
masterfrom
sz/java-tooling-api-poc
Draft

SCANCLI-223 Experiment with the Gradle Tooling API#278
Seppli11 wants to merge 3 commits into
masterfrom
sz/java-tooling-api-poc

Conversation

@Seppli11

@Seppli11 Seppli11 commented Jun 19, 2026

Copy link
Copy Markdown

Summary by Gitar

  • New CLI functionality:
    • Added --dump-gradle-java-properties option to generate sonar-project.properties from Gradle builds.
    • Implemented GradleJavaPropertiesDumper to interface with the gradle-tooling-api and map project metadata.
  • Project configuration:
    • Added gradle-tooling-api dependency in pom.xml.
  • Documentation:
    • Included sonar-scanner-engine-issue-comparison.md detailing the semantic analysis gap between Gradle and property-dumped scans.
    • Added a sample scanner-engine-sonar-project.properties file.

This will update automatically on new commits.

@hashicorp-vault-sonar-prod hashicorp-vault-sonar-prod Bot changed the title Sz/java tooling api poc SCANCLI-223 Sz/java tooling api poc Jun 19, 2026
@hashicorp-vault-sonar-prod

hashicorp-vault-sonar-prod Bot commented Jun 19, 2026

Copy link
Copy Markdown

SCANCLI-223

Comment thread pom.xml
Comment on lines +1 to +15
sonar.projectBaseDir=/home/sebastian.zumbrunn/code/sonar-scanner-engine
sonar.sources=
sonar.tests=
sonar.exclusions=cloud/license-api/**,cloud/plugins/sonar-xoo-plugin/**,cloud/process-executor/**,cloud/sarif-parser/**,cloud/sonar-scanner-engine/**,cloud/sonar-scanner-protocol/**,cloud/sensor-test-fixtures/**,cloud/sonar-core/**,cloud/sonar-scanner-engine-light/**,cloud/sonar-scanner-extension-a3s/**,cloud/sonar-scanner-extension-api/**,cloud/sonar-scanner-extension-architecture/**,cloud/sonar-scanner-extension-sca/**,cloud/sonar-scanner-plugin-framework/**,cloud/sonar-scanner-report-viewer/**,cloud/sonar-scanner-spring-di/**,cloud/webapi-client/**,server/plugins/sonar-xoo-plugin/**,server/private/core-extension-common/**,server/private/core-extension-developer-scanner/**,server/private/license-api/**,server/sonar-scanner-engine/**,server/sonar-scanner-protocol/**,server/sonar-core/**,server/sonar-plugin-api-impl/**,server/sonar-ws/**,shared/log-utils/**,shared/plugin-api-scanner-impl/**,shared/protobuf-utils/**,shared/scanner-engine-commons/**,shared/sonar-channel/**,shared/sonar-duplications/**,shared/sonar-scanner-extension-framework/**
sonar.modules=cloud_license_api,cloud_plugins_sonar_xoo_plugin,cloud_process_executor,cloud_sarif_parser,cloud_scanner_engine_cloud,cloud_scanner_engine_protocol_cloud,cloud_sensor_test_fixtures,cloud_sonar_core,cloud_sonar_scanner_engine_light,cloud_sonar_scanner_extension_a3s,cloud_sonar_scanner_extension_api,cloud_sonar_scanner_extension_architecture,cloud_sonar_scanner_extension_sca,cloud_sonar_scanner_plugin_framework,cloud_sonar_scanner_report_viewer,cloud_sonar_scanner_spring_di,cloud_webapi_client,server_plugins_sonar_xoo_plugin,server_private_core_extension_common,server_private_core_extension_developer_scanner,server_private_license_api,server_scanner_engine_community,server_scanner_engine_protocol_server,server_sonar_core,server_sonar_plugin_api_impl,server_sonar_ws,shared_log_utils,shared_plugin_api_scanner_impl,shared_protobuf_utils,shared_scanner_engine_commons,shared_sonar_channel,shared_sonar_duplications,shared_sonar_scanner_extension_framework
cloud_license_api.sonar.projectBaseDir=/home/sebastian.zumbrunn/code/sonar-scanner-engine/cloud/license-api
cloud_license_api.sonar.exclusions=
cloud_license_api.sonar.sources=/home/sebastian.zumbrunn/code/sonar-scanner-engine/cloud/license-api/src/main/java
cloud_license_api.sonar.tests=/home/sebastian.zumbrunn/code/sonar-scanner-engine/cloud/license-api/src/test/java
cloud_license_api.sonar.java.libraries=/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/com.google.code.findbugs/jsr305/3.0.2/25ea2e8b0c338a877313bd4672d3fe056ea78f0d/jsr305-3.0.2.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/org.sonarsource.api.plugin/sonar-plugin-api/13.8.0.4399/6667ac51f1440d2c6f6170e380555b47b66cd76c/sonar-plugin-api-13.8.0.4399.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/org.slf4j/slf4j-api/1.7.30/b5a4b6d16ab13e34a88fae84c35cd5d68cac922c/slf4j-api-1.7.30.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/com.google.guava/guava/33.6.0-jre/c376b13067cc99a5774403530953f7b05a91e218/guava-33.6.0-jre.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/org.apache.commons/commons-csv/1.14.1/467354980fade8528b6a9f9bdf7f4f19ab9b3373/commons-csv-1.14.1.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/commons-codec/commons-codec/1.21.0/d95f998db5f89900fe895daf6cd2cddcb2f1d64b/commons-codec-1.21.0.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/commons-io/commons-io/2.22.0/5b1e18bc0ad651ed878029d83f88d9c8189fd51e/commons-io-2.22.0.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/org.apache.commons/commons-lang3/3.20.0/65897b3e5731220962e659e001904af3c3cbeba9/commons-lang3-3.20.0.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/org.slf4j/slf4j-api/2.0.18/78a9e7a37cd6360e0b818e86341b24123d28d4df/slf4j-api-2.0.18.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/com.google.guava/failureaccess/1.0.3/aeaffd00d57023a2c947393ed251f0354f0985fc/failureaccess-1.0.3.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/com.google.guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/b421526c5f297295adef1c886e5246c39d4ac629/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/org.jspecify/jspecify/1.0.0/7425a601c1c7ec76645a78d22b8c6a627edee507/jspecify-1.0.0.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/com.google.errorprone/error_prone_annotations/2.47.0/e64e70c8e2b5a30ce7f1b6c9e3eb7016881e0411/error_prone_annotations-2.47.0.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/com.google.j2objc/j2objc-annotations/3.1/a892ca9507839bbdb900d64310ac98256cab992f/j2objc-annotations-3.1.jar
cloud_license_api.sonar.java.test.libraries=/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/com.google.code.findbugs/jsr305/3.0.2/25ea2e8b0c338a877313bd4672d3fe056ea78f0d/jsr305-3.0.2.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/org.sonarsource.api.plugin/sonar-plugin-api/13.8.0.4399/6667ac51f1440d2c6f6170e380555b47b66cd76c/sonar-plugin-api-13.8.0.4399.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/org.slf4j/slf4j-api/1.7.30/b5a4b6d16ab13e34a88fae84c35cd5d68cac922c/slf4j-api-1.7.30.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/com.google.guava/guava/33.6.0-jre/c376b13067cc99a5774403530953f7b05a91e218/guava-33.6.0-jre.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/org.apache.commons/commons-csv/1.14.1/467354980fade8528b6a9f9bdf7f4f19ab9b3373/commons-csv-1.14.1.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/commons-codec/commons-codec/1.21.0/d95f998db5f89900fe895daf6cd2cddcb2f1d64b/commons-codec-1.21.0.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/commons-io/commons-io/2.22.0/5b1e18bc0ad651ed878029d83f88d9c8189fd51e/commons-io-2.22.0.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/org.apache.commons/commons-lang3/3.20.0/65897b3e5731220962e659e001904af3c3cbeba9/commons-lang3-3.20.0.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/org.slf4j/slf4j-api/2.0.18/78a9e7a37cd6360e0b818e86341b24123d28d4df/slf4j-api-2.0.18.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/com.google.guava/failureaccess/1.0.3/aeaffd00d57023a2c947393ed251f0354f0985fc/failureaccess-1.0.3.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/com.google.guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/b421526c5f297295adef1c886e5246c39d4ac629/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/org.jspecify/jspecify/1.0.0/7425a601c1c7ec76645a78d22b8c6a627edee507/jspecify-1.0.0.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/com.google.errorprone/error_prone_annotations/2.47.0/e64e70c8e2b5a30ce7f1b6c9e3eb7016881e0411/error_prone_annotations-2.47.0.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/com.google.j2objc/j2objc-annotations/3.1/a892ca9507839bbdb900d64310ac98256cab992f/j2objc-annotations-3.1.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/org.junit.jupiter/junit-jupiter-params/6.1.0/6e6dcbd963a6c16217350535a640e1c0fde0d619/junit-jupiter-params-6.1.0.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/org.junit.jupiter/junit-jupiter-api/6.1.0/5376d10370f32af4f3b1b7a378906ee58dcdacb3/junit-jupiter-api-6.1.0.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/org.junit.platform/junit-platform-commons/6.1.0/3bb0447338b81f4396648c406d3e1c22f65f689/junit-platform-commons-6.1.0.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/org.junit.jupiter/junit-jupiter/6.1.0/52aef21f8c9fa491ff7eb20008e39102a8479f79/junit-jupiter-6.1.0.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/org.assertj/assertj-core/3.27.7/2f4f64f054c9d618d4b1d89e7611559f5e2cfff7/assertj-core-3.27.7.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/junit/junit/4.13.2/8ac9e16d933b6fb43bc7f576336b8f4d7eb5ba12/junit-4.13.2.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/net.bytebuddy/byte-buddy/1.18.3/c35b2e4bf0e22e4d492936d46506bb2e6d8fafc8/byte-buddy-1.18.3.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/org.hamcrest/hamcrest-core/1.3/42a25dc3219429f0e5d060061f71acb49bf010a0/hamcrest-core-1.3.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/org.opentest4j/opentest4j/1.3.0/152ea56b3a72f655d4fd677fc0ef2596c3dd5e6e/opentest4j-1.3.0.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/org.apiguardian/apiguardian-api/1.1.2/a231e0d844d2721b0fa1b238006d15c6ded6842a/apiguardian-api-1.1.2.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/org.junit.jupiter/junit-jupiter-engine/6.1.0/82414ee1a0308d2f096c37d317b93b66c13dbb9a/junit-jupiter-engine-6.1.0.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/org.junit.platform/junit-platform-launcher/6.1.0/78124de837a3e0b9e4e32a2c80ba47117f7f8c60/junit-platform-launcher-6.1.0.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/org.junit.vintage/junit-vintage-engine/6.1.0/af18e7c935d0b0a31f484adab7d9d15083b15b09/junit-vintage-engine-6.1.0.jar,/home/sebastian.zumbrunn/.gradle/caches/modules-2/files-2.1/org.junit.platform/junit-platform-engine/6.1.0/754271e8493a0be2838f3500b30971969b8603d0/junit-platform-engine-6.1.0.jar
cloud_license_api.sonar.java.source=17
cloud_plugins_sonar_xoo_plugin.sonar.projectBaseDir=/home/sebastian.zumbrunn/code/sonar-scanner-engine/cloud/plugins/sonar-xoo-plugin
cloud_plugins_sonar_xoo_plugin.sonar.exclusions=
cloud_plugins_sonar_xoo_plugin.sonar.sources=/home/sebastian.zumbrunn/code/sonar-scanner-engine/cloud/plugins/sonar-xoo-plugin/src/main/java

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Quality: Committed generated sample leaks developer home path/username

scanner-engine-sonar-project.properties is a 234-line generated artifact committed at the repository root. Every entry contains absolute, machine-specific paths from a developer's workstation (e.g. /home/sebastian.zumbrunn/code/... and /home/sebastian.zumbrunn/.gradle/caches/...), embedding a personal username and local Gradle cache layout. Generated/sample output with hardcoded local paths is not reproducible, can go stale, and unnecessarily exposes a developer's environment.

If this sample is needed for documentation, consider moving it under docs/ with sanitized/placeholder paths (e.g. /path/to/project), or omit it and reference the comparison doc instead. At minimum it should not live at the repo root.

Was this helpful? React with 👍 / 👎

@Seppli11 Seppli11 changed the title SCANCLI-223 Sz/java tooling api poc SCANCLI-223 Experiment with the Gradle Tooling API Jun 19, 2026
@Seppli11 Seppli11 force-pushed the sz/java-tooling-api-poc branch from b4acdfe to 0ed596e Compare June 19, 2026 12:03
Comment on lines +145 to +154
private static IdeaProject loadIdeaProject(Path projectRoot) {
GradleConnector connector = GradleConnector.newConnector()
.forProjectDirectory(projectRoot.toFile());

try (ProjectConnection connection = connector.connect()) {
return connection.getModel(IdeaProject.class);
} catch (Exception e) {
throw new IllegalStateException("Failed to load the Gradle IDEA model from " + projectRoot, e);
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Edge Case: Dump mode triggers a real Gradle build with no version pinning

loadIdeaProject creates a GradleConnector with only forProjectDirectory(...) and then calls connection.getModel(IdeaProject.class). Without useGradleVersion(), useDistribution(), or useBuildDistribution(), the Tooling API resolves the Gradle distribution from the target project's wrapper (or downloads the connector's default), and configuring the IDEA model executes a full Gradle configuration phase on the user's machine. Consequences: (1) network access to download a Gradle distribution may be required, which can fail in offline/CI environments; (2) the resolved Gradle version may be incompatible with tooling-api 8.14.5 (the Tooling API only supports a bounded range of Gradle versions); (3) any build-script error surfaces as a wrapped IllegalStateException. For a CLI feature this behavior should be documented and ideally the supported Gradle version range validated up front. Since this is an experimental/draft feature this is acceptable for now but should be addressed before shipping.

Pin or validate the Gradle version and document the runtime Gradle execution requirement.:

// Optionally pin / validate the Gradle version to avoid surprises:
GradleConnector connector = GradleConnector.newConnector()
  .forProjectDirectory(projectRoot.toFile());
// e.g. .useGradleVersion("8.14.5") or document that the project's wrapper is used
  • Apply fix

Check the box to apply the fix or reply for a change | Was this helpful? React with 👍 / 👎

Comment thread pom.xml
<artifactsToPublish>${project.groupId}:${project.artifactId}:zip,${project.groupId}:${project.artifactId}:zip:linux-x64,${project.groupId}:${project.artifactId}:zip:linux-aarch64,${project.groupId}:${project.artifactId}:zip:windows-x64,${project.groupId}:${project.artifactId}:zip:macosx-x64,${project.groupId}:${project.artifactId}:zip:macosx-aarch64,${project.groupId}:${project.artifactId}:json:cyclonedx</artifactsToPublish>

<maven.compiler.release>11</maven.compiler.release>
<gradle.tooling.api.version>8.14.5</gradle.tooling.api.version>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Quality: Experimental feature adds ~3MB and a new external repo to the CLI

Adding gradle-tooling-api pulls a sizeable dependency into the shipped distribution: the requireFilesSize enforcer rule was bumped from 9.2-9.3MB to 12.1-12.2MB, i.e. roughly +3MB on every published artifact (linux/windows/macos x64/aarch64). It also introduces a new required Maven repository (https://repo.gradle.org/gradle/libs-releases) to the build. For an experimental/draft feature, weighing this permanent size and build-dependency cost against the value is worth doing before merge — consider whether the dumper should ship in the main CLI artifact at all, or be a separate/optional module.

Re-evaluate bundling the tooling-api into the core CLI distribution.:

<!-- Consider scoping the gradle-tooling-api dependency to a separate artifact
     or feature module rather than bundling ~3MB into every CLI distribution. -->
  • Apply fix

Check the box to apply the fix or reply for a change | Was this helpful? React with 👍 / 👎

Comment on lines +80 to +86
if (cli.isDumpGradleJavaProperties()) {
configureLogging(cli.properties());
dumpGradleJavaProperties();
displayExecutionResult(stats, SUCCESS);
status = Exit.SUCCESS;
return;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Quality: Dump mode bypasses skip handling and uses only CLI properties

In analyze(), the cli.isDumpGradleJavaProperties() branch returns early before conf.properties() and checkSkip(p) are evaluated, and it configures logging from cli.properties() only (ignoring global/project sonar-scanner.properties and environment settings). As a result sonar.scanner.skip is not honored in dump mode, and verbose/debug logging configured via property files (rather than -D/-X) will not take effect. This may be intentional for the POC, but if dump mode is meant to behave consistently with normal runs it should resolve the full property set (or at least honor the skip flag) before generating output.

Resolve full properties and honor skip/logging in dump mode.:

if (cli.isDumpGradleJavaProperties()) {
  Properties p = conf.properties();
  checkSkip(p);
  configureLogging(p);
  dumpGradleJavaProperties();
  displayExecutionResult(stats, SUCCESS);
  status = Exit.SUCCESS;
  return;
}
  • Apply fix

Check the box to apply the fix or reply for a change | Was this helpful? React with 👍 / 👎

@gitar-bot

gitar-bot Bot commented Jun 19, 2026

Copy link
Copy Markdown
CI failed: The build failed because the 'gradle-tooling-api' dependency could not be resolved from the internal SonarSource repository.

Overview

The build failed during the dependency resolution phase of the Maven lifecycle. A single failure pattern was identified where a new dependency requirement could not be satisfied by the configured artifact repository.

Failures

Missing Dependency: gradle-tooling-api (confidence: high)

  • Type: dependency
  • Affected jobs: 82345651144
  • Related to change: yes
  • Root cause: The project attempts to pull org.gradle:gradle-tooling-api:8.14.5, which is not available in the internal SonarSource repository and not properly proxied.
  • Suggested fix: Add the official Gradle repository (https://repo.gradle.org/gradle/libs-releases) to the project's pom.xml under a <repository> block or ensure the dependency is uploaded/proxied to the sonarsource Artifactory.

Summary

  • Change-related failures: 1 (failed to resolve new project dependency).
  • Infrastructure/flaky failures: 0
  • Recommended action: Update the project's repository configuration in pom.xml to include the upstream Gradle repository to resolve the missing dependency.
Code Review ⚠️ Changes requested 1 resolved / 5 findings

Adds Gradle Java properties dump mode and documentation, but requires resolution for hardcoded developer paths in samples, unpinned Gradle build versions, and size budget violations.

⚠️ Edge Case: Dump mode triggers a real Gradle build with no version pinning

📄 src/main/java/org/sonarsource/scanner/cli/GradleJavaPropertiesDumper.java:145-154

loadIdeaProject creates a GradleConnector with only forProjectDirectory(...) and then calls connection.getModel(IdeaProject.class). Without useGradleVersion(), useDistribution(), or useBuildDistribution(), the Tooling API resolves the Gradle distribution from the target project's wrapper (or downloads the connector's default), and configuring the IDEA model executes a full Gradle configuration phase on the user's machine. Consequences: (1) network access to download a Gradle distribution may be required, which can fail in offline/CI environments; (2) the resolved Gradle version may be incompatible with tooling-api 8.14.5 (the Tooling API only supports a bounded range of Gradle versions); (3) any build-script error surfaces as a wrapped IllegalStateException. For a CLI feature this behavior should be documented and ideally the supported Gradle version range validated up front. Since this is an experimental/draft feature this is acceptable for now but should be addressed before shipping.

Pin or validate the Gradle version and document the runtime Gradle execution requirement.
// Optionally pin / validate the Gradle version to avoid surprises:
GradleConnector connector = GradleConnector.newConnector()
  .forProjectDirectory(projectRoot.toFile());
// e.g. .useGradleVersion("8.14.5") or document that the project's wrapper is used
💡 Quality: Committed generated sample leaks developer home path/username

📄 scanner-engine-sonar-project.properties:1-15

scanner-engine-sonar-project.properties is a 234-line generated artifact committed at the repository root. Every entry contains absolute, machine-specific paths from a developer's workstation (e.g. /home/sebastian.zumbrunn/code/... and /home/sebastian.zumbrunn/.gradle/caches/...), embedding a personal username and local Gradle cache layout. Generated/sample output with hardcoded local paths is not reproducible, can go stale, and unnecessarily exposes a developer's environment.

If this sample is needed for documentation, consider moving it under docs/ with sanitized/placeholder paths (e.g. /path/to/project), or omit it and reference the comparison doc instead. At minimum it should not live at the repo root.

💡 Quality: Experimental feature adds ~3MB and a new external repo to the CLI

📄 pom.xml:68 📄 pom.xml:71-79 📄 pom.xml:96-103 📄 pom.xml:258-265

Adding gradle-tooling-api pulls a sizeable dependency into the shipped distribution: the requireFilesSize enforcer rule was bumped from 9.2-9.3MB to 12.1-12.2MB, i.e. roughly +3MB on every published artifact (linux/windows/macos x64/aarch64). It also introduces a new required Maven repository (https://repo.gradle.org/gradle/libs-releases) to the build. For an experimental/draft feature, weighing this permanent size and build-dependency cost against the value is worth doing before merge — consider whether the dumper should ship in the main CLI artifact at all, or be a separate/optional module.

Re-evaluate bundling the tooling-api into the core CLI distribution.
<!-- Consider scoping the gradle-tooling-api dependency to a separate artifact
     or feature module rather than bundling ~3MB into every CLI distribution. -->
💡 Quality: Dump mode bypasses skip handling and uses only CLI properties

📄 src/main/java/org/sonarsource/scanner/cli/Main.java:80-86 📄 src/main/java/org/sonarsource/scanner/cli/Main.java:118-123

In analyze(), the cli.isDumpGradleJavaProperties() branch returns early before conf.properties() and checkSkip(p) are evaluated, and it configures logging from cli.properties() only (ignoring global/project sonar-scanner.properties and environment settings). As a result sonar.scanner.skip is not honored in dump mode, and verbose/debug logging configured via property files (rather than -D/-X) will not take effect. This may be intentional for the POC, but if dump mode is meant to behave consistently with normal runs it should resolve the full property set (or at least honor the skip flag) before generating output.

Resolve full properties and honor skip/logging in dump mode.
if (cli.isDumpGradleJavaProperties()) {
  Properties p = conf.properties();
  checkSkip(p);
  configureLogging(p);
  dumpGradleJavaProperties();
  displayExecutionResult(stats, SUCCESS);
  status = Exit.SUCCESS;
  return;
}
✅ 1 resolved
Bug: Gradle tooling-api nightly version not on Maven Central

📄 pom.xml:88-92
The new dependency pins org.gradle:gradle-tooling-api:7.3-20210825160000+0000. That timestamped version is a Gradle nightly/snapshot build that is published to the Gradle repository (e.g. https://repo.gradle.org/gradle/libs-releases), not to Maven Central. No <repositories>/<pluginRepositories> section is declared in pom.xml, so Maven will only resolve against Central (plus inherited repos), and this artifact will fail to download — breaking the build for anyone without that nightly cached locally.

Fix: depend on a released Gradle Tooling API version that is available on Maven Central (e.g. 7.3, or a newer stable release), or add the Gradle releases repository to the POM so the nightly can resolve.

🤖 Prompt for agents
Code Review: Adds Gradle Java properties dump mode and documentation, but requires resolution for hardcoded developer paths in samples, unpinned Gradle build versions, and size budget violations.

1. 💡 Quality: Committed generated sample leaks developer home path/username
   Files: scanner-engine-sonar-project.properties:1-15

   `scanner-engine-sonar-project.properties` is a 234-line generated artifact committed at the repository root. Every entry contains absolute, machine-specific paths from a developer's workstation (e.g. `/home/sebastian.zumbrunn/code/...` and `/home/sebastian.zumbrunn/.gradle/caches/...`), embedding a personal username and local Gradle cache layout. Generated/sample output with hardcoded local paths is not reproducible, can go stale, and unnecessarily exposes a developer's environment.
   
   If this sample is needed for documentation, consider moving it under `docs/` with sanitized/placeholder paths (e.g. `/path/to/project`), or omit it and reference the comparison doc instead. At minimum it should not live at the repo root.

2. ⚠️ Edge Case: Dump mode triggers a real Gradle build with no version pinning
   Files: src/main/java/org/sonarsource/scanner/cli/GradleJavaPropertiesDumper.java:145-154

   `loadIdeaProject` creates a `GradleConnector` with only `forProjectDirectory(...)` and then calls `connection.getModel(IdeaProject.class)`. Without `useGradleVersion()`, `useDistribution()`, or `useBuildDistribution()`, the Tooling API resolves the Gradle distribution from the target project's wrapper (or downloads the connector's default), and configuring the IDEA model executes a full Gradle configuration phase on the user's machine. Consequences: (1) network access to download a Gradle distribution may be required, which can fail in offline/CI environments; (2) the resolved Gradle version may be incompatible with tooling-api 8.14.5 (the Tooling API only supports a bounded range of Gradle versions); (3) any build-script error surfaces as a wrapped `IllegalStateException`. For a CLI feature this behavior should be documented and ideally the supported Gradle version range validated up front. Since this is an experimental/draft feature this is acceptable for now but should be addressed before shipping.

   Fix (Pin or validate the Gradle version and document the runtime Gradle execution requirement.):
   // Optionally pin / validate the Gradle version to avoid surprises:
   GradleConnector connector = GradleConnector.newConnector()
     .forProjectDirectory(projectRoot.toFile());
   // e.g. .useGradleVersion("8.14.5") or document that the project's wrapper is used

3. 💡 Quality: Experimental feature adds ~3MB and a new external repo to the CLI
   Files: pom.xml:68, pom.xml:71-79, pom.xml:96-103, pom.xml:258-265

   Adding `gradle-tooling-api` pulls a sizeable dependency into the shipped distribution: the `requireFilesSize` enforcer rule was bumped from 9.2-9.3MB to 12.1-12.2MB, i.e. roughly +3MB on every published artifact (linux/windows/macos x64/aarch64). It also introduces a new required Maven repository (`https://repo.gradle.org/gradle/libs-releases`) to the build. For an experimental/draft feature, weighing this permanent size and build-dependency cost against the value is worth doing before merge — consider whether the dumper should ship in the main CLI artifact at all, or be a separate/optional module.

   Fix (Re-evaluate bundling the tooling-api into the core CLI distribution.):
   <!-- Consider scoping the gradle-tooling-api dependency to a separate artifact
        or feature module rather than bundling ~3MB into every CLI distribution. -->

4. 💡 Quality: Dump mode bypasses skip handling and uses only CLI properties
   Files: src/main/java/org/sonarsource/scanner/cli/Main.java:80-86, src/main/java/org/sonarsource/scanner/cli/Main.java:118-123

   In `analyze()`, the `cli.isDumpGradleJavaProperties()` branch returns early before `conf.properties()` and `checkSkip(p)` are evaluated, and it configures logging from `cli.properties()` only (ignoring global/project `sonar-scanner.properties` and environment settings). As a result `sonar.scanner.skip` is not honored in dump mode, and verbose/debug logging configured via property files (rather than `-D`/`-X`) will not take effect. This may be intentional for the POC, but if dump mode is meant to behave consistently with normal runs it should resolve the full property set (or at least honor the skip flag) before generating output.

   Fix (Resolve full properties and honor skip/logging in dump mode.):
   if (cli.isDumpGradleJavaProperties()) {
     Properties p = conf.properties();
     checkSkip(p);
     configureLogging(p);
     dumpGradleJavaProperties();
     displayExecutionResult(stats, SUCCESS);
     status = Exit.SUCCESS;
     return;
   }

Tip

Comment Gitar fix CI or enable auto-apply: gitar auto-apply:on

Options

Auto-apply is off → Gitar will not commit updates to this branch.
Display: compact → Showing less information.
Unblock → Override a blocking verdict and allow merging.

Comment with these commands to change:

Auto-apply Compact Unblock
gitar auto-apply:on         
gitar display:verbose         
gitar unblock         

Was this helpful? React with 👍 / 👎 | Gitar

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant