Build Chain(构建链)
构建链是由 快照依赖关系连接的构建序列。 有时构建链被称为“管道”。 启用修订同步的快照依赖性链接的构建链的部分使用相同的源快照。
tip
请参阅我们的 视频指南 ,了解如何在 TeamCity 中 组成一个 pipeline。
指定构建链的最常见用例是在不同平台上运行您项目的相同测试套件。 例如,在进行 发布构建之前,您需要确保在不同的平台和环境下测试能正确运行。 为此,您可以指示 TeamCity 首先运行测试,然后是集成构建,最后是发布构建。
让我们详细了解构建链机制是如何运作的。 当触发 发布构建配置的依赖构建时,TeamCity 会进行以下操作:
解决 发布构建配置快照所依赖的所有构建配置链。
检查所有依赖构建配置的更改,并在构建链中的第一个构建进入构建队列时进行同步。
将所有需要用特定修订版构建的构建都添加到构建队列中。
要在您的构建配置中指定依赖关系:
打开 配置设置 ,并导航到 依赖项设置选项卡。
单击 添加新的快照依赖项 按钮。
请参阅 构建依赖项设置 以获取详细信息和示例。
如果正在被停止或从构建队列中移除的构建是构建链的一部分,那么在注释字段下方会有一条消息:“ 此构建是构建链的一部分”。
如果构建链中有其他正在运行或排队的部分(即其他正在运行的构建或排队的构建,与执行中的构建相关联),这些构建将在标签“ 停止其他部分 ”下方列出。
如果用户有权停止列表中的构建,则其旁边有一个复选框。 如果停止当前构建肯定会导致列表中的构建失败(例如,如果列出的构建依赖于被停止的原始构建),则复选框默认为选中状态。
如果用户没有停止列表中构建的访问权限,复选框将不可见。
选择此复选框将选中的构建标记为从队列中停止/删除。
如果用户没有查看构建链中的某个构建的访问权限,那么该构建对用户完全不可见。 如果存在至少一个此类构建,会显示一个警告:" 您无权访问它的所有部分" 。 该条纹显示在消息 "此构建是构建链的一部分" 的正下方。
在所有其他构建链部分无法被当前用户查看的情况下,我们会显示一个带有警告的黄色条纹:" 您没有查看其其他部分的访问权限 "。
如果构建链中没有正在运行或排队的构建(即,构建链的所有其他部分已经完成),则不会显示额外信息。
您可以在推进构建时为构建配置的快照依赖性 禁用修订同步。
如果您从链部分 1 推进到链部分 2 的构建,并且部分 2 的第一个构建配置已禁用此选项,那么此选项将起作用。 在这种情况下,TeamCity 可以为部分 1 和部分 2 的构建使用不同的源代码版本。 请参阅 构建依赖设置中的示例建立环境。
这在您需要运行一个依赖构建但不需要将其代码版本与其依赖项(链中的前序构建)同步时非常有用。
例如,您可以将较旧的构建提升为 部署构建配置 ,该构建将使用最新的部署脚本运行。
在负载/接受测试中,当您将测试存储在版本控制系统中并经常更改它们来测试您的系统时,您不需要完全重建您的应用程序;相反,您可以直接从测试阶段开始选择链。
基本上,每一个构建链都是一个 有向无环图 ,也就是说它不能有循环。
构建链在 TeamCity 网络用户界面的各个地方都可见:
如果一个构建配置是构建链的一部分,则相关信息会显示在 构建配置设置 | 依赖项 | 快照依赖项 中。 点击构建链路将在单独的窗口中打开构建链的预览及其配置。 预览显示了构建链的构建情况;配置了自动触发的构建将被标记这个图标: 。

note
您可以在项目页面和构建配置页面上查看构建链:当配置了快照依赖时,这些页面上都会出现一个 构建链 选项卡。
该选项卡显示了包含该项目或此构建配置的构建链列表,并具有过滤它们的能力。 请注意,构建链按照最后完成的构建的顺序进行排序,以便在列表的顶部显示具有最后完成构建的构建链。
饼状图图标显示了构建链中各状态的比例。 将鼠标悬停在饼状图上时,将显示详细信息:

当链展开时,还可以获得以下信息:
此构建链包含的所有构建
这些构建的状态:未触发,排队中,运行中或已完成及其详细情况
链显示实际执行顺序的构建,即最先开始的构建在左边。
在链中点击构建会高亮显示所选构建及其所有直接依赖项。 这个页面:
为链提供了简洁的表示方法:如果几个顶部构建触发了相同的依赖构建链,则 TeamCity 会显示一个包含几个顶部构建的构建链。
具有额外的显示选项:按项目分组和隐藏详情。
当在构建链中选择一个构建时,它将传递性地突出显示所有下游/上游构建。
在此页面,您还可以:
如果还有"未触发"的构建,继续执行链。 单击 运行 ,一个新构建将基于链修订启动,并与该链中的构建相关联。
点击
打开带有预选构建链修订的 自定义构建对话框。 如果您想重新运行链中的某些构建,可以使用此操作。
如果配置了依赖项,您可以在构建结果页面的 依赖 选项卡上查看其详细信息。 此选项卡还显示间接依赖关系,例如,如果构建 A 依赖构建 B,而 B 又依赖构建 C 和 D,那么这些构建 C 和 D 就是构建 A 的间接依赖。
此选项卡还显示由构建链中的构建下载和交付的工件。 它还允许对构建进行分组/取消分组,并突出显示从以前的链中重用的构建(合适的构建)。
当两个构建配置通过快照依赖链接时,依赖构建总是在开始之前需要完成另一个构建。 然而,有时只需要运行部分构建链。 本节解释如何跳过不必要的链配置并仅运行所需的配置。
如果您很少需要运行链的一部分,您可以保持链配置不变,并在需要运行链的一部分时使用 运行自定义构建对话框。 切换到对话框的 依赖 选项卡,并为您想忽略的构建配置选择“跳过”选项。

请注意,该对话框仅允许您跳过直接链接到您即将运行的配置的构建配置。 例如,启动“Build 1 → Build 2 → Build 3 → Build 4”链中的“Build 4”仅允许您跳过“Build 3”。 您无法触发“Build 4”并告诉 TeamCity 忽略“Build 3”之前的任何配置。
从 2024.12 版本开始,TeamCity 支持 teamcity.build.chain.skipTags
和 teamcity.build.chain.onlyTags
配置参数。 这些参数允许您配置条件构建依赖。
teamcity.build.chain.skipTags
参数显式跳过不需要的配置。 链将仅运行未排除的构建。teamcity.build.chain.onlyTags
参数指定您想要运行的配置。 然而,这并不限制构建链仅运行提到的配置。如果
onlyTags
引用了具有自身依赖的配置,这些依赖也将运行。在
onlyTags
参数中提到的配置之间的配置无法跳过。
两个参数都接受以逗号分隔的标签和配置 ID 作为值。
标签是
teamcity.configuration.tags
参数的值。 使用此参数为任何配置设置标签,并在skipTags
/onlyTags
中设置相同的值。 多个标签值可以用空格、逗号或分号分隔。配置 ID 显示在配置设置中,位于配置名称下方。
您还可以从与配置相关的页面的 URL 中复制配置 ID。 这些 ID 通常具有
projectName_configurationName
格式。 例如,“https://foo.com/buildConfiguration/Glacier_TestWin/2554”URL 对应于构建结果页面,其中“Glacier_TestWin”是配置 ID,“2554”是内部构建编号。
当链(或其部分)被触发时,TeamCity 仅从最顶层配置读取 skipTags
和 onlyTags
参数。 来自上游构建的参数将被忽略。
以下构建链展示了三个示例配置,它们链接在一个“BuildA → BuildB → BuildC”链中。
// Configuration A
object BuildA : BuildType({
id = AbsoluteId("BuildA")
params {
param("teamcity.configuration.tags", "extra")
}
})
// Configuration B
object BuildB : BuildType({
id = AbsoluteId("BuildB")
params {
param("teamcity.configuration.tags", "extra")
param("teamcity.build.chain.skipTags", "extra")
}
dependencies { snapshot(BuildA) {} }
})
// Configuration C
object BuildC : BuildType({
id = AbsoluteId("BuildC")
name = "BuildC"
dependencies { snapshot(BuildB) {} }
})
如果您启动一个新的“Configuration B”构建,它将作为单独的构建运行,跳过“Configuration A”。 然而,启动“Configuration C”将触发整个“BuildA → BuildB → BuildC”链。
如果您跳过了一个 提供工件 给另一个构建的构建,则下游构建将失败,因为没有交付工件。 为防止这种情况发生,TeamCity 动态将严格的工件依赖替换为 可选依赖 (?:build.jar => build/libs/
替代 +:build.jar => build/libs/
)。
如果一个构建跳过了其一些上游配置,TeamCity 会将其视为具有修改依赖的构建。 因此,后续的链运行将不会 重用 此构建,而是触发一个新的构建。
以下链包括多个构建和测试配置,其中“Build All” 复合配置触发整个链。

运行整个链可能会消耗大量时间和资源。 为了让“Build All”仅运行核心“Build...”配置,请使用标签或 ID 作为值添加 teamcity.build.chain.skipTags
参数。 两种方法是相同的,请选择最适合您的需求的方式。
将 teamcity.configuration.tags
参数添加到您想要跳过的每个配置中。 将这些参数设置为您想要的任何字符串,并使用相同的字符串作为 teamcity.build.chain.skipTags
参数。
Kotlin代码片段下面使用“optional”标签标记不需要的配置。
object TestWin : BuildType({
id("TestWin")
params {
param("teamcity.configuration.tags", "optional")
}
})
object TestAndroid : BuildType({
id("TestAndroid")
params {
param("teamcity.configuration.tags", "optional")
}
})
// ...
// Other optional build configurations
// ...
object TeamcityGatedPrDemo_BuildAll : BuildType({
id("BuildAll")
type = BuildTypeSettings.Type.COMPOSITE
params {
param("teamcity.build.chain.skipTags", "optional")
}
dependencies {
snapshot(BuildLinux_iOS) {}
snapshot(BuildPlugins) {}
snapshot(BuildPortable) {}
snapshot(BuildWin) {}
}
})
与其为每个不需要的配置标记标签,您可以使用此配置 ID 作为 teamcity.build.chain.skipTags
参数值。
object TestWin : BuildType({
id("TestWin")
})
object TestAndroid : BuildType({
id("TestAndroid")
})
// ...
// Other build configurations
// ...
object TeamcityGatedPrDemo_BuildAll : BuildType({
id("BuildAll")
type = BuildTypeSettings.Type.COMPOSITE
params {
param("teamcity.build.chain.skipTags", "TestAndroid,TestIOS,TestLinux,TestPS,TestWin,BuildPlugins")
}
dependencies {
snapshot(BuildLinux_iOS) {}
snapshot(BuildPlugins) {}
snapshot(BuildPortable) {}
snapshot(BuildWin) {}
}
})
要运行整个链,请移除 teamcity.build.chain.skipTags
参数或将其设置为与配置标签或 ID 不匹配的任何值。 例如,添加一个 计划触发器 ,用于运行完整的夜间构建,而在缩短的日常构建中省略某些配置。 TeamCity 触发器设置包括 构建自定义 部分,允许您添加或修改构建参数。
object TeamcityGatedPrDemo_BuildAll : BuildType({
id("BuildAll")
type = BuildTypeSettings.Type.COMPOSITE
params {
param("teamcity.build.chain.skipTags", "optional")
}
triggers {
schedule {
// Full "Build All" chain running daily at 3 AM
schedulingPolicy = daily { hour = 3 }
triggerBuild = always()
withPendingChangesOnly = false
buildParams {
param("teamcity.build.chain.skipTags", "nightly-build-mode")
}
}
}
})
此示例使用了与示例 1 相同的链:

每个单独的配置都使用 teamcity.configuration.tags
参数进行了标记。 为了方便起见,此链的 Kotlin 配置被分类到选项卡中。
object TestWin : BuildType({
id = AbsoluteId("TestWin")
params { param("teamcity.configuration.tags", "tests,windows") }
})
object BuildWin : BuildType({
id = AbsoluteId("BuildWin")
params { param("teamcity.configuration.tags", "build,windows") }
dependencies {
snapshot(TestWin) {}
}
})
object TestLinux : BuildType({
id = AbsoluteId("TestLinux")
params { param("teamcity.configuration.tags", "tests,linux") }
})
// Shared configuration for Linux and iOS
object BuildLinux_iOS : BuildType({
id = AbsoluteId("BuildLinux_iOS")
params { param("teamcity.configuration.tags", "build,linux,ios") }
dependencies {
snapshot(TestIOS) {}
snapshot(TestLinux) {}
}
})
object TestIOS : BuildType({
id = AbsoluteId("TestIOS")
params { param("teamcity.configuration.tags", "tests,ios") }
})
// Shared configuration for Linux and iOS
object BuildLinux_iOS : BuildType({
id = AbsoluteId("BuildLinux_iOS")
params { param("teamcity.configuration.tags", "build,linux,ios") }
dependencies {
snapshot(TestIOS) {}
snapshot(TestLinux) {}
}
})
object TestAndroid : BuildType({
id = AbsoluteId("TestAndroid")
params { param("teamcity.configuration.tags", "tests,portable") }
})
object TestPS : BuildType({
id = AbsoluteId("TestPS")
params { param("teamcity.configuration.tags", "tests,portable" }
})
object BuildPortable : BuildType({
id = AbsoluteId("BuildPortable")
params { param("teamcity.configuration.tags", "build,portable") }
dependencies {
snapshot(TestAndroid) {}
snapshot(TestPS) {}
}
})
object BuildPlugins : BuildType({
id = AbsoluteId("BuildPlugins")
params { param("teamcity.configuration.tags", "build,plugins") }
})
object TeamcityGatedPrDemo_BuildAll : BuildType({
id("BuildAll")
type = BuildTypeSettings.Type.COMPOSITE
params {
select("teamcity.build.chain.onlyTags","",
label = "Choose a sub-chain to run",description = """
* run all — runs the entire chain
* desktop — runs "Build (Win)" and "Build (Linux/iOS)" builds with their related tests
* portable — runs the "Build (Portable)" build with its related Android/PS tests
* windows — runs the "Test (Win) > Build (Win)" sequence
* linux — runs the "Test (Linux) > Build (Linux/iOS)" sequence
* ios — runs the "Test (iOS) > Build (Linux/iOS)" sequence
* plugins — runs the solo "Build Plugins" configuration
""".trimIndent(),
display = ParameterDisplay.PROMPT,
options = listOf(
"run all" to "",
"plugins",
"desktop" to "windows,linux,ios",
"portable" to "BuildPortable",
"windows",
"linux",
"ios"))
}
dependencies {
snapshot(BuildLinux_iOS) {}
snapshot(BuildPlugins) {}
snapshot(BuildPortable) {}
snapshot(BuildWin) {}
}
})
复合“Build All”配置 样式化teamcity.build.chain.onlyTags
参数为“选择”参数,并具有“提示”行为模式。 每当链被手动触发时, 运行自定义构建 对话框会弹出,允许用户选择他们想要启动的链的部分。

run all — 映射到一个空字符串的标签。 这是
onlyTags
参数的初始/默认值。 运行此链的所有九个配置。plugins — 触发“Build Plugins”配置。 此配置将单独运行,因为没有其他配置具有“plugins”标签,并且它不依赖于其他构建。
desktop — 运行具有“windows”、“linux”和“ios”标签的五个构建/测试配置的子链。
portable — 明确指向其 ID 为“BuildPortable”的配置。 此配置依赖于“TestAndroid”和“TestPS”,因此所有三个配置都将运行。 与使用“portable”标签作为参数值相同。
windows/linux/ios — 参数值映射到相同的标签。 触发特定平台的“Test → Build”短子链。 请注意,“linux”和“ios”子链是相同的,因为触发共享的“BuildLinux_iOS”配置会强制运行链接的“TestLinux”和“TestIOS”配置。
可用值列表 不 包括以下选项:
build — 此值将直接触发所有“Build ...”配置,这些配置反过来会启动其链接的“Test ...”配置。 结果是整个链将运行。
tests — 此值可能会让用户感到困惑,因为您无法仅触发最左侧的“Test ...”和最右侧的“Build All”配置,而保留“Build ...”配置不变。 这是因为 TeamCity 无法跳过链中间的配置,因为这样会不清楚如何处理从未运行的配置之间的依赖关系。
从上游构建配置的任何构建步骤发送 ##teamcity[skipQueuedBuilds tags='value1,value2,...' comment='Your comment']
服务消息 ,以取消下游配置的排队构建。 与 skipTags
/onlyTags
参数 相同,此消息的 标记
参数接受:
添加到配置中的
teamcity.configuration.tags
参数的值;配置 ID。
使用服务消息取消构建链的某些“分支”。 例如,您可能希望从“Build”配置发送 skipQueuedBuilds
以取消单个测试套件。 在某些测试运行而某些测试被跳过的情况下,“Build → Test → Deploy”链的完整性仍然保持不变。
Build ----|---- Test Suite 1 ----|
|---- Test Suite 2 ----|
|---- Test Suite 3 ----|
|---- Test Suite 4 ----|
|---- Test Suite 5 ----|---- Deploy
如果您跳过了所有这些测试,链的整个中间部分将消失。 这将产生一个可能令人困惑的“Build → ??? → Deploy”链。 为避免这种情况,请考虑 克隆配置并创建一个单独的“Build → Deploy”链。
Thanks for your feedback!