At this point, it’s highly unlikely that you haven’t heard of CI/CD, an abbreviation that embraces Continuous Integration, Delivery & Deployment. These three DevOps practices focus on automating and simplifying the most error-prone and tedious aspects of software development process:
- integrating code written by different developers into a single code base;
- delivering stable and bug-free software through frequent, thorough, and automated testing;
- deploying new versions of the software to users as often as possible, without causing any downtime or inconvenience to the user base.
It surely won’t surprise you that there’s no “silver bullet” solution to automation, a one-size-fits-all setup that will do wonders in all projects. There is, however, a list of practices that have proven to work great, making the CI/CD process so much better, more efficient, and helpful.
What is the aim of CI/CD pipelines? What are the CI/CD best practices? Let’s find out!
The mother of all CI/CD best practices: it’s a must-have
Articles with 'top practices' in the title almost always kick off with a ready-to-go list of dos and don'ts, trying to maximize the reader’s limited attention span. I’m going to play it a bit risky here, however, and start with a practice that… isn’t really a practice.
Believe it or not, there are still teams with no CI/CD implementation of any sort. Heck, there are developers that do not use version control! After all, why would they? They spent years doing things manually, so why change anything in their trusted-albeit-fragile integration schedule?
Sure, along the way a few things might’ve gone south, they might’ve had to deal with some FUBAR situations but hey – they've been delivering software this way day in and day out and always overcome the hassle at the end of the day.
Now, this might seem perfectly fine. “Different strokes for different folks” goes the saying, but is it applicable here? Is this way of thinking really beneficial for software developers? While the non-automated approach might be sufficient, treating automation and CI/CD processes like a novelty puts your team at a disadvantage right at the start of the race for the customer’s love and wallet.
Serious players have a well-established CI/CD process working in their favor, and without a comparable setup in place, you just can’t compete with their deployment frequency, delivery speed, and overall code quality. Continuous Delivery is not a novelty anymore. It’s a must-have. As such, the first good practice of this list is to actually HAVE a CI/CD setup implemented. You’ll thank me later.
Looking to make your first steps? Sign up for a free account in Buddy and start automating today:
Be smart about automation – decide which processes to automate first with CI/CD
Now that the importance of having a CI/CD process in place has been established, let’s focus on the actual practices you can apply when dealing with CI/CD.
Although the ultimate goal of Continuous Delivery is automating (almost) everything, it might be a bit daunting to come face-to-face with the idea of re-thinking everything you do with your code before it gets to the end-users. Worry not - you don’t have to do everything at once.
Identify tests that can be automated
Software projects are like snowflakes: all are unique and use unique DevOps practices on every step of the code’s journey. So is their test base. As such, not all tests can be easily automated when building CI/CD pipelines.
Some tests you’re running might require a very specific hardware setup, others might need to run in a customized, experimental environment that cannot be left without supervision. Oh, and let's not forget testing scenarios that have to be performed manually.
Other tests, however, are generic and straightforward. Unit tests? Integration tests? Visual tests? If all they require is someone there to trigger them and make sure that they pass, they are the perfect candidates for automation.
When building CI/CD pipelines, don’t force yourself to automate everything. If some of the tests you run are very specialized and depend on custom components, it’s okay to let them live outside of the CI/CD process.
Just as you don’t have to automate specialized, custom tests, you also don’t have to force yourself to automate the other part of your tests which are more generic, but still pretty complicated. Take it slow when you’re starting out.
Pick a group of simple, cornerstone tests, and free your team from the tedious task of running them manually and inspecting the test results. Create pipelines, sit back sipping your favorite beverage, and relax thinking of all the time you saved with that move.
With the batch of simple tests automated, you’ve probably gained some much-needed experience in managing a CI/CD setup. When you’re ready, use this experience to take care of automating more complex tests.
Supercharge your CI/CD pipeline processes with parallelism
It’s natural to create a CI/CD process that follows a logical, chronological sequence of steps. First, you build, then you deploy to a test environment, then you start running tests one after another, making sure the execution stops as soon as a test fails.
Is this a bad CI/CD implementation? No, not at all. But it’s not necessarily the most efficient way to go. You can benefit from treating your pipelines in less of a linear way, more like shooting a movie. After all, the opening shot of a movie wasn’t necessarily shot as the first one, right?
One of the more fruitful CI/CD strategies asks you to run some of your tests in parallel which can give you a better overview of the actual state of your application. Picture this: your app has four critical functions, each of them covered with a Cypress browser test:
What will happen if one of these functions doesn’t pass? With a linear CI/CD process flow, you probably won’t get to know the results of the test performed on the other 3 functions.
However, if you decide to run these tests in parallel, you’ll get more useful feedback in case one or more of them fail. Without re-running your pipeline, you’ll know that one of the functions stopped working, while the 3 others did just fine.
This way you’ll know exactly what to fix. And, if all parallelized tests pass, you cut the pipeline's execution time significantly. It’s a win-win situation.
Make your CI/CD pipeline the only way to deploy to production
Do you know that feeling when you get a new piece of gear and you want to use it all of the time? You carry your DSLR camera everywhere instead of taking quick pics with your phone’s camera, you wear these new headphones day in and day out even when you’re not listening to any music - you know the drill.
Now make sure to treat your CI/CD pipelines like one of your new gadgets that you just got and have all your code go through it. Especially the code you want to deploy to production.
After you spend the time setting everything up: builds, tests, notifications, the whole shebang, don’t allow yourself to succumb to the temptation of skipping these steps and using a backdoor to get a new version of your app to the users. Stay true to your CI/CD process!
Yes, I know – it’s just a simple bug fix. It’s a simple class rename. It’s just one line of code. But is it really? Your CI/CD implementation is there for a reason. It’s there to check if that one quick fix or update is playing nice with the code that’s already there, and it’s going to do so objectively, making sure that this quick fix meets the quality standards you vowed to follow. Just let it do its job.
If you’re the one maintaining a CI/CD setup, a DevOps engineer as one would say, you should make sure that your colleagues, even when tempted, won’t be able to publish anything without going through your pipelines. I’d suggest going as far as blocking the ability to merge commits to your project’s master branch without going through a dedicated pipeline.
Watch this video to learn more about using branch protection rules to ensure that all changes go through your CI/CD setup:
Design your pipelines to be fast
The CI/CD pipeline should be designed to speed things up, make them easy, error-free, and convenient – all thanks to automation.
Since things happen “on their own”, developers sometimes treat their pipelines like hungry hippos, happy to stomach anything that’s thrown at them. But even though the work is done by machines, it’s a good idea to put some thought into what gets into your pipelines and how you arrange them.
Run the fastest tests first
One of the CI/CD best practices that is ridiculously simple to introduce: the order in which you arrange tests in your pipelines. Although we saw a good example of this when we discussed running tests in parallel, let’s now focus on arranging tests that cannot be run in parallel.
It’s a good idea to let your fastest, smallest tests run first before you bring out the big guns. No, it’s not about letting your CI server warm up before it tackles the more demanding tests that take longer to run.
Picture this: the first test in your pipeline takes 10 minutes to run. After this one, there are five more you want to run. What happens when the first test fails? You lost 10 minutes to learn that there’s something wrong in one of the six tests you intended to run.
If this same test failed, but you relegated it to a later stage in your pipeline, you’d have more information available before the CI even gets to the test that fails. Maybe one of the simpler, quicker tests does fail as well? If you let it run first, you’ll know much quicker and maybe even you’ll be able to fix it in the time it’ll take to run the more demanding test.
Run everything in your CI/CD environment
Having control over everything in your CI/CD process can yield great benefits: speed, flexibility, agility, reliability – you name it. Being able to influence and control every aspect of your process is one thing, but let’s look at it from the technical point of view.
Many actions that make up your pipelines use different tools. You should make sure you run them all in the pipeline’s environment instead of simply triggering executions on some external architecture. This gives you the most in-depth knowledge about each of the processes, direct access to logs, the ability to tweak settings between executions effortlessly, also making you independent from any number of external providers.
Your CI/CD pipeline should be a one-stop shop that takes care of everything your code needs before it gets to the users. This way you can tweak your setup to reach Apple-like performance levels, which the Cupertino behemoth achieves by handling everything that makes up their devices in-house.
Whereas not all of Apple’s practices can, should, or are worth applying to CI/CD, this absolute control over every stage of their product development and production translates beautifully into the development automation realm.
Mirror, mirror on the wall – have your testing environment mirror production
For our final advice, let’s talk about your test environment. First of all, you should have one. Let’s assume you do.
How does it look? Is it just a barren, low-spec server (gotta cut those operational costs) that has just barely enough horsepower to run the app? Does it have all accompanying monitoring or networking components installed? No, really: does it?
The answer is: it should. Ideally, your testing environment should be a direct copy of your production server. If you can’t do that, you should make sure that it’s as close as it can be. After all, the tests you run are supposed to make sure that the application works great in circumstances that reflect the situation where it gets into the hands of the users.
The users access the application running in the production environment, and so should all the test and processes in your pipelines. Since the aim of software development is to have customers using your application in live environment, this environment exactly should be replicated to a testing environment.
This way you’ll get the truest results of all your tests which will give you the certainty that whatever works on “dev” will surely work on production as well.
That's a wrap!
Now that you’re armed with these 5 DevOps best practices, use them to automate your deployments like a true pro. No matter if you’re handling CI/CD on your own, or you're having it taken care of by a dedicated DevOps team, you’re bound to get great results by following these CI/CD best practices.