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.
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.
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 mvnor 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.
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.
Knowledge check
Two builds are green but their Maven versions differ. Are they proven equivalent?
No. Green results do not prove identical toolchain or artifact bytes; compare source, toolchain evidence, dependency state, and artifact digests.
What is the safest repair for a deliberate PATH ownership conflict?
Restore one explicit authoritative tool-selection strategy and verify the resolved executable/version, rather than stacking more PATH entries.
Why record wrapper properties checksum?
It ties the project-owned Maven distribution configuration to the exact build evidence.
Is byte-for-byte reproducibility guaranteed just because source and tool versions match?
No. Timestamps, archive metadata, dependencies, locale, environment, and other inputs may still differ.
What is the bridge to Chapter 09?
Chapter 08 proves the execution toolchain; Chapter 09 explains how Jenkins Pipeline allocates nodes/workspaces and durably orchestrates stages/steps that use that toolchain.
Official references and version notes
- Jenkins LTS changelog — current LTS line and tested Java configurations.
- Java Support Policy — Java versions supported for running Jenkins controller, agents, and CLI.
- Upgrade to Java 21 — controller/agent runtime inspection and migration guidance.
-
Declarative Pipeline
toolsdirective — preconfigured JDK, Maven, and Gradle tool installations and PATH behavior. - Pipeline examples — selecting named JDK/Maven installations and recording versions.
- Using Docker with Pipeline — containerized execution environment, image selection, caching, and Docker Pipeline prerequisites.
- Docker Pipeline plugin — plugin release and compatibility information for Pipeline container steps.
- Apache Maven Wrapper and Gradle Wrapper — project-owned build-tool version selection.
- Node.js downloads and project lockfile documentation — runtime/package-manager pinning belongs with the project or build image.
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.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this
address.