Scanner Ecosystem: CLI, Maven, Gradle, .NET, and Build Integration: Guided Hands-On Workflow
Run one build-neutral CLI analysis and one Maven-integrated analysis against local Community Build, then compare what each scanner learns from its environment.
Learning objectives
- Create two tiny synthetic repositories with separate stable project keys.
- Run Scanner CLI against a Python fixture and SonarScanner for Maven against a Java fixture.
- Capture build/scanner/runtime/indexing/report/Compute Engine evidence for each path.
- Compare where parameters and compiled context come from.
- Revoke project-scoped credentials and preserve sanitized artifacts.
1. Disposable-lab preflight
Use the local/private Community Build server created earlier. The mandatory lab requires Git, curl, Scanner CLI 8.1.0.6389, JDK 21, and Maven 3.9.16. Maven scanner version 5.7.0.6970 is pinned explicitly in the invocation.
git --version
curl --version
sonar-scanner --version
java -version
mvn -version
curl --fail --silent http://127.0.0.1:9000/api/server/version
academy-sonarqube-p07-cli and one for
academy-sonarqube-p07-maven. Store raw values only in
process environment for the active run. Never place them in
repository files or evidence archives.
2. Fixture A: build-neutral Python + Scanner CLI
mkdir sonar-p07-cli && cd sonar-p07-cli
git init
mkdir src
cat > src/app.py <<'PY'
def classify(value):
if value < 0:
return "negative"
return "non-negative"
PY
cat > sonar-project.properties <<'EOF'
sonar.projectKey=academy-sonarqube-p07-cli
sonar.projectName=Academy SonarQube P07 CLI
sonar.sources=src
sonar.sourceEncoding=UTF-8
EOF
git add . && git commit -m "scanner cli fixture"
git rev-parse HEAD
The scanner has no build system to interrogate. Project-local properties and the filesystem define the intended scope.
3. Run and capture the CLI path
export SONAR_HOST_URL='http://127.0.0.1:9000'
read -rsp 'CLI project token: ' SONAR_TOKEN; echo
export SONAR_TOKEN
sonar-scanner -Dsonar.host.url="$SONAR_HOST_URL" | tee scanner-cli.log
cp .scannerwork/report-task.txt report-task-cli.txt
cat report-task-cli.txt
Record the scanner version/runtime, exact revision, indexed-file
evidence, effective base directory, report-task.txt, CE
task status, and final project gate. Do not assume a fixed issue
count; analyzer/rule-profile changes can legitimately alter results.
4. Fixture B: Java + Maven reactor context
Create a second repository rather than reusing the CLI project key. This keeps evidence and token scope unambiguous.
cd ..
mkdir sonar-p07-maven && cd sonar-p07-maven
git init
mkdir -p src/main/java/academy
cat > pom.xml <<'XML'
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>academy</groupId>
<artifactId>sonar-p07-maven</artifactId>
<version>1.0.0</version>
<properties>
<maven.compiler.release>21</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<sonar.projectKey>academy-sonarqube-p07-maven</sonar.projectKey>
<sonar.projectName>Academy SonarQube P07 Maven</sonar.projectName>
</properties>
</project>
XML
cat > src/main/java/academy/App.java <<'JAVA'
package academy;
public final class App {
public static int square(int n) { return n * n; }
private App() {}
}
JAVA
git add . && git commit -m "maven scanner fixture"
git rev-parse HEAD
5. Build and analyze through Maven
mvn -version
mvn -B clean verify
find target -maxdepth 3 -type f | sort | head -50
read -rsp 'Maven project token: ' SONAR_TOKEN; echo
export SONAR_TOKEN
mvn -B org.sonarsource.scanner.maven:sonar-maven-plugin:5.7.0.6970:sonar -Dsonar.host.url="$SONAR_HOST_URL" | tee scanner-maven.log
find target -name report-task.txt -o -path '*/sonar/*' | sort
Running clean verify first makes compilation evidence
explicit. In many pipelines the build and scan can be composed in
one Maven invocation, but teaching them as observable stages makes
the bytecode boundary easier to verify.
6. Compare the two evidence chains
| Question | CLI fixture | Maven fixture |
|---|---|---|
| Project identity | sonar-project.properties |
Maven properties / scanner parameters |
| Compilation | Not required for Python fixture | Maven produces target/classes |
| Scanner version | CLI 8.1.0.6389 | Maven plugin 5.7.0.6970 |
| Runtime evidence | CLI launcher + provisioned/system Java | Maven Java + scanner-provisioned/system Java |
| Working metadata | normally .scannerwork |
scanner metadata associated with Maven project build |
| Server evidence | report/task → CE → gate | report/task → CE → gate |
7. Optional extension: inventory Gradle and .NET without pretending they are CLI
gradle --version || true
dotnet --info || true
If installed, read the current Gradle plugin and .NET scanner documentation and sketch the native invocation. Do not run a fake “equivalent” CLI command. Gradle requires its plugin/task model and Java bytecode for Java projects. .NET requires the begin → build → end sequence.
8. Challenge: choose the scanner, not the familiar command
A repository contains pom.xml, several Java modules,
JaCoCo XML, and a working mvn verify. A teammate
proposes sonar-scanner -Dsonar.sources=. because CLI is
already cached in CI. Choose the safer scanner path, list the
evidence you expect Maven to supply, and identify what the CLI
shortcut could omit or mis-scope.
9. Cleanup
- Revoke both project-analysis tokens.
-
Unset
SONAR_TOKENandSONAR_HOST_URLif the shell is shared. - Preserve sanitized logs/task files before deleting local fixtures.
- Delete only the disposable SonarQube projects if later lessons will not reuse them.
- Do not delete global scanner caches as routine project cleanup.
Knowledge check
What is the main extra state Maven contributes in the Java fixture?
Native build/module metadata and compiled bytecode produced by the Maven lifecycle.
Why use separate project keys for CLI and Maven fixtures?
So each scanner path, token scope, analysis history, and task evidence remain independently attributable.
Can Gradle analysis be accurately demonstrated by substituting Scanner CLI?
No. That would erase the Gradle plugin/source-set/build-context boundary the lesson is teaching.
Where should the token value be kept during these labs?
In process environment only for the active run, then revoked/unset; never in repository or evidence files.
What evidence converges for both scanner styles?
Both ultimately produce a report/task ID that the server processes into project measures/issues/gate state.
Official references and version notes
- SonarScanner CLI — build-neutral scanner usage, cache behavior, project base directory, and Docker notes.
- SonarScanner CLI 8.1.0.6389 — official release provenance.
- SonarScanner for Maven and release 5.7.0.6970.
- SonarScanner for Gradle and release 7.3.1.8318.
- SonarScanner for .NET usage and release 11.2.1.137242.
- Scanner environment general requirements and JRE auto-provisioning.
- Official scanner examples — recommended scanner choice by build ecosystem.
- Apache Maven downloads — Maven 3.9.16 is the current stable Maven baseline used in the Maven lab.
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.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this
address.