TeamCity
Powerful CI/CD for DevOps-centric teams
Creating TeamCity project templates with Kotlin DSL context parameters
In version 2019.2, TeamCity introduced the ability to use context parameters in Kotlin DSL project configurations. These parameters can vary from project to project in TeamCity while the common project declaration stays the same. It means that you can create one DSL project template and reuse it in as many projects on the TeamCity server as necessary. This is far more convenient than storing similar DSL specifications in multiple branches or creating a complex project hierarchy in TeamCity.
In this video, we’ll explore an example project and show you how to utilize the power of context parameters in your DSL projects. You can find a quick text recap of the tutorial below.
Let’s consider a TeamCity project that builds a plugin for integration with the GitHub issue tracker. It comprises three build configurations connected to a build chain.
The "Test It" build configuration contains a VCS trigger that detects changes in the source repository.
The project is also synchronized with the "DSLDemo" repository, where its settings are stored in the settings.kts
file. This file describes the project configuration in the portable Kotlin DSL format.
The source code of the plugin is hosted on GitHub. Thus, the VCS root specification should point to the respective repository:
object PluginRepo : GitVcsRoot({ name = "GitHub Issues Plugin Repo" url = “git@github.com:JetBrain/teamcity-github-issues.git” branchSpec = "+:refs/heads/*" authMethod = uploadedKey { uploadedKey = "id_rsa" } })
This is how you would specify these settings explicitly, without context parameters. But imagine you want to reuse this code in a similar project that, for example, builds a plugin that implements the Bitbucket issue tracker integration. You’d need to copy this whole DSL project and replace the name
and url
values. To make changes in the shared code that the projects have in common, you would have to change it in both projects, which is surely not the best approach.
Using context parameters is a good solution to this problem. You can add them under Versioned Settings | Context Parameters if versioned settings are enabled for your project.
Remember to add them in the DSL as well. A context parameter is declared as follows:
${DslContext.getParameter(<name>)}
And this is how the DSL code above becomes a single source for multiple potential projects:
object PluginRepo : GitVcsRoot({ name = "${DslContext.getParameter("repoName")} Repo" url = DslContext.getParameter("fetchUrl") branchSpec = "+:refs/heads/*" authMethod = uploadedKey { uploadedKey = "id_rsa" } })
Moreover, you can use context parameters to compose custom logic. For example, you may need the "Deploy It" build configuration only in some of your TeamCity projects – not in all of them.
This is how the project DSL would look normally:
project { vcsRoot(PluginRepo) buildType(BuildIt) buildType(TestIt) buildType(DeployIt) }
Now, you can perform an extra check and add the DeployIt
build type only if the deploy
context parameter is set to true
in a given TeamCity project:
project { vcsRoot(PluginRepo) buildType(BuildIt) buildType(TestIt) if ("true".equals(DslContext.getParameter("deploy"))) buildType(DeployIt) }
As all required context parameters are now in the project DSL, let’s use this specification to create a new TeamCity project for the Bitbucket integration.
After you add the project, go to its Versioned Settings and enable the synchronization of the versioned settings with the "DSLDemo" repository. After the settings have been synchronized, specify the custom values for the context parameters in the Versioned Settings | Context Parameters tab. Until you do, the project configuration will be inactive in TeamCity.
Since we set the deploy
parameter to false
, the "Deploy It" build configuration will be absent from this project.
Note that you can only modify common settings for projects that contain context parameters in their source DSL code. Editing them in the TeamCity UI is prohibited, as it contradicts the single-source approach.
Pro tip: When you generate settings from your DSL code locally, the placeholder values will be displayed instead of the context parameters. If you want to use particular values of these parameters for local tests, you can temporarily add them in the pom.xml
file under the Mavin plugin settings:
<plugin> <groupId>org.jetbrains.teamcity</groupId> <artifactId>teamcity-configs-maven-plugin</artifactId> <version>${teamcity.dsl.version}</version> <configuration> <format>kotlin</format> <dstDir>target/generated-configs</dstDir> <contextParameters> <repoName>My repo</repoName> <fetchURL>git@...</fetchURL> <deploy>true</deploy> </contextParameters> </configuration> </plugin>
We hope context parameters will make your build pipeline even more efficient and powerful.
Happy building!