⚙️DevOps
Foundations · Lesson 4/8

CI/CD Pipelines — Automated Delivery

35 min 2 exercises 1 quiz

What you'll learn

  • What CI and CD actually mean
  • The stages of a real pipeline
  • Why automation beats manual deployment every time
  • You'll build a pipeline-stage runner

The automated assembly line 🏭

CI/CD is the beating heart of DevOps — the assembly line that carries code from a Git push to live production, automatically.

CI = Continuous Integration. Every time anyone pushes code, an automated system immediately builds it and runs the tests. If something breaks, the team knows in minutes, not after release. This catches bugs while they're small and cheap — no more "it worked on my machine, why is main broken?"

CD = Continuous Delivery/Deployment. After CI passes, the code is automatically prepared for release (Delivery) or pushed straight to production (Deployment). The best teams deploy dozens of times a day, each change small and safe.

A typical pipeline is a sequence of stages, and if any stage fails, the pipeline stops — bad code never reaches users:

push → [Build] → [Test] → [Security scan] → [Deploy to staging] → [Deploy to production]
          ✓         ✓            ✓                  ✓                     ✓
     (any ✗ stops the line and alerts the team)

You define this pipeline as a config file in your repo (tools: GitHub Actions, GitLab CI, Jenkins). This very IMBEGNAL site uses GitHub Actions — every push to main automatically builds the site and deploys it. That's CI/CD in action.

Why it's transformative:

  • Speed — ship features in minutes, not weeks of manual release rituals.
  • Safety — automated tests + gates catch problems before users do.
  • Consistency — the same steps every time; no forgotten manual step at 2 a.m.
  • Confidence — small, frequent, automated releases are far less risky than rare, giant, manual ones.

CI/CD is the skill that ties together everything in DevOps: Git triggers it, Docker is what it builds, and the cloud is where it deploys. Mastering pipelines is what makes you a DevOps engineer rather than just someone who knows the tools.

Exercise 1

Build a pipeline runner. Write runPipeline(stages) where stages is an array of { name, passed }. Run them in order and return a string reporting where it stopped:

  • If all pass: "SUCCESS: all stages passed"
  • If one fails: "FAILED at <stage name>" (stop at the first failure — later stages don't run)

Triggers and parallel stages ⚡

So far you've seen a pipeline as one straight line. Two more ideas make real pipelines faster and smarter.

Triggers. A pipeline doesn't run because someone remembers to click a button — it runs because an event fired. The most common trigger is a webhook: GitHub itself calls your CI system's API the instant you push, saying "new commit on branch X, go!" Teams also configure different triggers for different branches: a push to any feature branch might only run Build + Test (fast feedback for the developer), while a push to main runs the full pipeline including deploy stages. A scheduled trigger (like a cron job) can also kick off a pipeline nightly — useful for slow test suites you don't want blocking every push.

Parallel stages. Not every stage has to wait for the one before it. If "run unit tests" and "run a linter" don't depend on each other, a smart pipeline runs them at the same time, on separate machines, instead of one after another:

push → [Build] → ┬→ [Unit tests]   ┬→ [Deploy]
                  └→ [Lint + scan] ┘
        (both branches run in parallel, pipeline waits for both before deploying)

This is called a fan-out/fan-in shape, and it's why a pipeline with 10 stages can still finish in a couple of minutes — independent checks run simultaneously, and only truly sequential steps (you can't deploy before tests pass) wait their turn. Recognizing which stages must be sequential and which can run in parallel is a core pipeline-design skill.

Exercise 2

Build a trigger router. Write pipelineFor(branch) that decides which pipeline to run based on the branch name:

  • if branch is "main", return "full" (build + test + scan + deploy)
  • otherwise, return "fast" (build + test only)

This mirrors how real CI systems configure different jobs per branch.

Real-world case study: Knight Capital's $440M deployment 🔍

In August 2012, Knight Capital, a major U.S. trading firm, deployed new trading software to its production servers. The deployment process was manual: an engineer had to copy the new code to eight servers by hand. They missed one — it still ran old, dormant test code left over from years earlier.

When markets opened, that one server's leftover code activated and began firing enormous, unintended stock orders. Nobody had an automated pipeline that verified all eight servers ran the same, correct version before going live — so nothing caught the mismatch. It took 45 minutes to even diagnose the problem, by which point Knight Capital had lost roughly $440 million and nearly went bankrupt overnight.

The lesson is exactly what this lesson teaches: a real CI/CD pipeline builds one verified artifact and deploys that identical artifact everywhere, with automated checks confirming every target matches — eliminating the "we forgot one server" class of failure entirely.

Quick quiz

Question 1 of 6

What is Continuous Integration (CI)?

Question 2 of 6

If a pipeline's Test stage fails, what happens?

Question 3 of 6

Why is frequent automated deployment safer than rare manual releases?

Question 4 of 6

What typically triggers a CI/CD pipeline to run?

Question 5 of 6

Why do pipelines run independent stages (like tests and linting) in parallel?

Question 6 of 6

What actually caused Knight Capital's $440M loss in 2012?

Summary

  • CI = auto build + test on every push; CD = auto prepare/deploy after CI passes
  • Pipelines are staged; any failed stage stops bad code from shipping
  • Tools: GitHub Actions, GitLab CI, Jenkins (this site uses GitHub Actions!)
  • Pipelines are event-driven (webhook triggers) and can run independent stages in parallel (fan-out/fan-in) to finish faster
  • You built a stage-by-stage pipeline runner and a branch-based trigger router
  • Knight Capital's 2012 $440M loss shows why deploying one verified, identical artifact everywhere matters

Next: Kubernetes — orchestrating containers at scale in production.