Skip to content

rodm/teamcity-dsl-extensions

Repository files navigation

TeamCity DSL Extensions

Maven Central License

A library that extends the TeamCity Kotlin DSL providing a pipeline type, stages, a matrix build type and a number of convenience functions.

Using the library

To use the library add the following dependency to the Maven POM in the .teamcity directory.

    <dependency>
        <groupId>com.github.rodm</groupId>
        <artifactId>teamcity-dsl-extensions</artifactId>
        <version>0.9</version>
        <scope>compile</scope>
    </dependency>

Import the pipeline function

import com.github.rodm.teamcity.pipeline

Use the DSL method to create a pipeline with one or more stages, and each stage with one or more build configurations.

The example below shows the creation of a build template and a pipeline with 2 stages. The first stage defines default settings for each of the following build configurations. Each stage is represented in TeamCity as a composite build configuration with dependencies on each build configuration defined in the stage. Build configurations in subsequent stages have a dependency on the previous stage build configuration.

    import com.github.rodm.teamcity.pipeline

    project {

        val buildTemplate = gradleBuildTemplate {
            id("GradleBuild")
            name = "Gradle Build"
            ...
        }

        pipeline {
            stage("Stage 1") {
                defaults {
                    failureConditions {
                        executionTimeoutMin = 10
                    }
                }

                build {
                    templates(buildTemplate)
                    id("Build1")
                    name = "Build 1"
                }

                build {
                    templates(buildTemplate)
                    id("Build2")
                    name = "Build 2"
                }
            }
            stage("Stage 2") {
                deploy {
                    templates(buildTemplate)
                    id("ExamplePublish")
                    name = "Publish"
                }
            }
        }
    }

The VCS root settings for a stage build configuration can be changed from the default settings using the vcs configuration block.

            stage("Stage") {
                vcs {
                    showDependenciesChanges = false
                    excludeDefaultBranchChanges = true
                    buildDefaultBranch = false
                }
            }

The deploy configuration creates a build configuration with the Deployment type with personal builds disallowed and a maximum number of running builds set to 1.

Stages can have an optional description

            stage("Stage") {
                description = "Build the library"

                ...
            }

The default dependency for a stage can be overridden by using the dependsOn function. A stage can depend on one or more earlier stages.

    import com.github.rodm.teamcity.pipeline

    project {
        pipeline {
            val stage1 = stage("Stage 1") {
                ...
            }
            stage("Stage 2") {
                ...
            }
            stage("Stage 3") {
                dependsOn (stage1)
                ...
            }
        }
    }

The above can also be written using the stage(name: String) extension function to lookup a previous stage by name.

    import com.github.rodm.teamcity.pipeline

    project {
        pipeline {
            stage("Stage 1") {
                ...
            }
            stage("Stage 2") {
                ...
            }
            stage("Stage 3") {
                dependsOn (stage("Stage 1")
                ...
            }
        }
    }

Templates can be defined within a stage and the template(name: String) extension function can be used to lookup a template when configuring a build or deploy build configuration.

Multiple build configurations can be defined using the matrix configuration block.

    pipeline {
        stage("Stage1") {
            matrix {
                axes {
                    "OS"("Linux", "Windows", "Mac OS X")
                    "JDK"("JDK_18", "JDK_11")
                }
                build {
                    name = "Build - ${axes["OS"]} - ${axes["JDK"]}"

                    val os = axes["OS"] as String
                    requirements {
                        matches("os.name", os)
                    }
                    val jdk = axes["JDK"] as String
                    params {
                        param("java.home", "%${jdk}%")
                    }
                }
            }
        }
    }

The matrix configuration block contains an axes block that defines one or more axes followed by a build configuration block that can use values from the defined axes. A build configuration is created for each combination of values defined when multiple axes are defined. An axes defines a name, in the above example OS and JDK, with a number of values, from the above example Linux, Windows and Mac OS X for OS and JDK_18 and JDK_11 for JDK. The example will create 6 build configurations, one for each combination of OS and JDK.

If not all the combinations defined by the matrix axes are required, combinations can be removed by using the excludes block. Each exclusion is a map of name and value pairs, if a build configuration matches the values defined by the exclusion it is removed.

The example below will create 4 build configurations, the combination of Windows and JDK_18 and the combination of Mac OS X and JDK_11 are removed.

   pipeline {
        stage ("Stage1") {
            matrix {
                axes {
                    "OS"("Linux", "Windows", "Mac OS X")
                    "JDK"("JDK_18", "JDK_11")
                }
                excludes {
                    exclude("OS" to "Windows", "JDK" to "JDK_18")
                    exclude("OS" to "Mac OS X", "JDK" to "JDK_11")
                }
                build {
                    name = "Build - ${axes["OS"]} - ${axes["JDK"]}"
                    ...
                }
            }
        }
    }

Artifacts can be defined using the Artifact type. The producerRules and consumerRules patterns define the paths of build output artifacts collected from a producing build and the paths the artifacts are written to for a consuming build. More on the patterns can be found in TeamCity documentation, Artifact Paths and Artifact Dependency.

val artifact = Artifact("producerRules", "consumerRules")

The Artifact is passed to the build that produces the artifact using the produces extension function and passed to the build that uses the artifact using the consumes extension function.

    pipeline {
        val artifact = Artifact("producerRules", "consumerRules")
        stage("Stage1") {
            build {
                name = "Build1"
                produces(artifact)
            }
            build {
                name = "Build2"
                consumes(artifact)
            }
        }
    }

Configuring a GitHub issue tracker can be defined using the githubIssueTracker function

    import com.github.rodm.teamcity.project.githubIssueTracker

    project {
        features {
            githubIssueTracker {
                displayName = "TeamCityDSLExtensions"
                repository = "https://github.com/rodm/teamcity-dsl-extensions"
                pattern = """#(\d+)"""
            }
        }
    }

Compatibility

Library versions and the supported TeamCity versions

Library version

TeamCity version

0.9

2023.11 and later

0.8

2022.04 to 2023.05

0.7

2020.2 to 2021.2

License

The library is available under the Apache License, Version 2.0.