在构建链中使用参数
这个主题演示了您如何使用 TeamCity 构建参数 在 构建链 的配置之间交换简单数据。
访问前序链构建的参数
依赖构建可以访问前一个链构建的预定义和自定义参数,形式为 dep.<bcID>.<parameter_name>
,其中 bcID
是您需要访问其参数值的源构建配置的名称。
您可以使用 dep...
参数,即使当前配置仅具有间接依赖关系,也可以从配置中访问参数。 例如,在 A → B → C 的链中,C 依赖于 B,B 依赖于 A,配置 C 可以访问 A 的参数。
以下构建配置用于构建并推送 Docker 镜像。 这个镜像的名称被写入到 DockerImageName
参数中。
TAG=v1
docker build -f Dockerfile --tag your.registry/MyApp:${TAG}
docker push your.registry/MyApp:v1
echo "##teamcity[setParameter name='DockerImageName' value='MyApp:${TAG}']"
如果此配置的名称是 "ConfigA",则进一步沿着构建链执行的构建可以访问镜像名称为 dep.ConfigA.DockerImageName
:
docker run -d your.registry/%dep.ConfigA.DockerImageName%
覆盖前置配置的参数
在目标配置中添加一个带有 reverse.dep.<build_conf_ID>.<parameter_name>
名称语法的参数,以覆盖在当前配置之前定义的 <parameter_name>
参数。
例如,以下的 Kotlin 代码定义了一个项目,该项目包含三个构建配置,这些配置在一个单一的构建链中统一(ConfigA → ConfigB → ConfigC)。 每个构建配置都有一个 chain.ConfigX.param
参数,并带有其自定义值。 最后的配置有额外的 reverse.dep.ChainConfigA.chain.ConfigA.param
参数。
import jetbrains.buildServer.configs.kotlin.*
project {
buildType(ChainConfigA)
buildType(ChainConfigB)
buildType(ChainConfigC)
}
object ChainConfigA : BuildType({
name = "ChainConfigA"
params {
param("chain.ConfigA.param", "Config A")
}
steps {
script {
scriptContent = """echo "Parameter value is: %chain.ConfigA.param%""""
}
}
})
object ChainConfigB : BuildType({
name = "ChainConfigB"
params {
param("chain.ConfigB.param", "Config B")
}
steps {
script {
scriptContent = """echo "Parameter value is: %chain.ConfigB.param%""""
}
}
dependencies {
snapshot(ChainConfigA) {
reuseBuilds = ReuseBuilds.NO
}
}
})
object ChainConfigC : BuildType({
name = "ChainConfigC"
params {
param("chain.ConfigC.param", "Config C")
param("reverse.dep.ChainConfigA.chain.ConfigA.param", "Value Overridden in ConfigC")
}
steps {
script {
scriptContent = """echo "Parameter value is: %chain.ConfigC.param%""""
}
}
dependencies {
snapshot(ChainConfigB) {
reuseBuilds = ReuseBuilds.NO
}
}
})
如果您运行 ConfigA 或 ConfigA → ConfigB 子链,第一个配置将会报告其原始参数值。
# ConfigA build log
Parameter value is: Config A
然而,如果您运行一个以 ConfigC 结束的完整构建链,这最后的配置将为 ConfigA 提供一个定制的参数值。
# ConfigA build log
Parameter value is: Value Overridden in ConfigC
您可以在参数名称中使用 *
通配符,以便在多个前面的配置中使用相同的参数。 例如,以下示例中的 ConfigC 具有 reverse.dep.ChainConfig*.MyParam
参数,该参数覆盖了 ConfigA 和 ConfigB 中的 MyParam
。
object ChainConfigA : BuildType({
params {
param("MyParam", "OriginalValue_A")
}
})
object ChainConfigB : BuildType({
params {
param("MyParam", "OriginalValue_B")
}
dependencies {
snapshot(ChainConfigA) {
reuseBuilds = ReuseBuilds.NO
}
}
})
object ChainConfigC : BuildType({
params {
param("reverse.dep.ChainConfig*.MyParam", "CustomValue_C")
}
dependencies {
snapshot(ChainConfigB) {
reuseBuilds = ReuseBuilds.NO
}
}
})
冲突的参数覆盖
如果在 ConfigA → … → ConfigB → … → ConfigC 配置链中,ConfigB 和 ConfigC 配置试图覆盖 ConfigA 的参数,由于 ConfigC 依赖于 ConfigB (直接或通过中间配置),所以 ConfigC 有更高的优先级。
object ChainConfigA : BuildType({
params {
param("MyParam", "OriginalValue_A")
}
})
object ChainConfigB : BuildType({
params {
// Lower priority
param("reverse.dep.ChainConfigA.MyParam", "CustomValue_B")
}
// Depends on config A
dependencies {
snapshot(ChainConfigA) {
reuseBuilds = ReuseBuilds.NO
}
}
})
object ChainConfigC : BuildType({
params {
// Higher priority
param("reverse.dep.ChainConfigA.MyParam", "CustomValue_C")
}
// Depends on config B
dependencies {
snapshot(ChainConfigB) {
reuseBuilds = ReuseBuilds.NO
}
}
})
然而,如果 ConfigB 和 ConfigC 彼此间没有依赖关系,关于哪种配置应具有优先级的问题就会出现。 TeamCity 试图通过比较参数名称并优先考虑具有最具体构建配置 ID 的参数来解决这种歧义。
最高优先级:构建配置 ID 中没有通配符的参数(例如, reverse.dep.ChainConfigA.MyParam
)。
中等优先级:具有部分配置 ID 的参数(例如, reverse.dep.Chain*A.MyParam
)。 目标配置 ID 越具体,此参数的优先级就越高。 例如, ChainConf*A
ID 优先于 Chain*A
ID,因为它被认为更为特定。
最低优先级:参数使用 *
通配符,而非配置 ID (例如, reverse.dep.*.MyParam
)。
如果所有冲突的配置都有相似的参数名称,且没有一个明显的赢家,那么 TeamCity 就会报告一个冲突并创建额外的 conflict.<build_config_ID>.<parameter_name>=<value>
参数(每个冲突的配置都有一个)。
object ChainConfigA : BuildType({
params {
param("MyParam", "OriginalValue_A")
}
})
object ChainConfigB : BuildType({
params {
// Equal priority
param("reverse.dep.ChainConfigA.MyParam", "CustomValue_B")
}
// Depends on config A
dependencies {
snapshot(ChainConfigA) {
reuseBuilds = ReuseBuilds.NO
}
}
})
object ChainConfigC : BuildType({
params {
// Equal priority
param("reverse.dep.ChainConfigA.MyParam", "CustomValue_C")
}
// Depends on config A
dependencies {
snapshot(ChainConfigA) {
reuseBuilds = ReuseBuilds.NO
}
}
})
// Composite build configuration that runs the entire chain
object ChainABC : BuildType({
type = BuildTypeSettings.Type.COMPOSITE
dependencies {
snapshot(ChainConfigB) {}
snapshot(ChainConfigC) {}
}
})
其他考虑因素
在队列构建中处理 reverse.dep.*
参数,这些参数在此处定义。 既然此阶段应已知道参数值,那么必须在构建配置或者 自定义构建对话框 中分配这些值。 将参数设置为在构建期间计算的值将无效。
将新参数推送到构建中会覆盖 "如果存在合适的版本,则不运行新版本 " 快照依赖项选项,并可能在参数设置为非默认值时触发新的构建。
reverse.dep.
参数的值会“原样”推送到依赖性构建中,没有 引用解析。 %
-引用,如果有的话,将在目标(target)构建的范围内得到解决。
最后修改日期: 16日 7月 2024年