It’s occurred to me fairly recently that there’s sufficient confusion about what the CD in CICD stands for, to warrant some simple explanation. I’m not even certain that people generally understand the CI part either. I’ve noticed on a few occasions developers tend to say, “A CICD pipeline is an automated way of delivering code into production.” I feel this is often interpreted as, “you commit code over here in your repository, and it automagically pops up in production over there.”
“What on earth could possibly go wrong with that?” the system operations team might ask sarcastically, turning distinctly green then pale at the thought of developers having ultimate control over production releases. I’ve also noticed non-developers ask, “Is it Continuous Delivery, or Continuous Deployment?” Is there even a difference? It seems a number of people interchange Delivery and Deployment without really understanding what each of them actually is. Isn’t this just typical developer double-speak for exactly the same thing?
To provide some historical context to this explanation, it’s useful to understand software development life cycles before Virtualisation and Cloud. Right up until the mid-2000s, software feature releases were typically very slow. Products might have gone four years before they got an update, and the savvy never installed a “dot-one” (.1) release, let alone a dot zero (.0). Frequently they were buggy and unreliable. It often wasn’t until a “one- dot-two” (1.2) release that people started getting any confidence. Even then, that only ensured catastrophic bugs were eliminated. Other glitchy behaviours often still existed but didn’t contribute to a total loss of work.
“You do back up your work every half hour right?” was the catch cry long before Cloud, autosave and versioning were as widespread as it is today.
A significant change that virtualisation helped bring about, was the ability to more cheaply run a non-production staging environment. A place to test out new changes before releasing them into production. Cloud via infrastructure as code makes non-production environments even faster, easier and cheaper to provision for testing purposes. The key to an effective staging environment is that it’s as Production-like as possible. This helps avoid embarrassing and costly “roll-backs” when code changes don’t behave in production as expected because there was too much variation between prod and non-prod.
Running in parallel to these infrastructure changes was the development and rapid adoption of software version control systems. In the bad old days, files were versioned by either commenting out old lines of code and introducing new lines. Alternatively, old files on production servers were renamed, and new files introduced in their place. It was less than ideal and alarmingly widespread. “When was the last backup done?” wasn’t something you wanted to hear in a development team. It often meant somebody had overwritten something they shouldn’t have.
Version control in the form of SVN, then later Git and other alternatives allowed a new copy of a code file to be added to a repository, and the old version kept completely intact. What’s more, the developer could comment during the commit, what had been changed.
This lead to the practice of Continuous Integration (CI), where developers could collaborate together more rapidly by sharing small code changes via the version control repository, and by doing so, minimise the impact each code change had on others. Everyone was effectively working on the same code base, rather than having separate copies that diverged more and more widely, the longer each developer worked on their private copy of the code.
This brings us then to Continuous Delivery which is the automatic build and test of committed code changes with the aim of having production ready features available for release. Getting to Continuous Delivery after the successful implementation of Continuous Integration is relatively straight forward using AWS Services. By using Code Pipeline to automate the test and build of code commits, most of the tooling required is readily available.
AWS services like Elastic Beanstalk make it incredibly simple to replicate production application stacks into non-production environments for testing. AWS OpsWorks and CloudFormation can greatly simplify the reproduction of more complex application stacks for production-like staging.
Many organisations get to Continuous Delivery and don’t adopt Continuous Deployment. They either use a manual authorisation step to deploy changes into production or a semi-automated delivery approach of code into production. Continuous Deployment then is the automatic deployment of production-ready code into production with no manual interventions. If changes fail the build and test processes, they are rejected and sent back to the development team for revision. If however, all changes pass the test, they are automatically deployed into production, and this is continuous deployment.
The fundamental key to all this working well is small frequent changes. The historic issue with large complex changes over an extended period of time was that the root cause of any particular issue was extremely difficult to pin down. This made people reluctant to release changes unless it was absolutely necessary. With the collaboration made possible by Continuous Integration, it ensures everyone is working on a single code base. This prevents accumulative errors common when everyone is working in isolation on big changes.
So there is an important distinction between Continuous Delivery and Continuous Deployment. The latter can be arrived at in an incremental manner after successfully adopting CI, then getting continuous delivery and testing to a robust enough point that well vetted, small feature changes can be continuously deployed into production.
Consegna have significant experience in helping organisations adopt CICD successfully. If you’d like to find out more information, email firstname.lastname@example.org.