Search code examples
kotlinteamcitydsl

TeamCity Kotlin DSL - Dynamically generate `BuildType`s


I am trying to use the Kotlin DSL for TeamCity to dynamically generate build configurations. In particular, I am looking to create a function to generate BuildTypes from parameters.

However, I am having a hard time generating objects that buildType() is happy with. Consider the following minimal example:

import jetbrains.buildServer.configs.kotlin.v2019_2.*

version = "2021.2"

fun bar() = object : BuildType({ name = "bar" }) {}

project {
    description = "Example"
    buildType(bar())
}
$ mvn -o org.jetbrains.teamcity:teamcity-configs-maven-plugin:generate 
[...]
[ERROR] Validation error: BuildType(uuid='', id='null', name='bar'): mandatory 'id' property is not specified

The compilation complains that the id property hasn't been specified. However, the following compiles fine (note that I am not explicitly setting any id property):

import jetbrains.buildServer.configs.kotlin.v2019_2.*

version = "2021.2"

object Foo : BuildType({
    name = "foo"
})

project {
    description = "Example"
    buildType(Foo)
}
$ mvn -o org.jetbrains.teamcity:teamcity-configs-maven-plugin:generate
[...]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  2.924 s
[INFO] Finished at: 2022-11-28T16:29:39+01:00

I am confused, as I believe that both examples are semantically equivalent...

Am I misunderstanding something in Kotlin, or with the TeamCity DSL? Is there dark magic at play?


Solution

  • I think that in the second case TeamCity sets id from object name which is Foo in your example while in the first case:

    1. Object doesn't have a name
    2. Moreover, you could call bar() multiple times and there must be a way for TeamCity to assign different id for each call

    So you should somehow explicitly set id in bar() for example

    fun bar(buildName: String) = object : BuildType({
      name = buildName
      id = AbsoluteId(buildName.toId())
    }) {}