Chapter 08Lesson 05~150 minutes

Checkpoint Lab — Tool Installations, JDKs, Maven, Gradle, Node.js, Docker CLI, and Reproducible Build Environments

Prove toolchain reproducibility by building the same synthetic source with two controlled strategies, injecting a version-selection mismatch, correcting it explicitly, and producing an evidence packet that binds source, toolchain, and artifact.

CheckpointReproducibilityEvidence packetMismatch injectionArtifact digestCleanup

Learning objectives

  • Build one synthetic source revision through two deliberate toolchain strategies.
  • Predict and verify toolchain state changes before execution.
  • Inject a controlled version mismatch without touching production infrastructure.
  • Correct the mismatch by changing the authoritative toolchain definition rather than relying on PATH luck.
  • Produce a compact evidence packet that can explain whether two artifacts were built equivalently.

1. Mission

Use one disposable Jenkins controller and agent pool to build the same tiny Java source twice. Strategy A uses an explicitly selected Jenkins/agent JDK plus Maven installation; Strategy B uses the same build JDK but the committed Maven Wrapper. Then intentionally create a Maven-selection mismatch in a copy of the lab job, diagnose it from evidence, and repair the ownership conflict.

Success is not “both jobs are green.” Success is proving which source and toolchain produced each artifact and explaining any byte or behavior difference.

2. Baseline assumptions

  • Disposable Jenkins 2.568.3 LTS controller.
  • Controller and agent Remoting runtime use Java 21 (Java 25 is also supported by this Jenkins LTS).
  • Disposable Linux agent labelled lab-linux; routine builds do not execute on the built-in node.
  • Synthetic repository contains a tiny Java project and reviewed Maven Wrapper.
  • No real secrets or external deployment target.
  • Optional Docker comparison is allowed only on a dedicated disposable Docker-capable agent and is not required.

3. Predict state changes before running

Prediction How you will verify it
Strategy A will prepend/select the configured Maven/JDK tool paths on the assigned agent. command -v, JAVA_HOME, Java/Maven version output.
Strategy B will obtain Maven version intent from wrapper metadata at the source SHA. Wrapper properties + ./mvnw -V --version.
Both builds will produce a JAR whose checksum can be compared. sha256sum archived with each build.
The injected mismatch will be visible as a different executable/version before compilation. Pre-build toolchain evidence file.

4. Strategy A — controlled platform toolchain

Create ch08-platform-tools on lab-linux. Select the named JDK and Maven tools configured for the lab. Before invoking Maven, capture:

set -eu
{
  printf 'strategy=platform-tools\n'
  printf 'job=%s\n' "$JOB_NAME"
  printf 'build=%s\n' "$BUILD_NUMBER"
  printf 'node=%s\n' "$NODE_NAME"
  printf 'source_sha=%s\n' "$(git rev-parse HEAD)"
  printf 'arch=%s\n' "$(uname -m)"
  printf 'java_home=%s\n' "$JAVA_HOME"
  command -v java
  java -version 2>&1
  command -v mvn
  mvn -B -V --version 2>&1 | sed -n '1,8p'
} | tee toolchain-evidence.txt
mvn -B -DskipTests package
sha256sum target/*.jar | tee artifact-sha256.txt

Archive toolchain-evidence.txt, artifact-sha256.txt, and the training JAR.

5. Strategy B — project-owned Maven Wrapper

Create ch08-wrapper-tools from the same source SHA and same build JDK. Do not require a Jenkins global Maven for this strategy.

set -eu
test -x ./mvnw
{
  printf 'strategy=maven-wrapper\n'
  printf 'job=%s\n' "$JOB_NAME"
  printf 'build=%s\n' "$BUILD_NUMBER"
  printf 'node=%s\n' "$NODE_NAME"
  printf 'source_sha=%s\n' "$(git rev-parse HEAD)"
  printf 'wrapper_properties_sha=%s\n' "$(sha256sum .mvn/wrapper/maven-wrapper.properties | awk '{print $1}')"
  java -version 2>&1
  ./mvnw -B -V --version 2>&1 | sed -n '1,8p'
} | tee toolchain-evidence.txt
./mvnw -B -DskipTests package
sha256sum target/*.jar | tee artifact-sha256.txt

6. Compare evidence before comparing green badges

Place both evidence files side by side. Confirm source SHA and build JDK identity. Note whether Maven versions match. Compare the JAR checksum. If the artifacts differ, do not assume a defect immediately; first identify whether timestamps, archive metadata, tool versions, dependency state, or source inputs differ. Reproducible-build techniques are project-specific and may require additional controls beyond the scope of this introductory Jenkins chapter.

7. Inject a controlled mismatch

Clone the lab job as ch08-mismatch. Alter only the Maven ownership path—for example, select a different deliberately installed training Maven or place a known alternate Maven earlier on PATH. Do not download an unknown binary from an arbitrary URL.

Before running, predict that the toolchain evidence will differ even though the source SHA remains the same. Run once and preserve the evidence.

8. Diagnose and correct

Start from the failed/different build record. Compare:

  • job/build and source SHA;
  • agent and architecture;
  • command -v mvn or wrapper path;
  • Maven/JDK version output;
  • PATH/JAVA_HOME;
  • wrapper properties or global tool name;
  • artifact checksum and console output.

Repair by restoring one authoritative Maven strategy. Rebuild from the same source SHA and prove the intended executable/version now runs. Do not “fix” it by adding more PATH entries until the right binary happens to win.

9. Optional container strategy

If a dedicated isolated Docker-capable lab agent is available, repeat the build in a reviewed Maven/JDK image. Record both the tag and resolved digest. This is an optional architecture comparison, not a requirement for course completion.

Boundary: do not expose a general-purpose shared agent’s host Docker socket simply to complete this exercise.

10. Required evidence packet

  • Jenkins core and runtime Java version.
  • Job full name, build number/URL, cause, and source SHA.
  • Agent/node label, OS/architecture, workspace path.
  • Selected strategy and controller tool names, if any.
  • PATH/JAVA_HOME subset and resolved executable paths.
  • Exact JDK/Maven versions; Node/Docker versions only if used.
  • Wrapper properties checksum or container image digest when applicable.
  • Artifact filename and SHA-256.
  • Mismatch diagnosis and correction note.
  • Assumptions/limitations, including whether byte-for-byte artifact reproducibility was achieved.

11. Cleanup and rollback

Delete the three disposable Chapter 08 jobs and their temporary workspaces only after preserving evidence. Remove any lab-only alternate tool installation if nothing else references it. Remove optional lab containers/images only by exact identity. Leave shared controller tool definitions intact unless you created them solely for this chapter and verified there are no dependencies.

12. What this chapter adds to a production Jenkins model

You can now separate controller tool metadata from agent binaries, distinguish Jenkins runtime Java from build JDKs, choose between global tools/wrappers/images by ownership, and bind an artifact to a concrete toolchain evidence chain. Chapter 09 builds on that foundation by introducing Pipeline execution itself: Jenkinsfile identity, durable Pipeline state, nodes, workspaces, and stages.

Next lesson

Chapter 09 — Pipeline Fundamentals

Move from toolchain selection into Pipeline-as-Code, Jenkinsfile identity, durable execution, node/workspace allocation, and stage structure.

Knowledge check

Two builds are green but their Maven versions differ. Are they proven equivalent?

What is the safest repair for a deliberate PATH ownership conflict?

Why record wrapper properties checksum?

Is byte-for-byte reproducibility guaranteed just because source and tool versions match?

What is the bridge to Chapter 09?

Official references and version notes

Version and compatibility note

Rechecked on 2026-09-16. Examples assume Jenkins 2.568.3 LTS, tested with Java 21 and 25. The lab uses Java 21 for the Jenkins controller/agent runtime, but deliberately treats the application build JDK as separate state. Declarative tools supports Jenkins-configured jdk, maven, and gradle tools. Docker-based Pipeline examples are optional and require the Docker Pipeline plugin plus a deliberately isolated Docker-capable agent; the mandatory path does not mount a host Docker socket into untrusted builds.

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.