Chapter 26Lesson 05~180 minutes

Checkpoint Lab — Marketplace, Plugins, Extension Risks, and Compatibility Management

Produce a plugin-governance inventory and execute one reversible isolated extension lifecycle with provenance, compatibility, startup evidence, rollback proof, and an upgrade decision record.

PluginsSupply chainCompatibilityRollbackOperations

Learning objectives

  • Build a complete plugin-governance inventory for an exact Community Build release.
  • Predict the server/filesystem/startup/capability state transitions before a plugin lifecycle change.
  • Execute a reversible isolated install/remove lifecycle only after provenance and compatibility gates pass.
  • Preserve startup and optional scanner/ceTaskId evidence without deleting the original failure context.
  • Prove rollback to the known-good baseline and document what must be reconsidered at the next SonarQube upgrade.
  • Produce an evidence packet that is useful to security, legal/licensing, platform, and application owners.

1. Checkpoint scenario

You own a disposable SonarQube Community Build training server. A team requests a nonessential third-party plugin because it adds a capability not currently present in the built-in analyzer set. Your job is not merely to “make it appear in the UI.” You must decide whether the plugin is governable, install it only if all preflight gates pass, verify the server/capability, remove it, and prove the exact baseline returns.

2. Exact assumptions

Layer Checkpoint assumption
SonarQube Community Build 26.9.0.129388
Container sonarqube:26.9.0.129388-community on localhost port 9026
Java Official image runtime; external self-managed 26.x runtime requires Java 21+
Database/search Disposable container state only; no production/external DB changes
Scanner Optional smoke analysis with SonarScanner CLI 8.1.0.6389; not required merely to prove web/plugin loading
Plugin One currently matrix-compatible, nonessential, open-source plugin chosen at checkpoint time
Commercial/Data Center Simulation/documentation only; no commercial binaries required

3. Governance inventory template

server_release,plugin_key,plugin_version,artifact,sha256,source_url,source_repo,license,maintainer,last_release,compatibility_checked,plugin_api_min,dependencies_reviewed,owner,required_by,rollback_artifact,next_upgrade_action
26.9.0.129388,<key>,<version>,<jar>,<digest>,<url>,<repo>,<license>,<publisher>,<date>,2026-09-08,<manifest>,<yes/no+note>,platform-quality,<fixture>,<path>,<keep/upgrade/remove/replace>

The checkpoint fails if required provenance fields are unknown. “Marketplace” is not an acceptable value for source_repo unless it points to the actual publisher/source record.

4. Resource and credential preflight

  • ☐ Docker is available and port 9026 is free.
  • ☐ The container/volume names are unique to this lab.
  • ☐ The chosen plugin is nonessential and explicitly compatible with 26.9 according to current evidence.
  • ☐ Canonical source/release, immutable artifact URL, exact version, SHA-256/signature evidence, and license are recorded.
  • ☐ A copy of the verified JAR is stored outside the extensions volume as evidence/rollback material.
  • ☐ No production database, cluster, IdP, reverse proxy, CI secret, or source tree is connected.
  • ☐ If a read-only API token is used, it is a disposable lab user token and will be revoked.

5. Predictions before mutation

Write predictions before installation. At minimum:

  • Prediction A: copying the verified JAR changes only the extensions volume; capability is not active until the required restart succeeds.
  • Prediction B: after restart, startup logs and installed-plugin inventory will show the exact key/version, while the baseline plugin set remains otherwise unchanged.
  • Prediction C: removing only that JAR and restarting will return the plugin inventory and health to baseline.
  • Prediction D: a deliberately wrong expected digest will block installation before the server changes.

6. Execute the lifecycle

# 1) Baseline exact image and isolated volumes.
export LAB_NAME=sq-ch26
export LAB_URL=http://localhost:9026
export SQ_IMAGE=sonarqube:26.9.0.129388-community
mkdir -p evidence/{baseline,stage,installed,rollback}

docker volume create sq-ch26-data
docker volume create sq-ch26-logs
docker volume create sq-ch26-extensions
docker run -d --name "$LAB_NAME" -p 9026:9000 \
  -e SONAR_ES_BOOTSTRAP_CHECKS_DISABLE=true \
  -v sq-ch26-data:/opt/sonarqube/data \
  -v sq-ch26-logs:/opt/sonarqube/logs \
  -v sq-ch26-extensions:/opt/sonarqube/extensions \
  "$SQ_IMAGE"

# 2) Preserve baseline after the server is UP.
curl -fsS "$LAB_URL/api/system/status" > evidence/baseline/status.json
docker exec "$LAB_NAME" sh -c 'ls -lah /opt/sonarqube/extensions/plugins' \
  > evidence/baseline/plugin-files.txt
docker logs "$LAB_NAME" > evidence/baseline/container.log 2>&1

# 3) Download the exact current compatible plugin selected in preflight.
curl -fL "$PLUGIN_URL" -o "evidence/stage/$PLUGIN_JAR"
ACTUAL_SHA256="$(sha256sum "evidence/stage/$PLUGIN_JAR" | awk '{print $1}')"
test "$ACTUAL_SHA256" = "$EXPECTED_SHA256"
unzip -p "evidence/stage/$PLUGIN_JAR" META-INF/MANIFEST.MF \
  > evidence/stage/manifest.txt
cp "evidence/stage/$PLUGIN_JAR" "evidence/rollback/$PLUGIN_JAR"

# 4) Install only after gates pass; restart exactly once because plugin lifecycle requires it.
docker cp "evidence/stage/$PLUGIN_JAR" \
  "$LAB_NAME:/opt/sonarqube/extensions/plugins/$PLUGIN_JAR"
docker restart "$LAB_NAME"
curl -fsS "$LAB_URL/api/system/status" > evidence/installed/status.json
docker logs "$LAB_NAME" > evidence/installed/container.log 2>&1

# 5) Remove only the introduced artifact; restart and prove baseline recovery.
docker exec "$LAB_NAME" rm -f "/opt/sonarqube/extensions/plugins/$PLUGIN_JAR"
docker restart "$LAB_NAME"
curl -fsS "$LAB_URL/api/system/status" > evidence/rollback/status.json
docker exec "$LAB_NAME" sh -c 'ls -lah /opt/sonarqube/extensions/plugins' \
  > evidence/rollback/plugin-files.txt
docker logs "$LAB_NAME" > evidence/rollback/container.log 2>&1

7. Optional analyzer smoke scan

If the selected plugin is scanner/analyzer-side, a clean web startup is necessary but not sufficient. Use a tiny synthetic repository appropriate to that plugin’s language and preserve the ordinary analysis chain:

git rev-parse HEAD > evidence/installed/fixture-revision.txt
sonar-scanner -X 2>&1 | tee evidence/installed/scanner.log
cp .scannerwork/report-task.txt evidence/installed/report-task.txt
CE_TASK_ID="$(sed -n 's/^ceTaskId=//p' .scannerwork/report-task.txt)"
printf '%s\n' "$CE_TASK_ID" > evidence/installed/ceTaskId.txt
curl -fsS -H "Authorization: Bearer $SONAR_API_TOKEN" \
  "$LAB_URL/api/ce/task?id=$CE_TASK_ID" \
  > evidence/installed/ce-task.json

Scanner success, report upload, ceTaskId/Compute Engine completion, resulting measures/issues, gate state, and CI status remain separate facts. The plugin’s existence does not collapse these states.

8. Verification checklist

  • ☐ Exact Community Build image/release and baseline plugin inventory are preserved.
  • ☐ Plugin key/version/source/repository/license/digest and compatibility evidence are complete.
  • ☐ Deliberate bad-digest check failed before installation and its evidence was retained.
  • ☐ Only the verified JAR was copied into the isolated extensions volume.
  • ☐ Server returned to UP after the required install restart.
  • ☐ Startup logs identify the exact plugin or otherwise prove the expected loading state.
  • ☐ If scanner-side, a synthetic fixture independently verifies analyzer behavior and preserves ceTaskId.
  • ☐ Plugin removal changed only the introduced JAR.
  • ☐ Server returned to baseline health and plugin inventory after rollback.
  • ☐ Upgrade decision record says what happens to this plugin on the next SonarQube release.

9. Required evidence packet

Minimum packet
  • inventory.csv with identity / version / provenance / license / compatibility / owner / rollback / upgrade fields.
  • Exact image/server version and baseline plugin files/checksums/startup logs.
  • Downloaded JAR hash and manifest plus source/release/compatibility citations recorded in an assumptions note.
  • Deliberate checksum failure output.
  • Install restart evidence, post-install status/log excerpt, and capability observation.
  • Optional scanner log, report-task.txt, ceTaskId, CE task and result evidence if the plugin participates in analysis.
  • Rollback restart, post-removal plugin inventory, health, and inventory comparison.
  • License/dependency limitations and Data Center notes if relevant.

10. Cleanup and rollback

# Only after rollback evidence is complete:
docker rm -f sq-ch26
docker volume rm sq-ch26-data sq-ch26-logs sq-ch26-extensions
unset SONAR_API_TOKEN PLUGIN_URL PLUGIN_JAR PLUGIN_KEY PLUGIN_VERSION EXPECTED_SHA256

If a plugin caused the server not to start, the rollback is not “delete the evidence and rebuild everything.” Remove only the introduced artifact, restart the isolated server, and prove baseline recovery. In a real governed environment, use the approved maintenance/backup procedure rather than improvising direct database/search edits.

11. What Chapter 26 adds to the operating model

The governed SonarQube model now includes executable extension inventory as first-class configuration: every plugin has provenance, exact bytes, compatibility, license/dependency ownership, startup evidence, a rollback artifact, and a next-upgrade decision. Platform availability is no longer assumed to survive arbitrary JAR changes.

Chapter 27 continues naturally into Server Logs, Monitoring, Health, Elasticsearch, and Operational Diagnostics, where the startup and runtime evidence used here becomes a broader observability and incident-diagnosis discipline.

Knowledge check

What does a successful checksum prove—and what does it not prove?

If the server returns to UP after install, is the checkpoint complete for an analyzer plugin?

Why is the baseline plugin inventory needed after rollback?

A plugin is compatible today but has no maintained release for the planned next SonarQube upgrade. What should the inventory say?

What is the correct Data Center fallback in this Community Build lab?

Next lesson — Next chapter

Server Logs, Monitoring, Health, Elasticsearch, and Operational Diagnostics

Chapter 27 broadens the startup evidence used here into continuous server logs, health, Elasticsearch, and operational diagnostics.

Official references and version notes

Version and compatibility note

Rechecked 2026-09-08. Mandatory examples target SonarQube Community Build 26.9.0.129388 using the official sonarqube:26.9.0.129388-community Docker image. Community Build supports Marketplace and manual plugin installation; current commercial SonarQube Server documentation requires manual installation. Third-party plugins are not provided by Sonar and are installed at the operator’s risk. Compatibility must be checked against the current Plugin version matrix and plugin release documentation before every install/upgrade. The checkpoint deliberately chooses the plugin at run time rather than hard-coding a third-party version that may become abandoned. The server image contains its supported Java runtime; outside the image, current Community Build 26.x requires Java 21+. No external database, production cluster, identity provider, reverse proxy, or paid capability is required. Data Center plugin consistency is taught as an optional/simulated commercial path.

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.