CI/CD can be represented as a pipeline (refer to the following figure), where new code is submitted on one end, tested over a series of stages (source, build, staging, and production), and then published as production-ready code. It can iteratively approach this pipeline if an organization is new to CI/CD. This means that they should start small and iterate at each stage so that they can understand and develop the code in a way that will help the organization grow.
Each stage of the CI/CD pipeline is structured as a logical unit in the delivery process. In addition, each stage acts as a gate that vets a certain aspect of the code. As the code progresses through the pipeline, the assumption is that the quality of the code is higher in the later stages because more aspects of it continue to be verified. Problems uncovered in an early stage stop the code from progressing through the pipeline. Test results are immediately sent to the team, and all further builds and releases are stopped if the software does not pass the stage.
Businesses can adapt the stages based on their needs. Stages can be repeated for multiple types of testing, security, and performance. Depending on the project’s complexity and team structure, some stages can be repeated several times at different levels. For example, the end product of one team can become a dependency on the project of the next team. This means that the first team’s end product is subsequently staged as an artifact in the next team’s project.
The presence of a CI/CD pipeline has a huge impact on maturing the capabilities of an organization. Organizations should start with small steps and not build a fully mature pipeline with multiple environments, many testing phases, and automation in all stages at the start. Even organizations that have highly mature CI/CD environments still need to continuously improve their pipelines.
Building a CI/CD-enabled organization is a journey, with many destinations along the way. The next section discusses a possible pathway that an organization could take, starting with continuous integration through the levels of continuous delivery.
The first phase in the CI/CD journey is to develop maturity in continuous integration. Developers should regularly commit their code to a central repository (such as one hosted in CodeCommit or GitHub) and merge all changes to a release branch for the application. No code should be held in isolation. If a feature branch is needed for a certain period of time, it should be kept up to date by merging from upstream as often as possible. Frequent commits and merges with complete units of work are recommended for the team to develop discipline and are encouraged by the process. A developer who merges code early and often will likely have fewer integration issues down the road.
Developers should create unit tests as early as possible for the applications and run these tests before pushing the code to the central repository. Errors caught early in the software development process are the cheapest and easiest to fix.
When the code is pushed to a branch in a source code repository, a workflow engine monitoring, that branch will send a command to a builder tool to build the code and run the unit tests in a controlled environment. The build process should be sized appropriately to handle all activities, including pushes and tests that might happen during the commit stage, for fast feedback. Other quality checks, such as unit test coverage, style check, and static analysis, can also happen at this stage. Finally, the builder tool creates one or more binary builds and other artifacts, like the application’s images, stylesheets, and documents.
Continuous Delivery – Creating a staging environment
Continuous delivery (CD) is the next phase and entails deploying the application code in a staging environment, which is a replica of the production stack and running more functional tests. The staging environment could be a static environment premade for testing or provision and configure a dynamic environment with committed infrastructure and configuration code for testing and deploying the application code.
Continuous delivery: creating a production environment
In the deployment/delivery pipeline sequence, after the staging environment, is the production environment, which is also built using infrastructure as code (IaC).
The final phase in the CI/CD deployment pipeline is continuous deployment, which may include full automation of the entire software release process including deployment to the production environment. In a fully mature CI/CD environment, the path to the production environment is fully automated, which allows code to be deployed with high confidence.
Path Forward and Beyond
As organizations matures, it will continue to develop the CI/CD model to include more of the following improvements:
- More staging environments for specific performance, compliance, security, and user interface (UI) tests
- Unit tests of infrastructure and configuration code along with the application code
- Integration with other systems and processes such as code review, issue tracking, and event notification
- Integration with database schema migration (if applicable)
- Additional steps for auditing and business approval
- Even the most mature organizations that have complex multi-environment CI/CD pipelines continue to look for improvements. DevOps is a journey, not a destination. Feedback about the pipeline is continuously collected and improvements in speed, scale, security, and reliability are achieved as a collaboration between the different parts of the development teams.