Diploma in DevOps
CI/CD Pipelines with Jenkins or GitHub Actions
•
Diploma
Pipeline Architecture and Design
Introduction
Continuous integration and continuous delivery (CI/CD) pipelines are automated systems that transform a change in source code into a tested, deployable, and observable software release. A pipeline is not merely a sequence of shell commands. It is an executable model of software delivery: it expresses what must happen, in what order, under which conditions, using which execution resources, and with what evidence of success.
In Jenkins, this model is commonly expressed through a Jenkinsfile, using Declarative or Scripted Pipeline syntax. In GitHub Actions, it is expressed through YAML workflow files stored in the .github/workflows directory. Although their syntax differs, both systems support common architectural ideas: events, jobs or stages, steps, workers, dependencies, artifacts, environments, approvals, secrets, and reusable definitions.
A sound pipeline architecture balances four objectives:
Speed: rapid feedback for developers.
Reliability: repeatable and evidence-based delivery.
Security: controlled access, trusted dependencies, and protected environments.
Maintainability: understandable, reusable, and version-controlled automation.
Poorly designed pipelines can be slow, fragile, difficult to diagnose, and capable of deploying unverified software. This chapter presents a systematic approach to designing pipelines that are clear, secure, fail-fast, and suitable for professional use.
Learning Objectives
By the end of this chapter, you should be able to:
Model a CI/CD pipeline using stages, jobs, steps, agents or runners, and dependencies.
Select appropriate triggers for branches, pull requests, schedules, and releases.
Design gates, environments, approvals, and promotion paths.
Apply pipeline-as-code and reusable components in Jenkins and GitHub Actions.
Design fail-fast workflows that provide rapid and useful feedback.
Identify security, governance, maintainability, and operational risks in pipeline designs.
Explain a pipeline architecture through a practical delivery scenario.
Each activity should have a clear purpose and a defined outcome. For example, a build job should produce a versioned artifact, while a deployment job should change an environment and report the resulting state.
A pipeline has two related dimensions:
Control flow: the order and conditions under which activities run.
Data flow: the movement of source code, compiled packages, test reports, metadata, and credentials between activities.
These dimensions must be designed together. A job that compiles software but does not publish its output cannot support a later deployment job. Similarly, a deployment that does not record the artifact version weakens traceability.
CI/CD pipeline architecture showing triggers, jobs, artifacts, environments, and gates
Figure: A conceptual pipeline in which control flow moves from trigger to deployment while artifacts and evidence are retained separately.
2. Stages, Jobs, and Steps
A stage is a logical phase of delivery, such as Build, Test, Security Scan, or Deploy. A job is an executable unit assigned to one runner or agent. A step is an individual command or action within a job.
The terms are not perfectly identical across products. GitHub Actions explicitly defines workflows, jobs, and steps. Jenkins commonly uses stages and steps, while parallel branches or nested stages can represent job-like units. The conceptual distinction remains useful:
Level
Main purpose
Typical example
Workflow or pipeline
Complete delivery definition
web-service-ci
Stage
Business or technical phase
Test
Job
Unit of execution and isolation
unit-tests
Step
Command or reusable action
npm test
Artifact
Output passed or stored
container image
A stage should represent a meaningful decision or transformation, not every individual command. Excessively fine-grained stages make logs difficult to navigate and introduce unnecessary orchestration overhead. Conversely, a single enormous job obscures failures and prevents useful parallelism.
Sequential and Parallel Structure
Stages are sequential when a later activity depends on the output or evidence of an earlier one. Independent jobs should run in parallel when doing so reduces feedback time without compromising resource limits.
For example, linting, unit tests, and dependency scanning may run concurrently after checkout. Integration tests may wait for a built artifact. Production deployment must wait for approval and successful verification.
Parallelism should not be used indiscriminately. It can increase runner consumption, create contention for databases or test environments, and make failures harder to interpret. A useful design question is: Can these activities execute independently and produce reliable results when they do?
3. Agents and Runners
A Jenkins agent or GitHub Actions runner is the execution environment in which a job runs. It supplies an operating system, tools, network access, CPU, memory, and permissions.
Runners may be:
Hosted: managed by the platform provider and usually recreated for jobs.
Self-hosted: operated by the organisation and tailored to special requirements.
Static: long-lived machines with persistent state.
Ephemeral: created for a job and destroyed afterward.
Specialised: equipped with GPUs, mobile SDKs, restricted networks, or hardware.
Ephemeral execution is generally easier to trust because it reduces contamination from previous jobs. Persistent workspaces can cause hidden dependencies: a build may succeed only because an old file remains on the machine. Clean checkouts and explicit dependency installation improve reproducibility.
Runner selection is also a security boundary. A job handling untrusted pull-request code should not automatically receive access to production credentials or a sensitive self-hosted network. Labels, permissions, isolation, and network policies should reflect trust levels.
4. Triggers and Event Design
A trigger determines when a pipeline starts. Common triggers include:
push to a branch;
pull-request creation or update;
annotated tag or release creation;
manual dispatch;
scheduled execution;
completion of another workflow or upstream job;
external webhook or API event.
Trigger design should match the delivery policy. Pull requests usually require fast validation. A merge to the main branch may build and publish a candidate artifact. A release tag may initiate production promotion.
Broad triggers can waste resources. For example, running a full deployment pipeline for documentation-only changes is unnecessary if the pipeline can detect affected paths. However, path filtering must be used carefully: a change in a shared library may affect many services even when their directories are unchanged.
A secure trigger design also considers who can cause execution. Pull-request workflows may process attacker-controlled input. Secrets should not be exposed to untrusted code, and commands must not interpolate untrusted values into shell scripts without safe handling.
5. Dependencies, Artifacts, and Data Flow
Dependencies specify when a job may run and what it requires. A dependency can be:
a preceding job's successful completion;
a required artifact;
a test report or quality result;
a provisioned environment;
an approval or policy decision.
A strong architecture builds once and promotes the same artifact. Rebuilding separately for staging and production can create different binaries from the same source revision, weakening confidence that the tested object is the deployed object.
Important artifact metadata includes:
source commit identifier;
build number or release version;
dependency lock-file state;
compiler or runtime version;
test and scan results;
image digest or package checksum.
A container tag such as latest is convenient but mutable. An immutable digest or content-addressed identifier provides stronger traceability. The pipeline should record the mapping between source revision, artifact, environment, and deployment time.
6. Gates and Environments
A gate is a condition that must be satisfied before a pipeline proceeds. Gates may be automated or human-controlled.
Automated gates include:
all required tests pass;
code coverage or quality thresholds are met;
vulnerability policy is satisfied;
the artifact is signed;
infrastructure validation succeeds;
a deployment health check reports success.
A human gate may be required before production deployment, particularly where regulatory, financial, safety, or customer-impact considerations apply. Approval should not be treated as a substitute for automated evidence. It is a controlled decision informed by that evidence.
An environment is a target context such as development, test, staging, or production. It includes configuration, infrastructure, data, access controls, and operational expectations. Environment-specific values should be injected through managed configuration rather than embedded in source code.
A typical promotion model is:
Build once → Deploy to test → Verify → Deploy to staging → Approve → Deploy to production → Monitor
Environment protection may include required reviewers, restricted branches, deployment windows, concurrency limits, and environment-specific secrets. These controls should be documented because excessive restrictions can delay urgent fixes, while insufficient restrictions can permit accidental production changes.
7. Pipeline-as-Code
Pipeline-as-code stores delivery definitions in version control. It provides:
peer review of automation changes;
history and rollback;
reproducibility;
consistency across branches and services;
discoverability;
integration with normal development practices.
A Jenkins Declarative Pipeline may conceptually look like this:
pipeline {
agent any
stages {
stage('Validate') {
steps { sh './ci/validate.sh' }
}
stage('Build') {
steps { sh './ci/build.sh' }
}
stage('Test') {
steps { sh './ci/test.sh' }
}
}
}
A GitHub Actions workflow may express a similar model:
These examples are intentionally small. Production workflows should pin or otherwise govern third-party actions and plugins, define permissions explicitly, preserve reports, and handle failures deliberately.
Pipeline-as-code introduces a special risk: changing the pipeline changes the security and delivery system itself. Pipeline files therefore require code review, protected branches, ownership rules, and testing. A change that disables a security scan or redirects deployment credentials is operationally significant even if application code is unchanged.
8. Reusable Components
Reuse reduces duplication and makes organisational standards easier to apply. Reusable components include:
Jenkins shared libraries;
GitHub reusable workflows;
composite actions;
shell or Python scripts stored in the repository;
centrally managed templates;
container images containing standard build tools.
Reuse should occur at a stable abstraction boundary. A component should have a clear interface, documented inputs and outputs, predictable error behaviour, and versioning. Over-abstraction is harmful when a component hides important decisions or makes debugging difficult.
A practical rule is to keep domain-specific policy visible in the service pipeline while centralising repeated mechanics such as authentication, artifact publication, report collection, and standard security checks.
9. Fail-Fast Design
Fail-fast design aims to detect inexpensive, high-probability failures early and stop work that cannot produce a valid result. Typical early checks include syntax validation, formatting, linting, dependency resolution, and unit tests.
Fail-fast does not mean “stop after every failure regardless of context.” Some tests should continue after one failure so that developers receive a complete diagnostic report. A useful distinction is:
Informational checks: failure is reported but does not yet block delivery.
Advisory checks: results inform improvement and may become blocking later.
A pipeline should define failure semantics explicitly. Examples include whether a failed parallel branch cancels siblings, whether reports are uploaded in an always or post section, and whether deployment automatically rolls back.
Feedback time can be considered as a simple sum of durations for sequential activities:
Here, Tfeedback is the time from trigger to useful result, Tqueue is runner or scheduling delay, Tcheckout is source retrieval time, and the summation covers sequential activities. For parallel branches, only the slowest branch contributes to elapsed time, assuming sufficient capacity and no shared-resource contention. This expression is a planning model, not a universal performance law.
Fail-fast improvements therefore include reducing queue time, moving cheap checks earlier, caching safely, parallelising independent work, and avoiding unnecessary environment provisioning. Caching must not compromise correctness: cache keys should include relevant dependency and tool-version information.
10. Testing and Quality Gates
A pipeline commonly contains several test layers:
Static checks: formatting, linting, type checking, and policy validation.
Unit tests: isolated tests of small components.
Integration tests: interaction with databases, queues, APIs, or services.
System or end-to-end tests: behaviour across a complete application.
Performance and resilience tests: response under load or failure conditions.
Security checks: dependency, secret, code, container, and infrastructure scanning.
The fastest reliable tests should run first. Expensive tests should be reserved for changes or environments where their evidence is necessary. Test results, logs, screenshots, and coverage reports should be retained as pipeline evidence.
Quality thresholds require governance. A numerical coverage threshold, for example, does not guarantee good tests; it can encourage superficial testing. Gates should therefore combine quantitative indicators with meaningful test design and risk-based review.
11. A Worked Pipeline Design
Consider an illustrative online bookstore. Developers submit pull requests to a protected main branch. The service is packaged as a container and deployed to Kubernetes.
Requirements
The bookstore requires:
fast pull-request feedback;
one immutable image promoted through environments;
automated security checks;
approval before production;
rollback capability;
traceability from deployment to source commit.
Proposed Architecture
Pull-request trigger: checkout, formatting, linting, unit tests, and dependency scanning run in parallel where possible.
Merge trigger: the pipeline builds the container, runs integration tests, scans the image, signs it, and pushes it to the registry.
Test deployment: the signed image is deployed to an isolated test namespace.
Verification: smoke and API tests run against the deployment. Failure blocks promotion.
Staging deployment: the same image digest is deployed to staging, followed by end-to-end tests.
Production gate: a protected environment requires an authorised reviewer and a successful policy evaluation.
Production deployment: the image is deployed using a controlled rollout.
Post-deployment verification: health checks, error-rate monitoring, and a short observation period determine whether to continue or roll back.
Analysis
The design separates validation from deployment and preserves the artifact across environments. Pull requests do not receive production secrets. The production environment has a restricted deployment path, and the image digest provides evidence that the tested image is the deployed image.
A possible failure policy is:
lint failure: stop the affected validation job;
unit-test failure: block merge and publish test reports;
image-scan failure: block publication or promotion according to severity policy;
test deployment failure: block staging;
failed production health check: stop rollout and invoke rollback procedure.
Outcome
This architecture reduces accidental production changes, shortens feedback for common coding errors, and improves auditability. It also introduces operational costs: runners, registries, environments, test data, and monitoring must be maintained. The organisation should periodically review whether each gate provides sufficient risk reduction for its cost.
Learning Points
The central lesson is that pipeline design is a systems problem. Execution order, artifact identity, permissions, test evidence, environment controls, and operational feedback must be designed as one system.
12. Security, Governance, and Ethical Considerations
Pipelines often hold significant power: they can access source code, cloud accounts, registries, customer environments, and production data. Security controls should include least-privilege permissions, short-lived credentials, secret masking, protected branches, dependency review, and auditable approvals.
Secrets should never be committed to repositories or printed in logs. Environment credentials should be scoped to the required job and environment. Third-party actions and Jenkins plugins should be reviewed, updated, and pinned according to organisational policy.
Pull-request code is potentially untrusted. Avoid executing attacker-controlled scripts with privileged credentials or on sensitive self-hosted runners. Shell commands should quote variables safely, and inputs should be validated.
Governance also includes separation of duties, change records, retention policies, and evidence suitable for audits. In regulated contexts, the pipeline may need to demonstrate who approved a release, which source revision was used, which tests passed, and what was deployed.
Ethically, automation should not conceal consequential decisions behind opaque rules. Teams should understand why a release was blocked, how exceptions are granted, and who is accountable for overriding a gate. Automated vulnerability tools can produce false positives and false negatives; their results require informed interpretation.
13. Contemporary Developments and Limitations
Modern pipeline platforms increasingly support reusable workflows, policy-as-code, software supply-chain attestations, signed artifacts, ephemeral runners, deployment strategies such as canary releases, and observability-driven verification. AI-assisted tools can help generate tests, explain failures, or suggest workflow changes, but generated automation must be reviewed. AI output can contain insecure commands, incorrect assumptions, or excessive permissions.
No pipeline eliminates risk. Tests may miss defects, staging may differ from production, external services may fail, and monitoring may detect problems only after customer impact. Pipeline metrics should therefore be interpreted carefully. Useful measures include deployment frequency, lead time, change failure rate, recovery time, queue time, flaky-test rate, and mean pipeline duration. Metrics should support improvement rather than encourage unsafe pressure to deploy.
Best-Practice Checklist
A professionally designed pipeline should generally:
use version-controlled pipeline definitions;
validate changes early;
build once and promote an immutable artifact;
separate jobs according to meaningful responsibilities;
parallelise independent work safely;
use clean or ephemeral execution environments where practical;
define explicit dependencies and failure behaviour;
protect production environments and credentials;
retain test, scan, and deployment evidence;
use reusable components with clear interfaces;
provide actionable logs and reports;
support rollback or forward-fix procedures;
review third-party actions, plugins, and dependencies;
test the pipeline itself through code review and controlled changes.
Chapter Summary
Pipeline architecture models software delivery as controlled flow from an event to a verified release. Stages organise meaningful phases; jobs provide executable isolation; steps perform actions; and runners or agents supply the execution environment. Triggers determine when work begins, while dependencies and artifacts define control and data flow.
Effective designs use automated gates, protected environments, immutable artifacts, and pipeline-as-code. Reusable workflows and shared libraries reduce duplication, but they must have clear interfaces and governance. Fail-fast design moves inexpensive and reliable checks early, while parallel execution reduces feedback time when resources and independence permit. Security requires least privilege, protected secrets, trusted runners, and review of pipeline changes. Finally, deployment verification, observability, and rollback planning extend the pipeline beyond compilation and testing into responsible operational delivery.
Key Terms
Agent: A Jenkins execution environment assigned to run pipeline work.
Artifact: A versioned output such as a package, binary, or container image.
Approval gate: A human or organisational decision required before progression.
Dependency: A condition or prior result required by a job.
Deployment: The act of releasing an artifact into an environment.
Environment: A target context with infrastructure, configuration, access, and operational rules.
Ephemeral runner: A temporary execution worker created for limited use.
Fail-fast: Designing work so useful failures are detected early and unnecessary work is avoided.
Gate: A condition that must be satisfied before pipeline progression.
GitHub Actions: GitHub’s workflow automation service based on YAML-defined jobs and steps.
Immutable artifact: An output whose contents cannot change under its identity.
Jenkinsfile: A version-controlled file defining a Jenkins pipeline.
Job: An executable unit assigned to a runner or agent.
Pipeline-as-code: Storing delivery automation definitions in version control.
Runner: A machine or environment that executes a GitHub Actions job.
Stage: A logical phase of a pipeline, such as build or test.
Step: An individual command or action within a job.
Trigger: An event that starts pipeline execution.
Workflow: A complete automated process, especially in GitHub Actions.
Review Questions
Short Answer Questions
Distinguish between a stage, job, and step.
Why is building once and promoting the same artifact preferable to rebuilding for each environment?
Identify three common CI/CD triggers.
What is the purpose of an approval gate?
State two security risks associated with self-hosted runners.
Long Answer Questions
Explain how control flow and data flow interact in a CI/CD pipeline.
Compare hosted, self-hosted, persistent, and ephemeral runners.
Describe the principles and benefits of pipeline-as-code.
Explain how a pipeline can be designed for fail-fast feedback without hiding useful diagnostic information.
Discuss the role of environments, gates, artifacts, and verification in production delivery.
Analytical / Application Questions
Design a pipeline for a web application that must run pull-request checks, publish a container after merge, deploy to staging, and require approval before production. Identify triggers, jobs, dependencies, artifacts, gates, and environments.
A pipeline takes 35 minutes although most tests are independent. Analyse likely architectural causes and propose improvements without reducing test reliability.
A pull-request workflow runs untrusted code on a self-hosted runner that has cloud production credentials. Evaluate the risks and propose a safer design.
Multiple Choice Questions with Answers
Question 1
Which element represents an individual command or action within a job?
A. Trigger
B. Step
C. Environment
D. Artifact
Correct Answer: B. Step
Question 2
What is the main advantage of promoting one immutable artifact through multiple environments?
A. It eliminates the need for testing
B. It ensures each environment receives a newly rebuilt package
C. It improves traceability between tested and deployed software
D. It removes the need for environment configuration
Correct Answer: C. It improves traceability between tested and deployed software
Question 3
Which activity is most appropriate as an early fail-fast check?
A. Production rollback
B. Formatting or lint validation
C. Manual customer training
D. Long-term performance observation
Correct Answer: B. Formatting or lint validation
Question 4
What is a primary security concern when untrusted pull-request code uses a self-hosted runner?
A. The job may have access to sensitive networks or credentials
B. The repository cannot contain YAML
C. Unit tests will always run sequentially
D. Artifacts become automatically immutable
Correct Answer: A. The job may have access to sensitive networks or credentials
Question 5
In GitHub Actions, what commonly expresses that one job must wait for another?
A. The needs relationship
B. The uses version
C. The runs-on label alone
D. The artifact filename
Correct Answer: A. The needs relationship
Question 6
Which practice best supports release traceability?
A. Using only the mutable tag latest
B. Recording the source revision and artifact digest
C. Deleting test reports after every job
D. Rebuilding independently in production
Correct Answer: B. Recording the source revision and artifact digest
Question 7
What is the purpose of an environment protection rule?
A. To prevent all automated testing
B. To control access and progression into a target environment
C. To replace source control
D. To remove the need for deployment monitoring
Correct Answer: B. To control access and progression into a target environment
Question 8
When is parallel execution most appropriate?
A. When activities are independent and resources are sufficient
B. When every activity modifies the same temporary file
C. When one job requires the output of another
D. When failure evidence is not needed
Correct Answer: A. When activities are independent and resources are sufficient
Question 9
What does pipeline-as-code primarily provide?
A. A way to avoid reviewing automation changes
B. Versioning, review, and reproducibility of delivery definitions
C. Automatic immunity from security vulnerabilities
D. A guarantee that all deployments succeed
Correct Answer: B. Versioning, review, and reproducibility of delivery definitions
Question 10
Which statement about human approval gates is most accurate?
A. They should replace automated testing
B. They provide controlled decision-making informed by automated evidence
C. They make artifact identity unnecessary
D. They are required for every development commit
Correct Answer: B. They provide controlled decision-making informed by automated evidence
CI/CD Pipelines with Jenkins or GitHub Actions
Chapter 3
of 14