Chapter 27Lesson 01~155 minutes

Job DSL, Seed Jobs, Folder Hierarchies, Programmatic Job Creation, and Jenkins API Automation: Concepts, Architecture, and Mental Model

Job DSL turns a reviewed desired-state description into Jenkins items, but the generator itself is privileged automation. Learn to separate the versioned DSL source, seed-job identity, sandbox/approval state, generated-item ownership, folder boundaries and removal policy before allowing a seed build to mutate controller item configuration.

Job DSLSeed jobsFoldersOwnershipSandboxAPI evidence

Learning objectives

  • Explain Job DSL, seed jobs and generated-item ownership without confusing them with Pipeline DSL.
  • Trace versioned DSL source through a seed build into persisted folders/jobs.
  • Separate seed identity, Script Security, folder permissions and generated-item lifecycle.
  • Inspect current state before allowing generator mutations.
  • Define auditable idempotency and recovery evidence for generated jobs.

1. The practical problem: hundreds of UI-created jobs do not scale

Creating one Jenkins job in the UI is easy. Creating the same class of job for dozens of services, keeping every option consistent, proving who changed it and rolling back a bad bulk edit is not. Job DSL solves this by treating item definitions as reviewed Groovy-based desired-state code.

The dangerous part is equally important: Job DSL is not a harmless template engine. A seed job can create, update, disable or delete persisted Jenkins items. The generator therefore belongs in the controller trust model alongside JCasC, plugins and trusted Shared Libraries.

Security boundary. Never let arbitrary application contributors edit and execute admin-equivalent Job DSL. Protect the DSL repository, run the seed under an intentional identity, prefer sandboxed DSL where practical, constrain folder scope and make destructive removed-item behavior an explicit reviewed policy.

2. Mental model: source → seed → generated state

Read this flow from left to right. The Git commit is the desired-state input. The seed job supplies execution identity, workspace and build audit. Job DSL interprets the files under sandbox/approval rules. Jenkins then persists item configuration. Later builds of generated jobs are separate runs with their own source, queue, agent and artifacts.

Causality: generator identity and source remain distinct from generated-job execution
flowchart TD
  A[Versioned Job DSL source\ncommit + files] --> B[Seed job\nfull name + build + identity]
  B --> C[Job DSL execution\nsandbox or approved script]
  C --> D[Desired folders and jobs\nfull names + ownership]
  D --> E[Created / updated / disabled / deleted items]
  E --> F[Generated-job builds\nqueue + agent + workspace]
  F --> G[Reports / artifacts / statuses]
  B --> H[Seed audit evidence\nconsole + generated objects + API]
  E --> H

The arrows matter. A green generated application build does not prove the seed source was safe. A green seed build does not prove every generated job later runs correctly. Persisted item configuration and build runtime are different states.

3. Terminology before commands

Term Meaning State to record
Job DSL Groovy-based domain-specific language that creates/updates Jenkins items. plugin version, DSL files, source commit
Seed job A Jenkins job/Pipeline that executes the Job DSL step. full name, build number/URL, cause, run identity
Generated item Folder/job/view/config produced and tracked by the Job DSL run. full name, config digest, lifecycle action
Sandbox Script Security mode that restricts Groovy operations to approved signatures. sandbox flag, rejected/approved signatures
Lookup strategy How relative item names are resolved: Jenkins root or seed-job folder. JENKINS_ROOT or SEED_JOB
Removed-item action Policy for items previously generated but no longer described. IGNORE / DISABLE / DELETE
Ownership marker Human-readable metadata such as a description/tag plus plugin-generated tracking. seed name, team, source path; not an ACL

4. State boundaries you must keep separate

Controller/configuration

Job DSL, Folders, Script Security, authorization plugins, JENKINS_HOME and persisted config.xml files.

Seed item/build

Seed configuration, build number, exact SCM commit, workspace and console/generated-object action.

Generated items

Folders/jobs/views, full names, descriptions, disabled state and ownership.

Runtime builds

Queue, executor, agent, workspace, Pipeline CPS and artifacts of generated jobs.

Identity/trust

Seed run-as identity, folder ACL, sandbox/approval and source-review boundary.

Recovery

Git revert, controller snapshot/backup and retained job histories before destructive lifecycle actions.

5. Read-only inspection before mutation

On the disposable controller, inspect rather than configure first. Record the values in a small evidence file:

# Controller/runtime evidence
curl -fsSI "$JENKINS_URL/login" | grep -i '^X-Jenkins:' || true
java -version

# Plugin versions through the authenticated API (token stored outside shell history)
curl -fsS --user "$JENKINS_USER:$JENKINS_API_TOKEN" \
  "$JENKINS_URL/pluginManager/api/json?depth=1" > evidence/plugins.json

# Existing items only; no POST and no mutation
curl -fsS --user "$JENKINS_USER:$JENKINS_API_TOKEN" \
  "$JENKINS_URL/api/json?tree=jobs[fullName,_class,color]" > evidence/items-before.json

Use an API token through a protected environment/file binding; never put a real token in lesson files or command history. API-token-authenticated POSTs are exempt from crumb requirements, while username/password scripted clients generally need the crumb/session flow.

6. Seed identity is part of the desired-state contract

A seed should not run with more authority than needed. In a strong design, the seed’s build identity can configure/create items in its platform/team folder and cannot administer the controller or mutate unrelated folders. When sandboxed Job DSL performs Jenkins access checks, a deliberate build identity is especially important; Authorize Project is one current mechanism for that.

Folder-relative generation helps but does not replace authorization. lookupStrategy: 'SEED_JOB' makes relative names resolve beneath the seed’s folder. Pair that with folder permissions and a test that an out-of-scope write is denied.

7. Job DSL is not Pipeline DSL

// Job DSL: creates a Pipeline job
pipelineJob('apps/api-ci') {
  description('[managed-by=job-dsl][owner=platform-lab]')
  definition {
    cpsScm {
      scm {
        git { remote { url('file:///workspace/app-repo.git') } }
      }
      scriptPath('Jenkinsfile')
    }
  }
}
// Pipeline DSL: executed later *by* the generated job
pipeline {
  agent { label 'linux-ci' }
  stages {
    stage('Test') { steps { sh './test.sh' } }
  }
}

The first script mutates Jenkins item configuration. The second governs one build’s runtime. Mixing them produces confusing syntax and trust failures.

8. Removed items: lifecycle, not garbage collection

Action Effect Use
IGNORE Previously generated item remains unchanged. Safest while ownership is uncertain.
DISABLE Job stays with history/config but cannot run normally. Recommended intermediate state for controlled retirement.
DELETE Generated item is removed. Only after explicit ownership, retention and recovery checks.

When multiple Job DSL steps run in one seed build, apply DISABLE/DELETE removed-item actions only on the last relevant Job DSL step; otherwise an item can be disabled/deleted before a later step recreates it.

9. DevOps connection: generator evidence makes automation reproducible

A useful generated job has a chain you can reconstruct: DSL repository commit → seed full name/build/cause → sandbox/identity → generated item full name/config → later build source/queue/agent → reports/artifacts. If any link is implicit, debugging and governance become guesswork.

10. Common wrong approaches

  • Give every developer permission to edit an admin-equivalent seed.
  • Run arbitrary unsandboxed Groovy because “the source is in Git.”
  • Use names with timestamps/random suffixes and call repeated generation idempotent.
  • Delete jobs that merely happen to share a naming prefix.
  • Use Job DSL to replace JCasC global configuration or Pipeline runtime logic.
  • Treat a 200 API response as proof a queued/generated job completed successfully.
Next lesson

Guided Hands-On Workflow and Core Operations

Build a synthetic DSL repository, run a folder-scoped seed twice, inspect generated configuration, make one controlled change and disable one intentionally removed generated job.

Knowledge check

Answer before revealing the explanation.

1. What problem does Job DSL solve that a Jenkinsfile does not?

2. Why is a seed job a security boundary?

3. What does lookupStrategy SEED_JOB change?

4. Why is removedJobAction not just cleanup convenience?

5. What is the difference between a generated-item marker and an authorization control?

Official references and version notes

Verified baseline — 17 September 2026. Labs target Jenkins 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.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this address.