构建配置和部署
部署者构建步进

本教程涵盖的主题:
构建配置
部署配置
部署者构建步骤
参数显示和行为设置
在构建链中传递参数
步进执行条件
项目连接
构建功能(构建审批等)
开始之前
部署构建通常意味着更新外部资源,例如上传安装程序到生产网站、发布软件包或将镜像发布到注册表。 在本教程中,通过构建配置来探索 TeamCity 的这一概念,但部署任务同样可以在流水线中处理。
同样的灵活性也适用于构建步进。 TeamCity 包含多种 部署者 :为常见部署任务预置好的可用步进,比如 上传文件到 FTP 服务器。 但部署配置不仅限于专门的部署者。 可以使用任何适合你工作流程的构建步进。
在本教程中,我们正部署 Docker 镜像,因此 Docker 构建步进是自然选择。 对于 .NET 应用程序,更可能会使用 .NET 构建步进。 如需更特定的情况,也可以随时使用通用的 命令行(脚本) 步进。
步骤 1:创建部署配置
点击 创建构建配置。
由于该构建配置仅上传 Docker 镜像到 Docker Hub,不处理存储于 VCS 的应用程序,因此不需要访问仓库(关联的 VCS 根)。 在 设置您的构建 页面上,选择 无仓库。
输入构建配置的名称。
在点击 创建 前,先点击 显示更多 查看更多设置,并将配置类型从“常规”更改为“部署”。

TeamCity 支持三种构建配置类型:
常规 — 一组用于构建和/或测试应用程序的构建步进。
部署 — 在功能上等同于常规配置,但在界面展示上针对部署工作流进行了优化。
复合 — 设计为 构建链的最后元素或其中部分。 此配置无法包含构建步进,作为仪表板聚合前置构建结果,让你能够在一个界面追踪构建链状态。
可随时在 常规 设置中更改构建配置类型。

将新建构建配置设置为在 上一个教程 中创建的“Build Docker image”流水线之后运行。 这样它就成为同一个构建链的一部分。
通过向上游元素添加依赖项,构建配置与流水线一样被添加到构建链中。 在构建配置设置中,打开 依赖 选项卡并点击 添加新的快照依赖项。 将所有依赖项设置保持为默认值。 这些设置与 步骤 2:配置构建链。 中所述一致。

在实际 CI/CD 工作流中,通常会将“build image”和“push image”作为同一个构建配置或流水线的构建步进。 本教程为了演示,将其拆分到不同阶段,这样会导致潜在问题。
“Build Docker image”流水线会构建 Docker 镜像,并将其存储在运行于构建代理上的 Docker 引擎中。 Docker 镜像只存在于创建它的本地 Docker 实例上,因此若代理使用不同的 Docker 引擎,将无法找到该镜像。 为让部署构建能够推送由上一构建创建的镜像,两个构建都必须在同一构建代理上运行。
为确保构建链按预期运行,请为两个构建配置相同的 代理要求。 最简单的选项是使用代理名称,如 步骤 3:发布并交换工件。 所示。
# Build image pipeline jobs: Job1: name: Docker build ... runs-on: self-hosted: - requirement: exists name: ImageBuilderTool parameter: container.engine - requirement: equals name: Agent name parameter: teamcity.agent.name value: MyAgent1 ...// Deploy image configuration import jetbrains.buildServer.configs.kotlin.* object UploadDockerImage : BuildType({ name = "Upload Docker Image" type = BuildTypeSettings.Type.DEPLOYMENT dependencies { snapshot(BuildDockerImage) { reuseBuilds = ReuseBuilds.NO } } requirements { equals("teamcity.agent.name", "MyAgent1") }})新建构建配置当前还没有任何构建步进。 仍可运行它以检查是否能按预期启动上游构建链。
这样还能直观了解 Deployment 配置与常规配置有何不同。
- '部署' 按钮
最明显的区别是右上角主操作按钮的名称:此处为 部署 ,而不是 运行。

部署任务通常会影响外部资源,如上传 NuGet 软件包、更新生产环境、发布 GitHub 发布版等。 部署 标签可起到简单的保护作用,降低错误触发敏感操作的风险。
- '部署' 部分
上游构建会在 部署 部分的 概述 选项卡中展示其下游部署配置。

在该区域,你可以:
视图所有与该构建相关的下游部署配置。 例如,“Build app”流水线可为“Deploy to staging”和“Deploy to production”都提供输入。 如有任一部署正在运行,其状态会在此显示。
可从已完成的上游构建启动部署。 如部署配置尚未运行,请点击其名称旁的 部署。 首次运行后,此按钮将变为 重新部署。
此按钮可以让你暂停评估构建结果,仅在准备就绪时再部署,无需重跑整个链。
步骤 2:配置构建步进
同一上游构建的结果可部署到多个位置。 如暂存和环境服务器。 最简方式是创建独立配置。 本教程中,我们将采用更高级的方法:使用单一配置,根据参数值决定其操作。
在 Docker Hub 账户下准备两个仓库:一个用于 私有,一个用于公有镜像。 例如,
valrravn/teamcity-gs-private和valrravn/teamcity-gs-public。编辑 Build Docker image 流水线 ,让镜像初始被标记为私有仓库。 这将作为默认部署目标。
jobs: Job1: name: Docker build steps: - type: script script-content: >- docker build -f ./docker/Dockerfile -t valrravn/teamcity-gs-private:%build.number% .在构建配置设置中,打开 参数 选项卡,按如下属性创建新参数:
名称:
deployment.target。值类型:
选择。 这样编辑器将变为具有预定义值的下拉框。值:
private。 此为默认值,除非你选择其他项,否则将采用此值。条目:
public、private和both,各占一行。 这些是你可供选择的值。 也可通过label => value语法添加与实际参数值不同的自定义 UI 标签。显示:
提示。 通常,用户只能通过 运行自定义构建对话框来重写参数。 提示型参数每次构建启动都会弹出此对话框,确保你在部署前选择一个值。Label描述: 为可选文本,帮其他 TeamCity 用户理解此参数的作用。
object UploadDockerImage : BuildType({ name = "Upload Docker Image" type = BuildTypeSettings.Type.DEPLOYMENT params { select("deployment.target", "Private", label = "Upload to", description = "Choose the Docker Hub repository to which this image should be uploaded.", display = ParameterDisplay.PROMPT, options = listOf("Private repository" to "Private", "Public repository" to "Public", "Both")) } })现在 TeamCity 每次启动该配置时,无论是直接运行还是通过上游构建点击 部署 或 重新部署 ,都会要求你选择部署目标。

保存未应用的更改并离开构建配置设置。 打开父项目设置并转到 连接 页面。
添加新的 Docker 注册表连接。 TeamCity 会使用此连接在 Docker Hub 进行身份验证,并推送 Docker 镜像。

返回构建配置设置并添加 Docker 注册表连接 构建功能。 选择在上一步创建的 Docker 注册表连接。
将 Docker 构建步进添加到配置中,并设置以下选项:
Docker 命令:
推送镜像名称:标记:
valrravn/teamcity-gs-private:%dep.<BuildImagePipelineID>.build.number%(见下方说明)推送后从代理中移除镜像:
已禁用,因为某个部署选项要求同时推送到公有和私有仓库。 因此我们需要两个 Docker 构建步进。 第一个步进结束后,应将镜像剩余给下一个步进使用。
import jetbrains.buildServer.configs.kotlin.* object UploadDockerImage : BuildType({ name = "Upload Docker Image" type = BuildTypeSettings.Type.DEPLOYMENT // ... steps { dockerCommand { name = "Push to private repo" id = "Push_to_private_repo" commandType = push { namesAndTags = "valrravn/teamcity-gs-private:%dep.GSFirstBuild_BuildDockerImage.build.number%" } } } // ... })在构建步进设置中找到 执行步骤 并点击 添加条件 | 其他条件...。 添加
deployment.target does-not-equal public条件。此条件通过前面创建的参数控制步进何时运行。 仅当启动构建时选择“Private”或“Both”,Docker 镜像才会推送到私有仓库。 详细信息请参见 构建步骤执行条件。
steps { dockerCommand { conditions { doesNotEqual("deployment.target", "Public") } // ... }多次运行部署构建配置,确认仅当选择“Private”或“Both”时镜像才会上传到私有 Docker Hub 仓库。
重复步骤 7 和 8,添加一个类似的 Docker 步进,这次用于上传公有镜像。 还需要一个 命令行(脚本) 步进,在推送前重新标记镜像。
object UploadDockerImage : BuildType({ name = "Upload Docker Image" type = BuildTypeSettings.Type.DEPLOYMENT // ... steps { // ... script { // Change the image tag to match the public repository name = "Retag image" id = "Retag_image" conditions { doesNotEqual("deployment.target", "Private") } // The 'p' char is added before the build number // to better distinguish public and private versions scriptContent = "docker tag " + "valrravn/teamcity-gs-private:%dep.GSFirstBuild_BuildDockerImage.build.number% " + "valrravn/teamcity-gs-public:p%dep.GSFirstBuild_BuildDockerImage.build.number%" } dockerCommand { // Push the re-tagged image to the public repo id = "DockerCommand" conditions { doesNotEqual("deployment.target", "Private") } commandType = push { namesAndTags = "valrravn/teamcity-gs-public:p%dep.GSFirstBuild_BuildDockerImage.build.number%" } } } // ... })请再次部署构建配置,以验证所有三种部署目标选项是否按预期工作。
私有仓库(默认选项,镜像以构建号为标签):

公共仓库(镜像以构建号和
p前缀为标签):
步骤 3:保护部署配置
最后,让我们确保部署配置不会被误运行。
将配置设置为“部署”后,会通过将“运行”按钮标签更改为“部署”来增加注意。 然而,更可靠的选项是配置 构建审批 构建功能,以保护敏感构建配置。 该功能会让新的构建保持排队,直到指定的审核者(单个 TeamCity 用户或 用户组成员)明确允许其运行。 未及时获批的构建将会被自动取消。 如果你在 第一个教程 中配置了 不受信任的构建 ,可能已经见过类似的行为。

如果希望部署配置可以由任何人运行,但仍有某种确认逻辑,可以利用 TeamCity 参数的外观和行为设置创建自定义确认提示。 添加一个 提示参数 类型为正则表达式,只有在用户输入指定词语后配置才会启动。
