In the previous post, I talked about Continuous Integration and the benefits of using it to automate project development. In this post, I will show you how to apply Continuous Integration practice on your project using the JetBrains Continuous Integration tool TeamCity.

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 20 build configurations. Before going further into the details of TeamCity configuration, let us have a look at some basic concepts and terms in TeamCity.

Basic concepts

Build Agent. This is the “engine” of the TeamCity. Build agents are responsible for all the work that is needed to build and test the project. They are configured through the TeamCity server and can be setup to build and run on different platforms and operating systems. Build agent utilizes the power of the machine that it is installed on.

TeamCity server. The server does not run anything. Its main purpose is to configure, monitor, distribute queued builds, manage users and send reports. These tasks are just the small part of the TeamCity server repertoire.

Build queue. It represents the list of triggered builds, waiting to be delegated to the build agent for the processing. As soon as the compatible agent becomes idle, TeamCity server assigns the build to it.

The build. It has the dual meaning. It refers both to the process of creation of the application version and the version itself. Build Artifacts are the result of the completed build process.

Build Artifacts. These are the files or archives created on 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 is 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.

  1. TeamCity monitors the changes in the VCS root you provided in the build configuration.
  2. Once the changes happen, the build triggers and it is added to the build queue.
  3. If the compatible agent is idle, the build is assigned to it, otherwise build server waits for the build agent to become available and then assigns the build to it.
  4. When the build starts, it executes build steps defined in the build configuration. Progress is monitored and all the logs, reports, test results etc. are being shown dynamically.
  5. When the build finishes, the build artifacts are being sent to the build server.
  6. The server sends feedback and reports to all the relevant project member so they can see if the build was successful or not. If the project failed to build, one or more project members can be assigned to investigate the problem.

Supported platforms and environments

TeamCity supports a variety of different IDEs, platforms, frameworks and tools to 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.

You can find the list of the supported environments on the diagram on the TeamCity documentation page, as well as a more comprehensive list here.

Configuring TeamCity for your .NET project

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 your VCS is on the TeamCity supported list.

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.

create new project

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. First thing that you will see when you select the build configuration is the general settings page.

First thing that you will see when you select the build configuration is the general settings page.

build configuration panel

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: counter (eg. 1.0.83). The build counter is incremented 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 created the project using the repo URL, you can forget about this step because it is already being populated by TeamCity. Otherwise, now is your chance to setup your repository URL from which the TeamCity will monitor for changes.

The next phase in build configuration is the build steps definition. The build steps page lets you 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.

So what do we actually need to implement the most basic Continuous Integration cycle? 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 will be described in a separate post.

First step: Adding the Visual Studio solution runner

Before the project is ready to be packaged and distributed, it must be compiled. In order to do this, you need to go to the Add build step and then choose the Visual Studio (sln) option from the drop down menu. After that you should see something like this:

build steps

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:

nunit build step

After naming your step, selecting runner, platform and .NET version, you need to add the path to the assembly with your tests. For some reason, this editor does not give you the option to select the assembly path from the tree structure like some other editors in TeamCity so you are left with a few choices. 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.

Setting triggers

If you followed this post so far, you have probably found out the little lightbulb near the run button in TeamCity. This little lightbulb is trying to tell you that you forgot to add the VCS trigger to your project.

lightbulb trigger

If you follow its suggestion, you will be directed to the Triggers page and there you will be able to select a trigger that you need. There are two triggers you should care about for now. One is the VCS trigger, which will trigger your build configuration when changes are detected in the repository and the Schedule trigger with which you can schedule your build at the regular time intervals (nightly builds maybe?).

Sending notifications

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 dropdown below your profile name. Once there, 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.

notification settings

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 setup within TeamCity. TeamCity offers a plethora of other basic or 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, setting up .NET project in the 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.