In this post, I’m going to talk about a commonly used software practice, continuous integration, by first describing what it is and the problem it solves. Next, we’ll look at what the continuous integration process looks like and what some common steps are. Finally, I’ll outline some common arguments and counterpoints to them.
What is Continuous Integration?
First thing’s first. What do we mean when we say continuous integration? From Wikipedia
Continuous integration (CI) is the practice, in software engineering, of merging all developer working copies with a shared mainline several times a day. . . .The main aim of CI is to prevent integration problems, referred to as “integration hell” in early descriptions of XP (Extreme Programming).
Long story short, continuous integration is the act of merging changes (i.e. pull requests) into the main branch multiple times a day (instead of one big push daily) to minimize the effort needed to merge those changes. If you’ve worked on any project with multiple contributors, then you realize that merging changes can be a tough business, but with continuous integration, you can verify that your merge didn’t break anything.
Something that needs to be mentioned is that you will hear the terms continuous integration and continuous build used interchangeably. In the beginning, these terms meant different things, but now they have become synonymous. With that being said, my experience is that you will more likely hear the phrase “CI Server” more so than “Continuous Build Server”.
So What Does Continuous Integration Look Like?
To implement continuous integration, you will need a server that listens to your repository for changes. When changes have been detected, the server will then run a series of steps in order to ensure that the software still builds and passes tests. A sample workflow would look like this:
- Checkout the latest copy of the source code
- Compile the source code.
- Run automated tests
- Run deployment scripts (this could be creating an installer or by deploying a website)
- Send an email notification with the completion status (success, or failure if one of the steps failed)
The beauty of this process is that you’re defining the steps that constitute a stable version of your code. If all of these steps pass, then you know that your changes/merges did not break functionality and you have a stable build to run tests on (i.e. the build is not broken).
On the other hand, if any of these steps fail, then you have a much smaller scope of changes to look at (the last check-in) and what step did they fail on? For example, if the automated tests failed, why did they fail and do they fail on your machine?
Why Should I Use It?
In this piece, we’ll explore possible reasons why you’re not using CI and provide counterexamples to each of these points.
I don’t have time to setup CI
For the most part, the only resources that a continuous build server takes is the initial configuration. After that, it’s pretty much “set it and forget it”. Even with no experience setting up the CI server, you can easily go from nothing to up and running in a couple of hours.
I’m a sole developer so I don’t have merge issues
Granted, the odds of having a merge issue are lower, I still find it very unlikely that you will never have merge issues. The main reason is that rarely will you have only one change going on at a time. It’s much more likely that you’ll be working on a new feature and still be doing bug fixes. If you follow best practices for Git or Mercurial by branching per change, you will eventually have merge issues.
However, let’s pretend that you never have merge issues, how do you guarantee that the changes you’ve made haven’t broken anything? By running the code on your own machine (i.e. it works on my machine, but not in production)? By deploying to QA? None of these solutions really work.
It takes too long to maintain the server and/or the job
For this argument, let’s approach it two ways. First, if maintaining the server is taking too much of your time (or you don’t have the IT resources), go ahead and choose a cloud solution. The rates are reasonable, (for example Shippable offers a great package for $12 a year) and they handle the updating of the server for you. Second, once the job is setup, it will need little tweaking. Maybe to add another step, but for the most part, you’re build process won’t change a whole lot. And even if it does, it’s as simple as adding an additional step or removing a step.
I don’t care about catching merge issues, that’s what QA is for
Unfortunately, I’ve gotten into many arguments with developers who don’t use continuous integration and why they don’t use it. My argument is essentially that a developer’s job to either save the company money (by solving the company’s problems) or to make the company money (by creating a service/product).
Given this, it’s in our best sense to find and fix issues when they’re the cheapest and the earlier issues are found, the cheaper they are to fix (source). By the time QA has found an issue, it’s much more costly to fix the bug than if it was found at the development stage.
Wrapping Things Up
In this post, I introduced continuous integration and the problem it was supposed to solve. In addition, we looked at what continuous integration looks like by explaining the different build steps. Finally, we wrapped up with some common arguments against using CI and how to counter them.