Chapter 24Lesson 05~200 minutes

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.

MonoreposModulesAnalysis scopeReport pathsGovernance

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/src only; worker analysis will index modules/worker/src only. Generated/vendor files will not enter either project because they are outside both initial scopes.
  • Prediction B — path defect: with worker projectBaseDir=modules/worker, setting sonar.python.coverage.reportPaths=modules/worker/coverage.xml will fail to import the intended coverage report even though source indexing still succeeds.
  • Prediction C — repair: changing only that value to coverage.xml at 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

Minimum contents
  • topology.yaml and predictions.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?

Why is the Community Build Markdown summary not an Application?

If API and worker are independently deployed, should you create an Application just because it is licensed?

Which cleanup action is unsafe after this lab?

What must be correct before Enterprise monorepo/Portfolio aggregation is useful?

Next lesson — Next chapter

Portfolios, Applications, Enterprise Reporting, and Governance Boundaries

Chapter 25 moves from correct component projects to commercial applications, portfolios, enterprise reporting and aggregation caveats.

Official references and version notes

Version and compatibility note

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.

Complex-layout evidence rule. Preserve repository root, exact revision, project key/owner, 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.

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