While developing enterprise solutions nowadays, It is difficult to imagine projects which do not follow a set of practices by Fowler commonly known as Continuous Integration. The most important goal of these practices is the reduction of time (and therefore cost) of introducing changes to the project by integrating these changes early and frequently. The changes are the result of many programmers’ work in a team. The idea of Continuous Integration is 10 year old. During that time many tools were created which helps us – the programmers – to use this idea in everyday’s work (in our own projects).
Among many applications supporting the idea of Continuous Integration a very special place is taken by integration servers, called CI servers. They enable automatic project building, test running and informing about encountered errors and failures. These are only basic capabilities of CI servers. The most advanced systems offer many more interesting features and useful functions.
One of those advanced tools is TeamCity, which gathered many users during last year. The main reason for that is a unique feature; pre-tested commit.
To fully appreciate its advantages, I remind a standard scenario of everyday programmers work:
1. Update code from the repository.
2. Changes in several classes (the actual programming).
3. [optional] Changes’ verification – running the unit tests.
4. Committing changes to the repository (preceded with an update – this is taken care of by the repository itself).
5. Automatic download of the newest source code by the CI server and starting to build the project.
6. [optional] Checking whether the CI server successfully built the project with the introduced changes.
We all work that way. One could ask: what is wrong with this way of work, and furthermore, it is so commonly used? The main problem is the fact, that even when the programmer ran the unit tests before commit, there are no guarantees that the same code would compile on the CI server and pass all the tests. All of us were in such a situation some time. There are many reasons for that situation. The most popular one is the difference between the development environment and the CI server environment. These could be a hard-coded file path, a different version of a software library or other unknown assumptions i.e. privileges to access remote disk. It is possible that one build could contain many changes which worked separately but do not work together. Sometimes the cause is very simple; not all modified classes were sent to the repository, which makes the code impossible to compile. This is the time when the search for the guilty one in the team begins. Finding the guilty one is not very difficult, but fixing the error might by. In the worst scenario the work of the whole team is halted and it is caused by only one bad commit.
There are many solutions to this problem; introducing a high discipline of work among programmers or highly complicated SCM solutions like stable trunk (which require high discipline as well as a higher work effort).
Engineers from JetBrains invented a unique solution of this problem. They modified the above mentioned scenario in such a way that a faulty code could not get into the repository and at the same time is not a burden for the users. This is the pre-tested commit feature which is supported by TeamCity among others.
The work scenario of a programmer with TeamCity is as follows:
1. Update the code from the repository.
2. Changes in several classes (the actual programming).
3. Sending the modified files to TeamCity (using an IDE plugin).
4. Start of the build process using the files send by the programmer and the files from the repository:
a) Adding the modified files in the repository if the build was successful.
b) No changes in the repository if the build failed.
5. Send information to the programmer about the build result.
As it can be seen, the repository contains only checked code in this scenario. The amount of checks depends only on our tests. We have the guarantee that an error of one programmer does not block the entire team and work is not stopped.
Using pre-tested commit is very simple in practice and resembles using plugins for code repositories. A working instance of TeamCity server and an IDE plugin is required. IntelliJ IDEA and Eclipse environments were supported at the time of writing this article. Plugin for Eclipse adds four new tabs and Remote Run is the most important one. It allows to use the pre-tested commit feature. It is possible to start a build with "private" changes, which is called "Personal Build" (private build).
You can choose on the Remote Run tab:
Checking the option Commit after build(s) finish, changed files are added to the repository only if the build completed successfully. And this is the core of pre-tested commit idea – the repository only contains the files which were tested on the CI server.
It is worth mentioning that Personal Build can be used as a tool to increase the productivity of a programmer (or even as an alternative to provide him a more powerful workstation). Using this feature a programmer can run his tests (build project) remotely and, at the same time, working on another part of his solution. His workflow is not interrupted by waiting for the local build to finish, which often is time and resource consuming.
The company behind TeamCity is JetBrains, known mainly from the IntelliJ IDEA environment. Even though TeamCity is a proprietary solution, it is available free of charge as a Professional edition. This edition has a restricted number of users, project configurations (builds – 20) and Build Agents (3). The number of Build Agents sets the maximal number of concurrently running build processes. These restrictions however could not prevent deploying this solution in small and medium projects free of charge.
To sum it up TeamCity is an innovative product in the CI servers’ world. This solution can reduce the number of problems with continuous integration which occur in everyday work of programmers’ teams causing loss of time and money. Using the pre-tested commit feature is easy and does not require the programmer to seriously change his work scenarios, which makes it cheap and feasible to implement (the team would not raise any objections).
Translation: Paweł Cegła