What is Continuous Integration?

Continuous Integration (CI) is a software development practice backed by a set of tools.

It is best to think of continuous integration as a mindset that allows you to reduce risks by frequently integrating incremental software development changes. Risks are managed by discovering them earlier and by applying quality checks at each change.

Quality checks need to provide more confidence that your software may be put into production. They can include :

  • compiling the software (at the very minimum, it should compile),
  • testing the software (all tests must pass),
  • checking code conventions breaches,
  • static analysis of the code
    • find design violations,
    • search for duplicated code,
    • search overly complex code (cyclomatic complexity),
  • and any relevant rules.

It implies to publish often changes to the mainline of the central repository shared by all developers.

Continuous Integration big picture
Figure 1 : Continuous Integration big picture

A classical continuous integration worflow is as follows:

  1. A developer commits changes to the version control system (central repository).
  2. The repository, via a post-commit hook, tells the CI server a change has occurred.
  3. The CI server retrieves the latest sources from the central repository and then builds the software (build script is shipped with sources). This step is called integration.
  4. The CI server aggregate build results and generates a feedback. This feedback is often materialized by emails but it can also be instant messaging, tweets, a visual feedback on a screen or a red light in the dev room, etc.

Top 10 rules to apply continuous integration

  1. Check-in regularly to mainline
    Continuous Integration is about integrating early and often. To take advantages of the CI methodology, you need to share your code with all developers in the mainline (core repository, trunk) quickly. It implies small tasks / increments.
  2. Have an automated test suite / use TDD
    Each piece of code should come with its automated tests. A good practice is to write tests before the code: Test-Driven Development.
  3. Always run tests locally before committing
    Yes, there is a server that runs test for you … but it does not prevent us to run a minimum set of tests in your development environment. The CI server is here to detect problems not seen in your development environment.
  4. Don’t commit broken code to the mainline!
    A source code repository is not a disk backup. A (known) broken code should never be committed to the mainline.
  5. Don’t check-in on a broken build
    If you commit on a broken build, you loose feedback on this integration. If there are several commits on a broken build, you may end with a lot of bugs introduced in the mainline and loose your time to track problems.
  6. Fix broken build immediately
    Fix broken builds should be the highest priority of the team. It prevents other developers to check-in and will end with a big integration task. The solution is to time-box the fix.
  7. Time-box fixing before reverting
    Define a reasonable time (for example 20 minutes) allowed to fix a broken build. Once this time elapsed, revert to the latest working version and take the time you need to fix it. Then commit again.
  8. Never go home on a broken build
    We don’t want you to stay at work all the night! If you don’t have time, revert, go home, and fix it the next day.
  9. Don’t comment out failing tests
    We don’t want broken builds but we need to be confident in our code robustness. We need all tests, more tests!
  10. Keep your build fast
    The key is to get a rapid feedback. So, you need to get your build fast (ideally <10 min). If you cannot speed the build up, use a staged build.

Some references