Chapter 01Lesson 02~130 minutes

Static Analysis, Clean Code, Technical Debt, and Quality Governance: Guided Hands-On Workflow

Run one small, reproducible Community Build analysis against synthetic code and prove the chain from Git revision and scanner inputs through report processing, findings, measures, New Code context, and quality-gate outcome.

Community BuildSonarScannerEvidence chainSynthetic repositoryBaseline

Learning objectives

  • Create a loopback-only SonarQube Community Build lab with pinned, recorded versions.
  • Analyze a synthetic Git revision without putting a token in project files or the scanner command line.
  • Preserve scanner logs and report-task evidence before interpreting the UI result.
  • Compare expected versus observed findings without depending on an exact issue count.
  • Remediate one finding and explain which source, task, project, and governance states changed.

1. Lab baseline and prerequisites

This workflow deliberately uses the smallest free path needed to make Chapter 01’s governance model observable. The server is SonarQube Community Build 26.9.0.129388 using the official Docker tag sonarqube:26.9.0.129388-community. The standalone SonarScanner CLI baseline recorded for this lesson is 8.1.0.6389 from SonarSource update-center metadata. Recheck scanner/JRE prerequisites when executing because launcher and Java requirements evolve independently of the server release.

You need Docker, Git, a current supported SonarScanner CLI installation, a text editor, and enough local resources for Community Build. The server binds to 127.0.0.1:9000; do not expose the lab to a public interface.

Preflight: confirm port 9000 is free, Docker is pointed at your local engine, the target directory is disposable, and no real SonarQube token exists in shell history or project files. Stop if the Docker command would operate on a shared/production host.

2. Create a synthetic repository and anchor the revision

The source is deliberately tiny. We care about reproducibility and evidence, not about manufacturing a specific issue count.

mkdir sq-ch01-quality-lab
cd sq-ch01-quality-lab
git init
mkdir src evidence

Create src/pricing.js:

export function checkoutTotal(items, coupon) {
  const debugPassword = "password-FAKE_DO_NOT_USE";
  let total = 0;

  for (const item of items) {
    if (item.price < 0) return -1;
    if (item.price < 0) return -2;
    total += item.price * item.quantity;
  }

  if (coupon === "SAVE10") total = total * 0.9;
  if (coupon === "SAVE10") console.log("coupon applied");
  console.log(debugPassword);
  return total;
}

The duplicate condition and fake secret-like value are teaching fixtures. Analyzer behavior is version/profile/mode dependent; do not assert that a particular number or category of issues must appear. The fake value is not a credential.

git add src/pricing.js
git commit -m "ch01: add synthetic pricing sample"
git rev-parse HEAD > evidence/source-revision.txt
git status --short

Expected state: the worktree is clean and source-revision.txt identifies the exact source commit. The evidence file itself is intentionally not part of the source commit yet.

3. Start a pinned loopback-only Community Build server

docker pull sonarqube:26.9.0.129388-community
docker image inspect sonarqube:26.9.0.129388-community \
  --format '{{.Id}}' > evidence/server-image-id.txt

docker run -d \
  --name sq-ch01-server \
  -p 127.0.0.1:9000:9000 \
  sonarqube:26.9.0.129388-community

On Windows PowerShell, put the command on one line or use PowerShell’s backtick continuation instead of the Bash backslash. Follow the container logs until the service reports readiness:

docker logs -f sq-ch01-server

Do not delete or truncate logs if startup fails. The container image identity, server logs, and exact tag are part of first-failure evidence.

4. Create one local project and a project-scoped analysis token

Open http://127.0.0.1:9000, complete the documented first-start authentication/password-change flow, and create a local project with project key:

devops-academy-sonarqube-ch01

Create an analysis token with the narrowest scope available for that project. Copy it once into the current shell environment. Do not put it in sonar-project.properties, Git, screenshots, or the evidence folder.

# Linux/macOS - paste interactively without echo if your shell supports it
read -s SONAR_TOKEN
export SONAR_TOKEN
export SONAR_HOST_URL="http://127.0.0.1:9000"

# Windows PowerShell equivalent:
# $env:SONAR_TOKEN = Read-Host "Project analysis token"
# $env:SONAR_HOST_URL = "http://127.0.0.1:9000"
Trust boundary: the token proves scanner authorization. The Git revision proves source identity. They solve different problems; never use “the scan authenticated” as evidence that the intended commit was analyzed.

5. Declare stable project analysis inputs

Create sonar-project.properties:

sonar.projectKey=devops-academy-sonarqube-ch01
sonar.projectName=DevOps Academy SonarQube Chapter 01 Lab
sonar.sources=src
sonar.sourceEncoding=UTF-8

Keep this file non-secret. The scanner can obtain SONAR_HOST_URL and SONAR_TOKEN from the environment. Later chapters study parameter precedence in depth. For this lab, the governance rule is simpler: project identity and source scope belong in versioned configuration; credentials do not.

sonar-scanner -v | tee evidence/scanner-version.txt
git add sonar-project.properties
git commit -m "ch01: add reproducible analysis configuration"
git rev-parse HEAD | tee evidence/analysis-revision.txt

The analysis revision differs from the first source-only revision because the configuration is now committed. Record the revision you actually scan.

6. Predict the evidence chain before execution

Layer Prediction How to verify
Source The current Git revision contains src/pricing.js and project configuration. git rev-parse HEAD, git status --short
Scanner Only files under the configured source scope should be indexed as source input. scanner log/index summary
Report A local scanner report is created and uploaded. scanner log and .scannerwork/report-task.txt
Server task The uploaded report receives an asynchronous task identity and terminal status. background task/UI using recorded task ID
Project The project displays findings/measures for the completed analysis. project result and analysis history
Policy The active profile/New Code/gate determine interpretation. record effective profile, New Code definition, gate/status

7. Run the baseline scan and preserve first-pass evidence

sonar-scanner 2>&1 | tee evidence/scanner-baseline.log
cp .scannerwork/report-task.txt evidence/report-task-baseline.txt

If the command fails, stop here and preserve the log; do not rerun until you understand whether the failure is local runtime, authentication/network, indexing/configuration, report upload, or server processing. If the command uploads successfully, report-task.txt gives you the server-side task/result linkage. Do not publish that file blindly because environments can encode server URLs or identifiers you may consider internal.

Wait for the corresponding background task to reach a terminal state. Only then inspect issues, measures, New Code context, and the quality-gate result. Scanner process completion and server analysis completion are different events.

8. Interpret findings without gaming them

Record what the current analyzer actually reports. For each finding you choose to discuss, capture the rule key/name, affected line, classification/impact, status, and why the rule exists. Then decide whether the code should change, the finding requires contextual review, or the rule/policy deserves a separate governance discussion.

Do not lower a gate, deactivate a rule, mark a finding false-positive, or change mode merely to make this training project green. Those actions mutate policy and can hide the very evidence the lab is meant to teach.

Baseline evidence packet

server image ID · scanner version · exact Git revision · non-secret project properties · scanner log · report-task file · background-task status · active profile/mode · New Code definition · issue/measure snapshot · gate/status · interpretation note.

9. Remediate one source problem and compare states

Choose one clear maintainability/reliability problem the current analysis identified—or, if the analyzer did not flag the duplicated condition, fix it anyway as a code-review defect. For example, remove the duplicated impossible branch and avoid logging the fake password-like value. Commit the code change:

git add src/pricing.js
git commit -m "ch01: remove duplicated branch and debug value"
git rev-parse HEAD | tee evidence/remediated-revision.txt
sonar-scanner 2>&1 | tee evidence/scanner-remediated.log
cp .scannerwork/report-task.txt evidence/report-task-remediated.txt

After server processing completes, compare the two analyses. The source revision changed; a new report/task exists; project measures/findings may change; the policy objects normally stay the same. This is the core causal pattern behind a trustworthy quality program.

10. Challenge: identify the owning layer

For each symptom, name the first layer you would inspect and the evidence you need:

  1. The scanner cannot connect to 127.0.0.1:9000.
  2. The scanner uploads, but the project UI still shows an older analysis.
  3. The UI shows the expected analysis, but the gate is red.
  4. A teammate sees a different issue classification after changing product mode.
  5. The Git commit in the evidence packet does not match the CI checkout.

Do not answer with “rerun the scan.” The point is to isolate source, scanner/network, server task, policy, mode, or CI ownership before changing anything.

11. Preserve evidence, then clean up safely

docker logs sq-ch01-server > evidence/server-final.log 2>&1
unset SONAR_TOKEN SONAR_HOST_URL
# PowerShell: Remove-Item Env:SONAR_TOKEN, Env:SONAR_HOST_URL

docker stop sq-ch01-server
docker rm sq-ch01-server

Delete the local project through the UI only if you created it for this lab and have verified the exact project key. Do not issue broad deletion commands. The container in this minimal lab has no persistent production data; later deployment chapters introduce durable storage deliberately.

Knowledge check

Why record the Git revision again after committing sonar-project.properties?

Why is report-task.txt important after a successful upload?

Why should SONAR_TOKEN stay out of sonar-project.properties?

The first scan reports zero issues. What may you conclude?

A gate is red after the analysis completed successfully. Is that a scanner failure?

Next lesson

Choose policy deliberately instead of accumulating settings

Lesson 3 compares Clean-as-You-Code with all-code enforcement, advisory and enforced gates, default and customized standards, and risk-focused interpretation versus raw counting.

Official references and version notes

Version and compatibility note

Version-sensitive statements were rechecked against current SonarSource primary documentation on 2026-09-07. The executable local path in this chapter pins SonarQube Community Build 26.9.0.129388 with official image sonarqube:26.9.0.129388-community. Where a standalone SonarScanner CLI is used, the lab records 8.1.0.6389 from SonarSource update-center metadata. Current scanner Java/JRE auto-provisioning behavior and exact bootstrap requirements must be rechecked at execution time. Commercial SonarQube Server/Data Center and SonarQube Cloud features are not required for this chapter.

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.