We’ve all been there: you clone a repository, run your project and… nothing happens. Well, nothing but a series of errors; from missing files to compiler warnings. You seek some advice and ask your co-worker: “I just cloned the repo, but nothing seems to work and the readme file is blank. Do you know what’s going on?”. That’s when you hear it. The most overused excuse in the dev world.
“It worked on my computer.”
This excuse, and others like it: “Last time I worked on the project everything was fine”, “Did you install all the dependencies?”, “The last person to work on it was X, ask him” are not just annoying but entirely unnecessary these days. Oh, and feel free to add any excuses you have heard to this list via the comments section. I’m sure we could put together quite a collection!
Working on a new project is hard enough; new tools, new code, new business logic, (maybe even a) new programming language. And then, on top of that, we add another layer of complexity for a newcomer: a broken build.
There are multiple approaches out there that attempt to solve this issue. From the inexpensive, but far from foolproof, readme.txt file solution, all the way to the more complex, but efficient, building a Continuous Integration solution. This is an article on the latter, so let me try and sell you on the benefits of the Continuous Integration (CI) option.
Quick aside: You may have noticed I am using the term ‘build’ and thought, “wait, Ruby on Rails is not a compiled language. There is nothing to build!” And you’d be right – in a sense. The reason I use ‘build’ throughout this article is because it is the term used in CI documentation, where it signifies a group of jobs. Such as check out the repository from GitHub, run unit tests, merge that code, compile the project or deploy to a staging or test environment. You can read more here.
Continuous integration is the practice of introducing changes into a codebase several times a day. Typically, a CI process will look like this:
Logically, we start by making any desired changes to the code. Once done, we run Unit Tests on this new code. If these tests complete successfully, we can move to the final step: Integration. This is where we merge the new tested code into the codebase, and optionally create a new build or deploy the code to a staging environment.
Great. But how does this help me?
Having this methodology in place is more efficient for a variety of reasons. To start with, and most importantly, broken code is less likely to reach the main codebase and leave you with a non-functional project.
CI will also help you identify problems as soon as they happen – literally – by alerting the whole team of any errors. That way, when something fails, everybody is aware of the problem and it can be fixed promptly. This scenario also removes the convenient “I didn’t know it was broken” excuse.
The configuration of the CI also acts as comprehensive documentation, enabling any developer on the project to delve into the history of a project and see how the build process works.
Wait there’s more? Delivery and Deployment
Continuous delivery takes this a step further. This is essentially the same as CI with one crucial difference: it allows us to deploy to production with a manual step, like the tap of a button.
What is great about this solution, is that everybody on the team can deploy; a project manager, a tester or the product owner. This is because there are no weird, secret dev-only procedures.
If you want a 100% automated process, you need to make the jump to what is commonly called Continuous Deployment. With this in place, nobody needs to touch a button to have a working build deployed – every step is automated!
Which CI method should I choose?
Continuous Delivery and Deployment are all incremental approaches to the CI process we outlined earlier. My advice would be to start with the CI process and progress from there.
Something else to consider: if you are working on a web project, it makes sense to deploy continuously. Your users won’t notice, and they will always have the most recent version of your code running. Win-Win. But what happens if your product is an iOS or Android app? Do you want to automatically deploy every time someone pushes new code? Of course not, that would be annoying to users as they could see multiple updates per week pushed to their devices. Facebook (and several other leading apps) handle this problem by releasing one automatic update every week. You can see this by checking the version history of the iOS app version releases. This is the perfect compromise between keeping an app updated and a good UX.
How do I know if my project is ready for CI?
A few factors play into this decision:
- Lead Time
Budget: There is a strong case to be made for CI on small projects, as long as they are ongoing in nature. This is because, while CI requires a significant initial investment, its automated aspects will save you time and money with every new build. So, saving on the initial outlay is a false economy. We call this tech-debt: where you feel like you are saving time in the beginning, but you pay for it later in more complex daily processes.
With CI correctly setup, there are no more “make a new build” tasks, because the builds are always there. Nor are there any “get the latest version deployed to staging” tasks. Those disappear as well, as the build is always deployed to staging.
These might sound like minor savings, but incrementally they add up. Deployment takes time and happens regularly. If you don’t have CI in place you will have to spend development time on deployment, which means your productivity decreases.
Lead Time: Because of the initial time investment discussed earlier, in setting up CI, projects with short lead times are not ideal candidates.
Experience: Setting up a CI process requires a specific skill-set. You need to consider if you have the time and budget to hire that person. This does not need to be a daunting task, at Scalable Path we can often find people and induct them into a team in less than a week.
The building process should not be dependant on engineering ‘black magic’. For example, specific parameters being sent to the compiler that nobody is aware of, or environmental variables that are only known by one person on the team.
CI uses a build machine to resolve this issue. This is a computer, somewhere in the world, waiting for something to trigger the build process when a pull request is created, for example.
It’s not a good idea to have this on a developer’s computer because we want this machine to be “a single source of truth”. In other words, the one location everyone in the company agrees is trusted and correct. To achieve this goal, the build machine should be an independent machine dedicated to this purpose.
I consider a project healthy only if it can be built automatically while passing all the Continuous Integration steps without error.
You can either have your own build machine (onsite or hosted with a cloud provider) or hire a third party continuous integration platform. There are advantages and disadvantages to both, so let’s take a look at them:
Self-Hosting: This is the option for those who want full control – and the configurations options are virtually endless – but you also assume more risk this way. Anything could bring your server down: from power outages, internet downtime or having your dog eat through the power cords.
If you opt for this option, I suggest you use an automation server like Jenkins.
With control comes responsibility. In this case, that means having to take care of configuring the machine and software yourself.
Cloud Hosting: As with Self-hosting above, this relies on you setting up a machine and installing Jenkins. In this case, as the computer is not sitting in your office you reduce the risk of downtime from power outages and all other similar nasty things.
Third-party services: Opting for one of these services is the hassle-free option. You trade flexibility for convenience and peace of mind. CircleCI, Travis-CI and Buddy Build are some of the many great options out there.
Having a build machine and an automated process for app deployment may sound like overkill. But as your project evolves and your team grows, you will be happy you spent the initial time setting it up.
For one, team productivity will increase. But that is just the tip of the iceberg. You will also gain the peace of mind that comes with knowing you are creating a stable, comprehensively tested and easily deployable product. You’ll sleep better at night basically.
I really feel that setting up Continuous Integration is not just suitable, but essential, for many more projects than the Airbnb and Facebooks of this world. And I hope that this article has convinced you of as much.
If I have convinced you of the benefits of CI, great! But a note of caution: while correct CI implementation can be beneficial at any stage, it is more complex to implement it into an existing project. So, be extra diligent with your research.
Once your Continuous Integration process is up and running, you will wonder how you lived so long without it!