What is CI/CD?
Building software is hard. A developer needs to write the code, test it, build it, and then deploy it to production. Each of these steps is complicated and has a high likelihood of mistakes. CI/CD is a fantastic way to reduce errors by automating away parts of the development process.
Continuous integration/Continuous deployment
If you’re writing software, whether it be a website, an iPhone app, or a low-level library, your steps to production will look something like the below:
These steps mean different things to different projects, but every project will involve some form of writing code, testing, building, and deploying.
Continuous integration and continuous deployment (CI/CD) introduces automation into the software process. Instead of manually running tests, building your software, and deploying it, CI/CD automates these steps away. Continuous integration automatically builds and tests your software on a regular basis, while continuous deployment will automatically deploy it when certain conditions are met.
CI/CD often integrates with version control software such as git, allowing you to trigger automated tests and software builds when you commit or create a pull request.
With a CI/CD tool, your process looks like the following diagram:
To take an example, say you write some code and open a pull request on your repository. Your CI will pick up the new code, test it, and build it. Your CI tool might also show you the test and build status within your pull request. Once you are happy with the code, you will merge the pull request, and your CD tool will pick up the built software and deploy it.
There are lots of tools out there to implement CI/CD including Jenkins, Travis CI, CircleCI, TeamCity, and many more. Choosing a tool should be done on a case-by-case basis and will depend on your project, your budget, the previous experience of your team members, and what other tooling you are already using.
What is the difference between continuous integration and continuous deployment (CI vs CD)?
Continuous integration (CI) is the automation of the test and build stages in the software lifecycle. A CI system will build your software and run your test suite on some kind of automated trigger. This trigger could be pushing code to a source control repository. For those of you who’ve used GitHub/GitLab, the usual example is that a CI system will run for every pull/merge request.
Continuous deployment (CD) is the automation of the deployment stage. This could include copying a binary to a public download URL or copying the build artifacts to your production servers. With continuous deployment, every time a code change builds and passes tests, it gets deployed into production.
Continuous delivery (also CD!) is a subset of continuous deployment. While continuous deployment will automatically deploy when tests pass and the build succeeds, continuous delivery will deploy whenever you choose to deploy. This could either be a manual button press or a regular time period such as once a week.
It is possible for a team to use CI without using CD, however, it’s considered best practice to use both where possible. Generally, teams will first adopt CI, and then once they have confidence in their tests, and CI system will adopt CD.
Advantages of using CI/CD
There are many advantages to using CI/CD when creating software. It’s considered good practice for good reason!
Remove human error
Humans aren’t as reliable as machines. When people do things, especially boring things that we have to repeat, there’s a good chance that we will make mistakes. When you’re running complicated test, build, or deployment workflows, there are infinite things that could go wrong:
- You might forget to run tests before committing
- You might forget to pass a flag to your test tool
- You could accidentally build a different branch
- You could forget that you have local changes in a file important to your software’s build
- You might accidentally run a debug build instead of a production build
- You could deploy an old version of your software to production
- You might deploy to the wrong machine if you have multiple production machines
This list might seem long, but it’s by no means exhaustive. People are infinitely creative, including in the problems we make.
Ship fewer bugs
Having an automated test suite that requires no effort to run encourages people to write more tests. When your software is covered by more tests, it’s more likely that the tests catch any bugs that you introduce.
On top of this, being able to rely on automation to run your tests ensures that tests have been run! When tests have to be run manually, it’s easy to forget to do it.
CI/CD also makes your tests more visible, which can help to enforce a culture of testing in the team. When a team cares about testing, the software they produce tends to have fewer bugs.
Release more frequently
Implementing CI/CD on your software projects helps you ship software faster. There are a few mechanisms behind this.
The first is that CI/CD increases your team’s trust in the code you write. Seeing a green check mark next to changes that you make is reassuring and allows people to approve changes faster since they don’t have to build and test the changes themselves.
Second, automated feedback is usually faster than manual feedback. Software engineers on your team have multiple hats to wear. They have to gather requirements, write code, and think about test cases, all alongside reviewing other engineers’ code. Having CI automatically run your tests and build is like having an instant basic review every time you push to a branch. This can help catch early bugs and make it more likely that your code passes human review.
Finally, automated deployment processes are much faster and more reliable than manual processes. Traditionally, ops teams would deploy software to production environments using a lengthy manual process. An automated deployment process can be run in seconds/minutes and completely remove the chance of human error.
Does CI/CD have disadvantages?
For the majority of projects, CI/CD is overwhelmingly a good thing. As with everything in life, however, there are tradeoffs to setting it up and it’s important to consider them.
CI/CD is an investment
Everything has a cost, and CI/CD is no exception. Even though many CI/CD systems are open source and free for commercial use, setting up and maintaining the system brings other costs. For example:
- The initial setup takes engineering time
- The system will require ongoing maintenance (for example, upgrades and bug fixes) that also takes engineer time
- Hosting the system will incur server rental costs, or hardware maintenance costs when run on-prem
These costs have to be factored into your decision of whether or not to run a CI/CD system. When deciding whether CI/CD is worth it for your use case, you should weigh these costs against the potential costs of a bug in production.
CI/CD is not a substitute for having tests
Tests that run automatically aren’t guaranteed to be good tests or have good coverage of your code. Testing your code well should be a higher priority than implementing CI/CD and often requires organizational solutions instead of technical solutions.
CI/CD makes tests more useful by ensuring they gatekeep code changes, however, it doesn’t replace having tests in the first place. Without a good test suite for your code, many of the benefits of CI/CD don’t apply any more.
CI/CD increases friction for large changes
The newer a codebase is, the more likely it is to undergo large changes. This could include things like rewriting the code in a new language, rewriting the public interface, or architectural changes such as moving between a single monolith and multiple microservices.
Radical changes often mean that your CI/CD has to change since it’s likely that your test and build process is also changing. This means increased overhead and development time. For a small startup that is likely to go through many of these changes in a short period of time, CI/CD may be more trouble than it’s worth in the early stages.
The counterpoint to this argument is that CI/CD can increase trust when radical changes happen. If your codebase dramatically changes, but the integration tests are still passing, then you can be more confident that the code is still working as expected.
Conclusion
In this article, you learned:
- What CI/CD does
- What the difference is between continuous integration and continuous deployment
- The advantages and disadvantages of implementing CI/CD
CI/CD is a fantastic tool that can dramatically increase the reliability of your project and the speed with which you can deliver new code.
Aviator: Automate your cumbersome processes
Aviator automates tedious developer workflows by managing git Pull Requests (PRs) and continuous integration test (CI) runs to help your team avoid broken builds, streamline cumbersome merge processes, manage cross-PR dependencies, and handle flaky tests while maintaining their security compliance.
There are 4 key components to Aviator:
- MergeQueue – an automated queue that manages the merging workflow for your GitHub repository to help protect important branches from broken builds. The Aviator bot uses GitHub Labels to identify Pull Requests (PRs) that are ready to be merged, validates CI checks, processes semantic conflicts, and merges the PRs automatically.
- ChangeSets – workflows to synchronize validating and merging multiple PRs within the same repository or multiple repositories. Useful when your team often sees groups of related PRs that need to be merged together, or otherwise treated as a single broader unit of change.
- TestDeck – a tool to automatically detect, take action on, and process results from flaky tests in your CI infrastructure.
- Stacked PRs CLI – a command line tool that helps developers manage cross-PR dependencies. This tool also automates syncing and merging of stacked PRs. Useful when your team wants to promote a culture of smaller, incremental PRs instead of large changes, or when your workflows involve keeping multiple, dependent PRs in sync.