Checkpoint Lab — Monorepos, Multi-Module Builds, Generated Code, and Complex Repository Layouts
Prove a two-module analysis topology with exact project/file/report ownership, one deliberate path defect, independent task evidence, a Community Build aggregation fallback, and explicit Developer/Enterprise boundaries.
Learning objectives — Checkpoint objectives
- Design and prove a two-module analysis topology with exact project, file, report, credential and task ownership.
- Record and verify predictions before changing analysis topology or report coordinates.
- Preserve one deliberate report-path failure and repair only that path at the same Git revision.
- Produce a Community Build governance summary without pretending it is an Application/Portfolio.
- State the Developer/Enterprise alternatives and what additional problem each solves.
- Package revision, scope, scanner, report, task, measure, gate, concurrency and cleanup evidence for independent review.
1. Checkpoint scenario
You own one synthetic Git repository with an API module and a worker module. The teams release independently, so the governed target topology is two SonarQube projects. You must prove that each project analyzes only its own files, imports only its own report, uses its own scanner workspace/token, and retains an independent asynchronous task chain.
You will also run one intentionally wrong worker coverage path, preserve the failure, correct it without changing the Git SHA, and finish with a timestamped Community Build governance summary plus an edition-aware aggregation plan.
2. Exact assumptions and preflight
| Assumption | Checkpoint requirement |
|---|---|
| Server | Community Build 26.9.0.129388; local disposable instance |
| Scanner | SonarScanner CLI 8.1.0.6389 |
| Runtime | Scanner-reported runtime/JRE; current scanners can auto-provision JRE where supported |
| Build/test | Python 3.11+, pytest, pytest-cov; versions recorded |
| Projects |
sq-ch24-api, sq-ch24-worker plus
optional comparison sq-ch24-all
|
| Credentials | Project-analysis token per project; values never enter repository/evidence |
| Commercial capability | Native monorepo onboarding/Portfolio simulated only; optional Application/Enterprise discussion is clearly labeled |
git rev-parse --show-toplevel | tee evidence/repo-root.txt
git rev-parse HEAD | tee evidence/checkpoint-revision.txt
git status --short | tee evidence/git-status.txt
sonar-scanner --version | tee evidence/scanner-version.txt
python --version | tee evidence/python-version.txt
curl -fsS "$SONAR_HOST_URL/api/system/status" | tee evidence/server-status.json
3. Write the ownership manifest before scanning
repository: sq-ch24-layout-lab
revision: "<exact git sha>"
projects:
- key: sq-ch24-api
owner: team-api
base_dir: modules/api
sources: [src]
tests: [tests]
coverage: coverage.xml
scanner_workdir: .scannerwork-ch24-api
token_owner: project-analysis-token-api
- key: sq-ch24-worker
owner: team-worker
base_dir: modules/worker
sources: [src]
tests: [tests]
coverage: coverage.xml
scanner_workdir: .scannerwork-ch24-worker
token_owner: project-analysis-token-worker
generated:
generated/: excluded-from-owned-project-scopes
vendor:
vendor/: external/dependency ownership, not first-party module source
parallelism:
distinct_projects: permitted with isolated work/report artifacts
same_project_branch: serialize/supersede deterministically
4. Required predictions before execution
-
Prediction A — indexing: API analysis will index
modules/api/srconly; worker analysis will indexmodules/worker/srconly. Generated/vendor files will not enter either project because they are outside both initial scopes. -
Prediction B — path defect: with worker
projectBaseDir=modules/worker, settingsonar.python.coverage.reportPaths=modules/worker/coverage.xmlwill fail to import the intended coverage report even though source indexing still succeeds. -
Prediction C — repair: changing only that value
to
coverage.xmlat the same Git SHA will restore report-import evidence. - Prediction D — governance: Community Build will keep API and worker as independent project histories; any cross-project aggregate produced in this checkpoint is an external summary, not a native Application/Portfolio object.
Write these predictions into
evidence/predictions.md before running the broken scan.
5. Produce reports and prove their internal paths
(
cd modules/api
../../.venv/bin/python -m pytest tests --cov=src --cov-report=xml:coverage.xml
)
(
cd modules/worker
../../.venv/bin/python -m pytest tests --cov=src --cov-report=xml:coverage.xml
)
sha256sum modules/api/coverage.xml modules/worker/coverage.xml \
| tee evidence/report-sha256.txt
grep -n 'filename=' modules/api/coverage.xml | head -20 \
| tee evidence/api-report-files.txt
grep -n 'filename=' modules/worker/coverage.xml | head -20 \
| tee evidence/worker-report-files.txt
6. Analyze API with its owned coordinate system
SONAR_TOKEN="$SONAR_TOKEN_API" sonar-scanner -X \
-Dsonar.projectKey=sq-ch24-api \
-Dsonar.projectBaseDir=modules/api \
-Dsonar.sources=src \
-Dsonar.tests=tests \
-Dsonar.python.coverage.reportPaths=coverage.xml \
-Dsonar.working.directory=.scannerwork-ch24-api \
2>&1 | tee evidence/api-scanner.log
cp modules/api/.scannerwork-ch24-api/report-task.txt evidence/api-report-task.txt
API_TASK="$(sed -n 's/^ceTaskId=//p' evidence/api-report-task.txt)"
echo "$API_TASK" | tee evidence/api-ceTaskId.txt
Wait for Compute Engine terminal success, then capture
ncloc, coverage, Quality Gate and issue counts. Also
preserve the scanner lines proving which files were
indexed/imported.
7. Run and preserve the deliberate worker defect
git rev-parse HEAD | tee evidence/worker-broken-revision.txt
SONAR_TOKEN="$SONAR_TOKEN_WORKER" sonar-scanner -X \
-Dsonar.projectKey=sq-ch24-worker \
-Dsonar.projectBaseDir=modules/worker \
-Dsonar.sources=src \
-Dsonar.tests=tests \
-Dsonar.python.coverage.reportPaths=modules/worker/coverage.xml \
-Dsonar.working.directory=.scannerwork-ch24-worker-broken \
2>&1 | tee evidence/worker-broken-scanner.log
cp modules/worker/.scannerwork-ch24-worker-broken/report-task.txt \
evidence/worker-broken-report-task.txt
grep -Ei 'coverage|report.*not|no report|cannot' \
evidence/worker-broken-scanner.log \
| tee evidence/worker-broken-import-evidence.txt || true
Do not delete or overwrite this log. Capture the broken
ceTaskId and terminal task state too. A successful CE
task does not invalidate the report-import warning.
8. Repair only the path and prove the same SHA
SONAR_TOKEN="$SONAR_TOKEN_WORKER" sonar-scanner -X \
-Dsonar.projectKey=sq-ch24-worker \
-Dsonar.projectBaseDir=modules/worker \
-Dsonar.sources=src \
-Dsonar.tests=tests \
-Dsonar.python.coverage.reportPaths=coverage.xml \
-Dsonar.working.directory=.scannerwork-ch24-worker-fixed \
2>&1 | tee evidence/worker-fixed-scanner.log
cp modules/worker/.scannerwork-ch24-worker-fixed/report-task.txt \
evidence/worker-fixed-report-task.txt
git rev-parse HEAD | tee evidence/worker-fixed-revision.txt
cmp evidence/worker-broken-revision.txt evidence/worker-fixed-revision.txt
WORKER_TASK="$(sed -n 's/^ceTaskId=//p' evidence/worker-fixed-report-task.txt)"
echo "$WORKER_TASK" | tee evidence/worker-fixed-ceTaskId.txt
After terminal CE success, capture worker measures and compare scanner import evidence. The conclusion must say “report-path repair changed imported analysis evidence at the same revision,” not “coverage improved because code was fixed.”
9. Community Build aggregation fallback
Generate a timestamped Markdown summary from project-level APIs. Keep every row linked to its project and task/revision evidence. This is a governance report you own; it is not a SonarQube Application or Portfolio.
# summarize.py (conceptual excerpt)
projects = ["sq-ch24-api", "sq-ch24-worker"]
metrics = "ncloc,coverage,reliability_rating,security_rating,sqale_rating"
# GET /api/measures/component for each exact project key.
# Also query/record each project's Quality Gate status and latest analysis timestamp.
# Emit one row per project; never add percentages together naively.
| Project | Revision/task evidence | Coverage | Gate | Owner |
|---|---|---|---|---|
| sq-ch24-api | exact SHA + API ceTaskId |
project measure | project gate | team-api |
| sq-ch24-worker | same SHA + fixed worker ceTaskId |
project measure | project gate | team-worker |
10. Edition-aware aggregation plan
- Community Build: retain two independently governed projects and the external timestamped summary.
- Developer Edition+: if API and worker truly share a release lifecycle, consider an Application; otherwise keep them independent.
- Enterprise Edition: native monorepo onboarding/binding can associate multiple SonarQube projects with the same DevOps repository; Portfolios can provide broader governance views.
- Regardless of edition: preserve per-project scope/report/task evidence. Aggregation does not repair ownership.
11. Required evidence packet
-
topology.yamlandpredictions.md. - Repository root, exact Git SHA and clean/known working-tree state.
- Server, scanner, Python, pytest and coverage-tool versions.
- Module report SHA-256 values and internal filename excerpts.
- Sanitized effective scanner parameters for API, broken worker and fixed worker.
- Indexed-file/report-import log excerpts for each run.
-
Every
report-task.txt,ceTaskId, terminal CE JSON and project measure/gate output. - Project token ownership/type/creation/revocation record without token values.
- Generated/vendor exclusion rationale.
- Community aggregation summary with timestamp and caveat that it is external.
- Developer/Enterprise aggregation assumptions and limitations.
12. Verification checklist
- ☐ API and worker use distinct project keys, project tokens and working directories.
- ☐ Both successful module scans refer to the same intended Git SHA.
- ☐ API indexing evidence contains no worker source and worker indexing evidence contains no API source.
- ☐ Generated/vendor files remain outside the chosen project scopes for a documented reason.
- ☐ Broken worker scan preserves the wrong report path and first warning/task evidence.
- ☐ Fixed worker scan changes only the report-path coordinate and imports the report.
- ☐ Scanner success, CE success, gate state and CI outcome are recorded separately.
- ☐ Community summary does not claim native Application/Portfolio semantics.
- ☐ Optional commercial capabilities are labeled with edition prerequisites.
13. Cleanup and rollback
- Revoke all three disposable project-analysis tokens and verify they no longer authenticate.
- Export the evidence packet before deleting the three lab projects.
-
Delete only
sq-ch24-*projects that you created for the lab; do not touch unrelated projects. - Remove the local fixture only after the evidence packet has been preserved.
- Do not prune shared Docker volumes/databases or alter global quality profiles/gates as cleanup shortcuts.
14. What Chapter 24 adds to the operating model
Chapter 24 makes repository complexity an explicit governance object. Project keys, module owners, base directories, indexed source, generated/vendor policy, reports, scanner workspaces, concurrency and task evidence are now versioned as one topology contract. This prevents “green by omission” and “red by overlap” before those errors reach dashboards or executive views.
Chapter 25 continues into Portfolios, Applications, Enterprise Reporting, and Governance Boundaries, where the course will aggregate already-correct project evidence without hiding metric semantics or edition boundaries.
Knowledge check
What independent facts prove the worker path repair?
Same Git SHA, same project/source/test policy, broken import warning/task evidence, corrected report path, successful import evidence and resulting project measure after the fixed CE task.
Why is the Community Build Markdown summary not an Application?
It is an external report over project APIs; it does not create SonarQube’s commercial synthetic application object or consolidated application gate semantics.
If API and worker are independently deployed, should you create an Application just because it is licensed?
Not necessarily. Applications are most appropriate when projects share a release lifecycle; licensing does not redefine ownership.
Which cleanup action is unsafe after this lab?
Pruning shared databases/volumes or deleting unrelated projects. Cleanup must be bounded to named lab credentials, projects and local fixture files.
What must be correct before Enterprise monorepo/Portfolio aggregation is useful?
Each underlying project’s ownership, scope, reports, revision/task chain and policy result must already be correct.
Official references and version notes
-
Community Build — analysis parameters not settable in UI
—
sonar.projectBaseDir,sonar.sources,sonar.tests,sonar.working.directory, report-task path and token guidance. - Community Build — setting initial scope — source/test roots are simple paths relative to project base directory; no wildcards in initial roots.
- Community Build — analysis-scope introduction — generated/library code, coverage/duplication exclusions and verification workflow.
- Community Build — test coverage parameters — externally generated reports and project-root-relative path rules.
- Community Build — SonarScanner CLI — alternate project base directory behavior and CLI configuration.
- Community Build — Java/multi-module coverage — build-native JaCoCo generation and multi-module aggregation patterns.
- SonarQube Server — managing monorepo projects — Enterprise monorepo feature, multiple SonarQube projects bound to one repository, unique project keys and manual project definition.
- SonarQube Server — Applications — synthetic aggregation for projects sharing a lifecycle; commercial feature.
- SonarQube Server — Portfolios — Enterprise governance aggregation.
- SonarScanner CLI releases — current public scanner release baseline.
- SonarQube downloads — current Community Build/Server/LTA release identities.
Rechecked 2026-09-08. Mandatory examples target
Community Build 26.9.0.129388 and
SonarScanner CLI 8.1.0.6389. For CLI-managed
projects, sonar.projectBaseDir changes the analysis
directory; sonar.sources/sonar.tests are
simple paths relative to that base unless absolute. Most
coverage/external report paths are project-root/base-relative
unless their parameter docs state otherwise.
sonar.working.directory must be unique for each
project and is deleted before each analysis, so parallel jobs must
isolate scanner/report artifacts. Current native monorepo
onboarding/binding is an
Enterprise Edition feature and still requires
explicit projects; SonarQube does not infer monorepo projects
automatically. Applications are a commercial aggregation starting
in Developer Edition; Portfolios start in Enterprise Edition.
Community Build can still model multiple independent projects from
one repository manually with distinct project keys/base
directories and an external governance-summary fallback. Recheck
the exact scanner/build integration and report parameter semantics
before production use.
projectBaseDir,
source/test roots, inclusions/exclusions, generated/vendor policy,
report producer/path/internal filenames, unique scanner working
directory, token owner/type (never value), scanner log,
report-task.txt, ceTaskId, Compute Engine
state, measures/gate, CI concurrency identity and aggregation
edition/definition separately.
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.