TeamCity On-Premises 2026.1 Help

在构建链中使用参数

本主题演示了如何使用 TeamCity 构建参数构建链 的配置和流水线之间以及同一流水线的不同作业之间交换简单数据。

输入和输出参数

构建配置和流水线允许您创建两种类型的参数:输入和输出。

配置中的输入和输出
流水线中的输入和输出

它们都是手动创建的名称/值对。 关键区别在于预期的使用场景和可访问性设置。

输入参数

输入参数旨在由定义它们的同一配置或流水线使用。 例如,一个存储默认分支名称并在 VCS 根设置 中引用的输入参数。 此值对其他配置没有用处,因此不应对它们可见。

输出参数

输出参数在一个构建配置或流水线中配置,但可通过 快照工件 依赖项被另一个配置访问。 例如,一个构建 Docker 镜像的构建配置可以将此镜像名称写入其参数。 该参数随后由下游配置使用,该配置将此镜像部署到注册表。

输出参数可以共享现有参数(原样)、修改后的参数和常量。

outputParams { // Expose predefined parameter as is param("originConfName", "%system.teamcity.buildConfName%") // Expose modified parameter value param("buildNumber", "Build %\system.build.number%") // Expose input parameter as is param("name", "%customInputParam%") // Expose static value param("number", "54") }

读取上游对象的参数

只有当作业在同一流水线中按序连接时,它们才能与其他作业共享参数。 同样,流水线和配置也只有在构建链中连接时才能互相访问参数。

访问作业参数

流水线作业可以通过 job.<job_ID>.<param-name> 语法 获取前置作业参数的值

jobs: Job1: name: Job 1 steps: - type: script script-content: |- echo "Print Job1 parameter: %env.ParamJobA%" # prints 'foo' parameters: env.ParamJobA: foo Job2: name: Job 2 dependencies: - Job1 parameters: env.ParamJobB: '%job.Job1.env.ParamJobA% bar' steps: - type: script script-content: |- echo "Print parameter from upstream Job: %job.Job1.env.ParamJobA%" # prints 'foo' echo "Print modified parameter: %env.ParamJobB%" # prints 'foo bar'

同一链中的其他流水线和配置无法访问上游流水线的作业参数。 如有需要,可以将作业参数分配给流水线输出参数。

jobs: Job1: name: Job 1 parameters: jobParam: foo output-parameters: PipelineOutputParam: %job.Job1.jobParam%

访问配置和流水线参数

要将配置或流水线参数共享给下游配置或流水线,该参数必须为输出参数。 此时,任何下游配置或流水线都可以通过 dep.<config-or-pipeline-ID>.<parameter-name> 语法读取其值。

object Upstream : BuildType({ name = "Upstream config" params { param("inputParam", "foo") // Input parameter, cannot be shared } outputParams { // Output parameter, accessible via the 'dep.' prefix // Modified value of an input parameter param("outputParam", "%inputParam% bar") } }) object Downstream : BuildType({ name = "Downstream config" steps { script { id = "simpleRunner" // Prints 'foo bar' scriptContent = "echo ${Upstream.depParamRefs["outputParam"]}" } } dependencies { snapshot(Upstream) { }} })

输出参数对下游对象可见,但不能在其所属的父配置或流水线中使用。

parameters: PipelineInputParam: foo output-parameters: PipelineOutputParam: bar jobs: Job1: name: Job 1 steps: - type: script script-content: |- # Prints 'foo' echo "Input param: %PipelineInputParam%" # Unresolved reference: no compatible agents echo "Output param: %PipelineOutputParam%"

公开配置的所有输入参数。

在构建配置中, 添加新的输出参数 对话框有两个选项:手动输入值或直接共享现有的输入参数。 选择所需的输入参数后,TeamCity 会以 %inputParameter% 值创建输出参数。

添加输出参数

如果选中 所有参数对其他构建配置均可用 设置,无需单独共享每个输入参数。 它们会被自动公开,并可通过 dep.<config-ID>.<parameterName> 语法引用。

公开所有输出参数

为了向后兼容,此设置默认启用。 但是,我们强烈建议您执行以下操作:

  1. 检查所有被其他配置使用的输入参数的情况。

  2. 通过在新的输出参数中引用您希望继续共享的输入参数来公开它们。

  3. 禁用 所有参数对其他构建配置均可用 设置。

这样可以确保配置保持易于维护:您可以根据需要编辑和删除输入参数,而不会意外破坏通过 dep... 语法使用这些参数的下游配置。 此外,这通过隐藏从未设计为共享的参数来增强安全性。

重写上游对象的参数

下游配置或流水线可以通过 dep.<source-object-ID>.<parameter-name> 从上游配置或流水线读取参数。 相反,添加 override.dep. 前缀可以重写直接或间接依赖实体的上游参数值。

以下示例说明两个对象如何交换参数值:

  • 该构建链包含两个对象:上游流水线和下游构建配置。

  • 流水线声明一个默认值为 foo 的输入参数。 当流水线单独运行时,该值会用于构建脚本。

  • 当流水线作为构建链的一部分运行时(由配置的 快照依赖项 触发),下游配置会重写此参数并将其设置为 条形图

  • 流水线输出参数引用了输入参数,因此也会报告更新后的值。

换句话说,下游配置通过 override.dep.条形图 写入流水线输入,流水线通过其输出参数公开该值,下游配置随后可通过 dep. 读取回来。

# Upstream pipeline jobs: Job1: name: Job 1 steps: - type: script # Prints "foo" if the pipeline runs alone ## Or "bar" if runs in a chain script-content: 'echo "Input param: %PipelineInputParam%"' parameters: PipelineInputParam: foo output-parameters: # Output parameter shares input parameter as is PipelineOutputParam: '%PipelineInputParam%'
// Downstream configuration object DownstreamConfig : BuildType({ name = "Downstream build configuration" params { // Overrides the pipeline input parameter param("override.dep.MyProject_UpstreamPipeline.PipelineInputParam", "bar") } steps { script { id = "simpleRunner" // Prints "bar" scriptContent = """echo "${UpstreamPipeline.depParamRefs["PipelineOutputParam"]}"""" } } dependencies { snapshot(UpstreamPipeline) { }} })

发送方和接收方的类型没有影响。 在本示例中,构建配置重写了流水线参数,但相同的语法和行为适用于任意组合方式:流水线到构建配置、流水线到流水线或构建配置到构建配置。

通配符

与需要精确源对象 ID 的 dep. 参数不同, override.dep. 参数可以用星号(* )替换部分或全部 ID。 这样可以一次性重写多个匹配对象的输入参数。

例如,假设有一个包含三个用于构建 .NET 项目的配置的构建链,顶层为名称为“Build All”的 复合配置。 每个构建配置都有一个 build.mode 参数,用于 设置编译器模式 ,可以设置为 调试Release

从“Build All”运行整个链时,可以保持当前模式或一次性为所有三个配置更改。 为此,可使用一个 override.dep.*.build.mode 参数取代三个独立的 override.dep.<config-ID>.build.mode 参数。

// "Build All" composite configuration object OverrideWildcard_BuildAll : BuildType({ id("BuildAll") name = "Build All" type = BuildTypeSettings.Type.COMPOSITE params { // The "select" parameter with an extra "Default" value // Writes the same value to all upstream "build.mode" parameters select("override.dep.*.build.mode", "Default", options = listOf("<current setting>" to "Default", "Release", "Debug")) } dependencies { snapshot(BuildDmg) {} snapshot(BuildExe) {} snapshot(UnitTests) {} } }) // Regular build/test configurations object BuildDmg : BuildType({ id = AbsoluteId("BuildDmg") name = "Build dmg" params { // The default mode is "Release" // Other configurations can have this set to "Debug" // Note there's no "Default" option select("build.mode", "Release", options = listOf("Debug", "Release")) } steps { csharpScript { name = "Set default debug mode" id = "Set_default_debug_mode" // If "Build All" set the parameter to "Default"... conditions { equals("build.mode", "Default") } // ...then send a service message to revert it back to "Release" content = """ Console.WriteLine("The build.mode parameter was set to 'Default'."); Console.WriteLine("Setting the build mode to 'Release'..."); Console.WriteLine("##teamcity[setParameter name='build.mode' value='Release']"); """.trimIndent() tool = "%teamcity.tool.TeamCity.csi.DEFAULT%" } dotnetBuild { // TODO } } })

冲突解决

如果参数被多个由不同配置或流水线所有的 override.dep. 参数编辑,TeamCity 会采用最后运行的实体的最新编辑值。

ConfigD (runs last, triggers the chain) +------------------------------------------+ | override.dep.ConfigA.Fruit = "pear" | +------------------------------------------+ │ ▼ ConfigC (runs third) +------------------------------------------+ | override.dep.ConfigA.Fruit = "orange" | +------------------------------------------+ │ ▼ ConfigB (runs second) +------------------------------------------+ | override.dep.ConfigA.Fruit = "banana" | +------------------------------------------+ │ ▼ ConfigA (runs first) +------------------------------------------+ | Fruit = "apple" | +------------------------------------------+ Final value in ConfigA: "pear"

否则,如果由多个同级实体编辑,则目标参数保持其原始值。

特别说明

  • 输出参数无法通过 override.dep. 参数编辑。

  • override.dep. 参数只会更新目标配置或流水线中已存在的参数,不会创建缺失参数。 此外,已具有相同值的上游参数不会被强制更新,这允许 TeamCity 重用之前的构建

  • 在流水线中,只有流水线级参数可以带有 override.dep. 前缀。 作业参数无法修改远程参数。

    jobs: Job1: name: Job 1 parameters: # Ignored override.dep.TargetID.myParam: foo dependencies: - TargetID parameters: # Applied override.dep.TargetID.myParam: bar
  • 重写流水线参数时, override.dep.*.paramName 会更新所有 paramName ,无论其作用域如何:流水线输入和作业参数都会被修改。

  • 如果传递了参数引用,将在拥有此 override.dep. 的实体中解析参数,而不是在被编辑参数值的实体中解析。 如果无法解析,引用将作为纯文本传递,并在构建日志中显示“参数未完全解析”警告。

    object UpstreamConfig : BuildType({ name = "Upstream config" params { param("bar", "default") param("foo", "default") } steps { script { id = "simpleRunner" scriptContent = """ echo "%foo%" // Prints "Downstream config" echo "%bar%" // Prints "%invalid%" """.trimIndent() } } }) object DownstreamConfig : BuildType({ name = "Downstream config" params { param("override.dep.UpstreamConfig.foo", "%system.teamcity.buildConfName%") // The name of THIS configuration param("override.dep.UpstreamConfig.bar", "%invalid%") // Unresolved } dependencies { snapshot(UpstreamConfig) { } } })

    请注意,参数引用会在上游构建实际开始前被解析。 届时,所有参数的值必须在流水线/配置设置中分配,或通过 运行自定义构建对话框 传递。 如果引用的是在构建过程中计算的参数,将不会传递任何值。

'reverse.dep.' 参数

override.dep.<target-ID>.<parameter-name> 语法是在 TeamCity 2026.1 中引入的。 在早期版本中,上游参数通过类似的 reverse.dep.<target-ID>.<parameter-name> 语法进行修改。

reverse.dep. 依然受支持,但推荐使用 override.dep. ,因为其行为更简单、更可预测。

  • override.dep. 不同, reverse.dep. 不会解析参数引用,而是直接传递,这可能导致上游配置或流水线与部分构建代理不兼容。

  • reverse.dep. 还更具侵入性:如果目标配置或流水线没有匹配参数,TeamCity 会创建一个。 相比之下, override.dep. 只会更新已存在参数,忽略没有匹配参数的实体。 同时还需注意,新增参数会导致“ 如存在可用构建则不运行新构建 ”快照依赖项策略失效,因此上游构建将不会被重用。

  • reverse.dep. 使用更复杂的冲突解决机制。 当多个实体修改同一参数时,TeamCity 首先优先采用最后运行的配置或流水线,与 override.dep. 机制一致。 如果冲突编辑器为同一级别,TeamCity 将比较目标 ID 的特异性,ID 最具体的参数优先。

    Config A +-----------------------------------------------------------+ | person = "Mary" | +-----------------------------------------------------------+ ┌────────────────────├───────────────────────┐ ▼ ▼ ▼ Config B Config C Config D +----------------+ +----------------+ +----------------+ | reverse.dep. | | reverse.dep. | | reverse.dep. | | ConfigA.person | | Conf*.person | | *.person | | = John | | = Mike | | = Jane | +----------------+ +----------------+ +----------------+ └─────────────────────├───────────────────────┘ Run all ▼ +-----------------------------------------------------------+ | composite configuration | | depends on: ConfigB, ConfigC, ConfigD | +-----------------------------------------------------------+ Config B: fully clarified target ID Config C: ID partially replaced with a wildcard Config D: wildcard instead of target ID Final value in ConfigA: "John" (Config B)

    最后,如果冲突编辑来自同级且特异性相同的实体,TeamCity 会保留目标参数不变,并为每个唯一冲突值添加一个 conflict.<sender_config_ID>.paramName 参数。

    冲突的覆盖
2026年 8月 6日