Chapter 07Lesson 02~150 minutes

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.

CLI labMaven labJRETask evidenceComparison

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
Credential rule: create two disposable project-analysis tokens, one for 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

  1. Revoke both project-analysis tokens.
  2. Unset SONAR_TOKEN and SONAR_HOST_URL if the shell is shared.
  3. Preserve sanitized logs/task files before deleting local fixtures.
  4. Delete only the disposable SonarQube projects if later lessons will not reuse them.
  5. Do not delete global scanner caches as routine project cleanup.

Knowledge check

What is the main extra state Maven contributes in the Java fixture?

Why use separate project keys for CLI and Maven fixtures?

Can Gradle analysis be accurately demonstrated by substituting Scanner CLI?

Where should the token value be kept during these labs?

What evidence converges for both scanner styles?

Next lesson

Turn scanner choice into a design decision

Lesson 3 compares CLI versus build-integrated scanners, local versus CI execution, runtime provisioning, and centralized versus repository-pinned versions.

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.