Featured image of post CI/CD: More Than Commit -> Deploy

CI/CD: More Than Commit -> Deploy

This article is an entry in a topic I’m calling Reprints, where I’m collecting works that I have written in the past but published on other platforms in an effort to collect my work into a single place. Wherever possible I will be linking to currently available locations online of the original publications. In all cases there will be what I consider to be appropriate attribution and usage within either my explicit rights or Fair Use. If you think I’ve misstepped, please contact me.

This piece was originally written while I worked at Guild and published in April of 2020 on their Extra Credit tech blog.

Photo by Pablo Lancaster Jones on Unsplash

CI/CD is a central topic of DevOps. Usually, “CI/CD” is understood to mean “Continuous Integration / Continuous Deployment”. Its importance to DevOps adoption projects has led to the creation of dozens of tools designed to make that process easier. There’s lots of nuance and detail that should be part of this process, but unfortunately it’s frequently simplified down to “Commit Code -> Deploy Build”, and therein lies the danger.

Many people see that simplified process as the pinnacle of DevOps value, but lumping it all together like that can lead to problems later as your organization works to mature their DevOps practice. Why is that?

CI can be described as the process which consumes freshly committed code and runs a variety of tests and performs a “build”. Depending on the technologies involved and the maturity of the practice the details can vary widely, but at a high level, that’s pretty much it.

CD is the next step in the process, wherein that fresh build is deployed into a server environment so people can use it. Usually, this is a testing environment of some kind so the changes can be validated beyond whatever validation is done during the CI process, followed by a deployment into production.

Treating these two separate concerns as a single process prevents either of them from being as efficient or flexible as they should be. What happens when you need to move that code to another environment? In most cases, the answer is to merge those changes into another branch which will deploy there. But why would we do that? We should already have that code built and tested, why do we need to do that work and spend that time again?

How do we know for certain that the tests we performed in one environment accurately reflect what we can expect when the code is merged, rebuilt, and redeployed in another environment? If we have good automation we can be pretty sure it will be the same, but there is a chance that the merge and rebuild process could introduce changes that weren’t there before. This is especially true on teams where there are many people working fast on parallel projects. Why would we allow this risk to exist in processes that are supposed to be reducing risk as they progress?

This extra effort and risk can be significantly reduced by logically separating CI from CD, and treating them as separate processes. The most straightforward way to do that is to have the CI process create an artifact of some kind, which is then consumed by the CD process. This artifact could be a container image, a webpack, a serverless code archive, or any number of other kinds of packages that wrap up software. Whatever form it takes, the creation of this software artifact allows us to decouple the CI process from the CD process, which lets us do some pretty amazing things during CD.

It gives us much improved confidence that what we are currently deploying is the very same thing that we had previously tested. It allows us to “shift left” the risk and effort of code merges. It allows deploys to downstream environments to be faster because we’re not repeating the CI process when we don’t need to. It allows us to easily deploy the same code in multiple environments, or easily re-task an environment for testing different things by deploying a different version of some code to it. It allows us to adopt tooling around deployment that can be easily used by non-developers, eliminating developers as a bottleneck for deployments and moving the decision of “what should be where” closer to people who focus on business concerns. This list could continue, but that should illustrate well the benefits of decoupling CD from CI.

The benefits don’t stop in CD though! If we don’t have to run the CI process as often and have it be a blocker for CD, the cost of the time it takes is reduced. This gives us the space to add more thorough automated tests to the CI process, which can give us even more confidence in the build and reduce the need for manual QA later in the process.

I really believe in the value of separating concerns. If processes are designed to create bright lines or explicit handoffs between areas of concern, it makes the overall process much more powerful. Separating CI from CD is a great example of that effect, and one that I hope we will embrace at Guild as we progress in our DevOps journey. If you’d like to learn more about this space, check out Continuous Delivery by Jez Humble, it’s an amazing resource!

Built with Hugo
Theme Stack designed by Jimmy