We’re often asked how to run different build steps in different branches. In fact, this has already been possible in TeamCity for quite some time (since version 9.1), but it seems we need to do a better job explaining how to use this feature.
Let’s assume that you have a build configuration where building of feature branches is enabled.
First, enable Versioned settings for the project where this build configuration resides. TeamCity will ask for a VCS root where the settings are to be stored. For simplicity’s sake, let’s store the settings in the same VCS repository where other project files are located.
For the Versioned settings, make sure the option When build starts is set to the use settings from VCS value. TeamCity will then take the settings from a branch used by the build instead of the current settings.
Once versioned settings are enabled, TeamCity will commit the
.teamcity directory with the current project settings to the default branch of the selected VCS root. To start customizing the settings in our feature branch, we need to merge the
.teamcity directory from the default branch.
But before making any changes in the
.teamcity directory in your feature branch, bear in mind that not all the changes there will be applied. For instance, if you add a new project or a build configuration, such changes will be ignored. This happens because TeamCity does not support different sets of projects and build configurations in feature branches.
Besides, there is a chicken and egg problem. Currently TeamCity loads settings from
.teamcity while the build sits in the queue. But to load the settings from a repository, TeamCity needs to know this repository settings (VCS roots). Thus VCS roots are always taken from the current project settings.
The same story is with build triggers and snapshot dependencies. TeamCity needs triggers to decide when to place builds into the queue. And TeamCity needs snapshot dependencies to create a build chain (graph of builds) before the builds are going to the queue. Hence the changes in
.teamcity affecting these settings are ignored too.
But there are plenty of other settings whose changes will affect the build behavior:
- build number pattern
- build steps
- system properties and environment variables
- build features (except Automatic merge and VCS labeling)
- failure conditions
- artifact publishing rules
- artifact dependencies
By default, the settings are stored in the XML format. Since there is no publicly available documentation for this format, it is hard to guess how to change build steps correctly, or how to add a build feature. This is what a command line build step looks like in XML:
<runner id="RUNNER_76" name="" type="simpleRunner">
<param name="script.content" value="echo "Hello world!"" />
<param name="teamcity.step.mode" value="default" />
<param name="use.custom.script" value="true" />
What can help here is seeing how TeamCity generates these settings. For instance, get a sandbox project on your TeamCity server for such experiments, and browse the audit page for settings difference after each change:
Another option is to use Kotlin DSL (see the Settings format option on the Versioned settings page). In this case, instead of .xml files, .kt files will be stored under the
A Kotlin DSL project can be opened in IntelliJ IDEA Community (free and open-source IDE from JetBrains). Kotlin DSL files look much more concise, and IDE auto-completion makes it much easier to work with them, especially in the recent TeamCity versions. This is what the same command line build step looks like in Kotlin DSL:
scriptContent = """echo "Hello world!""""
Some additional hints:
- Since TeamCity 2017.2 you can browse Kotlin DSL documentation using the following URL:
<TeamCity server URL>/app/dsl-documentation/index.html
- If a build loads settings from the VCS repository, you should see something like this in the build log:
- Actual settings used by the build are stored in the
buildSettings.xmlfile under the hidden build artifacts. This file can be helpful if something does not work as expected.
- If you’re using remote runs instead of feature branches, then all the same abilities are also available, provided that the
.teamcitydirectory is present in your repository and versioned settings are configured as described above.
Finally, one more thing to keep in mind. If changes under
.teamcity in your feature branch were temporary, you should not forget to revert the settings during the merge with the default branch. For instance, if you removed some long running steps or switched off some tests for convenience.