Continuous Integration

Continuous Integration (CI) is a development practice that requires developers to integrate code into a shared repository several times a day. Each check-in is then verified by an automated build, allowing teams to detect problems early.

The practice was initially promoted as one of the XP practices by Ken Beck, back in 90’s, although back in 1991 Grady Booch named it in his method but he did not advocate integrating several times a day.

The whole idea of this practice, is by integrating regularly you can detect errors quickly and locate them more easily.

To better understand where CI fits, let’s look at the basic development flow executed by a developer when he needs to implement a new feature:

·      First the developer gets the latest version of the code from the repository on his/her local machine (is creating a local copy);

·      He starts working on the feature; this mean both adding new source files but also changing existing source files;

·      When he finishes he builds the application performs the tests and if everything is fine, is ready to commit the changes to the repository, in order to make them available to the rest of the team;

·      At this point, he needs to get the latest changes which were commited to the repository while he was working locally;

·      He resolves any possible conflicts (in case for example both him and other developer has affected the same section of the code and the client program for connecting to the source repository was not able to make a proper merge), he builds the application, checks if the feature is still working and then perform the commit.

The flow looks simple and if executed correctly what could be the problem? Why we would need a CI practice implemented? Let’s look at some not so visible flaws:

·      The implementation might affect sources that are used also by other features; the developer will most probably test only its own feature he might not even be aware that other features are using the same code;

·      Unless if some of the files changed were also changed in the meantime on the server, if a commit is performed without an latest update, the commit will not fail, everything will be fine, but no one has checked if the whole build is still working; this is a very common mistake from the developers;

·      If the application is modular, and the developer works on a particular module, performs all the steps and commits he might still be in trouble as he did not test the integration of the module into the whole application; the changed source files might make the linking of the libraries crash (for example a method exposed by the module through an interface was slightly altered and that method as called via an web-service from another module.

And these are just some flaws, there are many other situations that you can get into. The purpose of a CI is to minimze the number of these situations, and if they are detected, they should be detected as soon as possible to be more easily fixed.

What you cannot automate is the actual check-in. The developers have to be educated to do it regularly (even several times a day). What you automate is tests. A CI cannot exists without automated tests. Any feature developed should have tests that validates it. After a new feature is added by running the tests you can quickly find if something else has been broken and you can easily fix it.

Now the question is why you still need a CI if you have tests, and you run tests on every build? Shouldn’t be this enough? Let’s look at some aspects:

·      Tests can be from very fast unit tests which checks execution flows, to more complex, integration tests that connects to a database or integrates to some other external systems; this makes the build to take too long to be something performed regularly by each developer;

·      Your local development environment might hide some configurations which makes the build passes thus hiding some possible issues;

·      You still have a problem if the developer commits without an update and he did not get any errors (quite possible). Some other features might be broken and you don’t know about it.

The CI will help you will all these:

·      The CI server monitors the repository and checks out changes when they occur.

·      The CI server builds the system and runs unit and integration tests.

·      The CI server releases deployable artefacts for testing.

·      The CI server assigns a build label to the version of the code it just built.

·      The CI server informs the team of the successful build.

·      If the build or tests fail, the CI server alerts the team.

·      The team fix the issue at the earliest opportunity.

·      Continue to continually integrate and test throughout the project.

CI server can be configured to run the tests in several phases. First quickly run some fast unit tests to see everything is fine. Then, in paralel run the more complex integration tests. Even if you get a problem a bit later than the moment of commit, is still valuable since is recent enough to be able to quickly fix it (there is not that big amount of code changed).

Usually, when a build fails on CI the fist thing the developer should do is to revert the changes. You should not block the whole development in order to debug the problem. Do it offline, on your local machine, after you restore the stable state.

There are plenty of CI servers, open-source or commercial, which can be used. Make the choice depending on the project nature, the size of and the budget.

Wanna know more about Continuous Integration?

New Brain Concert open sessions! See the available courses and sign up!