Chapter 07Lesson 01~120 minutes

Scanner Ecosystem: CLI, Maven, Gradle, .NET, and Build Integration: Core Concepts and Mental Model

Understand why scanner choice follows the repository build model, and trace build context, runtime, indexing, report upload, and server computation without treating every scanner as interchangeable.

Scanner choiceBuild contextJREBytecodeEvidence

Learning objectives

  • Explain why CLI, Maven, Gradle, and .NET scanners have different invocation contracts.
  • Trace source/build evidence through the matching scanner to the same server-side Compute Engine model.
  • Separate build-tool runtime, scanner runtime/JRE, compiled outputs, coverage/test reports, scanner cache, and server state.
  • Recognize when a build-integrated scanner is safer than forcing a standalone CLI invocation.
  • Record scanner/server compatibility and release provenance before analysis.

1. Current baseline and scope

Chapter 06 proved the generic analysis chain. Chapter 07 keeps that chain but changes the client-side owner. A Python or build-neutral repository can use Scanner CLI. A Maven project should normally use SonarScanner for Maven; Gradle has its plugin/task; MSBuild and dotnet projects use the .NET scanner's begin/build/end lifecycle. The server still receives an analysis report and creates a Compute Engine task.

Boundary: do not force a repository through a scanner merely because that scanner is already installed. Scanner choice is part of build reproducibility. A mismatched scanner can omit compiled context, alter base-directory semantics, bypass lifecycle integration, duplicate analysis, or produce misleading coverage/test evidence.

2. Mental model: build ecosystem determines scanner entry point

Native build context to governed result

The client-side path differs by ecosystem; the server-side report-processing path converges.

flowchart TD
R[Repository + revision] --> B{Build ecosystem}
B -->|build-neutral| C[Scanner CLI]
B -->|Maven| M[Maven lifecycle + sonar plugin]
B -->|Gradle| G[Gradle tasks + sonar plugin]
B -->|MSBuild / dotnet| N[begin → build → end]
M --> X[Compiled/test/coverage context]
G --> X
N --> X
C --> A[Indexed files + analysis report]
X --> A
A --> U[Upload]
U --> CE[Compute Engine]
CE --> Q[Issues + measures + Quality Gate]

Scanner CLI starts from a filesystem/project configuration model. Maven and Gradle can derive properties from their build models and can coordinate Java bytecode and report locations. The .NET scanner modifies/observes the build between begin and end; running only an end command after an unrelated build is not equivalent.

3. State stores that move independently

State Owner Examples Evidence
Build model Maven/Gradle/MSBuild/dotnet modules, source sets, target frameworks mvn -version, Gradle tasks, dotnet --info
Scanner/plugin Scanner distribution or build plugin CLI 8.1.0.6389, Maven 5.7.0.6970, Gradle 7.3.1.8318, .NET 11.2.1.137242 scanner/plugin version output or dependency metadata
Scanner JRE/runtime scanner host / auto-provisioner system Java vs downloaded JRE scanner logs and runtime evidence
Compiled context build output target/classes, Gradle classes, .NET assemblies artifact tree + build logs
Test/coverage reports test/coverage tools JaCoCo XML, TRX, coverage XML report paths and timestamps
Cache scanner user home ~/.sonar or configured SONAR_USER_HOME cache path/ownership, not cache contents as project truth
Analysis report/task scanner + server .scannerwork, report-task.txt, CE task task ID/status
Governed result SonarQube project policy issues/measures/gate UI/API after CE success

4. Scanner selection rule

Repository Preferred scanner Why Wrong shortcut
Plain/build-neutral sources Scanner CLI Explicit filesystem/indexing model Using a build plugin when there is no matching build
Maven SonarScanner for Maven Reads Maven reactor/build metadata Generic CLI used without compiled/module context
Gradle SonarScanner for Gradle Understands Gradle project/source-set model Standalone scan from arbitrary subdirectory
.NET / MSBuild SonarScanner for .NET Analysis is integrated with the build lifecycle CLI used as if C# build context were optional

5. Runtime model: build JVM is not always scanner JVM

Current scanner generations support JRE auto-provisioning. That means the Java used by Maven or Gradle to run the build is not automatically proof of the Java runtime used by the scanner engine. Current Maven scanner documentation requires Maven 3.2.5+ and Java 21 when provisioning is not used, while Java 11+ can bootstrap current auto-provisioning. Current Gradle documentation similarly distinguishes normal Java requirements from the lower bootstrap requirement with auto-provisioning.

The .NET scanner no longer requires you to preinstall Java in the normal modern path because it provisions the scanner Java runtime. If provisioning is deliberately disabled or network policy prevents it, record the exact fallback runtime rather than copying an old “Java 17” tutorial.

6. Compiled context is part of the analysis input

Java analysis requires compiled bytecode. Maven and Gradle are good examples of why scanner choice belongs next to the build: mvn clean verify …:sonar or an appropriate Gradle build followed by sonar gives the scanner the compilation context produced by the same build. If you delete target/classes or point sonar.java.binaries at an empty/wrong directory, static analysis cannot infer the same semantic information from source text alone.

Key principle: source files, binaries, tests, coverage XML, generated code, and scanner parameters are separate inputs. “The repository contains it” does not mean “the scanner indexed or consumed it.”

7. Scanner cache is reusable dependency state, not analysis truth

Scanners use a user-home cache, normally under ~/.sonar; SONAR_USER_HOME can relocate it. CI systems commonly cache this directory to avoid repeated analyzer/JRE downloads. Cache reuse improves speed but must not be treated as project evidence. Record scanner versions and effective inputs separately, and diagnose cache permission/corruption problems without deleting first-failure evidence blindly.

8. Read-only inventory before choosing a scanner

git status --short
git rev-parse HEAD
sonar-scanner --version || true
mvn -version || true
gradle --version || true
dotnet --info || true
find . -maxdepth 2 -type f   \( -name pom.xml -o -name build.gradle -o -name build.gradle.kts      -o -name '*.sln' -o -name '*.csproj' -o -name sonar-project.properties \) -print

Do not install a scanner until you know which build descriptor exists, which build tool owns compilation, and whether previous test/coverage reports are expected.

9. DevOps connection: pin the client path like any other build dependency

Scanner drift can change runtime requirements, indexing behavior, dependency resolution, telemetry, or compatibility even when the server is unchanged. A reviewable pipeline therefore records the project revision, build tool/version, scanner/plugin version, runtime/provisioning mode, report paths, task ID, and server release. A centrally “latest” scanner with no provenance is operationally weaker than a controlled update process.

Knowledge check

Why is Scanner CLI not automatically the best choice for every repository?

Does the Java used to launch Maven always equal the scanner-engine Java?

What is special about .NET analysis?

Why preserve compiled bytecode for Java analysis?

What does the scanner cache prove?

Next lesson

Compare two scanner styles on controlled fixtures

Lesson 2 runs a build-neutral CLI analysis and a Maven-integrated Java analysis, then compares evidence, runtime, indexing, and lifecycle boundaries.

Official references and version notes

Version and compatibility note

Rechecked on 2026-09-07. The chapter targets local/private Community Build 26.9.0.129388. Current release baselines used for reproducible examples are Scanner CLI 8.1.0.6389, SonarScanner for Maven 5.7.0.6970, SonarScanner for Gradle 7.3.1.8318, and SonarScanner for .NET 11.2.1.137242. Mandatory execution uses CLI plus Maven; Gradle and .NET are optional executable extensions when their build prerequisites are installed. JRE auto-provisioning is kept enabled unless a lesson explicitly demonstrates the system-Java boundary. Re-check current scanner/server compatibility before future runs because scanner release trains move independently.

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this address.