Modern software development teams employ a wide array of methodologies and principles from the tried and tested Waterfall method, to more modern approaches like Agile or Kanban. Software development methodologies are useful tools for approaching the development lifecycle in an organized manner. Where they fall short however, is in what happens after development has been completed. Modern methodologies do nothing to address how a team handles their integration and deployment processes, which are an integral part of any software project.
Continuous Integration and Continuous Delivery (CI/CD)
Continuous Integration and Continuous Delivery (CI/CD) are software engineering approaches that dictate how a team handles combining individual development work, testing new code and eventually deploying applications into production. Without these tools, a software team is often left relying on outdated practices, or inefficient project pipelines that can seed confusion among developers, cause disruptions to the development cycle and push back delivery dates. With good CI/CD, a software team can avoid pushing unnecessary bugs to production, and speed delivery with automated deployment pipelines. In addition, CI/CD pipelines can be employed to enforce code consistency, run unit and integration tests, and clean up production servers to improve the efficiency of the application. The importance of Continuous Integration and Continuous Delivery is clear: providing a defined deployment pipeline and testing structure increases developer efficiency and speed time to delivery.
Continuous Integration Provides Version Control
In order to properly understand Continuous Integration, one must be familiar with common version control systems such as Git or Mercurial. These systems provide a place to store application code and view differences between files after changes have been made. Version control systems offer a paradigm called branching, in which a developer can create a copy of the source code, make changes to the source code and merge it back into the main branch without causing disruptions to other devs. The concept of Continuous Integration uses source control branching to merge developer working copies back into the mainline several times during the development cycle. The main goal of CI is to avoid conflicts and integration problems that can arise when developers work on the same files in a codebase, or a branch becomes out of date with its parent branch. By branching for things such as new features or bugs, teams decrease the time it takes to sort out multiple changes to the same files. When a developer branches for a new feature or a bug fix, the working copy can quickly become out of date as the mainline is updated with features and fixes from other devs. The longer a branch remains checked out, the worse integration into the mainline becomes. Development branches left untended can often enter ‘integration hell’, or a state where the branch’s code is so different from the mainline that it is very difficult to merge the two back together. By re-integrating a feature branch back into the mainline several times a day, developers can avoid integration hell by keeping their branches up to date. As a concept, CI is the merging of development branches back into the mainline several times a day. In practice however, CI employs a much more in-depth strategy to maintaining a code base. By setting up the version control in an organized manner, a team can not only streamline their development, but their deployment pipelines as well.
Where CI and CD Meet
Hand in hand with Continuous Integration lies the concept of Continuous Delivery. Whereas CI is a paradigm for organizing a team’s version control, CD handles what happens with the code after development and developer testing. CI and CD work well together, as the concepts employed by CI provide an efficient structure for deployment of completed code. Version control systems commonly keep track of a base branch, the top of the code tree so to speak. This base branch, called Master in Git and Default in Mercurial, is commonly used to store production ready code. CI provides the model for how developers handle the codebase from this master branch. Commonly, teams will create a staging or QA branch off of the main branch, and a development branch off of that. The development branch serves as a catchall for feature work, bug fixes, and any tweaks the team needs to make during a cycle.
Continuous Delivery Accelerates Deployment
Continuous Delivery is an approach in which a team deploys code to production during or after the completion of a development cycle. Teams will commonly set up their version control with event hooks, or special scripts that run when code is pushed to the QA or Master branches, which in turn run linters, unit tests, build the app, and deploy it to the server. Take for example a new feature on a production application. With the production code in the Master branch, and staging code in a QA branch, a developer creates a working copy of the code from a development branch and works on the feature. When the dev is satisfied that the feature is written as required, he or she runs local tests, lints the code, and submits the new feature for review. If the review goes well, the code can be merged into the QA branch, deployed to a staging server and tested, and eventually delivered into the production application. Deploying tested code into production in this manner increases developer efficiency, and speeds delivery time by avoiding unnecessary problems in the lifecycle.
Continuous Integration and Continuous Delivery are essential approaches to modern web app development. By providing dev teams with an organized, efficient development structure and deployment pipeline, software projects can get off the ground faster, produce features more efficiently, and run with fewer bugs in production.