Introduction to Jenkins and CI/CD¶
Overview¶
Teams ship broken software when builds are tribal knowledge: “works on my machine,” undocumented deploy steps, and green checkboxes that never meant “safe to release.” Continuous Integration (CI) and Continuous Delivery (CD) turn every meaningful Git change into an automated, repeatable proof of health — and keep a releasable artefact ready when policy says go.
Jenkins is a self-managed automation server that runs that loop as jobs. A controller schedules work and stores configuration; agents execute the untrusted build steps. This course uses Jenkins Long-Term Support (LTS) and Declarative Pipeline as the production path. Blue Ocean is legacy UI only — do not treat it as the learning track.
This is Tutorial 1 in Module 1: Introduction to Jenkins and CI/CD of the REBASH Academy Jenkins for Cloud & DevOps Engineers series — written for Cloud, DevOps, Platform, and Site Reliability Engineering (SRE) engineers. By the end you will map CI/CD vocabulary to a controller–agent model and leave a Pipeline sketch you can import after install.
Prerequisites¶
- Git — commits, branches, and pull requests
- Docker — for later modules that run Jenkins LTS in Compose
- A text editor and a shell (macOS, Linux, or Windows Subsystem for Linux (WSL))
- No running Jenkins controller required for this tutorial’s lab
Learning Objectives¶
By the end of this tutorial, you will be able to:
- Define CI, Continuous Delivery, and how Jenkins implements each
- Sketch controller, agent (node), executor, plugin, and
JENKINS_HOME - Contrast Jenkins LTS with weekly releases for production use
- Decide when a self-managed Jenkins controller beats forge-native SaaS CI
- Produce a Declarative Pipeline stub and a CI stage map under
~/rebash-jenkins/module-01
Architecture¶
Source events enter the controller; labelled agents run stages; status and artefacts return to Jenkins.
Theory¶
What it is¶
Continuous Integration (CI) means every push or merge request runs a known script: checkout, build, test, and report status. The goal is a shared automated truth about branch health — not a nightly hope.
Continuous Delivery (CD) means the same system also produces a releasable artefact and can deploy it, with a person or policy deciding when. Continuous Deployment is the stricter variant where every green mainline change ships without a human gate; most enterprises stop at delivery for production.
Jenkins is an open-source automation server. A controller holds configuration, plugins, credentials metadata, the job catalogue, and build history under JENKINS_HOME. Agents (also called nodes) provide executors and workspaces where builds actually run. Plugins extend Source Control Management (SCM), Pipeline, credentials, cloud agents, and reporting. Prefer Jenkins LTS for production; weekly releases expose newer features earlier with more churn.
The Pipeline Getting Started “Guided Tour” mental model matches this loop: define a Pipeline, run it, inspect the stage view and console.
Why it matters¶
Forge-native CI (GitHub Actions, GitLab CI) is excellent when your source of truth and identity already live there. Enterprises still run Jenkins when pipelines must reach private networks, custom toolchains, regulated environments, multi-SCM estates, or long-lived shared libraries owned by a platform team.
Platform and SRE teams treat the controller as a product: versioned configuration, agent isolation, plugin governance, and upgrade runbooks. If you only learn “click New Item,” you cannot recover after a disk failure or a bad plugin upgrade. CI/CD vocabulary first prevents treating Jenkins as a UI that builds instead of a scheduled, auditable delivery system.
How it works¶
Mental model: SCM event or schedule → controller selects a job → executor on an agent runs steps → status, artefacts, and logs return to Jenkins.
- Source changes land in Git (or another SCM).
- A trigger starts a build: webhook, poll SCM, timer (
cron), or manual. - The controller assigns an executor matching the job’s agent label or Pipeline
agentdirective. - The agent checks out code, runs stages and steps, and streams console output.
- Post actions publish tests, archive artefacts, or notify chat; history stays on the controller.
Declarative Pipeline encodes that path in a Jenkinsfile reviewed like application code. Freestyle jobs still exist for contrast later; this course centres Pipeline-as-code.
Key concepts and comparisons¶
| Term | Meaning |
|---|---|
| Controller | Schedules jobs; stores config, plugins, and history in JENKINS_HOME |
| Agent / node | Machine or container that runs builds |
| Executor | Slot on a node that can run one concurrent build |
| Workspace | Checkout directory for a build on an agent |
| Plugin | Extension that adds SCM, Pipeline, cloud, or reporting features |
| LTS | Long-Term Support line recommended for production |
| Without CI/CD | With Jenkins Pipeline |
|---|---|
| “Works on my machine” | Same agent image or label every run |
| Unreviewed production changes | Jenkinsfile in the pull request |
| Rebuild from memory after outage | Rebuild from a known Git SHA |
| Option | Strength | Trade-off |
|---|---|---|
| Jenkins (self-managed) | Flexible agents, private networks, shared libraries | You operate the control plane |
| GitHub Actions | Tight GitHub identity and marketplace | Harder for some private/on-prem toolchains |
| GitLab CI | Pipeline next to GitLab SCM | Best when GitLab is already the forge |
Common pitfalls¶
- CI is not “the controller” — the controller schedules; agents execute.
- A green build is not a production release unless you designed deploy stages and approvals that way.
- Building on the built-in node couples untrusted Pipeline code to the control plane and credentials store.
- Running weekly Jenkins without a test controller is how plugin upgrades become outages.
- Treating Blue Ocean as the modern path — Declarative Pipeline in classic UI (or Configuration as Code) is the supported route.
Hands-on Lab¶
Objective¶
Create a CI/CD stage map and a minimal Declarative Jenkinsfile under ~/rebash-jenkins/module-01, then prove both files with shell asserts. No live controller is required yet.
Prerequisites¶
- Bash shell and
grep,test - Write access to your home directory
Lab environment¶
Workspace: ~/rebash-jenkins/module-01
mkdir -p ~/rebash-jenkins/module-01 && cd ~/rebash-jenkins/module-01
set -euo pipefail
pwd | tee pwd-start.txt
Expected output
pwd-start.txt ends with module-01.
Real-world scenario¶
Your platform team is introducing Jenkins LTS next sprint. Before anyone installs a controller, you must agree on CI versus CD language, document which stages belong in Pipeline, and leave a stub Jenkinsfile that Module 2 can run after Docker Compose comes up.
Step-by-step tasks¶
Task 1 – Map CI stages to machine-readable YAML¶
Write a stage map that separates “prove the change” from “ship the change.”
Run:
Create ci-cd-stages.yaml:
ci:
description: Continuous Integration — every PR or push
stages:
- id: checkout
action: fetch Git SHA
- id: build
action: compile or package
- id: unit-test
action: fast tests; fail the build on red
- id: static-checks
action: lint, format, secret scan as policy
cd:
description: Continuous Delivery — main or release branch
stages:
- id: package
action: versioned artefact
- id: deploy-staging
action: automated or gated
- id: approve-production
action: human or policy gate
- id: deploy-production
action: explicit stage with scoped credentials
ownership:
controller: schedule, history, credentials metadata
agents: execute untrusted steps off the built-in node
Validate and archive:
python3 -c "
import yaml
with open('ci-cd-stages.yaml') as f:
d = yaml.safe_load(f)
assert 'ci' in d and 'cd' in d
assert len(d['ci']['stages']) >= 4
assert len(d['cd']['stages']) >= 4
print('ci-cd-stages.yaml OK')
" | tee stage-map-validate.txt
Expected output
stage-map-validate.txt shows ci-cd-stages.yaml OK.
Task 2 – Sketch controller versus agent responsibilities¶
Run:
Create controller-agent.yaml:
controller:
stores:
- JENKINS_HOME
- job definitions
- plugin catalogue
- credentials store (encrypted)
- build history and logs index
agents:
provide:
- workspaces
- toolchains (JDK, Node, Docker CLI as designed)
- build processes
- ephemeral build secrets in memory or env as injected
- CPU, memory, network for compile and test
policy:
builtin_node_executors_production: 0
preferred_agent_label: "linux && docker"
Validate and archive:
python3 -c "
import yaml
with open('controller-agent.yaml') as f:
d = yaml.safe_load(f)
assert d['policy']['builtin_node_executors_production'] == 0
assert 'JENKINS_HOME' in d['controller']['stores'][0]
print('controller-agent.yaml OK')
" | tee architecture-validate.txt
Expected output
architecture-validate.txt shows validation OK.
Task 3 – Write a minimal Declarative Jenkinsfile stub¶
Run:
Create demo-app/Jenkinsfile:
// REBASH Academy — Module 1 Declarative stub (import in Module 2+)
pipeline {
agent any
options {
timestamps()
disableConcurrentBuilds()
}
stages {
stage('Checkout info') {
steps {
echo "CI stub — replace agent any with a labelled agent before production"
sh 'uname -a || ver'
}
}
stage('Unit placeholder') {
steps {
echo 'Add real tests in later modules'
}
}
}
post {
always {
echo "Build finished: ${currentBuild.currentResult}"
}
}
}
Verify:
test -f demo-app/Jenkinsfile
grep -q 'pipeline {' demo-app/Jenkinsfile
grep -q 'stages {' demo-app/Jenkinsfile
grep -q 'post {' demo-app/Jenkinsfile
# Escape-safe check for agent directive
grep -E 'agent[[:space:]]+any' demo-app/Jenkinsfile
cp demo-app/Jenkinsfile ./Jenkinsfile
ls -l Jenkinsfile demo-app/Jenkinsfile | tee jenkinsfile-listing.txt
Expected output
Listing shows both copies; pipeline, stages, post, and agent any present.
Task 4 – Record LTS choice for the track¶
Run:
Create lts-policy.yaml:
release_line:
production: jenkins/jenkins:lts-jdk17
labs: jenkins/jenkins:lts-jdk17
weekly_preview: disposable controller only
upgrade:
order:
- test controller
- production
prerequisite: JENKINS_HOME backup
reference: https://www.jenkins.io/download/lts/
Validate and archive:
python3 -c "
import yaml
with open('lts-policy.yaml') as f:
d = yaml.safe_load(f)
assert 'lts-jdk17' in d['release_line']['production']
print('lts-policy.yaml OK')
" | tee lts-validate.txt
tar -czf module-01-evidence.tgz ci-cd-stages.yaml controller-agent.yaml lts-policy.yaml Jenkinsfile demo-app/Jenkinsfile *.txt
ls -l module-01-evidence.tgz | tee evidence.txt
Expected output
module-01-evidence.tgz exists; evidence.txt shows its size.
Validation steps¶
-
ci-cd-stages.yamlvalidates with Python and lists CI and CD stages separately -
controller-agent.yamlsets built-in node executors to 0 for production -
Jenkinsfilecontainspipeline,stages, andpost -
module-01-evidence.tgzarchives the artefacts
Common errors and fixes¶
| Error | Cause | Fix |
|---|---|---|
set: pipefail: invalid option | Old /bin/sh | Run under bash |
grep fails on Jenkinsfile | Typo in stub | Re-run Task 3 heredoc |
MacOS uname only | Expected | Lab allows uname -a \|\| ver |
Challenge exercise¶
Extend demo-app/Jenkinsfile with a third stage named Package placeholder that echoes a semver-style version string (for example 0.1.0-module01). Keep Declarative syntax valid. Re-run the grep checks from Task 3.
Learning outcomes¶
- Separated CI proof stages from CD ship stages in validated YAML
- Mapped controller versus agent responsibilities in
controller-agent.yaml - Produced an importable Declarative Jenkinsfile stub
- Recorded an LTS policy in
lts-policy.yamlfor the rest of the course
Cleanup¶
# Keep ~/rebash-jenkins/module-01 for Module 2 — no containers started in this lab
ls ~/rebash-jenkins/module-01
Validation¶
- Lab commands completed under
~/rebash-jenkins/module-01/ - You can explain CI vs Continuous Delivery without conflating “green build” and “released”
- You can sketch controller, agent, executor, and
JENKINS_HOME - You can name one production failure mode from building on the built-in node
Code Walkthrough¶
- Inspect vocabulary before tooling — agree CI vs CD before choosing plugins.
- Encode the path early — a stub
Jenkinsfilebeats a click-built Freestyle job you cannot review. - Capture evidence — validated YAML stage maps and archives help onboarding and audits.
- Prefer LTS — pin the support line; preview weeklies elsewhere.
- Isolate execution — design for labelled agents from day one, even if the stub still says
agent any.
Security Considerations¶
- Treat the controller as a high-value host: it holds credentials metadata and can schedule privileged deploys.
- Never run untrusted pull-request Pipelines on the built-in node.
- Do not commit real secrets into
Jenkinsfileor lab artefacts. - Limit who can administer the controller; developers usually need job permissions, not Overall/Administer.
- Plan backup of
JENKINS_HOMEbefore you care about the first production Pipeline.
Common Mistakes¶
Calling every green build Continuous Delivery
CI proves the change. Delivery requires packaging, environment credentials, and an explicit deploy path. Fix: name CD stages in the Jenkinsfile and in your stage map.
Building on the built-in node
Pipeline steps can reach controller filesystem and credential stores. Fix: use agent labels (or Kubernetes/Docker agents) and disable executors on the built-in node in production designs.
Chasing weekly Jenkins for production
Plugin and core churn breaks Monday mornings. Fix: LTS on production; weeklies only on a disposable test controller.
Learning Blue Ocean as the modern Jenkins
Blue Ocean is legacy. Fix: learn Declarative Pipeline syntax and the classic Pipeline Stage View / Blue Ocean-free workflows.
Best Practices¶
- Keep Pipeline definitions in SCM from the first real job.
- Prefer Jenkins LTS images or packages with pinned versions.
- Document controller versus agent ownership for every new team.
- Use the same mental model as the Guided Tour: stages you can see, console you can read.
- Destroy lab controllers when finished; keep
~/rebash-jenkins/artefacts for the track.
Troubleshooting¶
| Symptom | Likely cause | Fix |
|---|---|---|
| Debate: “Is deploy part of CI?” | Vocabulary clash | Use the Module 1 stage map: CI proves, CD ships |
| Job always queued | No matching agent / zero executors | Attach an agent or enable a lab executor carefully |
| “Works in UI, missing in Git” | Click-ops job | Move definition into Jenkinsfile |
| Fear of upgrades | No test controller | Add a disposable LTS controller for plugin trials |
| Confusion with GitHub Actions | Forge-native vs self-managed | Choose by network, identity, and ownership of the control plane |
Summary¶
CI automates proof of every change; Continuous Delivery keeps shipping ready under policy. Jenkins LTS implements that with a controller that schedules and agents that execute — never reverse those roles in production. Continue with Installing Jenkins LTS to bring up a Compose controller and unlock the Module 1 stub.
Interview Questions¶
1. What is the difference between Continuous Integration and Continuous Delivery?
Reveal answer
CI runs automated build and test on every meaningful change so defects surface quickly. Continuous Delivery also produces a releasable artefact and can deploy, with a human or policy gate deciding when production changes. Continuous Deployment removes that gate for every green mainline change.
2. What does the Jenkins controller store, and what should agents do instead?
Reveal answer
The controller stores JENKINS_HOME: jobs, plugins, credentials metadata, and build history. Agents provide workspaces, toolchains, and CPU so untrusted build steps do not run on the control plane.
3. Why prefer Jenkins LTS over weekly releases in production?
Reveal answer
LTS is the supported production line with a slower, more predictable upgrade cadence. Weeklies deliver features earlier but increase plugin and core churn. Validate weeklies on a non-production controller if you need them.
4. When would you choose Jenkins over GitHub Actions or GitLab CI?
Reveal answer
Choose Jenkins when you need self-managed agents on private networks, heterogeneous SCM, heavy shared libraries, or regulated environments where the platform team owns the control plane. Prefer forge-native CI when source, identity, and runners already live in that forge and meet your compliance needs.
5. What is an executor, and how does it relate to a node?
Reveal answer
A node (agent) is a machine or container registered with Jenkins. An executor is a concurrent build slot on that node. Two executors can run two builds at once on the same node, sharing its disk and tools — which is why noisy neighbours and workspace cleanup matter.
6. Why is building on the built-in node a production risk?
Reveal answer
Pipeline steps can touch the controller filesystem and credentials. A malicious or buggy build on the built-in node expands blast radius to the entire Jenkins estate. Production designs disable or severely limit built-in executors and force labelled agents.
7. How does the Guided Tour mental model help new Jenkins users?
Reveal answer
It ties UI concepts to Pipeline stages: you define stages and steps, run a build, then inspect stage status and console output. That loop matches how operators debug real jobs — less clicking Freestyle builders, more reading Pipeline as code.
8. Is a green CI build enough to call a release “done”?
Reveal answer
No. Green CI means the defined checks passed for that SHA. A release still needs packaging, environment promotion, credentials scoping, and whatever approval policy your organisation requires for production.