In the previous post, we’ve talked about Continuous Integration and its benefits in software development automation. Hopefully, by now you understand how important continuous integration is and want to learn how to improve your software by using it. Now, you will learn how to implement continuous integration with TeamCity, one of the best continuous integration tools available out there.
TeamCity offers free Professional Server License that allows you to use the full set of features it offers but is limited to 3 build agents and 100 build configurations. It is easily one of the best choices if you need stable, mature and user-friendly on-premises CI tool that to start with.
We are going to cover:
- Basic concepts of TeamCity
- Basic workflow
- Supported platforms and environments
- Creating your first .NET project in TeamCity
- Basic CI workflow in TeamCity
So, let’s begin by going through some basic concepts in TeamCity.
Build Agent. This is the “engine” of the TeamCity. Build agents do all the heavy lifting needed to build and test the project. They are configured through the TeamCity server and can be set up to build and run on different platforms and operating systems. A build agent utilizes the power of the machine that it is installed on.
TeamCity Server. The Main purpose of the server part is to configure, monitor, distribute queued builds, manage users, and send reports. These tasks are just the small part of the TeamCity server responsibilities.
Build Queue. It represents the list of triggered builds, which are the server delegates to the build agent for further processing. As soon as the compatible agent becomes idle, the TeamCity server assigns the build to it.
Build. It has the dual meaning. It refers both to the process of creation of the application version and the version itself.
Build Artifacts. Build artifacts represent the result of a successful build. For example, they can be zip archives, WAR files, log files, installers or any other packaging format you like or use.
Project. A project represents one software application/project. One project can have multiple build configurations.
Build configuration. It’s the combination of settings used to build an application. In the build configuration, you can create build steps, set triggers, and a version control system (VCS) root for example.
Build step. A single task. Build configuration usually consists of several build steps. Each build step executes one part of the build process. For example, in one build step, you can compile the source code and in the other run tests, or perhaps deploy the project.
Build trigger. It is the rule that defines when the build should be started. The build can be scheduled to run at specific times of the day, automatically on VCS changes, or when other builds are completed.
Now that the basic concepts are defined, let’s have a look at the basic TeamCity workflow.
- TeamCity monitors the changes in the VCS root you provided in the build configuration.
- Once the changes occur, the server triggers the build and adds it to the build queue.
- If there is a compatible, idle agent available, the build server assigns the build to it, otherwise, the build server waits for the first available agent
- When the build starts, it executes build steps defined in the build configuration. The server monitors the progress and generates the build log in real-time
- When the build finishes, the agent sends build artifacts back to the build server.
- The server sends notifications to all the relevant project member so they can see if the build succeeded or not. If the project failed to build, one or more project members can be assigned to investigate the problem.
Supported platforms and environments
When you do continuous integration with TeamCity you have a variety of different IDEs, platforms, frameworks, and tools that help you have a better environment to build your software project in.
TeamCity supports runners for the Java, .NET and Ruby by default and you can utilize command line runners for other languages as well. Various tools for monitoring, code coverage, code analysis, issue tracking are an integral part of the TeamCity repertoire and the TeamCity itself can be integrated with a few IDEs as well.
Some of the features and tools come by default bundled with TeamCity and others can be installed as plugins. JetBrains have their own set of plugins, but there are also many third-party plugins available. For the list of publicly available plugins, you can check this page.
Creating your first .NET project in TeamCity
So how do you go about setting TeamCity up? Whether you have some legacy code, or you are thinking about creating a brand new .NET project, your application is probably using one of the version control systems like Git or Subversion. TeamCity, like other CI servers, relies heavily on VCS, so make sure that TeamCity supports your VCS of choice.
Once you downloaded and installed both TeamCity server and, at least, one build agent, you can start configuring TeamCity. The first thing you want to do is to create a new project. You can do this by going to the administration page located at the top right of the TeamCity panel. On the administration page, you will immediately see two buttons for the project creation. The first one is for the manual creation of the project, and the second one helps you with the process by using the URL of the project repository you provided.
If you opt-in for the manual creation, you’ll need to fill in the name and the description of the project, and add the repository URL later. Create project from URL option does this for you and, in addition, adds a build configuration for you. You can see the list of the created configurations on the project settings page. The first thing that you will see when you select the build configuration is the general settings page.
The first thing that you will see when you select the build configuration is the general settings page.
Properties that you want to change here are the build number format and artifact paths, although you might want to build your project first so you can easily select files that will go into artifacts later. The build number format is something that you can use later by invoking %build.number%. It represents your project version: major.minor.build counter (eg. 1.0.83). The build counter increments automatically, but you can reset it if you need to. For now, let’s leave the artifacts intact, and go to the next page on the build configurations panel, which is version control settings.
If you create the project using the repo URL, you can skip this step. Otherwise, now is your chance to set up your repository URL which the TeamCity should monitor for changes.
The next phase of build configuration is the build steps definition. The build steps page gives you the option to automatically detect build steps for your project, or you can add them one by one manually.
Automatic build step detection is useful if the TeamCity supports your project runners by default. Otherwise, you can choose from various build tools like Ant or NAnt, or just use the command line or Powershell. This is where you can setup all your scripts and tests, do the deployment and code analytics. Some of the tools you need are supported by TeamCity by default, others need to be added using the TeamCity plugin manager.
Basic CI workflow in TeamCity
So how do we implement the most basic continuous integration cycle with TeamCity? As I explained in my article about Continuous Integration, we need to:
- build our project
- run the automated tests
- deploy the application
- do the acceptance testing
- send the notification on the completion of that process whether it finished successfully or failed
Since the deployment procedure is a bit harder to grasp, and a bit complicated to execute, it is described in a separate post.
So how do we do continuous integration with TeamCity?
First step: Adding the Visual Studio solution runner
Before we can package and distribute our application, we need to build it. In order to do this, we are going to add build step and then choose the Visual Studio (sln) option from the drop-down menu. After that you should see something like this:
After you enter the step name, you should select the path to your project solution file using the little tree button to the right side of the Solution file path input field. Both targets and solution configuration are already set for you, but if you want to change them just enter the new values and click Save.
Second step: Adding the NUnit
Now that we have the build step configured, we can add the test runner to our project. Most popular testing tools for .NET projects are xUnit and NUnit. While NUnit comes bundled with the TeamCity by default, if you use xUnit in your project you need to install it as a plugin.
Let’s say for example your project is using NUnit framework. To automatically run tests for your project, you can go to the Add build step button again, and from the drop-down menu select the NUnit. When you do that, TeamCity will generate a few properties you need to configure in order to run your tests. Your page should look like this:
After naming your step, selecting runner, platform and .NET version, you need to add the path to the assembly with your tests. This editor does not give you the option to select the assembly path from the tree structure like some other editors in TeamCity.
But there is a practical solution for that problem.
You can look up the path of assembly in your project manually, you can use wildcards like **\*Test.dll, or you can find the editor that does have the path select button and find the path to the assembly there and copy paste it in this editor. A bit of inconvenience, but nothing too serious.
If you followed this post so far, you have probably seen the little light bulb near the run button in TeamCity. This little light bulb is trying to tell you that you forgot to add the VCS trigger to your project.
If you click on it, it directs you to the Triggers page where you can select a trigger that you need. There are two triggers you should care about for now.
First one is the VCS trigger. It triggers your build when it detects the changes in the VCS repository. The other one is the Schedule trigger with which you can schedule your build at the regular time intervals (nightly builds anyone?).
The last thing we need to do in order to complete our Continuous Integration cycle is to manage notifications. This step is important because both you and your team need to have some feedback in order to act quickly if the project does not build successfully or tests fail.
To send the notifications, you must first set the email notifier in the administration section of the TeamCity. Once you set the SMTP settings, you need to go to the My Settings and Tools section that you can find in the drop-down below your profile name. After that, go to the notification rules tab, and simply add the rule you want to the appropriate user groups.
Notification settings are pretty flexible so use them to your preference. At the very least you should receive the notification when the build fails, so you can fix the problem quickly.
That’s about it. Just hit the run button and watch the magic happen. After your first build completes successfully, you should revisit the General Settings page and choose the artifacts for your project. Also, you might want to try committing some changes to the repository if you selected the VCS trigger.
Together with deployment to the staging environment and acceptance testing these steps make the most basic continuous integration with TeamCity. TeamCity offers a plethora of advanced features, so I encourage you to try them out and experiment a lot to get the most out of this powerful tool.
As you can see, continuous integration with TeamCity is not that hard. And the magic doesn’t stop there. You can automatically deploy your projects to the staging and production environments, integrate code analysis and code coverage tools, but more on these features in the future posts.
Thank you for reading and if you have any suggestions or problems you encountered while trying to follow this article, please feel free to contact me or leave the comment below.