Chapter 23Lesson 03~135 minutes

Web API, Webhooks, Automation, Provisioning, and Policy as Code: Configuration, Design Patterns, and Trade-Offs

Choose between Web API generations, imperative and declarative automation, polling and webhooks, create-once and reconcile-loop patterns, and mutation scopes using least privilege and observable state.

Web APIWebhooksAutomationPolicy as codeGovernance

Learning objectives

  • Choose deliberately between existing Web API and V2 endpoints instead of mixing contracts.
  • Compare imperative scripts with declarative/idempotent reconciliation.
  • Choose polling, webhooks, or a hybrid based on ownership, latency, reliability, and audit needs.
  • Design safe create/update/delete ownership rules and avoid cross-project policy drift.
  • Connect least privilege, portability, rollback, and version migration to concrete SonarQube state.

1. Design principle: automate desired state, not remembered click sequences

A click-sequence script is brittle because it assumes the same current state every time. Policy-as-code starts from a desired invariant—project exists, visibility is private, a specific gate/profile is selected, one owned webhook points to an approved receiver—and reconciles only the differences.

declared intent + current documented API state → computed diff → smallest authorized mutation → independent reread → recorded convergence

2. Existing Web API versus V2

Choice Use when Risk/control
Documented existing endpoint The exact target release still documents it and no replacement is mandated. Record endpoint changelog/deprecation; centralize it behind a client method.
Documented V2 endpoint The exact operation has a supported V2 contract. Test its path, method, content type, response/error/pagination model independently.
Dual-version adapter You must manage a known fleet spanning API transitions. Detect capability/version explicitly; never “try random paths until one works.”
Undocumented internal endpoint Never as production automation. Internal UI services are subject to change/removal and are outside the public compatibility contract.

A concrete current example is local project creation, still documented as POST /api/projects/create, while DevOps-platform project import already uses documented /api/v2/dop-translation/... endpoints. That coexistence is exactly why migration must be endpoint-specific.

3. Imperative versus declarative/idempotent policy code

One-shot imperative

Good for a one-time migration with strict preconditions and human review. Bad when rerun behavior is undefined.

Idempotent provisioner

Reads current state, creates missing state, and skips compliant state. Best for repeatable onboarding.

Reconcile loop

Continuously detects drift and restores only explicitly owned fields. Requires the strongest ownership and change-control discipline.

Read-only inventory

Best first step when ownership is uncertain. Export state before choosing a mutation model.

4. “Manage only what I own” is the deletion boundary

A safe controller tracks which objects it created and which fields it owns. If a webhook was added manually by another team, absence from your policy file is not proof that it should be deleted. A common pattern is:

{
  "managedProject": "sq-ch23-policy-lab",
  "managedWebhookName": "ch23-local-receiver",
  "managedSettings": ["sonar.coverage.exclusions"],
  "lastObservedEndpointContract": "Community Build 26.9",
  "deletionPolicy": "explicit-only"
}

This is why the Chapter 23 lab never deletes by ambiguous display name and stops if it discovers duplicate candidate objects.

5. Polling versus webhooks versus hybrid

Pattern Strength Failure mode Safer use
Polling Client controls cadence and can recover after downtime. Excess calls, stale intervals, rate/load pressure. Use bounded backoff, terminal-state checks, timeouts, and persisted cursor/task ID.
Webhook Low-latency push after analysis events. Receiver outage, route/TLS/HMAC errors, duplicates/retries. Validate HMAC; make event processing idempotent; store task identity.
Hybrid Webhook provides prompt signal; read API verifies authoritative state. More implementation complexity. Often best for high-value gate automation: receive event, then verify referenced task/project state.

6. Webhook semantics: notification is not transaction commit

Current SonarQube webhook payloads include status, a background task ID, project data, and Quality Gate information. Webhooks are sent around analysis completion and can report non-success task/gate states. Your receiver should therefore branch on the payload’s explicit status and correlate it with API state rather than interpreting “HTTP request arrived” as “analysis succeeded.”

Configure HMAC and treat signature validation as necessary but not sufficient: a valid SonarQube event still needs authorization in the receiver’s own workflow.

7. Which SonarQube state belongs in policy as code?

State Good automation candidate? Reason
Project existence/visibility Yes Stable identifiers and explicit create/update APIs.
Gate/profile association Yes, if ownership is clear Project-admin-capable APIs exist; gate/profile definition itself may have separate global ownership.
Project webhook Yes Project-admin API and exact webhook key; store secret in secret manager, not policy file.
Issue disposition Usually workflow automation, not baseline config Represents human/triage decisions and should not be mass-reset blindly.
Authentication secrets / TLS private keys Reference only Policy code declares secret reference/ownership; secret values stay in a secret store.
Database/search internal rows No Use supported application APIs; direct state edits bypass invariants.

8. Error and retry strategy

  • 400: validate request contract; do not retry unchanged.
  • 401: authentication/token state; rotate or correct secret source, not project policy.
  • 403: authenticated but unauthorized; change permission ownership deliberately rather than escalating to admin by default.
  • 404: may indicate absent object or wrong endpoint/version; prove which before creating/deleting anything.
  • 409/conflict-like semantics: reread current state and reconcile; do not blindly replay create.
  • 429/5xx/transient network: bounded exponential backoff is reasonable only for operations proven safe to retry.

The exact status vocabulary varies by endpoint/API generation. Your client should preserve status, response body, method/path, and a sanitized request identifier—not only raise “API failed.”

9. Worked decision table

Scenario Pattern Prerequisite Evidence
Onboard hundreds of projects with a naming standard Idempotent reconcile Create Projects + project-level ownership/template Desired-state file, page-complete inventory, create/skip log, reread verification.
Gate result must wake a release orchestrator Webhook + API verification Project/global webhook, HMAC secret, reachable receiver Signature, task ID, payload status, API reread, downstream decision.
Fleet spans old and new API generations Version/capability adapter Tested endpoint map per release Server version, endpoint selection log, contract tests.
Unknown manually configured project estate Read-only inventory first Browse/admin read permissions as appropriate Paginated export, ownership classification, no mutations.

Knowledge check

Why is a reconcile loop safer than repeating POST /api/projects/create?

When should a webhook receiver call the Web API after validating HMAC?

Is a 403 fixed by replacing the automation token with an administrator token?

What should policy-as-code do with a manual webhook it does not own?

Why centralize endpoint definitions?

Next lesson

Diagnose API and webhook failures without destructive retries

Lesson 4 engineers endpoint, authentication, pagination, retry, deletion, and webhook-trust failures and repairs them causally.

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. Current Community Build documentation states that Web API V2 is gradually replacing the existing Web API endpoint by endpoint; do not infer a mechanical /api/v2 rewrite. Bearer authentication with a User token is recommended for Web API calls, and authenticated responses normally expose SonarQube-Authentication-Token-Expiration for rotation planning. Unless an endpoint documents otherwise, traditional POST Web API calls should use form data / application/x-www-form-urlencoded. Project creation remains documented at POST /api/projects/create, while some newer capabilities already use V2 resources. SonarQube webhooks can be configured at project/global scope and can be protected with HMAC-SHA256 in X-Sonar-Webhook-HMAC-SHA256; validate the raw body before trusting a payload. Webhook payloads include background task and Quality Gate evidence, but delivery success is not equivalent to Compute Engine success or gate pass. Always recheck the exact target instance’s /web_api documentation, endpoint changelog, permission requirement, pagination/error schema, and V2 replacement status before production automation.

Automation evidence rule. Preserve endpoint generation/path/method, sanitized request intent, HTTP status/body, pagination completion, token owner/type/expiration (never the value), before/after policy state, revision, ceTaskId, Compute Engine result, webhook HMAC outcome, task/gate state, controller version, ownership record, and cleanup/revocation evidence 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.