Continuous Integration (CI): first steps

Continuous integration (CI) and delivery (CD) has sort of become my “thing” over the last year or so. I’ve been part of a team that’s gone from no CI or automation of any kind to having a solid build, test and deploy pipeline. The benefits are undeniable and once you start automating processes and making life easier for developers, it gets addictive.

Although many developers will shudder at the thought of not having a reliable CI solution (in my mind it’s like not having source control), many teams simply don’t have this sort of thing set up. This post will outline how we started this journey and some of the challenges we faced.

What is CI?

According to Martin Fowler:

Continuous Integration is a software development practice where members of a team integrate their work frequently, usually each person integrates at least daily - leading to multiple integrations per day. Each integration is verified by an automated build (including test) to detect integration errors as quickly as possible. - Martin Fowler

By integration, we’re talking about integrating code into a shared repository. So this could involve a merge to integrate your changes with those of other developers. In this post I use the term continuous integration to refer to the verification mentioned in Martin Fowler’s quote.

Why start CI?

I had been exposed to CI in previous roles so knew the benefits it could bring. The problems we were having were quite typical of teams with no formal solution, such as:

  • “What’s in production right now? Did John release that change yesterday?”
  • “It works fine on my machine…”
  • “I changed something and it caused a bug somewhere else, didn’t see that coming”
  • “Be really careful changing that, it might break and then we’ll all have to live as forest people exiled from mainstream society”

These types of problems are boring and time-consuming. They also introduce risk that simply doesn’t need to exist. There must be a better way…

Step 1: culture shock

Are the people you work with interested in this new-fangled CI stuff? Does your boss care? The first step is getting buy-in from these key stakeholders. This might be really easy, as often people are sick of Jane not checking in all dependencies, or Jimmy breaking stuff and then leaving for a 2 week holiday. A recent fluff-up down to missing dependencies or bad deployment practises might help further your cause also.

However, in larger enterprise teams with everyone working in silos if can be harder to foster that’s “merging is caring” ethos, and you may get pushback from developers who don’t really see the point in all this fancy CI stuff - “I’ve been editing just the file I changed on production for years and it’s just fine”.

A common sticking point can be trusting what you’ve got in source control isn’t going to override important changes on production. Most developers see the benefits of source control (right?) so I’d ask this question: if you’re worried about overriding changes, what is the point in source control? Let’s just use production as the gospel for how our code should be.

Get buy-in (especially form your boss), and if people still aren’t on board, have a long hard think about whether they’re the sort of people your mother would want you associating with in 2016.

Step 2: do you want to build a snowman DLL?

Great, people are excited for change. They want a nicer life and to never moan at Steve again for not committing some dependency. So what’s a good first step?

I recommend getting some builds up and running. Nothing too fancy, just running msbuild or ant (or whatever) when a commit is detected in source control. Don’t worry about tests and deployments, just builds. Start with your most simple application, and build up from there.** Resist the temptation to do it all. CI works best when it evolves.**

When setting up your build server, make sure it’s easily accessible to your developers (and therefore the tray notifiers etc. that are available). Our first build server was only accessible over RDP, which means we couldn’t take advantage of tray notifiers and developers were less interested in checking it.

There are loads of build servers out there. I would recommend TeamCity (my favourite build tool at the moment), but I’ve also used Bamboo (great if you use Jira) and Jenkins. Each have varying levels of complexity when it comes to configuration.

Step 3: start deploying using the build artifact

The build artifact is what’s produced by your build process. For .NET, this will be a set of files including a bin folder full of DLLs. It’s important to only deploy what is produced by the build server - this ensures that what is in source control is what you are deploying. To be clear - I’m not talking about a full automatic deployment solution here, copying and pasting to your environments (as you might from your desktop at the moment) is fine.

This is where you have to be firm with those resistant to change: no more deploys from dev machines, no more editing one file at a time. This is where it gets real and relates to the culture change - if people aren’t on board, they might not do it.

Continuous Integration and deploying artifacts

“Hang on!”, shouts a developer who knows all about this and has noticed we’re not writing tests yet. “What about tests!”. Well, I’m a big fan of testing (as is any developer worth their salt). However, going from zero-to-hero with a build/test/deploy pipeline is all about addressing the riskiest practices first. In my opinion, deploying from developer machines to production, and even editing individual files on production, is more risky than not testing for a team that currently has 0 tests.

Step 4: test, automate, repeat

So your apps are building, you’re getting artifacts out and deploying them to your environments. No-one is deploying from their local machines and you haven’t had any no-CI related issues in a few weeks. The next step is automated tests. Selling the benefits of testing can be harder than what we’ve discussed here due to the amount of extra development time that must be spent, so I’ll save it for another post.

The other obvious step is to start automating those artifact deployments. I highly recommend Octopus Deploy, but there’s plenty of choice out there.

The final step is to repeat. Continuously test, continuously automate and keep improving the process.

“The condition of a garden can never remain stationary; if it does not go forward, it goes back” - quote displayed at Hinton Ampner