Computing has reached an unprecedented point in speed, capability, storage, and scale, elevating user expectations for product innovation. To deliver against constantly evolving business goals, software development must embrace practices that prioritize shorter iterative cycles, tighter feedback loops, and delivery velocity so that code can ship quickly and more often to end users.
Continuous integration and continuous deployment (CI/CD) are part of the broader DevOps culture in modern software development, allowing teams to break down features, and then build and ship them quickly and often. Though closely related, CI, and CD are not exactly the same things. They’re often used in concert for modern software delivery, which is why it’s easy to conflate them as a single concept.
This guide will walk you through the concepts and practices of CI/CD and then highlight their differences, helping you gain a better understanding of what they both are, how they differ, and how they play nicely together as building blocks in modern software development.
Perhaps obviously, continuous integration is the CI part of CI/CD. It establishes the foundation for the CD part as well as most of the downstream stages in a software delivery production line. CI enables developers to code incrementally and integrate their changes into the codebase quickly and often.
This mitigates the risk of waiting to integrate code until the team needs to make several changes to the codebase. Updates that can break the build are discovered, and avoided more easily. Of course, quick and frequent code consolidation is only possible with instrumentation and automation. Otherwise, administrative tasks would become painful bottlenecks.
Relying heavily on automation, CI shortens the code-change-to-code-consolidation workflow, especially across a team. It tightens the feedback loop for developers, enabling them to stay agile and make incremental improvements to the software rather than big-batch, high-risk changes.
The Culture and Process of Continuous Integration
A number of tools and practices need to be in place and ready for automation for CI to work as expected. They include:
- Source control. The codebase needs a version and change management system that allows work isolation (branches), audit/change trail (commits), and change consolidation (merging) across a team.
- Committing early, pushing often. The goal of high velocity software delivery is driven by the practice of committing changes early and pushing batches of these changes often. This not only boosts developer productivity from a unit of work perspective, it enables traceability, allowing developers and code reviewers to isolate issues quickly.
- Quality gates. Every CI process needs to automate some kind of code quality gate that halts the build and provides feedback when code quality or implementation requirements are not met. Typical gates include validating the code against a format style by running a linter, and validating the code against requirements or acceptance criteria by running some unit tests. Remember that it’s super important for unit tests to stay as “unit” tests, and not become long-running tests as they evolve over time.
- A culture of feedback, collaboration, and collective ownership. Engineering teams that make the most of CI are teams that take action with feedback from the CI process, and do so with a sense of collective ownership. Pointing fingers at the one who wrote the feature that broke the build is counterproductive and creates a culture where engineers are not able to fail forward for fear of being called out. This inhibits the team from attaining the goal of shipping quickly and often.
Though the CI flow can include running integration tests, these should be clearly separate from unit tests. Integration tests often do not need to run on every code commit, particularly those that tend to be isolated (in git branches). Many CI pipelines introduce integration tests during code consolidation (merging into the mainline) or even further down the pipeline.
The key benefits of CI are:
- Improved feedback loop
- Confidence in tests
- A culture that drives higher developer productivity
As already mentioned, CI lays the foundation for CD. Let’s take a look at exactly how they tie in together.
The CD in CI/CD can mean continuous delivery or continuous deployment. They both layer over CI, but differ slightly from each other. For this article, our focus is on continuous deployment.
Continuous deployment leverages and builds on the automation established by continuous integration. It delivers code changes to users by automating the steps of deployment into a production environment so that features quickly get to the end user.
Once a build has passed all the checks in the previous stages of the pipeline, like automated tests in the CI stage, the build automatically gets deployed into a production environment.
CD shortens the feedback loop between code consolidation and feature access for users, allowing engineering and product teams to quickly see the effects of updates on users, validate assumptions and hypotheses, and then take necessary evidence-based action.
The Culture and Process of Continuous Deployment
A number of things need to be true for CD to be a practical reality in any organization. Let’s take a look at some of them.
Well-maintained and Fully Automated Gates in CI
CD doesn’t just build on top of CI —- it relies heavily on the gains of CI. As a downstream set of stages in a pipeline, CD depends heavily on the quality of test automation, and the overall confidence that the pipeline garners from a functional, and automated CI process. Thus, early and continuous investments in test quality and automation, as well as building the right CI culture, begin to pay off exponentially when the pipeline reaches the CD stage.
Prioritizing UX and Minimizing Chaos
If the goal of fully automating the release of incremental code changes to users is to be achieved with continuous deployment, then the risk of breaking production behavior with potentially unfinished functionality needs to be handled in a way that meets a few requirements. Your system for handling risk should be opaque and seamless to users, it should value stable and consistent release cycles, it should not unnecessarily increase complexity for the team, and it should provide visibility as to what functionality is and is not in use.
This is where feature flags, release channels, tiered environments, and atomic deployments that can be promoted up the environment tier, all come in to play.
The last thing anyone wants is the production environment becoming compromised because a developer account with access to the testing environment was compromised. The breach could automatically propagate unauthorized access to higher environments, and now the attacker is able to deploy code or intercept deployments (automatically, thanks to your CI/CD pipeline).
Ensuring that security is up to date and efficient across your entire team is paramount to the success of CI/CD.
The value of CD to a high-growth/high-velocity product is immense, but it comes with the responsibility of robust monitoring and observability. This helps the team build the right muscles to quickly respond to issues and minimize damage while establishing (over time) what the right pattern of appropriate system behavior is.
Comparing Continuous Integration with Continuous Deployment
The table below highlights some notable differences between CI and CD.
|Continuous Integration||Continuous Deployment|
|1||Is a CI/CD upstream process||Is a CI/CD downstream process|
|2||Prioritizes feedback loop for engineering team||Prioritizes feedback loop for product teams|
|3||Shortens feedback from code change to consolidation||Shortens feedback from code consolidation to feature use|
|4||Builds artifacts from validated changes||Deploys artifacts from validated changes|
|5||Quickly validate and rectify code changes||Quickly validate and rectify features|
|6||Needs quality gates and automation||Needs monitoring and infrastructure automation|
|7||Can be triggered by code check-in or code consolidation||Often triggered by code consolidation|
|8||Relies on test automation||Relies on deployment automation|
|9||Issues can impact developer productivity and is often localized to the engineering team||Issues can impact users, the product, and business objectives|
|10||Helps the engineering team fail forward||Helps the product and business fail forward|
The push, build, test, release, and deploy process is an incremental and continuous one, hence the name continuous integration and deployment.
Now that we’ve taken the time to run over the similarities and differences of continuous integration and continuous deployment, you should be able to appreciate how using both techniques in concert empowers engineering and product teams to quickly deliver features to end users. The visibility, transparency, feedback, and collaboration of CI/CD are currently vital to building the right culture for high velocity.
Interested in specific deployment tools to help ease the implementation and maintenance of continuous integration? Check out Earthly for repeatable, language-agnostic builds.
While you’re here:
Earthly is the effortless CI/CD framework.
Develop CI/CD pipelines locally and run them anywhere!