在构建链中使用参数
本主题演示了如何使用 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> 语法 获取前置作业参数的值。
同一链中的其他流水线和配置无法访问上游流水线的作业参数。 如有需要,可以将作业参数分配给流水线输出参数。
访问配置和流水线参数
要将配置或流水线参数共享给下游配置或流水线,该参数必须为输出参数。 此时,任何下游配置或流水线都可以通过 dep.<config-or-pipeline-ID>.<parameter-name> 语法读取其值。
输出参数对下游对象可见,但不能在其所属的父配置或流水线中使用。
公开配置的所有输入参数。
在构建配置中, 添加新的输出参数 对话框有两个选项:手动输入值或直接共享现有的输入参数。 选择所需的输入参数后,TeamCity 会以 %inputParameter% 值创建输出参数。

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

为了向后兼容,此设置默认启用。 但是,我们强烈建议您执行以下操作:
检查所有被其他配置使用的输入参数的情况。
通过在新的输出参数中引用您希望继续共享的输入参数来公开它们。
禁用 所有参数对其他构建配置均可用 设置。
这样可以确保配置保持易于维护:您可以根据需要编辑和删除输入参数,而不会意外破坏通过 dep... 语法使用这些参数的下游配置。 此外,这通过隐藏从未设计为共享的参数来增强安全性。
重写上游对象的参数
下游配置或流水线可以通过 dep.<source-object-ID>.<parameter-name> 从上游配置或流水线读取参数。 相反,添加 override.dep. 前缀可以重写直接或间接依赖实体的上游参数值。
以下示例说明两个对象如何交换参数值:
该构建链包含两个对象:上游流水线和下游构建配置。
流水线声明一个默认值为
foo的输入参数。 当流水线单独运行时,该值会用于构建脚本。当流水线作为构建链的一部分运行时(由配置的 快照依赖项 触发),下游配置会重写此参数并将其设置为
条形图。流水线输出参数引用了输入参数,因此也会报告更新后的值。
换句话说,下游配置通过 override.dep. 将 条形图 写入流水线输入,流水线通过其输出参数公开该值,下游配置随后可通过 dep. 读取回来。
发送方和接收方的类型没有影响。 在本示例中,构建配置重写了流水线参数,但相同的语法和行为适用于任意组合方式:流水线到构建配置、流水线到流水线或构建配置到构建配置。
通配符
与需要精确源对象 ID 的 dep. 参数不同, override.dep. 参数可以用星号(* )替换部分或全部 ID。 这样可以一次性重写多个匹配对象的输入参数。
例如,假设有一个包含三个用于构建 .NET 项目的配置的构建链,顶层为名称为“Build All”的 复合配置。 每个构建配置都有一个 build.mode 参数,用于 设置编译器模式 ,可以设置为 调试 或 Release。
从“Build All”运行整个链时,可以保持当前模式或一次性为所有三个配置更改。 为此,可使用一个 override.dep.*.build.mode 参数取代三个独立的 override.dep.<config-ID>.build.mode 参数。
冲突解决
如果参数被多个由不同配置或流水线所有的 override.dep. 参数编辑,TeamCity 会采用最后运行的实体的最新编辑值。
否则,如果由多个同级实体编辑,则目标参数保持其原始值。
特别说明
输出参数无法通过
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参数。