Kotlin DSL: Extracting classes to use as templates for microservices ends in duplicate ids

I am currently trying out the code pipeline feature from teamcity, as we FINALLY got an update from 2017 (!!!) to 2022 version.

As a help I found the tutorials from Marco. I have then came across this tutorial: https://www.youtube.com/watch?v=Icva0O5_xnQ

I absolutely loved the idea as I have a ton of projects to migrate and this would make it super easy.

I tried it out with 2 services, but unfortunately there is a problem with the id generation when I do it like that.

my extracted class (a few more look similar) looks as follows:

class ServiceBuildPublish(
    private val vcsRoot: GitVcsRoot,
    private val superClass: IdOwner
) : BuildType({
  templates(BuildPublishTemplate)
  name = "build publish"
vcs {
    root(vcsRoot)

    checkoutMode = ON_AGENT
    cleanCheckout = true
  }

  features {
    deploymentStatusPublisher(vcsRoot, CI)
  }
})

And one of my implementation looks like this:

object ServiceTemplate : Project({
name = "Service Template"

params {
param("docker.build.image", BUILD_IMAGE)
param("service-image.name", SERVICE_IMAGE_NAME)
param("service.name", "service-template")
param("service.version.file", "kreditsmart-%service.name%-version.txt")
}

buildType(BuildPublish)
buildType(CtServiceTemplateConsumer)
buildType(CtServiceTemplateProvider)
buildType(DeployDev)

vcsRoot(ServiceTemplateVcsRoot)

buildTypesOrder = arrayListOf(BuildPublish, CtServiceTemplateConsumer, CtServiceTemplateProvider, DeployDev)
})
But when I create 2 project with those extracted classes and run the generate, I get these errors:

[ERROR] Error while generating TeamCity configs:
[ERROR] Validation error: BuildType 'RootProjectId_ServiceBuildPublish': id 'RootProjectId_ServiceBuildPublish' is already used in BuildType(uuid='', id='RootProjectId_ServiceBuildPublish', name='build publish')
[ERROR] Validation error: BuildType 'RootProjectId_ServiceDockerContracttester': id 'RootProjectId_ServiceDockerContracttester' is already used in BuildType(uuid='', id='RootProjectId_ServiceDockerContracttester', name='CT: service-template -> service-template')
[ERROR] Validation error: BuildType 'RootProjectId_ServiceDeployDev': id 'RootProjectId_ServiceDeployDev' is already used in BuildType(uuid='', id='RootProjectId_ServiceDeployDev', name='deploy [DEV]')
[ERROR] Validation error: VcsRoot 'RootProjectId_TemplateGitVcsRoot': id 'RootProjectId_TemplateGitVcsRoot' is already used in VcsRoot(uuid='', id='RootProjectId_EuropacePrivatkreditGitVcsRoot', name='<correct-vcs-root>', type='jetbrains.git')

So for id generation it seems to use the class names of the extracted classes, which then of course ends up in duplicate ids. In the tutorial I cannot find anything about id generation, so I am confused now.

Any idea what I am doing wrong? I thought I did follow the tutorial, but maybe I did something different? Or maybe there is a change in the generation process that makes the tutorials outdated?

0
3 comments
Hi! I couldn't find the code from that demo, but in the tutorial, the IDs are generated in the Project.addPipeline() function here: https://youtu.be/Icva0O5_xnQ?t=337
I hope that helps!
0

Hi Anatoly Cherenkov

Thanks for your answer. This is true for the Git Vcs Root, but seems not to be for the extracted classes, for example the CompileService.

Or am I missing something?

0
I am not sure what exactly the final version of the CompileService class was in the tutorial, but I think it was something like this (note the id = RelativeId(name.toId()) line):
package buildTypes

import jetbrains.buildServer.configs.kotlin.BuildType
import jetbrains.buildServer.configs.kotlin.RelativeId
import jetbrains.buildServer.configs.kotlin.VcsRoot
import jetbrains.buildServer.configs.kotlin.buildSteps.gradle
import jetbrains.buildServer.configs.kotlin.toId

class CompileService(
    private val serviceName: String,
    private val artifactName: String,
    private val vcsRoot: VcsRoot
) : BuildType({
    name = "Compile $serviceName"
    id = RelativeId(name.toId())
    artifactRules = "build/libs/${artifactName}-1.0-SNAPSHOT.jar"

    vcs {
        root(vcsRoot)
    }

    steps {
        gradle {
            tasks = "clean build"
            gradleWrapperPath = ""
        }
    }
})
The BuildServiceDockerImage and DeployService probably used the same principle.
0

Please sign in to leave a comment.