Deployment Pipelines and Continuous Delivery
Deployment Pipelines and Continuous Delivery
This session moves past continuous integration into the deployment side of the pipeline. We look at what deployment is, the considerations a team should settle before deploying, the challenges that make release processes slow and risky, what a deployment pipeline is and how its structure looks, the value stream map with its cycle, waste, and lead times, intelligent pipeline scheduling, the release plan, smoke testing, and a quick CI/CD knowledge check.
13.1 Continuous Delivery and Continuous Deployment
What is the smallest possible difference between two of the most used terms in the DevOps vocabulary? One button — the button that pushes code into production.
Hook: Delivery and deployment describe the same automated chain of commit, build, and test. They split at exactly one point: who (or what) performs the final push to production. If a human presses that button, the flow is continuous delivery. If no human is needed, it is continuous deployment.
13.1.1 How the Delivery Flow Runs
The whole flow starts with the developers and the DevOps team changing code. The moment the code is committed to the source code management (SCM) repository — the single versioned home of the codebase — the build process triggers automatically. Nobody logs into a server and runs the build by hand; the commit itself is the trigger. Once the build finishes, the testing cycles start automatically as well: capacity testing (can the system handle the expected load?), functional testing (does each feature behave as specified?), and so on. Every step in this chain happens with tools and technology, not by hand.
This is an ongoing process. The team keeps adding a new feature, enhancing existing functionality, or fixing bugs, and the loop keeps running until the product cycle for that particular product is complete. Nothing about this loop is a one-time event: each check-in restarts the entire cycle, which is why the word "continuous" matters. In this course the flow is called continuous integration while it covers commit through build and test; the term continuous delivery (and its relative continuous deployment) starts where the artifacts begin moving toward the environments where users will meet them.
13.1.2 Continuous Delivery
Continuous delivery is the state where everything up to the production push is automated. The code is built automatically, tested automatically, and then delivered automatically to a staging, pre-production, or UAT (user acceptance testing) environment. That automated handoff to those intermediate environments is what the word "delivery" covers. The one step that stays manual is pushing the code to the production environment.
The distinction is sharp: if you deliver the code to the staging, pre-production, or UAT environment with automation, you call it continuous delivery — as long as the final step, pushing to production, is still a human action. Each intermediate environment has a purpose: staging is a rehearsal environment built to look like production; pre-production runs the last checks before going live; UAT is where end users (or their representatives) confirm that the software actually meets their needs. All three are delivery targets. Production is not one of them in continuous delivery — a human decides when the verified artifact is allowed in.
13.1.3 Continuous Deployment
Continuous deployment removes that last manual step. Everything is automatic, end to end: you commit a code change, the build process triggers with automation, further testing happens on the respective environments with automation, and pushing the artifact and the code to the production environment also happens via automation. The pipeline does not end until the code sits in the production environment.
So the difference between the two terms is one step: in continuous delivery the production push is manual; in continuous deployment it is automated too. Continuous delivery is the prerequisite for continuous deployment — just as continuous integration is the prerequisite for continuous delivery. You cannot meaningfully automate the production push of an artifact that has not been built and tested automatically first; each stage builds on the guarantees of the previous one.
13.1.4 The Contrast in One View
A useful way to remember the pair: continuous delivery gets you ready to deploy at any moment, with a human pressing the final button; continuous deployment does not wait for a human — every check-in that passes the pipeline ends up in production on its own. Both terms describe an automatic flow from commit through build and test; they split only at the production boundary.
| Dimension | Continuous delivery | Continuous deployment |
|---|---|---|
| Commit → build → test | Automated | Automated |
| Handoff to staging / pre-production / UAT | Automated | Automated |
| Push to production | Manual (human decision) | Automated |
| Requirement to practice | High-quality automated test suite covering everything before production | Everything in delivery, plus enough monitoring and rollback confidence to auto-ship |
| Typical users | Almost every context: web, mobile apps, embedded systems, packaged products | Mainly online services deployed frequently (web and cloud) |
The guiding question for a team: what happens between the last green test run and production? If the answer names a person pressing a button, the team is practicing continuous delivery. If the answer is "nothing — the pipeline does it", the team has moved to continuous deployment.
Pitfalls:
- Equating "automated build and test" with continuous deployment. Automation of commit, build, and test is continuous integration; the terms delivery and deployment are about the production boundary only.
- Assuming continuous deployment means no human oversight anywhere. It means no manual deployment step; teams still watch dashboards, respond to incidents, and decide policy.
- Treating the two words as interchangeable in interviews or exams — the standard question is exactly the one-step difference above.
Real-world: at Amazon and Google, most teams practice continuous delivery, and some practice continuous deployment — there is real variation between teams in how often they deploy and how the deployment happens. Teams choose based on the risk they are managing: an online service with strong automated tests and quick rollback can auto-ship every passing change, while a team shipping software to devices in the field usually keeps a human in the loop at the release boundary.
Recap: Continuous integration automates commit → build → test. Continuous delivery adds the automated handoff to staging, pre-production, or UAT and keeps the production push manual. Continuous deployment automates that final push as well — one step separates the two.
Bridge: Knowing what the end state looks like, the next section asks what a team must settle before it performs any deployment: the deployment considerations that the class brainstormed.
13.2 Deployment Considerations
Before any team performs a deployment, it should be clear about several considerations. The class brainstormed this exact question, and the list the discussion produced became the backbone of the rest of the session: four answers from the class itself, three formal additions from the discussion, and a fourth practical one — tools.
13.2.1 The Class Brainstorms Considerations
Q: After continuous deployment, what considerations should a team keep in mind? If anything goes wrong, we need a rollback. Unit testing should be there. Deployment should be a security check and should cause minimum or no downtime.
A: Yes, very clear. A rollback plan should be there. Unit testing is part of the continuous integration best practices — every kind of testing is done, unit testing included. Deployment needs a security check. Deployment should cause minimum or no downtime — that means zero downtime deployment.
So the class itself named four things: a rollback plan, unit testing, a security check, and zero downtime. The discussion then added three more formal considerations: compatibility, thorough testing (canary style), and rollback versus roll forward, plus a fourth practical one — tools. None of these are nice-to-haves; each one answers a question that will come up the moment a release goes wrong, so the checklist doubles as a risk register for the release.
| Consideration | Question it answers |
|---|---|
| Rollback plan | What do we do if the deployment goes wrong? |
| Unit testing (with every other test) | Do we know the change is correct before it ships? |
| Security check | Is the deployed software safe to expose to users? |
| Zero downtime | Do users stay online during the deployment? |
| Compatibility (backward and forward) | Do old and new versions of the app and its data keep working together? |
| Thorough testing (canary style) | Do real end users confirm the product is fit to use? |
| Rollback versus roll forward | Do we revert, or do we fix forward? |
| Tools | On what platform are we deploying, and with which toolchain? |
13.2.2 Compatibility: Backward and Forward
The first formal consideration is compatibility, and it comes in two directions: backward compatibility and forward compatibility.
Backward compatibility means the new version of your application should support the older version's services as well — the new version keeps the old version's behavior alive. The case study used was an e-grocery application.
Worked example — the signup schema. Version 1.0 of the e-grocery app asked for just two fields during signup: a user name and an email ID. That was the whole signup form in 1.0. Now version 1.1 arrives, and the team has improved the database schema: signup now needs more attributes — the user, the email, and two new fields, contact number and address.
| Field | Stored for version 1.0 users (50 users) | Stored for new users from version 1.1 |
|---|---|---|
| User name | ✓ | ✓ |
| Email ID | ✓ | ✓ |
| Contact number | null (unknown) | ✓ |
| Address | null (unknown) | ✓ |
Fifty users have already registered on version 1.0, and they are stored in the database with only a user name and an email — their contact and address entries are simply unknown, null.
The key demand of backward compatibility is that adding these two new elements to the database schema must not impact those previous 50 users. When the fifty-first user signs up, they give all the attributes the new form asks for. But the old 50 users must not start getting errors when they interact with the app — the software must not complain that "this entry is null" for contact or address. Null values for those users must be tolerated, not treated as a failure. The deployment of version 1.1 is backward compatible when it supports the older version's services without breaking them.
Sense-check: the question "would a 1.0 user still work after the 1.1 deployment?" gets a "yes" — the schema grew, but nothing the old users rely on was removed or made stricter.
The design rule behind the example: the safe way to evolve a schema is to add new fields or tables, not to repurpose or drop existing ones. The old behavior keeps working, and the new fields can be filled in gradually.
13.2.3 Forward Compatibility
Forward compatibility is the opposite direction: the application should be compatible with the upcoming versions, and users should always know which version they need to access a given feature. The same e-grocery story continues.
Worked example — the report feature. In version 1.0, report generation was not available. Version 1.1 introduces a new feature: an end user can generate a report of all the groceries they purchased in the last one month, and download it from version 1.1 of the application.
Now suppose a customer is still on version 1.0 and tries to access this report generation feature. The application should be in a position to give them a proper message: to access this feature, you have to use version 1.1, the latest version of the software. That message, rather than a crash or a blank screen, is what forward compatibility means in practice — the older version fails gracefully and tells the user exactly what to do next.
Sense-check: the question "would a user on the old version get a helpful path to the new feature?" gets a "yes" — they are told which version to upgrade to, instead of staring at a broken screen.
| Dimension | Backward compatibility | Forward compatibility |
|---|---|---|
| Direction | New version supports old version's services | Old version behaves gracefully toward upcoming versions |
| Failure mode to avoid | New version breaks old users (e.g., null crash on signup data) | Old version crashes or blanks out on a feature it does not have |
| Question it answers | Will existing users keep working after the upgrade? | Will users who have not upgraded yet know what to do? |
| Example | 1.1 tolerates null contact/address for the 50 users from 1.0 | 1.0 tells the user to move to 1.1 for the report feature |
The takeaway constraint: an application should always be backward and forward compatible at the same time. Both directions protect the same thing — the moment in between deployments when two versions of the system coexist in the world.
13.2.4 Canary Testing
A deployment should also be well tested. The class mentioned this in the brainstorm, and the fuller name for it is canary testing — some people call it alpha or beta testing. The idea: end users perform the testing and access the features, then report whether the product or application is fit to use or not. The canary question came up again later in the session.
Q: When will we cover canary testing?
A: We will talk about canary testing when we discuss deployment strategies in the upcoming session — the canary deployment strategies topic covers canary testing as well.
So canary testing is on the agenda under deployment strategies, which is a separate topic that comes after this one. What matters here is the role it plays in the consideration list: automated tests in the pipeline prove the software is technically sound, and canary testing is the layer where real users (the "end-user testers") judge whether the product is fit to use.
13.2.5 Rollback and Roll Forward
Rollback was the first thing the class named, and it gets a careful treatment.
Rollback answers the question: what if your deployment went wrong? The application is not working well in the production environment, bugs have appeared, and it is not easy to find the root cause of those bugs. If you do not know the root cause, you cannot fix it — so rather than keeping the application inactive (unavailable to end users), you go back to the previous version. The application shifts back and stays available; it is not a complete downtime. Meanwhile the team finds the root cause and solves the issue at its own pace.
The key property to notice: rollback is a downtime-avoiding move. The old version takes over instantly, users keep getting service, and the debugging happens in the background, without the pressure of a dead application.
Roll forward handles the same situation differently. Suppose there is a bug and you know exactly why it happened — the team understood why the bug was captured and how to fix it. Since you know the solution, you write the fix and push the package: by fixing two or three lines of code, you push that package on top of the latest version of your application. That is a roll forward.
The deciding factor between the two is knowledge: unknown root cause means roll back; known root cause and known fix means roll forward.
| Situation | Root cause known? | Action |
|---|---|---|
| Application broken in production, bugs appear, cause is unclear | No | Roll back to the previous version; keep service available; debug at leisure |
| A bug is captured and the team understands exactly why and how to fix it | Yes | Roll forward: fix two or three lines, push the new package on top of the latest version |
In practice the decision is rarely made by a machine: a human looks at how serious the error is and then chooses between rolling back and rolling forward. Rolling back is the more cautious path (it reverts to a known-good state), and rolling forward is simply a normal upgrade performed quickly — which is exactly why a team can only roll forward when it genuinely understands the bug.
These are the three basic, mandatory deployment considerations every team should be aware of: compatibility, testing, and rollback/roll-forward — and the fourth is tools.
13.2.6 Tools and Platform Choice
The fourth consideration is tools. When it comes to deployment, the big question is: on what platform are you deploying? Are you deploying on a local server inside the organization? Is the team deploying to a cloud platform, or onto a virtual machine? Based on the platform you choose, you need to know what kind of tools and technology your team will use to complete the deployment, and those tools must be clear to every team member, because they are the ones operating them during deployment.
The platform decides the toolchain: a local server inside the organization may be deployed to with simple scripts over SSH; a cloud platform brings managed deployment services; a virtual machine (VM) setup may need image baking and hypervisor tooling. Whatever the choice, the tools must be known to every team member — the deployment button is useless if the person who must press it does not know which tool produces which artifact.
Pitfalls:
- Treating null as a failure. In the signup example, "contact is null" is the expected state for old users; crashing on it turns a compatible release into a broken one.
- Upgrading a schema by modifying existing fields instead of adding new ones — that silently breaks everything the old version promised.
- Assuming the team can always roll forward. Roll forward requires a known root cause and a known fix; without that knowledge the only safe move is rollback.
- Forgetting that the platform choice comes first. Choosing tools before deciding whether the target is a local server, cloud, or VM leaves the team with mismatched tooling.
Real-world: e-commerce and banking apps deal with the compatibility question on every release — the app on a user's phone (an old version) must keep talking to the backend (a new version) while a deployment is in progress. That is why API versioning and tolerant null handling are standard practice, and why the rollback plan is rehearsed in production-like environments before it is ever needed in anger.
Recap: A team settles, before any deployment: rollback plan, unit testing, security check, zero downtime — plus compatibility (both directions), canary-style testing, rollback versus roll forward, and tools chosen for the deployment platform.
Bridge: These considerations exist because deployment is genuinely hard. The next section looks at exactly what makes it hard: the challenges and waste in deployment processes.
13.3 Challenges in Deployment
What is the biggest challenge in deployment? It is not automation — it is the waste hiding inside the process that automation is supposed to speed up.
13.3.1 Waste in the Deployment Process
The very first challenge — and the biggest one — is waste in the deployment process. Up to this point the discussion has only covered how to automate each process with particular tools and technology, plus the best practices of each stage: code practices in source code management, test-case writing in testing, best practices in continuous integration. Nobody touched the aspect that the process itself might contain waste.
Waste, in this context, is anything that adds no value to the product or the development cycle. The examples of waste seen in the software industry:
- Build and operations teams waiting for documentation or fixes. The build engineers and the operation team sit idle, doing no fruitful work, because they are blocked on something outside their control. Their time is spent waiting, not producing.
- Testers waiting for good builds of the software. They cannot perform testing until a decent artifact arrives, so their time is wasted. The tester is fully available, but the thing they test has not been delivered yet.
- Development teams receiving bug reports a week after the team has already moved to the new functionality. The feedback is delayed, reports do not arrive on time, and that delay is pure waste — the bug is now anchored to code the team has already left behind, so fixing it costs rework.
- Discovering towards the end of the deployment process that the application architecture will not support the system's non-functional requirements. The discovery comes far too late to matter cheaply. A non-functional requirement (NFR) is a property of the whole system — performance, security, scalability, availability — and if the architecture cannot deliver it, the discovery at the end of the process means the fix is expensive or impossible.
The common thread: every example is time spent not adding value — waiting, delayed feedback, or discovering problems too late to fix cheaply.
13.3.2 What Waste Produces
This kind of waste leads to software that is undeployable — because it has taken so long to reach a production-like environment — and buggy, because the feedback cycle between the development, testing, and operation teams is so long.
The key warning: even if you have a proper automation toolchain in place and everything is deployed, if you do not have a proper, value-added process, your organization will not see the actual results of DevOps. A team can call itself DevOps while the operation team still gets feedback way too late, while people do not follow the CI/CD pipeline, while the team is not aware of the tools and technology. Anything that adds waste, anything that adds no value to the product or the development cycle, is waste.
Pitfall: equating "we bought the tools" with "we are doing DevOps". Tools without a value-added process still ship software late and buggy. The automation chain only amplifies what the process around it does — if the process is full of waiting and delayed feedback, automation makes the waste faster, not smaller.
13.3.3 The New Approach to Deployment
The new approach should be an end-to-end way of delivering software:
- Deployment of the application should be easy and one-click-go. It should not be a manual task that creates a dependency on the team — the deployment must not require a specific person's memory or presence.
- A powerful feedback loop should exist — rapid feedback on both the code and the deployment process, given to the team.
- Lower the risk of release, and transfer knowledge of the deployment process to the development team. If the process is scripted and simple, the knowledge lives in the script, not in one person's head.
- Testing teams should deploy the builds into the testing environment by themselves, using the push button. This removes the waste of the tester waiting for a proper build or artifact — a pull system, where the person who needs the build pulls it on demand, replaces the push chain of handoffs.
- Operations should be able to deploy builds into staging and production environments at the push of a button.
- Developers should be able to see which builds have passed through which stage of the release process, and what problems were found at each stage.
These six points are really one idea: make every environment self-service. Each role pulls the build it needs when it needs it, and every role can see the state of every build.
13.3.4 The Water-Pipe Bottleneck Analogy
The intuition for why visibility matters comes from a simple image: a water pipe and a water tank.
The professor's analogy: imagine a pipe feeding a tank. If you do not know where the bottleneck is — the narrow point that limits how much water passes — improving some other aspect of the value stream will not make the water flow faster. The bottleneck is here, not somewhere else. You can widen the pipe at ten different points; if the real restriction is one narrow joint, the flow does not change until that joint is fixed.
The analogy carries over to software delivery exactly: the value stream is the pipe, the value-added work is the water, and the release process is full of narrow joints (waiting for builds, delayed feedback, late discoveries). Improving an arbitrary stage without knowing the bottleneck is wasted effort — which is itself waste, the very thing this section is about.
With a transparent release system, everybody in the delivery process gets two things: access to what they need when they need it, and visibility into the release process. The team sees where the problem is, gets feedback early, visualizes the bottleneck in the value stream, optimizes it, and removes it. The result is a delivery process that is not only faster but also safer, because you are rehearsing it — you use the same release process every time you change code, so by the time a real release happens, the process has already been exercised hundreds of times.
Real-world: the idea that waste kills flow comes from lean manufacturing — Toyota's production system — and entered software through the lean and DevOps movements. In industry, the concrete versions of these wastes are the queue of un-reviewed pull requests, test environments that take weeks to provision, and release tickets that sit in approval queues; every one of them is a pipe joint waiting to be measured and widened.
Recap: Waste is anything that adds no value — idle teams, testers waiting for builds, late bug reports, late architecture discoveries. It produces undeployable, buggy software, and automation alone does not cure it. The cure is a transparent, self-service, one-click process where everyone sees the bottleneck, exactly as a water pipe shows where the flow slows.
Bridge: The next section introduces the tool that makes the value stream visible and manageable: the deployment pipeline and its value stream map.
13.4 The Deployment Pipeline and the Value Stream Map
13.4.1 What a Deployment Pipeline Is
A deployment pipeline is the automated manifestation of your process for getting software from the version control system into the production environment. You change code, automatically it should build, it should test in subsequent internal environments, and then the code should push to the production environment.
This design increases collaboration between many individuals and gives the transparency to visualize what is going on — which particular version is in which state of the pipeline at any moment. The pipeline is the map of the delivery process turned into machinery: wherever the map shows a step, the pipeline shows an automated stage, and wherever the map shows a wait, the pipeline shows a bottleneck waiting to be removed.
13.4.2 Value Stream Map of Product Creation
A value stream map exercise maps every stage a product passes through — a flowchart of the product's journey from opportunity to release. The example below is taken from the textbook itself — a high-level value stream map for creating one particular product, with the value-added time at each stage (the time spent actually working) and the handoff time between stages (the elapsed waiting time):
| Stage | Value-added time | Handoff to the next stage |
|---|---|---|
| Product opportunity assessment | 3 days | 1 week |
| Product discovery | 1 week | 10 days |
| Product planning and estimation | 10 days | 3 days |
| Product creation (development) | 7 weeks | 5 days |
| Final testing and approval | 1 week | 2 days |
| Release | 2 hours | — |
First comes product opportunity assessment: assess what the product opportunities are. Then the idea becomes a product and you start discovering it — collecting requirements, deciding how the product will be, making sure it differs from competitive products. Different teams do these stages: the business team (PRM) hands the opportunity assessment to a requirement-gathering team for product discovery. After the requirements are identified, product planning and estimation decides which features go into the product, how much time and effort it needs, and what cost is involved. Then the actual development happens, followed by final testing, approval, and release.
Note on the development handoff: the map shows 5 days of waiting between development and testing, which is the value in the textbook figure this example comes from — that source explicitly calls out "a five-day wait between the development team completing work on the first release and the start of the testing process". The five days is also the value used in the waste-time arithmetic below, so the map and the sums stay consistent.
13.4.3 Cycle Time, Waste Time, and Lead Time
Three terms organize this map. Cycle time is the value-added time — the sum of all the productive stage durations, where the index runs over all the stages of the map:
For the example product, the lecture states the cycle time as 11 weeks, 3 days, and 2 hours. Waste time is the elapsed time spent between stages — the handoffs where nothing productive happens, where the index runs over all the handoffs between consecutive stages:
The waste components are 1 week plus 10 days plus 3 days plus 5 days plus 2 days, and the lecture states this to give five weeks of waste time. Finally, lead time is the overall cycle time plus waste time:
Lead time means the whole span from when the project started until the product is released to the market.
Worked example — adding up the map. Working the sums from the table, stage by stage:
The reconciled totals: the map's numbers add up to a cycle time of 10 weeks, 6 days, 2 hours, a waste time of 3 weeks, 6 days (27 days), and a lead time of 14 weeks, 5 days, 2 hours — about three and a half months. The textbook's own estimate of this map confirms the arithmetic: it says the whole process takes about three and a half months and that about two and a half months of that is actual work — and 76 days of value-added work is indeed about two and a half months.
Sense-check: the answer to "did the value-added time come out about right?" is yes — a little over two and a half months of work inside a three-and-a-half-month total, with roughly one month of waiting in between.
The lecture stated the totals as 11 weeks 3 days 2 hours (cycle time) and five weeks (waste time). Those stated figures are kept here as the exam-relevant versions; the arithmetic above is the reference form. Where does the four-day gap between the stated 11 weeks 3 days 2 hours and the computed 10 weeks 6 days 2 hours come from? The likely source is a unit slip in one stage: if the 10-day planning and estimation stage is counted as two weeks (14 days) instead of 10 days, the total becomes days, which is exactly 11 weeks 3 days — the stated cycle time. Similarly, the stated "five weeks" of waste does not match the 27 days the handoffs actually sum to. When you work such an example, always re-add the table yourself rather than trusting a spoken total.
13.4.4 The Value Stream Mapping Exercise
In a value stream mapping exercise, the team or organization tries to minimize the waste time as much as possible while increasing the value-added time. The challenges can be anything — teams sitting in different locations, email notification delays — and those challenges are addressed in the brainstorming session of the exercise. The organization then works to shrink the waste time and grow the cycle time.
The map is a measurement instrument, not a decoration: once the waiting times are written down, the team can see which handoff is the longest joint in the pipe (from section 13.3) and attack exactly that one. Every brainstorming session in the exercise is aimed at a specific handoff or delay — remote teams cause waiting, so fix the handoff protocol; email notifications delay decisions, so automate the notification.
Real-world: value stream mapping is borrowed from lean manufacturing, where factories map the path of a physical product through machines and waiting areas. In software, the same exercise maps the path of a feature from opportunity assessment to release — the map in this section is the canonical textbook example, and running the exercise is how organizations decide where their DevOps effort should land first.
Recap: The deployment pipeline automates the path from version control to production, and the value stream map makes that path measurable: cycle time is the sum of value-added times, waste time is the sum of the waiting handoffs, and lead time is the two added together.
Bridge: With the map and the pipeline defined, the next section looks at the structure of the pipeline itself — its expected steps, scenarios, and stages.
13.5 Structure of the Deployment Pipeline
13.5.1 Expected Steps
Every deployment pipeline follows the same expected steps.
Step 1 — Input: there is an input to the pipeline: a particular revision of the code in the version control system.
Step 2 — Build: every change should create a build — whenever you change code, the automatic build process triggers.
Step 3 — Fitness tests: the artifact from that build passes through a sequence of tests and challenges to its viability as a production release — the stages judge whether this artifact is fit to be pushed to production.
As the build passes each test of its fitness, confidence in it increases: this application will be fully quality even in a production environment. Confidence is not a feeling here — it is the accumulated evidence of each stage that the artifact survived. The more stages the build clears, the more resources the team is willing to spend on it: environments become progressively more production-like, exactly matching the growing confidence.
The objective of the design is to eliminate unfit release candidates as early as possible in the process. That gives the team feedback on the root cause of failure as rapidly as possible, so they can perform root cause analysis and fix the unfit release. Any build that fails a stage is generally not promoted to the next one: if the build fails, it does not move to testing — it goes back, the team gets the feedback that the build failed, they fix the code, revisit and refactor it, commit it to the version control system again, and the same pipeline triggers once more after the code change has been committed.
The loop is important: the pipeline is not a one-way road with a dead end at failure. A failed stage feeds back into the codebase — fix, commit, retrigger — so the pipeline is a closed loop around the delivery team. Failing early is a feature, not a bug: a failure at the first stage costs minutes; the same failure found in production costs an incident.
13.5.2 Three Scenarios in a Typical Pipeline
The same idea, shown as three concrete check-in scenarios:
| Scenario | What happens in the pipeline |
|---|---|
| 1 | The delivery team checks in code. The build and unit test stage runs and fails. The pipeline stops right here — nothing moves to the further steps — and feedback goes immediately back to the delivery team. |
| 2 | The delivery team checks in code. Build and unit test pass, but the automated acceptance test fails. Again the feedback goes straight back to the team. |
| 3 | Everything passes — build, unit test, automated acceptance tests. The build moves through each subsequent stage of the pipeline until the application is released into the production environment. |
Worked example — tracing the three scenarios. Track one delivery team, one pipeline, and three check-ins:
- Scenario 1 — failure at the first gate. The team commits revision R1. The commit stage compiles R1 and runs the unit tests; a unit test fails. The pipeline stops immediately: R1 never reaches the acceptance test stage, no artifact is promoted, and the failure message (which test, which line, which build) goes straight back to the developer. Cost so far: minutes. The developer fixes the code, commits R2, and the pipeline restarts from the top.
- Scenario 2 — failure at the second gate. The team commits R2. The commit stage passes and produces an artifact; the automated acceptance tests then run against that artifact and a functional check fails. The artifact is not promoted to any further environment, and the feedback — which acceptance test failed — returns to the team. The pipeline consumed more resources than in scenario 1, but the failure is still caught before any user sees it.
- Scenario 3 — the full pass. The team commits R3. Build and unit tests pass, the artifact is stored, automated acceptance tests pass, and the build moves through each subsequent stage of the pipeline (user acceptance testing, capacity testing) until the application is released into the production environment.
Sense-check: in all three scenarios the pipeline's job is the same — every failure is caught at the earliest stage and fed back; only scenario 3 earns the right to travel the whole path to production.
13.5.3 The Broad Overview: Stages
Looking at the broad overview, every stage gets tested and the stages fall into a familiar shape.
The commit stage contains the compile, the unit tests, the code analysis, and the build process — it produces the artifact. The same artifact is then exercised in the acceptance test stage: user acceptance testing and capacity testing. Finally the same artifact moves to deployment in the production environment.
Because each environment is exercised by the pipeline, you get faster feedback and the environments become more production-like, which raises the assurance that the build is ready for production. There is a trade-off built into this structure: the deeper the build travels, the more resources the stages consume (acceptance testing is far costlier than compiling), but the more production-like the environment it is tested in, the stronger the guarantee it will work in production. The pipeline is designed so that cheap stages run early and every build, while expensive stages run late and only for the survivors.
Visualize the pipeline as a funnel with three compartments: on the left, the commit stage (compile, unit tests, code analysis, build) — fast and cheap, filtering every check-in; in the middle, the acceptance test stage (user acceptance testing, capacity testing) — slower, filtering the survivors; on the right, deployment to production. Each compartment is labelled with two growing quantities — confidence in the build's production readiness (rising) and the production-likeness of the environments (rising) — and one shrinking quantity: the time between a mistake and its feedback.
Pitfalls:
- Skipping stages to save time. The funnel only works if every build passes through it; hand-placing a build into production bypasses the entire confidence ladder.
- Treating a failed build as "start over from scratch". The pipeline restarts from the commit, but the feedback from the failure is the most valuable input to the next commit.
- Assuming scenario 3 is instant. The full pass takes as long as the slowest stage takes; the design goal is to make each stage as fast as possible so the whole pass completes quickly.
Real-world: this is the shape used by every mainstream CI/CD tool — Jenkins pipelines, GitLab CI, GitHub Actions, Go — where a job graph of build → test → deploy stages mirrors the commit stage, acceptance stage, and production deployment. Teams read the pipeline board the way air traffic controllers read a runway: which change is where, and which stage is currently the bottleneck.
Recap: Every pipeline takes a version-control revision, builds it, and challenges the artifact through stages of fitness; unfit candidates are eliminated early with rapid feedback, and confidence grows stage by stage until the artifact earns production.
Bridge: The next section puts concrete tools on this structure — the repositories and scripts that make a basic deployment pipeline real.
13.6 A Basic Deployment Pipeline with Tools
13.6.1 From Source Repository to Artifact
With respect to tools and technology, the in-depth components of a deployment pipeline start with the source code repository — GitHub in this case.
Purpose: the pipeline turns every code change into a tested, stored, deployable artifact — one binary that every later stage will exercise.
Inputs: source code in the source repository (GitHub), configuration stored in version control, and the trigger of each commit.
Outputs: a binary artifact stored in an artifact repository, ready for the acceptance, capacity, and production stages.
Whenever a code change is committed, GitHub triggers the commit stage, which is your integration pipeline. Here you compile, run the commit tests, assemble the code, perform code analysis, and store the resulting binary artifact in the artifact repository. That artifact repository is a real, named component of the pipeline — the place where the binaries wait for the later stages.
The commit stage plays the role of the first gate: it rejects code that does not compile, code that fails its tests, and code that violates the analysis rules — before any environment is touched. Only the survivors are assembled into binaries and handed to the artifact repository.
13.6.2 Acceptance Staging and Configuration as Code
For acceptance staging — performing acceptance testing on the artifact — you access the environment and its configuration through the version control system itself. This is the practice of managing configuration as code and infrastructure as code: everything lives in version control, and you write scripts for it.
The configuration repository. You keep an environment and app configuration repository; with it you configure the environment, deploy the binaries, and perform the smoke test and the acceptance test. From there the artifact moves to the UAT capacity test, and finally to the production environment once every test is cleared.
The steps in the acceptance stage, in order:
- Configure the environment — pull the environment and app configuration from version control and apply it.
- Deploy the binaries — take the artifact from the artifact repository into the environment.
- Smoke test — verify the application actually started and answers.
- Acceptance tests — run the full automated acceptance suite against the deployed application.
The key idea: none of this is done by hand on a server. The environment's identity is a set of versioned scripts and config files, so the same procedure that builds the acceptance environment can build the capacity environment, the UAT environment, and production. A deployment becomes "run the script for this environment against this artifact".
13.6.3 The Component View
Real-world: the overall picture of the pipeline has four kinds of repositories working together — the artifact repository, the source control repository, and the configuration and environment infrastructure (infrastructure as code), all of which live in version control systems themselves. None of the environments are hand-configured; every stage pulls its configuration from a versioned script.
| Component | What it holds | Role in the pipeline |
|---|---|---|
| Source control repository (GitHub) | Application source code | Trigger of the pipeline; home of pull requests and version summaries |
| Artifact repository | Compiled binaries, reports, metadata | The single store where later stages pick up the tested artifact |
| Environment and app configuration repository | Scripts and configuration, as code | Describes every environment; enables configure → deploy → smoke → test |
| Infrastructure (infrastructure as code) | Versioned infrastructure definitions | Recreates environments reproducibly instead of hand-configuring machines |
The four work together: code flows from source control into the commit stage; binaries flow into the artifact repository; configuration flows from the config repositories into every environment; and each environment is scripted, never hand-made. This is what makes the pipeline repeatable — a new environment can be created from nothing but the versioned scripts, and a deployment cannot drift from how it was tested, because the scripts are the same everywhere.
Real-world: in industry the artifact repository is a concrete product — Nexus and Artifactory are the classic binary stores, and modern CI servers (Jenkins, GitLab CI) build artifact storage in natively. The configuration-as-code practice is what tools like Ansible, Puppet, and Terraform automate: the "environment" is a text file plus a script, exactly as the component view describes.
Pitfalls:
- Storing binaries in the source repository. Binaries are derivatives of a baseline, not part of its definition; they belong in the artifact repository, traceable back to the check-in that produced them.
- Hand-configuring environments "just this once". A hand-tweaked environment drifts from the versioned configuration, and the next deployment tests something nobody has written down.
- Treating the artifact repository as optional. Without it, later stages re-fetch or rebuild binaries, and the guarantee that every stage tested the same artifact disappears.
Recap: The basic pipeline is four repositories doing one job: source control triggers the commit stage, the commit stage produces a binary for the artifact repository, configuration-as-code scripts configure each environment, and every stage (acceptance, capacity, UAT, production) follows the same configure → deploy → smoke → test procedure.
Bridge: Why does the pipeline work so hard to carry one artifact through every stage? Because of the outcomes it buys — the next section: fast feedback and transparency.
13.7 Outcomes of the Deployment Pipeline
13.7.1 Fast Feedback
The ultimate purpose of everything in this pipeline is one thing: get feedback to your team as fast as possible. Every stage gives feedback back to the previous stages early. That is the first outcome — a fast feedback cycle.
Feedback is the product of the pipeline, not the deployments. A build that fails in the commit stage tells the developer, within minutes of the commit, exactly what broke. The same failure discovered in production would travel backward through support tickets and reproduce-the-bug sessions for days. The pipeline compresses that distance: every stage is a checkpoint that reports to the team immediately, and the earlier the checkpoint, the cheaper the lesson.
13.7.2 Transparency and a Smaller Debugging Scope
The second outcome is transparency. You can see which build is deployed into which environment, and which stage in the pipeline each build has passed — all of it visible from the pipeline itself.
Visualize the transparency as a table: each row is a check-in (with its check-in comments), each column is a stage of the pipeline (commit, acceptance, capacity, UAT, production), and each cell shows whether that build passed or failed that stage, and which environment the build currently sits in. One glance answers "where is version 4 right now?" for anyone on the team.
The quick-notice property follows: if you see a problem in acceptance testing, you can immediately find out which change caused it — which particular version of the source code triggered the acceptance test failure — and perform root cause analysis on that code base. Because every build process actually results in stable working software, the scope of the search becomes small. Instead of hunting a bug across the whole system, you look at the one change that entered the pipeline most recently.
Pitfalls:
- Assuming transparency means only managers look at the board. The developer whose build fails is the main consumer of the visibility; the pipeline board is the team's instrument, not a report for leadership.
- Waiting for a failure to appear before reading the pipeline. The fast feedback only works if the team actually watches each stage's result.
- Treating "the build passed" as "the change is fine". The pipeline narrows the debugging scope to the latest change, but the debugging still has to happen — transparency finds the change, not the fix.
Real-world: this traceability is exactly what release tools like Go, Jenkins, and GitLab's pipeline views are built around — and it is the same property that audit and compliance teams rely on: which change, built from which commit, was deployed to which environment, and when. When an incident strikes, the pipeline's trace is the first document pulled.
Recap: The deployment pipeline pays out in two currencies: fast feedback at every stage, and transparency that shrinks the debugging scope to the single latest change.
Bridge: Fast feedback and transparency both rest on one assumption — that every stage tested the same artifact. The next section examines the anti-pattern that breaks that assumption: recompiling binaries at every stage.
13.8 Binary Anti-Patterns: Build Once, Deploy the Same Artifact
13.8.1 The Anti-Pattern: Recompiling in Every Context
A commonly seen anti-pattern is dealing with binaries by recompiling the source code repeatedly in different contexts — during the commit process, at acceptance test time, during capacity testing, and often once for each separate deployment target. Organizations tend to build the artifact multiple times for multiple environments.
This is not best practice, because every time you compile the code you run the risk of introducing a difference in your artifact. Why would differences appear?
- The compiler differs. The version of the compiler installed in the later stage may differ from the version used at commit test time.
- The compiler configuration differs. Configuration changes in the compiler may change the behavior of the application.
- The dependencies differ. You may pick up a different version of some third-party library than the one you intended.
Any of these silently changes the artifact. The key word is silently: nothing announces the difference, no test comparison is run — the new binary simply behaves differently from the one that was validated.
And if the artifact differs, how can you say that the artifact which worked on the pre-production environment will definitely work in production? You are not testing the same artifact. That reasoning collapses — the guarantee you want is exactly what this practice destroys.
Worked example — the same source, two compilers. Suppose the team compiles revision R1 with compiler version 8 at commit time and the acceptance tests pass. For capacity testing, the capacity stage has compiler version 9 installed, so the code is recompiled there. Both builds come from the same source, yet the binaries differ: version 9 applies a different optimization or a different library binding, and the capacity-test binary exposes a bug the acceptance-tested binary never had. Capacity testing fails on a build that no longer represents the artifact the commit stage validated. Worse, if the difference is subtler — a slightly different logging format or a different default setting — the capacity stage might pass while production, recompiled again with yet another toolchain state, misbehaves.
Sense-check: the chain of "it passed at each stage" is worth nothing if each stage tested a different binary — the one guarantee the pipeline exists to provide ("tested artifact = deployed artifact") was broken at the first recompile.
13.8.2 The Two Principles It Violates
Recompiling at every stage violates two principles.
First, the efficiency of the deployment pipeline: the whole point is fast deployment feedback, and recompiling takes time — on large systems the build process is slow, so feedback arrives late. Each stage that recompiles adds a full build duration to the critical path of every change.
Second, the principle of always building upon the foundation: the binaries that get deployed to production should be exactly the same as those that went through the acceptance testing and all the other test stages. Recreating binaries breaks the link between what you tested and what you ship. The strongest implementations check this link mechanically: the hash of each binary is recorded when the binary is created, and later stages verify that the binary is identical at every step of the process.
13.8.3 The Remedies
The remedies form a short checklist of pipeline hygiene:
- Build your binaries only once, then deploy that same artifact to every environment. The build happens exactly one time, in the commit stage, and everything after that moves the artifact, not the source.
- Use the same release process everywhere: deploying with the same script to production that you use for development environments is a fantastic way to prevent the "it works on my machine" syndrome — where something works in one environment and nobody understands why it fails in another.
- Perform a smoke test of your deployments. When the artifact lands in an environment, immediately verify that it is actually up and running.
- Deploy always into a copy of production — a pre-production or staging environment that is an exact mirror of production.
- Each change should propagate through the pipeline instantly. No scheduled nightly builds; every commit triggers the first stage, and each stage triggers the next as soon as it finishes.
- Have intelligent pipeline scheduling (the topic of the next section).
- If any part of the pipeline fails, stop the line there itself. The whole team owns the failure and fixes it before anything else moves.
Pitfalls:
- Promoting source code instead of the built artifact. "We rebuilt it there, it's the same" is precisely the assumption that the anti-pattern disproves.
- Rebuilding "just for one environment" because a target has different needs. Every rebuild is a new bet that the result is identical; the disciplined fix is a different artifact built from the same pipeline, not an ad-hoc recompile.
- Skipping the smoke test after deployment and discovering a broken service only when users report it.
Real-world: binary artifact stores like Nexus and Artifactory exist largely to make this practice easy — the artifact is fetched, not rebuilt, at every stage, and its checksum travels with it. In audited industries, the recorded hash of the deployed binary is part of the evidence that what went to production is exactly what passed acceptance testing.
Recap: Recompiling at every stage is an anti-pattern: it risks silently different binaries, slows feedback, and breaks the tested-equals-deployed link. The remedy is build once, deploy the same artifact everywhere with the same script, smoke-test each deployment, deploy into a copy of production, propagate instantly, schedule intelligently, and stop the line on failure.
Bridge: The checklist ends with two scheduling ideas — instant propagation and intelligent scheduling. The next section shows what intelligent scheduling means when five developers check in at the same time.
13.9 Intelligent Pipeline Scheduling
13.9.1 The Five-Developer Scenario
Intelligent pipeline scheduling decides when a pipeline stage runs. The scenario that explains it uses one delivery team and five developers.
Purpose: run the expensive stages (like the automated acceptance test) as seldom as needed — once per batch of changes — instead of once per check-in, so resources are not burned and feedback stays fast.
Inputs: check-ins from many developers, the pipeline's stages, and the current state of each stage (running or idle).
Outputs: a schedule that triggers the first stage on every check-in but runs the expensive later stages only when they are free and new work has accumulated.
Developer 1 checks in. The build and unit test stage runs and passes, and the automated acceptance test starts — it is in progress. Meanwhile developers 2, 3, 4, and 5 make more check-ins:
- Developer 2's check-in triggers the build and unit test pipeline, which passes — but it does not trigger the automated acceptance test.
- Developer 3 is the same. Why not? Because the acceptance test is already in progress for the first check-in.
- Developer 4's check-in fails at the build and unit test stage, so it stops there.
- Developer 5's check-in passes its build and unit test.
13.9.2 What If Every Commit Triggers Acceptance Testing?
Q: What will happen if every commit triggers its own automated acceptance testing? If each small change retriggers the acceptance test while the previous one is still running...
A: It will take more time, because even testing consumes time, and then you get delayed feedback. One student added that the team always has a backup available — they can perform a forced release if there are any issues.
That student's point deserves its own note: the team always has a backup for every member — if there are issues, they can perform a forced release. But the main answer stands: letting every check-in fire the acceptance test stage burns resources and delays feedback, which is exactly what the pipeline was built to avoid. Each acceptance test run takes minutes to hours of computing time; queueing five of them for five tiny changes delays the last result by four runs, which is the opposite of fast feedback.
13.9.3 The Outcome
Now finish the scenario. By the time developer 5's build passes, the first acceptance test has completed. The acceptance test triggered by the fifth check-in now covers all the changes from check-ins 2, 3, 4, and 5 together — one test run, four changes verified. This is the optimized use of resources and time: you are not executing every stage of the pipeline for every tiny change, and the feedback stays fast. That is the intelligent way of scheduling.
Worked example — the schedule in a timeline. Track the state of the two stages as the five check-ins arrive:
| Check-in | Build & unit test stage | Automated acceptance test stage |
|---|---|---|
| Developer 1 | Runs, passes | Starts — in progress |
| Developer 2 | Runs, passes | Not triggered (acceptance still busy) |
| Developer 3 | Runs, passes | Not triggered (acceptance still busy) |
| Developer 4 | Runs, fails — pipeline stops, feedback to the team | — |
| Developer 5 | Runs, passes | First run finishes; one new acceptance run starts, covering changes 2, 3, 4, and 5 together |
The tally: five check-ins produced one acceptance-test run instead of five, the failure from developer 4 was caught at the cheapest stage, and the final acceptance run verified four changes at once — while the first run verified developer 1's change. The feedback for every developer arrived at the same pace as if the runs were serialized, but the computing bill was one-fifth.
Sense-check: "did the pipeline test everything?" — yes, every change was verified by exactly one acceptance run, which is the point of the schedule.
Real-world: in the early days of DevOps, when teams started using Jenkins, Jenkins did not have this intelligent scheduling built into the system — organizations had to configure their pipelines so scheduling worked this way. Today every tool, including Jenkins, ships with intelligent scheduling by default, so the system handles it on its own.
13.9.4 Parallel Pipelines
Q: Will parallel processing delay the pipeline? I mean two different branches, each with its own pipeline.
A: That kind of parallel processing is actually required for microservice architecture — separate branches with their own pipelines do not delay anything. What we want to avoid is retriggering the same test process on the same feature for every small commit while the first test run is still busy, because that delays feedback.
The clarification matters: parallel pipelines for separate branches are wanted — microservices demand them. Each service (and each branch) can have its own pipeline running its own acceptance tests, and those runs do not compete: they are different tests of different code. What is not wanted is repeatedly triggering the same test stage on the same feature from every small check-in, where the new runs queue behind the old one and the last developer waits for everyone else's runs to finish.
Pitfalls:
- Confusing "parallel pipelines" with "repeated runs". Parallelism across branches or services is good; stacking identical test runs of the same feature is the waste intelligent scheduling removes.
- Forgetting that the acceptance stage covers the accumulated state. The fifth check-in's run tests changes 2, 3, 4, and 5 together — if developer 4's failed change had been fixed and recommitted, its new version would ride the same batched run.
- Assuming intelligent scheduling only matters at scale. Even a two-developer team benefits: every duplicate acceptance run is delayed feedback for the next developer.
Recap: Intelligent scheduling triggers the cheap first stage on every check-in but batches the expensive acceptance runs — when the acceptance stage is busy, later check-ins wait and ride the next run together, so one test run verifies many changes. Parallel pipelines across branches or microservices are fine; repeated runs of the same test are not.
Bridge: Scheduling decides when releases happen; the next section decides what the release plan contains — and when it must be created.
13.10 The Release Plan
13.10.1 When the Release Plan Is Made
A release plan should be ready before you start implementing the application. This was put to the class: are you aware that the release plan exists well before you enter the implementation phase?
Q: When do we cover the release plan? Is it ready before we enter the implementation phase of the project?
A: Yes, the release plan is in place before development even starts. If you work with Scrum, you create it during sprint planning. If you work the traditional way, you have product discovery first, and then a planning and estimation phase.
So in an agile setup the release plan is born in sprint planning; in a traditional setup it appears during planning and estimation, right after product discovery. Either way, the plan exists before the first line of production code — because the plan determines what gets built (which tests the release must pass, which environments it must travel), and a plan invented after development is a plan that cannot shape the development.
13.10.2 Who Creates the Release Plan
The release plan is created and maintained by everyone involved in the delivery of the software — developers, testers, operations, infrastructure, and support personnel. Operations in particular should give their input on infrastructure: what kind of tools and technology they will need, which version, which operating system to look for. The release notes are part of this planning conversation too.
Q: Can release notes be created automatically during the deployment process?
A: Yes. Each commit carries a commit message, and each task has its own logs; those become the release notes when a change is pushed. A student added that you can capture Jira task status from Jira, and GitHub also creates a summary of all the new pull requests merged as part of a version automatically.
So the automatic release-note pipeline has three sources: commit messages and task logs, Jira task status, and GitHub's own per-version summary of merged pull requests. The planning conversation decides that release notes are generated from these three, so the notes never depend on someone writing them up by hand at the end.
13.10.3 What the Release Plan Must Cover
The plan must cover several things.
- Automate the process. Minimize the effect of people making mistakes by automating as much of the release plan process as possible — the planning includes what your project must pass: unit testing, capacity testing, integration testing, and so on, and each of those processes should be automated wherever you can.
- Practice the procedure. Practice it often, in a production-like environment, so you can debug the process and the technology supporting it. The rehearsed release is the safe release: the first real release should be the hundredth time the procedure has run.
- Back out safely. Have the ability to back out a release if things do not work out — the rollback must always be in the plan, with three decisions attached: when to roll back, how much time the rollback should take, and what deciding factor triggers it.
- Migrate configuration and data. Have a strategy for migrating configuration and production data as part of both the upgrade and the rollback process. Upgrading the code is only half of a release; the configuration and the data must move with it, and they must move back if the release rolls back.
13.10.4 The Goal: A Completely Automated Release
The goal is a completely automated release process. Releasing should be as simple as choosing a version of the application to release and pressing a button. And backing out — if something is not working properly, returning to the previous version — should be as simple as pushing the new one.
Exam note: the release plan exists before development starts (sprint planning in Scrum; planning and estimation after product discovery in traditional setups), it is created by everyone involved in delivery, it must cover automated gates (unit, capacity, integration testing), rehearsal in production-like environments, rollback with its three decisions (when, how long, what triggers it), and configuration/data migration for both upgrade and rollback — and the goal is a one-button release and a one-button back-out.
Pitfalls:
- Writing the release plan after implementation. A plan that is invented late cannot influence the tests, environments, or scripts that the plan is supposed to define.
- Leaving the rollback section blank. "We'll figure it out if it breaks" is not a plan; the three rollback decisions (when, how long, trigger) must be written down in advance.
- Forgetting data migration. The code rolls back, but the database changes stay — a release plan that covers only code will paint itself into a corner on upgrade day.
Real-world: this is the structure behind release strategies in industry: the release plan lives inside the release strategy document, covering first deployment steps, smoke-test steps, back-out steps, backup and restore, data migrations, log locations, and monitoring. Teams that rehearse this procedure — often with automated release drills — are the teams that can genuinely ship at the push of a button.
Recap: The release plan is written before implementation by everyone involved, covers automation, rehearsal, rollback (with when/how-long/trigger decisions) and data migration, and aims at a completely automated release where backing out is as simple as releasing.
Bridge: The plan says the release must be smoked-tested; the next section explains what smoke testing actually is — and how it differs from performance testing.
13.11 Smoke Testing and Performance Testing
13.11.1 What Smoke Testing Is
Smoke testing asks how strong the system is. The basic logic comes from the image behind the name: you want to check how strong your system is, so you put a fire rather than just smoke, and you watch how much impact that fire has on your application. One kind of smoke testing uses the monkey tool, which acts as the fire.
The professor's analogy: do not settle for smoke — light a real fire under the system and watch what happens. The "fire" is a deliberate failure (a server killed, a service shut down), and the "smoke" you observe is the visible impact on the application: does it shut down completely? Does performance collapse? The stronger the system, the less smoke a given fire produces.
The core distinction: in smoke testing you are not validating how well your application works — you are validating how bad it will be if something goes wrong. It is a survivability test, not a functionality test.
13.11.2 How to Perform Smoke Testing
The procedure is direct.
Steps:
- Break something. Try to shut down any server or any dependent resource of your application — try to break that service.
- Observe the impact. Once the service breaks, watch how much this impacts the performance of your application: does it shut down completely? Is the impact huge?
- Check the healing. Install a monitoring and configuration management system, and check whether that configuration management system addresses the problem and fixes it automatically when such a breakage happens.
That is the smoke test — a controlled breakage, followed by observation, followed by a check that the automation heals the system.
Worked example — a controlled breakage. The e-grocery application depends on a payment server. A smoke test shuts that payment server down deliberately. Observation: the app stays up but checkout requests fail; the main catalog pages are unaffected. The monitoring system detects the payment server's absence, and the configuration management system restarts it from a fresh copy — the service returns within minutes, and checkout works again. The smoke test has answered three questions: how badly the app degrades when a dependency dies (moderately — degraded checkout, no full outage), how fast the failure is detected (immediately, by monitoring), and whether the automation heals the system on its own (yes).
Sense-check: the test never asked "does checkout work?" — it asked "when the payment server dies, what happens to the app, and does the system fix itself?" — and that is exactly the survivability question smoke testing exists to answer.
A note on terminology: the professor's smoke test is a failure-injection test — break a service and watch the system survive. Many textbooks use the same name for a different, complementary practice: a fast post-deployment check that the application is up and running (launch the app, confirm the main screen loads, confirm its dependent services are reachable), which is why the deployment pipeline performs a smoke test after every deployment. Both practices share the same spirit — a quick, rough check of the system's health under stress or after a change — but on the exam, keep the professor's version: smoke testing is the fire test that checks how bad things get when something goes wrong.
13.11.3 Smoke Testing vs Performance Testing
Q: Will performance testing fall under smoke testing?
A: No, performance testing is not a kind of smoke testing. Performance testing measures how fast your system responds — for example, in the e-grocery application, after providing correct details and clicking the login button, how much time does the next page take? Smoke testing answers a different question.
The two get confused, so the boundary is worth stating:
| Dimension | Performance testing | Smoke testing |
|---|---|---|
| Question it answers | How fast does the system respond? | How bad is the system when something goes wrong? |
| Example | E-grocery: time from clicking login to the next page loading | Shut down the payment server; does the app survive, and does monitoring heal it? |
| Nature | Measures the speed of normal operation | Measures survivability under a controlled failure |
| Relation | Not a kind of smoke testing | Not a kind of performance testing |
Performance testing measures response — how quickly the system answers, like the time from clicking login to the next page loading. Smoke testing measures survivability — what breaks and how badly when something goes wrong. They are separate practices.
Pitfalls:
- Using smoke testing to check functionality. Smoke testing is not "does the feature work?" — it is "what happens when a dependency fails?"; feature correctness belongs to functional and acceptance testing.
- Running the smoke test without monitoring. The controlled breakage only teaches the team something if the system's behavior is observed and recorded.
- Assuming a performance test and a smoke test can replace each other — a system can be fast (good performance) and fragile (fails badly in smoke testing) at the same time.
Real-world: this kind of failure-injection testing is how resilience is engineered at scale — the principle that teams deliberately break components in controlled environments (a practice popularized as chaos engineering at companies like Netflix) to find out in advance which failures the system can absorb and which ones it cannot. The monkey tool named in the lecture is one implementation of that idea: a tool that acts as the fire.
Recap: Smoke testing is the fire test — break a dependent service deliberately, observe the impact on the application, and verify that monitoring plus configuration management heals the system automatically. It measures survivability, not speed, and it is not a kind of performance testing, which measures how fast the system responds.
Bridge: The session closes with a knowledge check — four quick questions that verify the class is aligned on the fundamentals of version control, build, and release.
13.12 Knowledge Check: CI/CD Fundamentals
A quick knowledge check tested whether the class was in line on the fundamentals of version control, build, and release. These four exchanges are the check and its answers.
13.12.1 Signaling That Code Needs Review
Q: What technique indicates to others that you have made changes to code which should be reviewed before being merged into the repository?
A: A pull request. That is the answer — a pull request is the technique you use to signal that your changes are ready for review before they are merged.
The pull request is the formal handshake of a code change: the developer pushes a branch, opens a pull request describing the change, reviewers see exactly which lines changed and discuss them, and the merge happens only after the review approves it. The word "reviewed" is the point — the technique exists so that no change reaches the repository silently.
13.12.2 Testing and Deploying the Same Asset
Q: Version control triggers a build. How do we make sure we are testing and deploying the same asset across the pipeline?
A: By using an artifact repository. The pull request option cannot give us that guarantee, and keeping our fingers crossed is not a plan. An artifact repository is the answer.
Exam note: the artifact repository is the mechanism that guarantees "tested artifact equals deployed artifact" — the same idea as building the binaries once. The build's output is stored in the artifact repository, and every later stage (acceptance, capacity, production) fetches that same stored binary instead of rebuilding or re-downloading source.
The rejected alternatives matter as much as the answer: a pull request reviews the source, not the artifact, so it cannot certify that the deployed binary is the tested one; and "keeping our fingers crossed" is the absence of a mechanism, not one.
13.12.3 Overlapping Changes From Two Developers
Q: Two individuals are both submitting code that needs to go out to the customer, and their changes overlap. How do we address the root cause of this conflict?
A: Merge more frequently. If both merge to the trunk often, overlaps surface early and can be resolved by hand. Merging less frequently makes the conflict bigger, not better.
The root cause of a merge conflict is not the overlap itself — it is the time the two changes spent diverging. Merging to the trunk often keeps every change small and recent, so an overlap is found while it is still small and both developers still remember their own changes well enough to resolve the conflict by hand. Postponing merges compounds the conflict: the longer the branches diverge, the larger the overlapping surface and the harder the resolution.
13.12.4 Indicators of a Good CI/CD System
Q: What are some indicators of a good CI/CD system?
A: All three of them — the system should help speed up builds, show why and where tests fail, and support whatever containers or build and deploy environment you use.
Exam note: a good CI/CD system must do all three — speed up builds, explain test failures, and support your chosen build and deploy environments.
The three indicators map directly onto the pipeline outcomes from section 13.7: fast builds feed the fast feedback loop; showing why and where tests fail turns a red status into an actionable message; and supporting the team's own containers and environments means the tool adapts to the team's reality instead of forcing the team to adapt to the tool.
Pitfall: scoring a CI/CD system on only one of the three indicators. A system that builds fast but gives no failure details is a black box with a green light; a system that explains failures but cannot run the team's environments is a demo, not a pipeline. All three must hold.
Recap: Pull requests signal code ready for review; the artifact repository guarantees the tested asset is the deployed asset; frequent merging resolves overlapping changes at their smallest size; and a good CI/CD system speeds up builds, explains test failures, and supports the team's environments.
Bridge: With the fundamentals checked, the session closes with exam guidance and the industry applications of everything covered today — from the assignment setup to the tools the tutorial will use.
Exam Guidance Summary
- Relative grading: the topper's score sets the top grade — a topper at 80 gets the A grade, and a topper at 95 or above gets A plus; there is no fixed band for A. Below that, the grades are divided across the class by marks — average scorers get B, C, or C minus. Everything is relative to overall class performance. Do not rely on the results portal's percentile: the Webbox results portal is a third-party tool with its own algorithm, and it is not in line with the institute's way of working.
- Comprehensive exam scope: the comprehensive exam covers the full syllabus — the entire course handout is its syllabus. Duration is 2 hours 30 minutes, against the mid-semester's 2 hours, and the question count is higher.
- Copy-paste is a risk: do not copy-paste content in the comprehensive exam. Write your own answers, even if they are wrong or not in perfect language — write your understanding. A lot of copied answers were found in the mid-semester, and that is a risk, not a strategy.
- Mid-semester is mandatory: missing both the regular and the makeup mid-semester is a regret case: the mid-semester is a mandatory component, and if both attempts are missed you will not be allowed to sit the comprehensive exam — and even if you sit it, you must give all the exams again.
- Mid-semester results: a few evaluations were still pending for some candidates; makeup exams take longer to evaluate, and a few students had attachment issues that were under discussion with the operations team. Reevaluation notifications come by mail.
- Expected-answer review (a real mid-semester question): a company is trying to build an MVP and time is essential — which development method is useful, and why is feature-driven development (FDD) not the answer? The expected answer was test-driven development (TDD), because the scenario needs both speed and quality; the one-liner expected was that the team is mature enough to use TDD. A first-time TDD team sees delayed productivity while learning to write test cases first. FDD is picked when you have multiple teams and many members — 50 or more people across different teams — and still want to follow agile. Marks were given to all answers, but that was the expectation. Also note: feature prioritization happens in every agile method — the product owner's roadmap puts higher-priority tasks on top, and some projects pick riskier tasks first — so prioritization alone never justifies choosing FDD.
- Case-study review (a real mid-semester question): a Scrum master is restricting the development team from communicating with the product owner. This is poor agile — the Scrum master should motivate the team to adhere to the proper agile process, not block communication. Resolution paths: reach out to an agile coach, who can revert the issue to the Scrum master; or, as one answer suggested, change the team if political challenges prevent that route. The product owner may be a client business person while the team is technical — even then the team must have the opportunity to talk directly to the product owner whenever needed.
- Sprint length: one-week sprints are not suggested anywhere in Scrum. A one-week sprint gives no chance to look back and understand mistakes — everything is done in a hurry. The ideal range is two to four weeks, not less and not more.
- Quiz and tutorial: a quiz follows the tutorial session; the tutorial covers Maven along with Jenkins. Do the quiz the same day.
- Assessment and assignment guidance: submit the assignment as a document or a recorded video — evaluation works with proper screenshots, and a recorded video shows each and every step; a written document is fine for those who prefer writing. Marks take about two to three weeks after upload, and you will see them before the comprehensive exam. Create your repository with your BITS ID for a more authenticated submission; if you use a personal account, make sure your name (not a fancy alias) identifies you. You may take an alternative approach to any task, but document in your submission why you used a given command and why the alternative is more efficient. Show a master branch plus two feature branches, raise a pull request into the master branch, and show both approved and rejected scenarios. Production deployment is not possible in this setting, so deploy to UAT instead — with two virtual machines you can treat the first as the UAT environment and the other as production. You need only Git Bash to run it locally, or you can use the CSIS virtual lab: log in to the ELN portal with your BITS SSO, book a slot for the DevOps course, confirm it, and connect with the provided RDP client, where the tools are already installed.
Key Industry Applications
- Real-world: GitHub as the source code management repository — the commit-stage trigger for the whole pipeline, and the home of pull requests; GitHub also auto-generates per-version summaries of merged pull requests.
- Real-world: Jenkins as the CI/CD automation server — the classic example used for integration pipelines, and the tool whose history illustrates intelligent pipeline scheduling (absent in early versions, built in today).
- Real-world: Maven alongside Jenkins in tutorial practice — build and package Java projects as part of the pipeline flow.
- Real-world: artifact repositories as the storehouse of the single artifact that every stage tests and deploys — the mechanism that guarantees you test exactly what you ship.
- Real-world: deployment targets in practice — local servers in the organization, cloud platforms, and virtual machines; the toolchain a team chooses depends on the platform, which is the fourth deployment consideration.
- Real-world: configuration as code and infrastructure as code — environments and their configuration kept in version control, scripted and reproducible, instead of hand-configured machines.
- Real-world: smoke testing with the monkey tool, and monitoring plus configuration management systems that automatically heal broken services after a controlled failure.
- Real-world: e-grocery applications as a running case study — signup schema evolution across versions, monthly purchase-report features, and login response-time measurements in performance testing.
- Real-world: virtual labs for hands-on practice — the CSIS virtual lab reached through the ELN portal, booked by slot, accessed with the BITS SSO login and an RDP connection, with the toolchain preinstalled.
- Real-world: Jira task status feeding release notes, plus commit-message and task-log aggregation, as the practical way release notes get generated during the deployment process.
ITD Lecture 13 notes · Deployment Pipelines and Continuous Delivery
Sections Breakdown
Continuous delivery automates everything up to the production push while keeping that final step manual; continuous deployment automates the push as well — one button separates the two.
The class brainstorms what a team must settle before deploying: rollback, unit testing, security, zero downtime, backward and forward compatibility, canary-style testing, rollback versus roll forward, and tools.
Waste in the deployment process — waiting teams, delayed feedback, late discoveries — produces undeployable, buggy software; the cure is a transparent, one-click, self-service process guided by the water-pipe bottleneck analogy.
A deployment pipeline automates the path from version control to production, and a value stream map makes that path measurable with cycle time, waste time, and lead time.
Every pipeline takes a version-control revision, builds it, and challenges the artifact through stages of fitness; unfit candidates are eliminated early with rapid feedback.
The concrete components of a basic pipeline: source control and artifact repositories, configuration as code, and the configure-deploy-smoke-test procedure every stage follows.
The pipeline pays out in fast feedback at every stage and transparency that shrinks the debugging scope to the single latest change.
Recompiling binaries in every context silently changes the artifact; the remedy is building once and deploying the same artifact everywhere.
Intelligent scheduling triggers the cheap first stage on every check-in while batching expensive acceptance runs; parallel pipelines across branches are fine, repeated runs of the same test are not.
Written before implementation by everyone involved in delivery, the release plan covers automation, rehearsal, rollback with its three decisions, and data migration — aiming at a one-button release.
Smoke testing is the fire test — break a dependency deliberately and verify the system heals — while performance testing measures how fast the system responds.
Four knowledge-check questions on pull requests, the artifact repository, merging more frequently, and the indicators of a good CI/CD system.
Exam Revision Notes
Below is the distilled, exam-ready core. Every entry comes from the full explanation above. Use this section for rapid review; return to the main notes when a point needs more context.
Continuous Delivery and Continuous Deployment
Must-know: Continuous delivery = everything automated up to staging/pre-production/UAT, with the production push manual; continuous deployment = that final push automated too; continuous integration is the prerequisite for delivery, and delivery for deployment.
⚠️ Top pitfall: Calling an automated build-and-test chain 'continuous deployment' — delivery and deployment differ only at the production boundary (manual vs automated push).
Self-check: If a team automates everything but a human presses the button to push to production, are they practicing continuous delivery or continuous deployment?
Connects to: Section 13.2
Deployment Considerations
Must-know: Backward compatibility: the new version keeps the old version's services working (v1.1 must tolerate null contact/address for the 50 v1.0 users). Forward compatibility: the old version handles missing features gracefully (v1.0 tells users to upgrade to 1.1 for reports). Rollback when the root cause is unknown; roll forward when the root cause and fix are known. Plus: rollback plan, unit testing, security check, zero downtime, canary testing, and tools matched to the platform.
⚠️ Top pitfall: Treating null values from older schema versions as failures — the software must tolerate nulls, not crash on them.
Self-check: An e-grocery app adds contact and address to signup in v1.1 while 50 users exist from v1.0. What must the app tolerate, and what message must a v1.0 user see when opening the new report feature?
Connects to: Section 13.1, Section 13.3
Challenges in Deployment
Must-know: Waste examples: build/ops teams waiting for docs or fixes, testers waiting for good builds, dev teams getting bug reports a week late, and discovering too late that the architecture cannot meet non-functional requirements. Waste produces undeployable, buggy software even with automation; the new approach is one-click, self-service deployment with a powerful feedback loop and visibility, guided by the water-pipe bottleneck analogy.
⚠️ Top pitfall: Thinking that a proper automation toolchain alone produces DevOps results — without a value-added process the organization still sees late feedback and waste.
Self-check: Why does widening the pipe at ten points not make the water flow faster, and what does that imply about improving a delivery process?
Connects to: Section 13.2, Section 13.4
The Deployment Pipeline and the Value Stream Map
Must-know: cycle time = sum of value-added stage times; waste time = sum of handoff waiting times; lead time = cycle + waste. For the textbook map: cycle = 3d + 1w + 10d + 7w + 1w + 2h = 10 weeks 6 days 2 hours; waste = 1w + 10d + 3d + 5d + 2d = 27 days = 3 weeks 6 days; lead = 14 weeks 5 days 2 hours (about 3.5 months). The lecture's stated totals (11 weeks 3 days 2 hours; five weeks) are kept as spoken, with the arithmetic as the reference form.
⚠️ Top pitfall: Trusting a spoken total instead of re-adding the map — the stated 11 weeks 3 days 2 hours differs by exactly four days from the computed 10 weeks 6 days 2 hours, and the stated five weeks of waste differs from the 27 days the handoffs sum to.
Self-check: Given value-added times 3 days, 1 week, 10 days, 7 weeks, 1 week, 2 hours and handoffs 1 week, 10 days, 3 days, 5 days, 2 days, what are cycle time, waste time, and lead time?
Connects to: Section 13.3, Section 13.5
Structure of the Deployment Pipeline
Must-know: Pipeline structure: input = a revision in version control; every change creates a build; the artifact passes a sequence of tests of its viability; unfit candidates are eliminated as early as possible with rapid root-cause feedback; the commit stage (compile, unit test, code analysis, build) produces the artifact that the acceptance test stage (UAT, capacity testing) exercises before production deployment.
⚠️ Top pitfall: Bypassing stages or hand-placing a build into production — that destroys the confidence ladder the pipeline builds stage by stage.
Self-check: In scenario 2, where does the pipeline stop, and what feedback goes back to the delivery team?
Connects to: Section 13.4, Section 13.6
A Basic Deployment Pipeline with Tools
Must-know: Pipeline components: source control repository (GitHub) triggers the commit stage; the artifact repository stores the binaries the later stages use; environment and app configuration live in version control (configuration as code, infrastructure as code); every stage does configure environment, deploy binaries, smoke test, acceptance test, and the artifact finally moves to UAT capacity test and production.
⚠️ Top pitfall: Hand-configuring an environment instead of pulling its configuration from version control — environments drift and the deployment no longer matches what was tested.
Self-check: Which component guarantees that the artifact tested in acceptance is the same artifact deployed to production, and where does each stage get its configuration from?
Connects to: Section 13.5, Section 13.7
Outcomes of the Deployment Pipeline
Must-know: Two outcomes: (1) fast feedback — every stage gives feedback to the team early; (2) transparency — you can see which build is in which environment and which stages it passed, so a problem in acceptance testing is traced to the exact source change, and because builds are stable, the debugging scope shrinks to the most recent change.
⚠️ Top pitfall: Reading the pipeline only after a failure — the feedback is only fast if the team actually watches each stage's result.
Self-check: An acceptance test fails. How does transparency tell you which change caused it, and why is the debugging scope small?
Connects to: Section 13.6, Section 13.8
Binary Anti-Patterns: Build Once, Deploy the Same Artifact
Must-know: Recompiling in every context is an anti-pattern: compiler version, compiler configuration, or third-party library differences silently change the artifact, so what was tested is not what is deployed. It violates (1) pipeline efficiency — slow rebuilds delay feedback — and (2) building upon foundations known to be sound — deployed binaries must be exactly the tested ones (verified by hashes). Remedies: build once, same release script everywhere, smoke-test deployments, deploy into a copy of production, propagate instantly, intelligent pipeline scheduling, stop the line on failure.
⚠️ Top pitfall: Promoting source code instead of the artifact — 'we rebuilt it there, it's the same' is exactly the assumption the anti-pattern disproves.
Self-check: Name three ways a recompiled binary can differ from the one that passed acceptance testing, and the two principles the practice violates.
Connects to: Section 13.7, Section 13.9
Intelligent Pipeline Scheduling
Must-know: Every check-in triggers the build and unit test stage, but the automated acceptance test only starts when it is free; later check-ins batch into the next acceptance run. Five check-ins where developer 1's acceptance test is in progress, developers 2 and 3 pass build but do not trigger acceptance, developer 4 fails at build, and developer 5's passing build triggers one acceptance run covering changes 2-5: one run, four changes verified. Letting every commit trigger acceptance testing takes more time and delays feedback.
⚠️ Top pitfall: Confusing parallel pipelines (fine — required for microservices) with retriggering the same acceptance test on the same feature for every small commit (bad — delayed feedback and burned resources).
Self-check: In the five-developer scenario, why does developer 2's check-in not trigger the automated acceptance test, and which changes does developer 5's acceptance run verify?
Connects to: Section 13.8, Section 13.10
The Release Plan
Must-know: Release plan: created before implementation (sprint planning in Scrum; planning and estimation after product discovery in traditional setups); created by developers, testers, operations, infrastructure, and support; covers automating unit/capacity/integration tests, rehearsing in a production-like environment, rollback with three decisions (when to roll back, how much time it takes, what triggers it), and configuration and production-data migration for both upgrade and rollback; goal: completely automated release — pick a version, press a button, and back out as easily.
⚠️ Top pitfall: Writing the release plan after implementation, or leaving out the rollback decisions and the data-migration strategy.
Self-check: When is the release plan created in Scrum, and what are the three rollback decisions the plan must attach to the back-out step?
Connects to: Section 13.9, Section 13.11
Smoke Testing and Performance Testing
Must-know: Smoke testing: controlled breakage — shut down a server or dependent resource, watch the impact on the application (does it shut down completely?), then verify that monitoring and configuration management detect and automatically fix the breakage. It validates how bad things get when something goes wrong (survivability). Performance testing is NOT a kind of smoke testing — it measures how fast the system responds (e.g., time from clicking login to the next page loading).
⚠️ Top pitfall: Treating smoke testing as a functionality test or as a variety of performance testing — it is a survivability test under a controlled failure, while performance testing measures response speed.
Self-check: An e-grocery app's payment server is shut down deliberately. What does the smoke test observe, and what must the monitoring and configuration management system do?
Connects to: Section 13.10, Section 13.12
Knowledge Check: CI/CD Fundamentals
Must-know: Pull request = technique to signal changes ready for review before merging. Artifact repository = mechanism guaranteeing tested artifact equals deployed artifact. Overlapping changes = merge more frequently so overlaps surface early and are resolved by hand. Good CI/CD indicators = all three: speed up builds, show why and where tests fail, support the containers/build and deploy environments used.
⚠️ Top pitfall: Believing a pull request guarantees the deployed asset equals the tested one — a PR reviews source, not the artifact; only the artifact repository gives that guarantee.
Self-check: Two developers submit overlapping changes. What is the root cause of the conflict, and what practice addresses it?
Connects to: Section 13.7, Section 13.8
Exam Guidance Summary
Must-know: Relative grading follows the topper's score; comprehensive exam = full syllabus, 2h30m; write your own answers (copy-paste is a risk); missing both mid-semester attempts bars the comprehensive exam; MVP question expects TDD (speed + quality, mature team), FDD for 50+ people across teams; Scrum master blocking communication is poor agile; sprints are 2-4 weeks; assignment: BITS-ID repository, master + two feature branches with approved and rejected PR scenarios, UAT on two VMs, submitted as document or video.
⚠️ Top pitfall: Copy-pasting answers into the comprehensive exam, or treating feature prioritization as a reason to pick FDD — prioritization happens in every agile method.
Self-check: Why is TDD the expected answer for the MVP scenario, and when should FDD be chosen instead?
Connects to: Section 13.12
Key Industry Applications
Must-know: GitHub triggers the commit stage and hosts pull requests; Jenkins is the classic integration server (intelligent scheduling now built in); Maven builds Java projects in tutorials; artifact repositories guarantee the tested artifact is the deployed artifact; deployment targets span local servers, cloud, and VMs; configuration and infrastructure live as code in version control; smoke testing uses the monkey tool with self-healing monitoring; the e-grocery app anchors compatibility and performance examples; virtual labs run through ELN portal with BITS SSO and RDP; release notes come from commits, task logs, Jira, and GitHub summaries.
⚠️ Top pitfall: Forgetting that the artifact repository is what actually ties testing to deployment in practice — tools alone do not guarantee it.
Self-check: Which two sources feed automatically generated release notes besides commit messages and task logs?
Connects to: Section 13.6, Section 13.9
Was this lecture useful?
BitsNotes AI Assistant
Subject Notes AssistantConfigure AI Chat
Choose how to access the chatbotSigned in as
Powered by BitsNotes — 20 messages per day. No API key needed. Want unlimited access? Use "Bring Your Own Key" mode.
Sign in to use AI Chat
Get 20 free AI messages per day to ask questions about your lecture notes. Sign in with Google or GitHub — it takes 5 seconds.
Sign In to BitsNotesSwitch to "Bring Your Own Key" tab above for unlimited access with any OpenAI-compatible provider.