Monday, April 8, 2013

Thoughts and Tips about Continuous Integration


In software development, Continuous Integration is the practice of integrating the team member’s work frequently.

Continuous Integration (CI) is, as mentioned (and have also blogged about), a practice. And the CI practice starts with source control.

We are (or should be), used to source control practices (although I must say I still find a scary lot of developers daily struggling with the most basic source control practices).

Checking code regularly prevents having to deal with large and complex merge operations. The more often you commit, the easier is to merge with other developer’s changes.

As a general rule of thumb, I’d expect people in my team to check their changes at least daily. Not checking in your changes before leaving is a bad practice and a dangerous one. Risking to loose changes and increasing the potential of bad and corrupt merge operations.

Distributed source control tools are gaining advocates, because they enable developers to quickly create local branches, try different things, move changes between local branches, shelve changes, move freely among their branches, and later on, perform clean ups and commits to the server. Although you will still risk loosing local changes because of computer or hard drive problems, at least you can still keep a good short-commit practice.

Now, source control tools and good-commit practices are just one part of the equation. To make sure that the commits and merge operations were done correctly, you need to automate the process of building the changes that are  (or again, should be) constantly pushed to the server. This way, you can almost immediately detect problems in the commits, and locate and notify the developer responsible so he can quickly fix it.

The whole process is what continuous integration is all about, and can also be extended to the concept of continuous delivery, which is simply an extension of the concept where the automated build process can also perform automatic deployments to the environments (named development, staging, quality assurance or production).

You will read a lot of theory about it when looking around. Martin Fowler is a big advocate of CI. You can find a lot of tenants about CI on topics like extreme programming, test-driven development, quality control, agile software development practices, etc.. There is a lot of talk, articles, books and much more about the subject and for some people might sound heavy and scary.

However, I’m more of a pragmatic, hands on developer and a believer that common sense and professionalism will take you to the right place, to do and deliver good work. I have been working towards implementing a more natural, creative and flexible way of working, enforcing an extremely productive, efficient and adaptive rapid prototyping practice (which I’ll be writing a lot more in the upcoming months).

Just keep in mind the following:

Continuous Integration should be a daily practice, where you and your team figure out a way to commit, merge, integrate your changes very frequently in a fast way, and have a technical solution to automate the build and deployment process of the integrated changes.

Try to commit at least twice a day, or worse case scenario, once a day. If you can commit more often than that, it is actually better. Although for production deployments you should not commit unstable or bloated code, don’t be afraid to commit changes that aren’t complete or fully functional, as long as they don’t break the build. This is quite relevant for development environments, where you are supposed to be in fact, in development!

Also, keep in mind the following principles:

  • keep good source control, good-commit practices. Be open and transparent with your team, and allow discussion and improvement.
  • find a technical solution for automating for Builds. You can use solutions like Team Foundation  Server, Cruise Control, Jenkins, Team Foundation Service, Bamboo or TeamCity.
  • try to make your automated build self-testing. Try to enforce the practice of having a set of unit tests that can be run with the Build (and at the same time enforce having a relevant, up to date test set).
  • commit-often and make sure that every commit is built.
  • keep the build fast, since the whole point is that you can see the result almost immediately. If your build process is too slow, try to break it into different components, that can be developed, built and deployed independently.
  • maintain different builds for different environments, so you can build for development, staging, production and any other environment independently.
  • in my personal opinion, the production build should be trigger manually from your build server, and should be deployed to a pre-production clone. You don’t want to override your production build by accident. You can always automate the process of deploying to the actual production environment by different means, just make sure the automation is not prone to error.

In terms of the actual technical tools and solutions you can use, there are plenty and they will depend on the platform and technical stack you use.

In the web development / open source world, SVN, Mercurial and GIT are the common source control solutions used, and Bamboo and Jenkins are also common CI solutions.

In .NET, Team Foundation Server is generally the de-facto solution for source control and CI, although it is difficult to setup and maintain. Recently, I found myself liking and feeling really comfortable using Mercurial and GIT for source control, and TeamCity or Team Foundation Service for CI. Azure is also a great tool for continuous deployment and easy to integrate to this set of services. Actually, I can say that TeamCity is one of the easiest and most user friendly CI server solutions I have worked with (here is a post I did on how to setup TeamCity step by step).

No comments:

Post a Comment