Checkpoint Lab — Job DSL, Seed Jobs, Folder Hierarchies, Programmatic Job Creation, and Jenkins API Automation
Generate a small folder/job hierarchy from an exact SCM revision, run the seed twice to prove idempotency, make a controlled schema change, intentionally remove one generated job, apply guarded DISABLE behavior, and capture enough controller/seed/API evidence to prove what changed and why.
Learning objectives
- Generate a small folder/job hierarchy from an exact SCM revision.
- Prove two identical seed runs are idempotent.
- Apply one safe schema change with before/after evidence.
- Handle one removed generated job with guarded DISABLE behavior.
- Produce a controller/seed/API evidence packet without exposing credentials.
1. Mission and success criteria
You are the platform engineer for a disposable controller. Build
platform-lab/apps/{api-ci,worker-ci} from versioned Job
DSL. The seed is platform-lab/seed. Run the same commit
twice, change api-ci, then intentionally remove
worker-ci and disable it rather than delete it.
Success means you can prove the exact DSL revision, seed build identity, sandbox/authorization state, generated full names, API-visible persisted state and lifecycle decision. No real repository, production controller or real credential is allowed.
2. Pinned assumptions
| Component | Checkpoint baseline | Evidence |
|---|---|---|
| Jenkins | 2.568.3 LTS | X-Jenkins header/system info |
| Java | 21 | controller/agent java -version |
| Job DSL | 3732.v9a_c49a_61a_313 | plugin inventory |
| Script Security | 1422.v06869826dd9b_ | plugin inventory |
| Folders | 6.1106.v3a_d9a_6d2465e | plugin inventory |
| Optional ACL helpers | matrix-auth 3.3; authorize-project 534.v2f208c45e11c | plugin inventory/config |
| Seed agent | trusted-seed |
node/label/workspace metadata |
Record the platform-specific Jenkins/agent image digests if containers are used.
3. Preflight: predict before mutation
Write evidence/predictions.md before running the seed.
Include at least these predictions:
-
Run 1 creates exactly
platform-lab/apps,api-ciandworker-ci. - Run 2 from the same commit changes no intended generated configuration.
-
The v2 commit changes only
api-cimetadata/policy. -
The removal commit leaves
worker-cipresent but disabled.
Also record seed run-as identity, sandbox state and whether folder ACL is fully implemented or faithfully simulated.
4. Create and commit the synthetic DSL repository
mkdir -p ch27-checkpoint/{jobs,evidence}
cd ch27-checkpoint
git init
git config user.name 'CH27 Checkpoint'
git config user.email 'ch27-checkpoint@example.invalid'
Create jobs/apps.groovy:
folder('apps') {
description('[managed-by=job-dsl][seed=platform-lab/seed][owner=checkpoint]')
}
['api-ci', 'worker-ci'].each { n ->
pipelineJob("apps/${n}") {
description("[managed-by=job-dsl][seed=platform-lab/seed][schema=v1]")
definition {
cps {
sandbox(true)
script("pipeline { agent { label 'linux-ci' } stages { stage('Identity') { steps { echo 'synthetic ${n}' } } } }")
}
}
}
}
git add jobs/apps.groovy
git commit -m 'checkpoint: generated hierarchy v1'
V1=$(git rev-parse HEAD)
printf '%s\n' "$V1" | tee evidence/v1-commit.txt
sha256sum jobs/apps.groovy | tee evidence/v1-dsl.sha256
5. Configure the seed with guarded lifecycle policy
The seed Pipeline checks out the exact repository commit on
trusted-seed and executes:
jobDsl targets: 'jobs/**/*.groovy',
sandbox: true,
lookupStrategy: 'SEED_JOB',
removedJobAction: 'IGNORE',
removedViewAction: 'IGNORE'
Archive git rev-parse HEAD and DSL SHA-256 as seed
artifacts. If Authorize Project is available, run as a dedicated
constrained seed user. Otherwise document that the permission
boundary is simulated and do not claim production-equivalent least
privilege.
6. Run 1: capture creation evidence
Trigger the seed once and save:
- seed queue/build number, URL, cause and result;
- console lines listing generated/added items;
- workspace path/agent identity;
- source commit and DSL hash artifacts;
- API output for
platform-labchildren.
curl -fsS --user "$JENKINS_USER:$JENKINS_API_TOKEN" \
"$JENKINS_URL/job/platform-lab/api/json?tree=jobs[fullName,displayName,color,_class]" \
> evidence/run1-items.json
7. Run 2: prove idempotency
Without changing Git, run the seed again. Record run 2 and compare item identity/description/configuration with run 1. The seed build number will differ; the desired generated item state should not.
If a job name or property changes unexpectedly, stop and investigate nondeterministic input before continuing.
8. Controlled schema change
Edit only api-ci so its description is
schema=v2 and it retains 10 builds. Commit the exact
diff:
git add jobs/apps.groovy
git commit -m 'checkpoint: api-ci schema v2'
V2=$(git rev-parse HEAD)
git show --stat --oneline "$V2" | tee evidence/v2-change.txt
Run the seed once. Verify api-ci changed and
worker-ci remained at v1. Capture API/config evidence.
9. Guarded removal
Remove worker-ci from the DSL and change the seed’s
removed policy to DISABLE. Commit this as a reviewed
lifecycle change:
git add jobs/apps.groovy Jenkinsfile 2>/dev/null || git add jobs/apps.groovy
git commit -m 'checkpoint: retire worker-ci with disable policy'
REMOVED=$(git rev-parse HEAD)
printf '%s\n' "$REMOVED" > evidence/removal-commit.txt
Run the seed. Verify worker-ci still exists and is
disabled. Do not delete it. Preserve its configuration and any
history.
10. Verify folder/identity boundary
If the lab includes project-based matrix authorization and Authorize Project, use the seed identity to attempt an out-of-scope create/update in a disposable test folder and expect authorization denial. Preserve the denial response/log. If your simplified lab lacks those plugins, document the limitation explicitly rather than pretending naming alone is an access control.
11. API and generated-state evidence
Capture exact state, not screenshots alone:
curl -fsS --user "$JENKINS_USER:$JENKINS_API_TOKEN" \
"$JENKINS_URL/job/platform-lab/job/apps/api/json?tree=jobs[fullName,color,buildable,description]" \
> evidence/final-items.json
curl -fsS --user "$JENKINS_USER:$JENKINS_API_TOKEN" \
"$JENKINS_URL/job/platform-lab/job/seed/lastBuild/api/json?tree=number,url,result,timestamp,duration" \
> evidence/final-seed-build.json
Redact Authorization headers and never archive the token itself.
12. Required evidence packet
| Evidence | What it proves |
|---|---|
| Jenkins/Java/plugin inventory | controller and generator compatibility baseline |
| Seed full name/build URLs/causes | who/what executed each mutation |
| V1/V2/removal Git commits + DSL hashes | exact desired state for each phase |
| Sandbox/identity/ACL note | trust and authorization assumptions |
| Run 1/run 2 generated-item comparison | idempotency |
| API item lists/config observations | persisted Jenkins state |
| Disabled worker evidence | guarded orphan handling |
| Agent/workspace metadata | seed checkout execution context |
| Predictions versus results | causal reasoning |
| Assumptions/limitations | which security boundaries were real versus simulated |
13. Cleanup/rollback
Delete only the disposable controller, agent and synthetic
repository created for this checkpoint. If retaining evidence,
remove credential/token files first. A rollback exercise should use
git revert to return DSL source to V1/V2 and rerun the
seed with a non-destructive lifecycle policy; do not bulk-delete
Jenkins items.
14. What Chapter 27 adds to the production operating model
You now have a controlled path from reviewed source to persisted Jenkins items: generator code has an owner and version; seed execution has an identity and audit trail; folder scope is explicit; repeated runs converge; removal is governed; and API evidence independently verifies live state.
Knowledge check
Answer before revealing the explanation.
1. What proves idempotency in the checkpoint?
Two runs from the same DSL commit produce the same intended generated-item configuration and names. The second seed build is new evidence, but there should be no unexplained item diff.
2. What two identities must be correlated for every generated change?
The seed build identity (full name, number/URL, actor/cause) and the DSL source revision. Together they explain who/what executed and which desired-state code was applied.
3. Why is the removed job first disabled?
Disabling preserves configuration/history and makes the lifecycle decision reversible while the learner verifies that the job was actually generated and is intentionally absent from the new DSL.
4. What evidence demonstrates folder containment?
The generated full names are under the expected parent folder, the seed uses folder-relative lookup, and the seed identity is denied or lacks permission for an out-of-scope item path.
5. Why retain API output as evidence after a successful seed build?
Console success proves the Job DSL step returned successfully; API/item inspection independently verifies that the persisted Jenkins state matches the expected generated hierarchy and lifecycle status.
Official references and version notes
- Job DSL plugin — current release, minimum core requirement, maintenance/security status and links to the API Viewer.
-
Jenkins Pipeline Steps — Job DSL
— current
jobDslparameters including sandbox, lookup strategy and removed-item actions. - Job DSL upstream repository — getting started, Job DSL versus Pipeline DSL, and API Viewer guidance.
- Job DSL — Script Security — sandbox/approval behavior and build-identity implications.
- Script Security plugin — Groovy sandbox and signature-approval boundary.
- Folders plugin — folder hierarchy baseline used by the examples.
- Matrix Authorization Strategy — optional fine-grained folder/item permission model for the lab.
- Authorize Project plugin — optional explicit build identity used when exercising sandboxed Job DSL with access-control checks.
- Jenkins Remote Access API and CSRF protection — current API authentication/POST semantics.
- Jenkins LTS changelog and Java support policy.
2.568.3 LTS with Java 21 (Jenkins
2.568.3 is tested with Java 21 and 25). Job DSL is
3732.v9a_c49a_61a_313, requires Jenkins 2.479.3 and is
currently marked “up for adoption” on the plugin site. Script
Security is 1422.v06869826dd9b_; Folders is
6.1106.v3a_d9a_6d2465e; Matrix Authorization Strategy
is 3.3; Authorize Project is
534.v2f208c45e11c. Re-check current plugin/API
documentation and security advisories before reusing the lab. The
mandatory path uses only a disposable local controller, synthetic
Git repository and fake identities.
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.