If your goals are high-velocity software development and frequent delivery of working builds to production, you need to automate at least part of the testing and delivery process. Ideally, that means implementing CI/CD pipelines for your projects, along with test suites to catch errors before customers see the software, and scripts that implement the steps of the pipelines.
Continuous integration (CI) is a methodology for automating software builds, packaging, and tests in a consistent way. CI helps to give a team some confidence that changes they check into source code version control will not break the build or introduce bugs into the software. The endpoint of CI is typically a completed check-in to the main branch of a software repository.
Continuous delivery (CD) automates the delivery of tested software to infrastructure environments. That doesn’t usually mean throwing it directly into production to see if customers complain. Typically, organizations start by pushing the build to a development environment. After the developers themselves beat on the new build and release it, it usually goes to a test environment, where it is used by a broader group of users (sometimes just dedicated internal testers, sometimes a larger cadre of users signed up for beta testing or “dog-fooding”) and monitored closely. Finally, if all goes well, the testers sign off and push the new version to a production environment.
At each stage of CD, there are options to revert quickly to an older build and generate bug report tickets for the developers to address in the new build. The goal is not to push lots of builds into production, but rather to continuously improve and enhance the software without introducing regressions. Another term for these practices is “devops.”
Why host CI/CD in the cloud?
Hosting a CI/CD platform in your own data center is a viable option, especially for companies that mandate hosting their applications and data inside the firewall. The disadvantage of doing this is that you’ll need a dedicated team to maintain the infrastructure, and you’ll incur some capital expenditures for servers.
If you are allowed to host in the cloud, it is usually a better option. The cost of hosting in the cloud is modest, and that operating expense is offset by the services provided: onboarding, infrastructure maintenance, security maintenance, support, and CI/CD software maintenance. Hosting your CI/CD software in the cloud often makes it easier and faster for the pipelines to interact with your source code repositories, if they are also in the cloud. If your developers and testers are geographically distributed, hosting your repositories in the cloud frequently gives developers a better experience than hosting in remote servers behind firewalls.
It’s also possible to deploy CI/CD on a hybrid of on-premises and cloud servers. Several of the latest CI/CD offerings run in containers on Kubernetes clusters, which are equally happy running on-premises and in the cloud. In a hybrid deployment scenario, you can place each component where it makes the most sense given the physical location of the developers themselves and the network locations of the other servers in the development infrastructure.
CI/CD must integrate with your repositories
As you may have gathered when you read “the endpoint of CI is typically a completed check-in to the main branch of a software repository,” repos are essential to CI and CD. Beyond being the end point of the check-in and test process, software repositories are the preferred place to store your CI and CD scripts and configuration files. Yes, many of the CI/CD platforms can store scripts and other files internally, but you are usually better off having them in version control outside of the tool.
Your CI/CD tools need to support your programming languages and tools
Each programming language or language group (JVM languages, LLVM compiled languages, .NET languages, and so on) tends to have its own build tools and testing tools. To be useful to you, a CI/CD tool must support all the languages that are part of a given project. Otherwise, you might need to write one or more plug-ins for the tool.
Docker images are becoming more and more important to distributed, modular, and microservice software deployments. It helps a lot if your CI/CD tool knows how to deal with Docker images, including creating an image from your source code, binaries, and prerequisites, and deploying an image to a specific environment. Again, lacking this, you might need to write plug-ins or scripts to implement the Docker functionality you need. Similarly, you’ll want your CI/CD tool to support Kubernetes and any other container orchestration systems that you use in your environments.
Do your developers understand CI/CD and the tools you’re considering?
The principles of CI and CD may seem obvious, but the details are not. The various CI/CD tools have differing levels of support and documentation. There are multiple books on Jenkins, which isn’t surprising since it’s the oldest of the bunch. For other products, you may have to investigate the documentation and support forums and paid support options as part of your due diligence in picking a tool.
For general background on CI, consider the Addison-Wesley book Continuous Integration by Duvall et al. Similarly, for general background on CD, consider Continuous Delivery by Humble and Farley. Both books won Jolt awards when they were published.
You can choose different CI/CD tools for different projects
While this guide is about choosing a CI/CD platform, please don’t assume that one platform will be optimal for all your software development projects. Most shops use multiple programming languages and environments, and not every CI/CD platform will support all of them well.
Feel free to pick the CI/CD platforms that work best for each of your projects rather than finding a single compromise platform. The general principles of CI and CD carry over from one platform to another, even though the scripts you write for them may not always be portable. While the additional onboarding time for each new platform may cost your devops team some time, that’s most likely less expensive than needing to customize a CI/CD tool extensively.
Plan for future CI/CD migration
Along the same lines, please don’t assume that a given CI/CD platform will serve the needs of your projects forever. Always hedge your bets, for example by storing scripts in repositories rather than within the CI/CD tool.
Prefer serverless CI/CD where appropriate
In general, cloud container deployments are less expensive than cloud server instance deployments, and serverless cloud deployments are less expensive than container deployments. Unfortunately, few CI/CD platforms can run serverless as of this writing.
Serverless means that the container running the process of interest is instantiated as necessary, generally in response to an event. For CI/CD, the triggering event is generally a code check-in to a specific repository branch; the repository Webhook then launches the serverless process. When the process completes, the resources are released.
One the few CI/CD platforms that can run serverless is Serverless CI/CD, part of Serverless Framework Pro, an enhanced version of the open source Serverless Framework. Serverless CI/CD is optimized for deploying serverless apps and currently runs only on AWS. You’ll have to determine whether it supports your application well enough to use.
Where are your current cloud assets?
To optimize a cloud-based CI/CD configuration (or any cloud application), it helps if all your assets are “near” each other. “Near” in this context partially refers to geographic location, and partially refers to network location.
For example, if your database is in Australia and your application is in North America, you’re going to have a large lag every time the application needs to read or write data. On a smaller scale, if your application and database are in the same availability zone (AZ), the latency between them will be minimized. If they are in different zones in the same region, the latency will be higher, but not as high as if they were in different regions.
Similarly, if your database is on Google Cloud Platform in Virginia and your application is on Microsoft Azure in Virginia, the latency will be higher than if both were on the same cloud provider in the same AZ. All of this also applies to your repository (which is essentially a database), your CI/CD software, your actual application, and your developers and testers. It helps if all are “nearby,” although the effects of lag aren’t as blatant in this situation as they would be for, say, a real-time interactive game.
If the developers can push code commits into the master repository reliably and without noticeable wait times, they’ll usually be happy. Similarly, if the users and testers are “near” enough to the application to get sub-second response times, they’ll also be happy. For the CI/CD software, the key is reliable connections to the points of deployment. A little lag can be tolerable as long as it doesn’t cause time-outs or dropped packets.
Do a proof of concept before committing
CI/CD will be a critical part of your infrastructure once you have it fully implemented. Bear that in mind as you get up to speed.
It’s important to perform a rigorous proof of concept before starting to roll out the CI/CD pipelines. Shake down the CI portion before beginning the CD phase. Make sure you exercise your test suites and rollback capabilities before connecting any CI/CD pipelines to production instances, and keep humans in the loop until you’re very sure that the automation is rock solid.