This week, I spent some time learning Team Build and configuring a build server for Continuous Integration (CI). I’ll tell you more about that experience in a separate post. But, before I go there, I want to make sure everyone is on the same page.
For those of you unfamiliar with the practice…
Continuous Integration is a mainstay in many agile tool belts. The idea behind it is that the longer you wait to integrate your code with the code of your peers, the harder it will be to do the integration. Many developers have direct experience with this phenomenon. Those who have been through it have a name for it: integration hell.
When combined with a comprehensive suite of unit tests, CI helps to prevent integration hell by encouraging developers (and testers) to make frequent check-ins. In fact, many agile developers integrate their code as frequently as every ten minutes (or faster!). That might seem extreme. But, it’s true. We do it here in patterns & practices.
In general, the CI integration process looks like this:
- Get the source from the repository and merge your local changes (if there are conflicts)
- Run all of the unit tests (to make sure you didn’t break anything)
- Fix any broken tests (even if you didn’t write them)
- Once all of the tests pass, commit your changes to the repository
In the early days of agile, many teams serialized this process by only allowing one developer (or one pair of developers) to integrate their code at a time. This prevented people from committing conflicting changes to the repository at the same time, which made integration much easier. But, the serialization clearly introduced a bottleneck.
Enter Continuous Integration Servers…
A CI server is a build server that runs a new build every time someone commits a change to the source code repository. When a team introduces a CI server, they can stop serializing integrations because the server will inform them immediately when something breaks the build or causes a test to fail. Instead of mitigating the risk of simultaneous integration through serialization, CI servers mitigate this risk by providing immediate feedback about integration problems.
For the curious, CI Servers integrate with source control servers in one of two ways: passively or actively. Passive integration involves the Observer pattern: the CI server registers for events fired by the source control server. Active integration involves polling the source control server at predetermined intervals, looking for changes. If your source control server doesn’t expose it’s event model, then you’re stuck with active integration. The advantage of passive integration is that it gives your CI server the opportunity to control exactly which changes make it into each build. The fewer changes compiled in a build, the easier it is to debug any problems that do occur.
Are you doing CI? Got questions? Drop me a line!