In TeamCity, when we need to build something, we create a build configuration. A build configuration consists of the build steps and is executed in one run on the build agent. You can define as many build steps as you like in one build configuration. However, if the number of steps grows too large, it makes sense to examine what the build configuration is doing – maybe it does too many things!
We can split the steps into multiple build configurations and use TeamCity snapshot dependencies to link the configurations into a build chain. The way TeamCity works with build chains enables quite a few interesting features, including parallel execution of the builds, re-using the build results, and synchronization for multiple source control repositories. But most of all, it makes the overall maintenance significantly easier.
In this blog post, we will explain how to create a build chain in TeamCity by configuring the snapshot dependencies for the build configurations.
The minimal build chain
To create a simple build chain, it is enough to create two build configurations and configure a snapshot dependency from one configuration to another.
For this example, we are using a GitHub repository. The repository includes a Gradle project that builds a Spring Boot application. In addition, there is a Dockerfile for building a Docker image.
We are going to build this project in two steps. First, we will build the application, and then build the Docker image with the binary produced in the first step.
First the build configuration, TodoApp, builds the Spring Boot application and publishes an artifact as a result. The second build configuration, TodoImage, depends on the TodoApp build configuration and builds a Docker image.
There are two kinds of dependencies that we will need to configure: the snapshot dependency and the artifact dependency.
The TodoApp build configuration publishes an artifact to the todo.jar file. Any other build configuration can download the file by configuring the corresponding artifact dependency.
On the Dependencies tab, click the “Add new artifact dependency” button. In the dialog, locate the build configuration from which the files should be downloaded and specify the patterns to match the file path(s).
The documentation page describes how to configure the artifact rules in more detail.
To configure a snapshot dependency, go to the Dependencies tab in the build configuration settings and click the “Add new snapshot dependency” button. In the dialog, locate the build configuration it will depend on and click Save.
There are a number of settings associated with the snapshot dependency. You can read about the various settings in the documentation. For our current example, the default configuration is sufficient.
When the TodoImage build configuration is triggered, TeamCity makes sure all the dependencies for this build configuration are up to date. Consequently, all the dependent build configurations that form a build chain via the snapshot dependencies will be added to a build queue. The result is visible on the Build Chains tab of the project:
Triggering the build chain
There are various kinds of triggers that are possible to set up for a build configuration in TeamCity. The VCS trigger is the one that reacts to the changes in a version control system.
In our example, there are two build configurations but we will only need one VCS trigger. This is because it’s possible to tell the trigger to monitor for the changes in the dependencies. In the configuration dialog, we have to enable “Trigger a build on changes in snapshot dependencies” checkbox.
We can configure a dedicated VCS trigger for each and every build configuration in the chain. However, each trigger creates some overhead: the server has to allocate some cycles to maintain the trigger. Additionally, it’s easier to make changes to the settings if you only have one trigger to configure. Hence, we can just add a single VCS trigger to the very last configuration in the build chain and it will do the job.
Re-using the results
The build chain completed successfully. We can start the build again. However, this time TeamCity will be smarter and skip running the builds for the dependencies where it detects no source changes.
For instance, on the first run, the build number for both our build configurations is 1. Now let’s try running the TodoImage build configuration a couple of times. Since there are no changes to TodoApp’s sources its build is not started and TeamCity re-uses the result of the 1st build. The TodoImage build number is now 3 since it was our intent to execute it.
It is also possible to enforce building the dependencies even if there are no source changes. For this, click on the ellipsis next to the Run button of the build configuration. From the dialog, choose the Dependencies tab, and select the dependencies that are required to run.
Configuring checkout rules
The current setup of our build chain doesn’t really provide us with much value yet. All the sources are located in the same GitHub repository, hence if we configure the trigger to fire on code changes both build configurations will run.
For instance, if we make a change to the Dockerfile we don’t need to run the build for the application. However, with the current setup, TeamCity detects that there’s a change in source control repository for TodoApp as well and both build configurations will execute incrementing the build numbers.
Instead, it would be nice to run the build only when necessary.
In this example, we would like to build TodoApp if there is a change to anything but the Dockerfile. And we only want to build a new image if just the Dockerfile changes – there’s no need to build the application in this case.
It is possible to configure the checkout rules for the VCS root accordingly. The checkout rules affect the actual checkout of the sources on the agent. That said, if we exclude any folders of the repository using the filters in checkout rules, those folders won’t end up in the workspace.
We will exclude the
docker/ folder from the checkout in the TodoApp build configuration. And we will only pull the
docker/ folder in the TodoImage build configuration, and ignore everything else.
Now, if we only change the Dockerfile, only TodoImage should execute and re-use the results from the previous TodoApp run without executing it.
The concept of snapshot dependencies is essential for configuring the build pipelines, aka build chains in TeamCity. The feature allows implementing incremental builds by re-using the results of the previous executions, thus saving a lot of time. In this article, we have also learned about triggering and VCS root checkout rules – both very useful for working with build chains.
Next, we will look at what else is possible with the features we have described – running the builds in parallel and also how to build projects from multiple source repositories.