TeamCity On-Premises 2024.03 Help

Configuring Finish Build Trigger

The finish build trigger starts a build of the current build configuration when a build of the selected build configuration is finished.

Key Takeaways

  • When the Finish build trigger is added to configuration A, it watches the target configuration B, and spawns a new A build whenever B finishes another build.

  • You can choose whether a build should be triggered only if the target configuration's build is successful.

  • Finish build triggers benefit from snapshot dependencies pointing to the same target configurations.

  • Alternatively to tracking all new builds of the target configuration, you can trigger new builds only if those target builds have new changes. To do this, use the Schedule Trigger instead.

Trigger Settings

Finish build trigger settings
  • Build configuration — choose a build configuration to track. See the Trigger Limitations section to learn why the snapshot dependency warning can be shown.

  • Trigger after successful build only — allows you to avoid triggering new build if a build of a target configuration failed.

  • Branch filter — a set of rules in the +|-:<branch_name> format that allows you to watch builds of specific branches only. See Branch Filter for more information.

  • Build customization — provides options similar to the Run Custom Build dialog. See the Triggered Build Customization section for more information.

Finish Build Triggers and Snapshots

To understand the difference between finish build triggers and Snapshot Dependencies, let's have a look at the following example.

A sample project has three child build configurations:

This configuration determines the current date and writes it to the project's product.release.date parameter. Note that since the new parameter is written with the setParameter Service Message, the new value is in effect only in the scope of this build.


import jetbrains.buildServer.configs.kotlin.* import jetbrains.buildServer.configs.kotlin.buildSteps.csharpScript object UpdateReleaseDate : BuildType({ name = "Update Release Date" steps { csharpScript { id = "csharpScript" content = """ var date = DateTime.Now.ToString("MM.dd.yyyy"); var serviceMessage = "##teamcity[setParameter name='product.release.date' value='" + date + "']"; Console.WriteLine(serviceMessage); """.trimIndent() tool = "%teamcity.tool.TeamCity.csi.DEFAULT%" } } })

This configuration increments the project's build.version parameter. Unlike "Update Release Date", this configuration sends a TeamCity REST API request to permanently change the parameter value.


import jetbrains.buildServer.configs.kotlin.* import jetbrains.buildServer.configs.kotlin.buildSteps.script object UpdateBuildVersion : BuildType({ name = "Update Build Version" steps { script { id = "simpleRunner" scriptContent = """ version=%build.version% ((version=version+1)) curl --location --request PUT 'http://<server_URL>/app/rest/projects/<project_name>/parameters/build.version' \ --header 'Accept: */*' \ --header 'Content-Type: text/plain' \ --header 'Authorization: Bearer your_token' \ --data ${'$'}version """.trimIndent() } } })

This configuration re-publishes artifacts. To do so, it first needs the actual release date and build number, which it retrieves from the other two configurations.

  • The updated release date is accessible via the dep.<configuration_name>.<parameter_name> syntax because a snapshot dependency on the "Update Release Date" configuration exists.

  • The updated build version is taken directly from the project's build.version parameter because the "Update Build Version" configuration utilizes REST API to write a permanent value.


import jetbrains.buildServer.configs.kotlin.* import jetbrains.buildServer.configs.kotlin.buildSteps.script import jetbrains.buildServer.configs.kotlin.triggers.finishBuildTrigger object Delivery : BuildType({ name = "Update Packages" steps { script { id = "simpleRunner" scriptContent = """ echo "Delivery date is ${UpdateReleaseDate.depParamRefs["product.release.date"]}" echo "Build version is %build.version%" # TODO: Re-publish packages with updated version and date values """.trimIndent() } } triggers { finishBuildTrigger { buildType = "${UpdateBuildVersion.id}" } } dependencies { snapshot(UpdateReleaseDate) { reuseBuilds = ReuseBuilds.NO } } })

In this setup, running new builds will result the following:

  • If a new "Update Release Date" build is triggered, other configurations will not be affected. A build will calculate a new parameter value that will not be used anywhere.

  • If the "Update Build Version" configuration is triggered, once this build finishes a new "Update Packages" configuration build will be spawned because of the Finish build trigger added to this configuration. However, since "Update Packages" also has a snapshot dependency on "Update Release Date" (with disabled build reuse), it will also request a current date. As a result, the entire "Update Build Version → Update Release Date → Update Packages" pipeline will run.

  • If a new "Update Packages" build is triggered, it will first run its dependency "Update Release Date" build. The release version will be taken from the project parameter without running a new "Update Release Version" build.

As a result, delivery builds always ensure the date is correct, but reuse the existing product version unless the "Update Build Version" configuration produces a new build. Incrementing a build version automatically triggers the delivery process.

Trigger Limitations

When used alone (without a snapshot dependency on the same configuration), the Finish build trigger has the following limitations:

  • A newly triggered build may not have the same revisions as the finished tracked build even if both configurations have the same VCS settings.

  • If a build configuration with the finish build trigger has an artifact dependency on the target build configuration, there is no guarantee that artifacts of a watched build will be used. This can happen because another build of a tracked configuration may finish while the triggered build sits in the build queue.

  • The build triggered by the finish build trigger will always be triggered in the default branch even if the finished build uses another branch.

  • The algorithm does not guarantee that every finished build in a monitored configuration will trigger a respective build in a configuration with the finish build trigger. In certain cases, for example, if two monitored builds finish somewhat simultaneously, only one respective build might be triggered. For more details on this limitation and its possible workarounds, see the related task in our issue tracker; if this limitation restrains your build pipeline anyhow, please leave a comment to this issue describing your use case.

All these limitations do not apply if a build configuration with the finish build trigger has a snapshot dependency on the same build configuration. In this case, the trigger will run build on the same revisions and will attach the build to the chain. It will also use consistent artifacts if they are produced by dependencies. For that reason, the finish build trigger settings dialog shows a warning if a corresponding snapshot dependency does not exist, suggesting you use both features in tandem.

Note that if a build configuration with the finish build trigger has a snapshot dependency on the selected build configuration, the trigger will be able to detect if the last monitored build has already been promoted to the current build configuration (either manually or by another trigger). In this case, the trigger will not run a new build.

Triggered Build Customization

The Build Customization tab of a trigger's settings allows configuring custom parameters of builds started by this trigger. Similarly to the Run Custom Build dialog, it lets you override values of build parameters and choose if the checkout directory should be cleaned before the build.

On this tab, you can customize the value of any parameter used in the current build configuration. Or, you can add a new parameter, and it will be available only in builds started by this trigger. If the current build has snapshot dependencies on other builds, such a parameter can also be used to override a certain property of a dependency build configuration: use the reverse.dep.<dependencyBuildID>.<property> syntax for this.

Note that if you redefine a build parameter inside a trigger and then delete the original parameter in Parameters, its redefined value will be converted to the trigger's own plain-text parameter. This is crucial to consider when customizing secure values, as they are only concealed if stored with the "Password" type and will become readable if converted to plain text.

TeamCity allows solving similar tasks in multiple ways, and in some cases it is still preferable to create different build configurations. For example, if there are too many custom runs in the same configuration, it might be harder for TeamCity to predict the exact duration of each build. If you need to trigger builds with numerous different parameters, we suggest that you create a build configuration template and use it as a blueprint for several configurations, each with its own parameters.

Last modified: 07 May 2024