In marketing materials from the world of Continuous Integration and Continuous Delivery (CI/CD) , one often comes across the idea there is a progression from continuous integration* (good) to continuous delivery** (better) to continuous deployment*** (best). The progression typically goes as follows:
- First, you write tests and implement continuous integration to ensure your tests are run when new code hits your main branch.
- Once your test suite is bulletproof and you are practicing continuous integration flawlessly, you can deploy code using continuous delivery techniques.
- Finally, your testing, integration, and delivery practices are so good you implement continuous deployment, wherein any code that passes all automated tests is automatically deployed to production.
Getting continuous deployment going is certainly a great goal in some situations, but this progression doesn’t suit everyone. Hiding in-progress work behind feature flags — which is often part of continuous deployment — may make adding functionality more cumbersome and, in the case of refactoring, necessitate maintaining multiple code paths to accomplish the same goal. An organization with deployment constraints (operating in a highly regulated environment, for example) may not need to fully implement continuous delivery, but might automate its release process with great results. Web apps that don’t have a substantial user base may not care about having the latest revision out on prod. The list goes on.
The good news, though, is organizations can reap benefits by implementing continuous integration and continuous delivery techniques in whatever form and order is best for them. Continuous delivery practices — primarily, automating the deployment and release processes — let business priorities drive deployment decisions, instead of vice versa. These practices can be implemented without continuous integration, although CI certainly gives software organizations the ability to confidently deliver code.
Similarly, teams can make huge improvements by implementing continuous integration without putting any thought towards continuous delivery. The wins are well-documented, but I’ll say it again: it is best practice to write good tests alongside your code, merge code frequently, and run all of your tests when code is merged. Some organizations may never reap the benefits of full continuous delivery, but can still implement continuous integration with great results.
To me, the best practices are clear:
- Write tests and run them when code is merged
- Make deployment frictionless
Apart from that, organizations have to think critically about which of these techniques can help them deliver quality software to the right people at the right time.
* Continuous Integration: “a software development practice where members of a team integrate their work frequently, usually each person integrates at least daily,” says Martin Fowler. It generally involves running automated tests that run every time a patch is merged (“integrated”) into the repository’s main branch of code.
** Continuous Delivery: a software development practice “in which teams produce software in short cycles, ensuring that the software can be reliably released at any time.”
*** Continuous Deployment: automatically deploying every passing build to production.