Chapter 21Lesson 05300–410 min

Checkpoint Lab — Webhooks, Jenkins and CI Integrations, Maven Deployments, Build Promotion, and Event Automation

Integrate the chapter into one evidence-driven checkpoint: build once, publish once, observe an event, promote the same bytes, prove identity, then remove only the disposable resources created by the lab.

CheckpointEvidence packetPromotionLeast privilegeVerification

Learning objectives

  • Build one synthetic artifact and preserve source/build/checksum evidence before publication.
  • Publish through a least-privilege service identity and independently verify Nexus component/asset state.
  • Validate a repository event with HMAC and deduplicate its delivery UUID, using a signed fixture when live webhook capability is unavailable.
  • Promote the exact published bytes to a second hosted repository without compiling again.
  • Create a complete evidence packet, verify negative authorization tests, and tear down only lab-owned resources.
Version and edition baseline (27 August 2026). This chapter uses Nexus Repository 3.95.2-01 as the dated self-hosted reference line and Java 21 as the current runtime requirement. Verify the running instance and current release notes before using version-sensitive UI, plugin, webhook, or staging behavior. The mandatory path is Community/free-compatible and uses only disposable local resources.
Credential and production boundary. Never paste real CI secrets, Maven server passwords, Jenkins credentials, webhook shared secrets, Authorization headers, production repository URLs, or employer namespaces into lesson files, shell history, Git, screenshots, or evidence bundles. Use a loopback/private lab, synthetic com.example coordinates, and disposable service identities.
Promotion boundary. Sonatype currently classifies Staging & Build Promotion and component tagging as Pro features. Therefore the required Community lab teaches the invariant—promote the exact already-built bytes—by downloading/verifying/re-uploading a disposable artifact between hosted repositories. Native Staging/Move/Tag workflows are optional Pro extensions, not prerequisites.

1. Checkpoint scenario and success contract

You operate a small internal service that produces com.example:learner-ch21:1.0.0. The build stage may publish only to learner-ch21-build. An event receiver records repository changes. A release controller may promote only an artifact whose published SHA-256 matches the build manifest. The destination is learner-ch21-release. No source rebuild is allowed after the manifest is frozen.

Checkpoint: verifiable artifact handoff
flowchart TD
  COMMIT[Source commit] --> BUILD[Build once]
  BUILD --> MAN[Manifest: GAV + SHA-256 + build ID]
  BUILD --> DEV[learner-ch21-build]
  DEV --> EVENT[Signed event / signed fixture]
  EVENT --> RX[Validate + dedupe]
  RX --> READ[Read Nexus state]
  READ --> GATE{Matches manifest?}
  GATE -->|yes| PROMOTE[Transfer same bytes]
  GATE -->|no| STOP[Stop + diagnose]
  PROMOTE --> REL[learner-ch21-release]
  REL --> VERIFY[Re-download + SHA-256]

2. Preflight and exact assumptions

AssumptionCheckpoint requirement
NexusDisposable self-hosted 3.95.2-01 reference; verify local exact version before execution
RuntimeJava 21; official bundles include a recommended JVM in current releases
Database/blobH2 + file blob store allowed only for the small archive-installation lab; not a production recommendation
EditionCommunity mandatory path; Pro Staging/Tagging optional only
NetworkNexus and receiver loopback/private; no public endpoint
MavenCurrent supported local Maven; record mvn --version and avoid global corporate settings
IdentityDisposable svc-learner-ch21 with add/read/browse only on lab repositories

3. Required predictions before execution

  1. After initial deployment, database/component metadata and blob assets will appear in learner-ch21-build, but learner-ch21-release will remain empty.
  2. After promotion, the destination repository will gain its own repository metadata/assets while the source artifact remains byte-identical; source compilation/build state will not change.
  3. A duplicate webhook delivery UUID will not produce a second promotion.
  4. The service identity will be able to upload/read the two lab repositories but will receive denial for repository/security administration.

4. Setup checklist

  • Create/verify the two disposable Maven hosted release repositories on a lab blob store.
  • Create a narrow service role/user; record its privilege IDs without secrets.
  • Create a temporary Maven local repository and settings file for isolation.
  • Start the loopback webhook receiver from Lesson 2.
  • If the repository webhook capability exists, configure it with a disposable secret; otherwise prepare the signed fixture path.
  • Create a temporary source directory containing the synthetic POM and one harmless class.

5. Build once and create the immutable handoff manifest

export BUILD_ID='local-ch21-001'
export SOURCE_COMMIT='synthetic-no-real-repo'
mvn -B -Dmaven.repo.local=/tmp/ch21-m2 clean package
ARTIFACT='target/learner-ch21-1.0.0.jar'
SHA256=$(sha256sum "$ARTIFACT" | cut -d' ' -f1)
cat > /tmp/ch21-manifest.txt <

This manifest contains no credential. Once created, do not run a build goal again in this checkpoint.

6. Publish and prove repository state

Deploy with the temporary Maven settings whose server ID matches learner-ch21-build. Capture the client HTTP outcome and then verify independently from Nexus: component/asset listing or Browse, repository path, downloaded JAR, and SHA-256.

mvn -B -s "$CH21_SETTINGS" -Dmaven.repo.local=/tmp/ch21-m2 deploy -DskipTests
curl --fail --silent --show-error -u "$NEXUS_SERVICE_USER:$NEXUS_CH21_PASSWORD"   -o /tmp/ch21-published.jar   "$NEXUS_URL/repository/learner-ch21-build/com/example/learner-ch21/1.0.0/learner-ch21-1.0.0.jar"
test "$SHA256" = "$(sha256sum /tmp/ch21-published.jar | cut -d' ' -f1)"

7. Negative authorization test

Using the same service identity, attempt one harmless read-only control-plane endpoint that requires administration or a repository-creation action that you know should be denied. Preserve only HTTP status/path, not credentials. Expected result is 403 (or another documented denial according to endpoint/auth state). If it succeeds, stop and narrow the role before continuing.

8. Event gate: authenticate and deduplicate

Trigger a repository event through the live capability when available, or replay the signed fixture. Record X-Nexus-Webhook-Id, X-Nexus-Webhook-Delivery, signature validation result, expected repository, and event timestamp. Send the exact same delivery a second time; the receiver/controller must report it as duplicate and perform no second promotion.

9. Controller gate: trust Nexus state, not payload claims

The controller extracts/derives the expected coordinate from its own workflow state, downloads the artifact from learner-ch21-build, computes SHA-256, and compares it to the manifest. Only equality opens the promotion gate. A valid webhook with a different coordinate or checksum is rejected and investigated.

10. Promote the same bytes

Use the already-downloaded JAR and POM. Do not invoke clean, compile, package, or another source build. Publish the existing files to learner-ch21-release with a destination-scoped credential context, or use native Pro Staging/Move only as an optional extension on an eligible instance.

# Guard: compare before transfer
EXPECTED=$(awk -F= '$1=="sha256" {print $2}' /tmp/ch21-manifest.txt)
test "$EXPECTED" = "$(sha256sum /tmp/ch21-published.jar | cut -d' ' -f1)"

# Transfer existing files; no build goals.
mvn -B -s "$CH21_RELEASE_SETTINGS" deploy:deploy-file   -DrepositoryId=learner-ch21-release   -Durl="$NEXUS_URL/repository/learner-ch21-release/"   -Dfile=/tmp/ch21-published.jar   -DpomFile=/tmp/ch21-published.pom

11. Independent destination verification

curl --fail --silent --show-error -u "$NEXUS_SERVICE_USER:$NEXUS_CH21_PASSWORD"   -o /tmp/ch21-promoted.jar   "$NEXUS_URL/repository/learner-ch21-release/com/example/learner-ch21/1.0.0/learner-ch21-1.0.0.jar"
PROMOTED=$(sha256sum /tmp/ch21-promoted.jar | cut -d' ' -f1)
test "$EXPECTED" = "$PROMOTED"
printf 'promotion_verified sha256=%s
' "$PROMOTED"

Also verify repository/component/asset state shows the coordinate in both expected locations and no unexpected SNAPSHOT/alternate version exists.

12. Inject one safe failure and diagnose it

Change the temporary release settings.xml server ID to a wrong value, then perform a non-destructive authentication/read or deployment attempt against a fresh disposable version such as 1.0.1-failure only if your repository policy permits. Capture the failure, explain the ID mapping problem, restore the correct temporary settings, and do not widen Nexus privileges.

13. Required evidence packet

EvidenceWhat it proves
Version/edition/runtime + repository configCompatibility and target scope
Source/build manifest without secretsBuild identity and expected checksum
Maven server/repository IDs, redactedCorrect client credential mapping
Service-role privilege matrix + negative testLeast privilege
Build repository component/assets + downloaded SHA-256Successful governed publication
Webhook event ID/delivery UUID + HMAC resultAuthenticated, deduplicated event handling
Promotion command showing no build goalBuild-once handoff
Release repository re-download SHA-256Byte identity preserved
Cleanup recordLab-owned state removed through supported mechanisms

14. Cleanup / rollback

Destructive step—disposable resources only. Confirm every target name begins with learner-ch21- and the base URL is the local lab before deletion.
  • Disable/delete the Chapter 21 webhook capability if created.
  • Delete the disposable service user/role after recording non-secret privilege evidence.
  • Delete learner-ch21-build and learner-ch21-release through Nexus UI/REST only.
  • Remove temporary Maven settings, temporary local repository, receiver process, and synthetic source directory.
  • Do not delete blob files or database rows directly. Physical reclamation follows the supported cleanup/compaction semantics from Chapters 18–19.

15. Verification checklist

□ Exact coordinate/version published. □ Original, source-repository, and destination-repository SHA-256 values match. □ No rebuild after manifest freeze. □ Service identity denied administration. □ Event HMAC validated or fixture path explicitly labeled. □ Duplicate delivery no-op proven. □ No real secret in files/logs/evidence. □ Community/Pro boundary stated correctly. □ Cleanup limited to lab-owned resources.

16. Knowledge check

What is the strongest evidence that the release artifact is the same artifact that CI published?

Why does the controller re-read Nexus after receiving a valid webhook?

A duplicate delivery causes a second upload but produces the same bytes. Is the receiver idempotent?

What should you do if the live Community instance does not expose the repository webhook capability?

What concept from this chapter carries into Chapter 22?

17. Chapter checkpoint summary

You have a production-grade mental model for the CI/Nexus handoff: build once, publish with a scoped noninteractive identity, authenticate and deduplicate events, re-read authoritative repository state, promote the exact bytes, and preserve evidence across every step. Chapter 22 adds Sonatype IQ/component-intelligence and policy evaluation without changing these repository identity boundaries.

Official references and version notes

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
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.