Continuous Integration, Continuous Delivery or Continuous Deployment? There is always a great misunderstanding of these terms out there! Let's clarify them in only 5 minutes.
Continuous Integration (CI) is a development practice from Extreme Programming that requires developers to integrate code into a mainline as often as possible, at least once a day, and each check-in is then verified by an automated build that compiles the code and run the suite of automated tests against it, allowing teams to detect problems early.
In the Git context, the mainline often turns out to be the master branch and each check-in is a new commit that emerges into the remote repository.
Implementing continuous integration provides several benefits:
• Merge hell, that is, endless merge conflicts while merging code into the mainline, is avoided because the code should be integrated to the mainline as often as possible (at least once a day).
• Allows to detect errors quickly as automated tests run on every single commit that checks-in the remote repository. Hence, less bugs get shipped to production.
• When an error is detected, it’s much easier to fix because the amount of code involved in each commit is much smaller.
• Promotes human communication earlier when merge conflicts occur. People can sit together and understand how their codes are actually influencing the other’s code.
• Building the release is easy as all integration issues have been solved early.
However, everything comes at a price. To implement continuous integration, the development team must understand that:
• Tasks should be split as small as possible in the planning stage because the code should be developed (including automated tests) and integrated to the mainline as often as possible, at least once a day.
• Automated tests should be present for each new feature, improvement or bug fix. They will ensure that a change (even a small one) is not breaking any other part of the system.
The second part of the definition states that "each check-in is then verified by an automated build that compiles the code and run the suite of automated tests". In order to run automated tests on every single commit that emerges into the remote repository mainline, the team will need to set up a Continuous Integration server. The most essential purpose of the CI server is to run automated tests on every new commit that emerges into the remote repository mainline, but it is actually capable of doing much more than that, such as issuing custom notifications when a test or build fail, triggering releases generation, triggering deployments to a specific environments, and so on. A well-known CI server is Jenkins, a leading open source CI server written in Java that provides hundreds of plugins to support building, deploying and automating any project.
A smooth Continuous Integration flow will ensure that the mainline is always in a deployable state. Continuous Integration and others Extreme Programming practices such as Automated Tests, Pair Programming, Test Driven Development, Refactoring, and Simple Design are all great contributors for the quality of an application code. If your team doesn't care for these (and others) techniques, it's very likely that you cannot ensure that the code actually works as intended. So, how could you have an automated deployment flow if you have no idea whether the code being delivered works or not? That's the reason why Continuous Integration is a requirement for implementing both Continuous Delivery and Continuous Deployment.
I really like Jezz Humble’s definition for continuous delivery:
"Continuous Delivery is the ability to get changes of all types; including new features, configuration changes, bug fixes and experiments into production, or into the hands of users, safely and quickly in a sustainable way".
In other words, when your team really implements continuous delivery what it actually means that the mainline is always in a deployable state, and one could decide to deploy it to production at any time at the touch of a button. This in turns is only possible because when this button is touched, an automated pipeline (a set of automated steps that your code changes goes through until it is finally deployed to production) is triggered. The key element for achieving continuous delivery is automation!
Well, if you can deploy to production at any time, the question is: when is it the right time? Of course the answer may vary depending on your business requirements, but the truth is that if you want to get the benefits of continuous delivery, you should deploy to production as early as possible to make sure that you release small batches that are easy to troubleshoot in case of a problem.
Continuous deployment is very similar to continuous delivery, but it takes even one step further regarding automation. In continuous delivery, every change pushed to the main repository is ready to be deployed to production, but starting this process still requires human interaction. In continuous deployment, the deployment to production is automatically triggered for every change that passes the test suite.
Continuous Delivery vs Continuous Deployment
As in continuous deployment every change that passes the test suite is deployed to production, it heavily relies on Feature Flags to release features to end users.
This article was based on the contents of my book Continuous Delivery for Java Apps: Build a CD Pipeline Step by Step Using Kubernetes, Docker, Vagrant, Jenkins, Spring, Maven and Artifactory. Click on the link and download the free book sample (110 free pages!) to learn more about Agile, Continuous Delivery, Scrum, Automated Tests (unit, integration, acceptance and performance tests), Feature Branch, Feature Flags, A/B Tests, Canary Releases, Apache Maven, Artifactory, Docker, Kubernetes and more!