TeamCity 2017.1 Help

Kotlin DSL

Besides storing settings in version control in XML format, TeamCity also allows storing the settings in the DSL (based on the Kotlin language). Using the version control-stored DSL enables you to define settings programmatically, without the need to use XML files. Since Kotlin is statically typed, you automatically receive the auto-completion feature in IntelliJ IDEA which makes discovery of available API options a much simpler task.

Note that once you enable storing of the settings in DSL, you no longer can use TeamCity UI to edit affected project's settings. Also, all the security implications apply.

Check also our blog post series on Kotlin DSL.

Advantages of Kotlin DSL vs XML

The Kotlin settings format provides higher level of abstraction, and better code reuse.

  • Build configurations often share settings and need to be different in few aspects only. For example, when you need to test your software against different platforms, let's take an ORM framework to be tested against different databases, then the builds running tests are mostly the same, the only difference is the part configuring a database connection.With Kotlin, you can extract the common part and reuse it across all builds which ensures that the common part does not change and makes maintaining builds easier.

  • Kotlin also allows you to describe your setup in terms of your domain. For example, TeamCity provides generic requirements for build agents and you can define requirements specific to your installation:

    val linux = Requirements() { contains("os.name", "linux") } val oracle = Requirements() { equals("db.name", "oracle") } val java6 = Requirements() { contains("env.JAVA_HOME", "1.6") }

    then you can use them in a build configuration:

    buildType { ... requirements(linux + oracle + java6) ... }

Getting Started with Kotlin DSL

Learning Kotlin

The Kotlin tutorial helps you learn most Kotlin features in a few hours.

Downloading Settings in Kotlin

To start working with Kotlin DSL, go to the project settings page, click the Actions menu and select Download settings in kotlin format, the option available since TeamCity 10.0.3. This will generate a .zip archive with project settings which can be used in your sandbox project.

When you have familiarized yourself with Kotlin, you can use the Kotlin-based DSL for project settings in production.

Using Settings in Kotlin in Production

  1. Storing Project Settings in Version Control for your project.

  2. Select kotlin as the format.

  3. Commit the settings to your version control.

  4. Once you apply the versioned settings to your project, TeamCity will generate necessary Kotlin files for this project and check them in to the specified repository under the.teamcity directory. If this repository already contains project settings in the XML format, they will be preserved, but TeamCity will no longer use them: once you get familiar with Kotlin files, these xml files can be removed.

The easiest way to experiment with DSL in TeamCity 2017.2+ is to edit settings in UI and check the UI diff script generated by TeamCity.

DSL Documentation

Since TeamCity 2017.2 a fter Kotlin DSL is enabled for a project, the TeamCity server provides html documentation for the core DSL API as well as the API provided by installed TeamCity plugins. The online documentation is available on your local server, accessible via the link on the Versioned Settings project tab in the UI or by running the mvn -U dependency:sources command in the IDE. See an example.

Working with Kotlin DSL

The.teamcity folder contains a maven project consisting of pom.xml file and the <Project Id> directory with thesettings.kts and Project.kt files, as well as buildTypes, pluginData, and vcsRoots subdirectories. If the project contains subprojects, they will be placed in the directories with corresponding names.

Opening Project in IDE

Open the pom.xml in your favourite IDE and check that the URL of the teamcity-server repository points to your TeamCity.

If the server url is correct and your TeamCity is up and running, all necessary dependencies will be resolved automatically and you can start working with Kotlin DSL right away.

Debugging Maven generate Task

The pom.xml file provided for a Kotlin project has the 'generate' task, which can be used to generate TeamCity XML files locally from the Kotlin DSL files. Since TeamCity 2017.2 this task supports debugging. If youre using IntelliJ IDEA, you can easily start debugging of a Maven task, see screenshot:

Dsl debug

Ability to Use External Libraries

Since TeamCity 2017.2 You can now use external libraries in your Kotlin DSL code, which allows sharing code between different Kotlin DSL-based projects. To use an external library in your Kotlin DSL code, add a dependency on this library into the.teamcity/pom.xml file in the settings repository and commit this change so that TeamCity detects it. Then, before starting the generation process, the TeamCity server will fetch the necessary dependencies from the Maven repository, compile code with them, and then start the settings generator.

Essential Files

settings.kts

The settings.kts script is an entry point for defining a single TeamCity project. TeamCity looks for the settings.ktsfile in a project directory and runs it if it is found, so the script name must not be changed and its package must be the same as the project's id.

The script should contain a single call to the project() function with a Project instance or the init function as an argument, you can also specify both of them to refine the specified Project in the init function.

Project.kt

This file contains the project definition.

VCS roots, Build types, and Templates of this project must be registered inside the project using the vcsRoot(),buildType(), and template() methods respectively.

Subprojects can be defined either in their own settings.kts or by calling thesubProjects() method in this project.

object Project : Project({ uuid = "my_project_id" // uuid should be some constant, never changing string; it is important for preserving history, new id means new entity with new history id = "ExampleOfDSL" parentId = "_Root" // id of the parent project name = "Example of DSL" val vcsRoot = GitVcsRoot({ uuid = "my_vcs_root_id" id = "ExampleOfDSL_VcsRoot" name = "Example of DSL VCS Root" url = "<url to my git repository>" }) buildType { uuid = "my_build_type_id" id = "ExampleOfDSL_Build" name = "Build" buildNumberPattern = "%build.counter%" vcs { root(vcsRoot) // thanks to Kotlin, here we can have static reference to project VCS root } steps { maven { goals = "clean test" } } requirements { contains("teamcity.agent.jvm.os.name", "Linux") } } })  

As this is a Kotlin code, you are free to add conditions, loops, methods, classes, etc.

Dedicated DSL for plugins

Since TeamCity 2017.2 dedicated DSL code is provided for new plugins bundled with TeamCity (Docker, .NET CLI) and coverage plugins. Here is typical DSL code for the Docker-Compose build step:

steps { dockerCompose { file = "docker-compose.yml" } }

Required Identifiers

All TeamCity entities - project, build configuration, VCS root and template have a so-called Identifier. The uuid is an identifier which can be used to uniquely distinguish this specific entity from others. If at some point the entity receives a new uuid, it is considered a new entity by TeamCity. For instance, if the build configuration uuid changes, the builds history of this build configuration will become empty (if you change it back before cleanup, the history will be restored). The same rule applies to a project - if its uuid changes, the project will lose its investigations and muted tests. We suggest selecting some naming scheme for uuid s in your project and never changing them.

There is also the id field (extId prior to TeamCity 2017.2) which is mandatory. The id is used to represent the project ID, build configuration (or template) ID / VCS root ID in the web UI; it is also used in the DSL to reference other entities. Besides, it is used in various links (such as build configuration links) and REST API.

Making Changes to Project Settings

Once a project is switched to the Kotlin DSL format, we recommend the following approach for changing the project settings:

  1. Set up unit tests.

  2. Create a dedicated project on your TeamCity server to run these unit tests.

  3. Create a separate branch/repository and run tests on your changes there.

  4. If the tests are green, merge the changes into the default settings branch.

Creating New Project

You can create a new project via DSL inside a parent project which already has uses settings in the Kotlin format. A new project can be added either in its own directory with or using thesubProject() method in the parent project.

Apply your changes as described in the section below.

Applying Changes to TeamCity

When you have made changes to your Kotlin DSL code, сommit your code into the .teamcity directory containing your project settings.

TeamCity will apply the changes to configuration as follows:

  1. TeamCity will detect the commit, execute Kotlin DSL files and produce new configuration files. Since internally TeamCity operates with XML, TeamCity will execute DSL files in a secure sandbox to produce XML configuration files. These XML files then will be applied to the existing project.

  2. TeamCity will apply the new configuration files to the project effectively changing its configuration. In case of any problems (compilation failures, runtime errors, etc.), new changes will not be applied, and the current project settings will be preserved on the server and the error message will appear under the Versioned Setting tab in project settings.

  3. The builds will run with the new settings.

Note that:

  • The Kotlin script is executed on the server, and since this is a potentially dangerous operation, the script is executed in the sandbox. It cannot modify the file system except the place where it is executed, it cannot run other programs, cannot use reflection, and so on.

  • The Kotlin DSL is experimental, and the provided API may change in future versions.

EditingKotlinsettingsinUIEditing Kotlin Settings in UI

Since TeamCity 2017.2, when you switch a project to the Kotlin DSL, project and build configuration settings can be editied in the web UI. All changes made in a project via the UI will be presented as a patch in the Kotlin format which will be checked in under the project patches directory. Moreover, if after switching to the Kotlin DSL you did not change the generated DSL files, the UI changes will be applied in place, no patch will be generated at all.

The existing projects in Kotlin need to switch to the new v2017_2  DSL API version.

Notes on patches

When settings are edited in the UI, TeamCity generates a patch script in the dedicated package <project id>.patches.(buildTypes|templates|vcsRoots|projects); the script name is <uuid of the entity>.kts. The patch script is executed after regular dsl scripts, it applies the UI changes to the generated settings if the settings are in the expected state. For example, if you change the build configuration name, the patch script checks that the name produced by the regular script isnt changed and then updates the name. Once the patch script is committed to the settings repository, you can apply its changes to your settings. After that, the patch script should be removed.

Example of a patch changing name of a build configuration:

/* This patch script was generated by TeamCity on settings change in UI. To apply it, change the buildType with uuid '5dc8e147-11dc-4cb6-83aa-cfdb2595797d' accordingly and delete the patch script. */ changeBuildType("5dc8e147-11dc-4cb6-83aa-cfdb2595797d") { check(name == "Old Name") { "Unexpected name: '$name'" } name = "New Name" }

Limitations 

Some of the UI actions will still be disabled for projects in Kotlin:

  • Changing the id (for all entities - project, build configuration, template or VCS root)

  • move actions

  • editing of the versioned settings VCS root

  • versioned Settings configuration change in a project

Common Problems

New URL of Settings VCS Root 

Problem: I changed the URL of the VCS root where settings are stored in Kotlin and now TeamCity cannot find any settings in the repository at the new location.

Solution:

  1. Fix the URL in the Kotlin DSL in the version control and push the fix.

  2. Disable versioned settings to enable the UI.

  3. Fix the URL in the VCS root in the UI.

  4. Storing Project Settings in Version Control with same VCS root and the Kotlin format again, TeamCity will detect that the repository contains the .teamcity directory and ask if you want to import settings.

  5. Choose to import settings.

Prior to TeamCity 2017.1

Problem: I do not want the password s to be committed to the VCS, even in a scrambled form.Solution:You can move the passwords to the parent project whose settings are not committed to a VCS.

Problem: I want to change passwords after the settings have been generated.Solution:The passwords will have to be scrambled manually using the following command in the maven project with settings:

mvn -Dtext=<text to scramble> org.jetbrains.teamcity:teamcity-configs-maven-plugin:scramble

Since TeamCity 2017.1

Solution: Use tokens instead of passwords. Please refer to the related section.

How to read files in Kotlin DSL

Problem: I want to generate a TeamCity build configuration based on the data in some file residing in the VCS inside the .teamcity directory

Solution:TeamCity executes DSL with the .teamcity as a current directory, so files can be read using the paths relative to the .teamcity directory e.g. File("data/setup.xml"). Files outside the .teamcity directory are not accessible to Kotlin DSL.

Last modified: 20 April 2023