Since the increase in popularity of continuous delivery (CD), there was an increase in the number of tools marketed as CD solutions. That’s normal. It is only natural for software vendors to ride the waves. They need to sell, and there’s nothing better to sell than whatever is popular at a given moment. Continuous delivery is one of those "popular" waves.
A video version of the same post is available in The DevOps Toolkit Series YouTube channel.
On the surface, there is nothing wrong with buying tools that solve problems. You have a problem, a vendor has a solution, you buy it, they earn money, and you have a good return on investment. Everybody wins, except when the tool does not do what it’s supposed to do. That’s when we run into issues.
Continuous delivery is one of those situations when vendors bend definitions to fit their needs. It is a common theme that we experienced many times before.
Now, I will not go into a rampage and start naming names. Instead, we’ll try to define what continuous delivery is. If we manage to do that, we should be able to define the requirements and the objectives the tools calling themselves as CD platforms should have. From there on, you should be able to decide by yourself whether a tool is indeed designed to perform continuous delivery or not.
What Is Continuous Delivery (CD)?
Continuous delivery (CD) is the ability to deploy changes to production as fast as possible, without sacrificing quality and security. It is about building a sustainable way to move from a suggested change into production without friction and fast. Most of the time, that means full automation of all the steps in the application lifecycle after pushing a change to a code repository.
Actually, the previous definition is not correct. Continuous deployment (CDP) is the ability to deploy changes to production as fast as possible, while continuous delivery is about having each release deployable to production, preferably with a single command or a button. Nevertheless, in the interest of brevity, I will treat both the same and use the term continuous delivery (CD) as an umbrella for both practices. You, on the other hand, should keep in mind that the difference is in a button that represents a manual confirmation that a release should be deployed to production.
Continuous delivery starts with a suggestion for a change. Today that is usually expressed through pull requests. When a developer is finished working on a feature, he or she creates a pull request. Until that moment, the work is mostly local. It is entirely in the hands of a developer or a small team. The clock starts ticking the moment a pull request is made, and it ends when the change is running in production. The less time passes between those two milestones, the better we are, and the benefits are more significant.
The sooner we can get a feature to production, the sooner our users will benefit from it. The higher the frequency of deployments, the lower the risk, and the faster we are getting to market.
There are many other reasons we want to apply continuous delivery, and I will not go through all of them. You probably already know them. Even if you don’t, it should not be hard to figure out why speed is of the essence and why having reliable and repeatable processes that are mostly (if not entirely) automated increases quality and decreases costs.
What matters for this discussion is the process itself. The goal is to deploy new features to production as fast as possible, but without sacrificing quality. However, it is not just about deploying something to production. As a matter of fact, there must be something to deploy in the first place, and that something must meet some business needs, fulfill some quality criteria, and so on and so forth.
So, if we know that the end goal is to deploy a release to production, let’s reverse-engineer the process.
For us to deploy something, we need to have that something. That means that before deployments, we need to create a release. We need to build the binaries that we are hoping to deploy. However, since it would be silly to deploy random binaries, we need to test them. Since it would be close to impossible to thoroughly test something without deploying it, we probably need to have at least two environments in which we deploy new releases. In other words, we need to deploy to a non-production environment, run some tests, and, if they are successful, we might deploy to production. I’ll call those runtime tests.
I’m using the term runtime tests to group all those that require a live application. That could be what you call functional, integration, performance, or many other types of tests. In this context, what matters is that I am using the term runtime tests for all those that require a live application.
If we continue reverse-engineering the process and moving backward, we want to fail fast. The sooner we fail, the sooner we’ll discover issues that might force us to delay the release until we fix the problems. When things are done right, most issues can be found through static tests (those that do not require a live application). They tend to be much faster than any other types of tests, so running them early allows us to fail fast and discover issues almost instantly.
I’m using the term static tests to group all those that do NOT require a live application. Those are the tests that can be executed right away without building binaries and without deploying anything anywhere. They can be unit tests, static analysis, security scanning, or many other things.
On top of all that, there are reviews, approvals, and quite a few other steps involved in the lifecycle of an application. Without those, there is no deployment to production, so any tool that aims to provide a continuous delivery solution needs to do all that, and probably much more. Or, to be more precise, it needs, at least, to orchestrate all those steps.
Most of the steps involved in continuous delivery are associated with pull requests. That’s where it starts. A developer creates a pull request (PR) with suggested changes to an application. Almost everything we do is related to PRs. As a matter of fact, the moment we merge a pull request to the master branch is the moment we are saying that "this is ready for production."
A PR is an expression of the intention to start the process of applying proposed changes to production, and merging to the master branch is the confirmation that the changes are (probably) ready for production. With that in mind, we can only conclude that almost everything is happening within the confines of a pull request.
There are many other things we might take into consideration, but those that we already mentioned represent the core steps without which no one should be allowed to deploy anything to production. Without the capability to orchestrate those, no one can claim that it is performing continuous delivery. As a result, any tool that claims to perform continuous delivery needs to run or orchestrate those steps.
Continuous delivery (CD) is the ability to deploy changes to production as fast as possible, without sacrificing quality and security. If that’s the case, then the core and minimal steps involved are as follows.
- Execute static tests
- Build binaries
- Deploy binaries to a non-production environment
- Run runtime tests
- Merge the PR to the master branch
- Deploy the binaries to production
All those are kicked with the creation of a pull request. PRs are a statement that can be described as "I think this is finished, let’s start the CD process."
The only thing missing is what comes at the end. We did not mention observability, self-healing, alerting, and whatever else comes after deployments. But those are not part of continuous delivery. The CD process stops when we have a new release running in production, and others kick in.
Let’s get back to the tools. If one wants to be considered a continuous delivery tool, it needs to be capable of orchestrating all those, and quite a few other steps. I intentionally said to orchestrate instead to perform since CD tools are not supposed to do all that. We already have the means to build binaries, run unit tests, perform security scanning, and so on and so forth. A CD tool is a tool that can orchestrate all the steps in application lifecycle and tie all the tools together.
Nevertheless, quite a few of the tools in the market took a different approach.
What Is The Difference Between Continuous Integration (CI) And Continuous Delivery (CD)?
Have you noticed that most of the steps involved in continuous delivery (CD) are the same as those used in continuous integration (CI)? To perform continuous integration, we need, as a minimum, to execute some static tests and build a binary. We might also be deploying to non-production environments and running functional tests. If we do, I might argue that we are already stepping into the CD territory, but that’s the gray area, which, for the sake of brevity, I will leave inside the CI process.
What matters, at least for this discussion, is that most of the steps involved in continuous integration are the same as those involved in continuous delivery. If we extend CI with deployments to production, and whatever else we might need to do around those deployments, we are getting continuous delivery. That might lead us to conclude that CD is an extension of CI. It is the evolution of the principles and the stages and steps characterized as CI. As such, we can say that CI is a subset of CD.
What we cannot say is that CI and CD are two separate processes orchestrated with different tools. If we would claim that, we would fall into the trap designed by some software vendors. They are not separate things. If we extend CI further, we get CD. To frame it differently, if we are performing only a part of the process, we are practicing CI. If we are following it fully, we are doing CD. There is no scenario in which we are doing both CI and CD. It’s one or the other, and which one it is depends on how far we can go in our automation and how mature our teams and processes are.
But, as I already mentioned, that’s not how some software vendors understood the differences between CI and CD. The reasons are usually commercial in nature, rather than a lack of understanding of what CD really is. A simple way to easily discard CD tools that are not really CD is to ask the vendor: "do you provide CI capabilities?" If they say no, it is not CD since CI is a subset of it. Now, the problem is that if they say yes, it still does not mean that they are indeed having a tool capable of orchestrating continuous delivery and, even if that is the case, whether it is any good by today’s standards. So, I did not equip you to distinguish good from bad, but at least you should be able to discard those that are clearly not it.
I’ll end it here since continuing would force me to start naming names, and today I am not in the mood for such a thing. I’ll leave you alone and let you think about the reasons why there is a discrepancy between what CI and CD are and what software vendors are trying to convince you. Heck, continuing might even force me to comment on even more ludicrous "inventions" like continuous testing. That would pose a risk of me having another fit with an increased chance of a heart attack. So, I’ll stop here and let you figure out the rest.
This text was taken from the book and a Udemy course The DevOps Toolkit: Catalog, Patterns, And Blueprints