使用修饰器将步骤注入管道
Azure DevOps Services | Azure DevOps Server 2020
管道修饰器允许向每个作业的开头和结尾添加步骤。 此过程不同于将步骤添加到单个定义,因为它适用于组织中的所有管道。
假设我们的组织需要在可以释放的所有生成输出上运行病毒扫描程序。 管道作者无需记住添加此步骤。 我们将创建一个自动注入步骤的修饰器。 管道修饰器会注入一个自定义任务,该任务会在每个管道作业结束时执行病毒扫描。
提示
查看有关使用 Azure DevOps 扩展 SDK 进行扩展开发的最新文档。
创作管道修饰器
此示例假定你熟悉 贡献模型。
通过创建扩展"开始"菜单。
完成本教程后,你将有一个 vss-extension.json 文件。
在此文件中,为新的管道修饰器添加贡献。
vss-extension.json
{
"manifestVersion": 1,
"contributions": [
{
"id": "my-required-task",
"type": "ms.azure-pipelines.pipeline-decorator",
"targets": [
"ms.azure-pipelines-agent-job.post-job-tasks"
],
"properties": {
"template": "my-decorator.yml"
}
}
],
"files": [
{
"path": "my-decorator.yml",
"addressable": true,
"contentType": "text/plain"
}
]
}
贡献选项
让我们看看属性及其用途:
| 属性 | 说明 |
|---|---|
id |
贡献标识符。 此扩展中的贡献中必须是唯一的。 |
type |
指定此贡献是管道修饰器。 必须是字符串 ms.azure-pipelines.pipeline-decorator。 |
targets |
修饰器可以在作业/指定任务之前、之后或同时运行。 有关可用选项,请参阅下表。 |
properties.template |
(必需) 模板是扩展中包含的 YAML 文件,该文件定义管道修饰器的步骤。 它是扩展文件夹根目录中的相对路径。 |
properties.targettask |
用于 ms.azure-pipelines-agent-job.pre-task-tasks 或 ms.azure-pipelines-agent-job.post-task-tasks 目标的目标任务 ID。 必须是 GUID 字符串,如下所示 89b8ac58-8cb7-4479-a362-1baaacc6c7ad |
目标
| 目标 | 描述 |
|---|---|
ms.azure-pipelines-agent-job.pre-job-tasks |
在经典生成或 YAML 管道中的其他任务之前运行。 由于源代码签出方式存在差异,此目标在 YAML 管道中签出之前运行,但在经典生成管道中签出后运行。 |
ms.azure-pipelines-agent-job.post-checkout-tasks |
在经典生成或 YAML 管道中的最后 checkout 一个任务之后运行。 |
ms.azure-pipelines-agent-job.post-job-tasks |
在经典生成或 YAML 管道中运行其他任务。 |
ms.azure-pipelines-agent-job.pre-task-tasks |
在经典生成或 YAML 管道中指定任务之前运行。 |
ms.azure-pipelines-agent-job.post-task-tasks |
在经典生成或 YAML 管道中指定任务后运行。 |
ms.azure-release-pipelines-agent-job.pre-task-tasks |
在经典 RM 管道中指定任务之前运行。 |
ms.azure-release-pipelines-agent-job.post-task-tasks |
在经典 RM 管道中指定任务之后运行。 |
ms.azure-release-pipelines-agent-job.pre-job-tasks |
在经典 RM 管道中的其他任务之前运行。 |
ms.azure-release-pipelines-agent-job.post-job-tasks |
在经典 RM 管道中运行其他任务。 |
在此示例中,我们仅使用 ms.azure-pipelines-agent-job.post-job-tasks ,因为我们希望在所有生成作业结束时运行。
此扩展提供管道修饰器。 接下来,我们将创建一个模板 YAML 文件来定义修饰器的行为。
修饰器 YAML
在扩展的属性中,我们选择了名称“my-decorator.yml”。 在贡献的根目录中创建该文件。 它保存每个作业后要运行的步骤集。 我们将从基本示例开始,并完成完整的任务。
my-decorator.yml (初始版本)
steps:
- task: CmdLine@2
displayName: 'Run my script (injected from decorator)'
inputs:
script: dir
安装修饰器
若要向组织添加管道修饰器,必须 安装扩展。 只有专用扩展才能提供管道修饰器。 必须先创作扩展并将其与组织共享,然后才能使用它。
扩展与组织共享后, 搜索该扩展 并安装它。
保存该文件,然后 生成并安装扩展。
创建并运行基本管道。
修饰器在每个作业结束时自动注入脚本 dir 。
管道运行类似于:

注意
修饰器在组织中每个管道中的每个作业上运行。 在后续步骤中,我们将添加逻辑来控制修饰器运行的时间和方式。
条件注入
在本示例中,仅当生成输出可能发布到公众时,才需要运行病毒扫描程序。
假设仅从默认分支生成 (通常会 master 发布) 。
应将修饰器限制为针对默认分支运行的作业。
更新的文件如下所示:
my-decorator.yml (修订的版本)
steps:
- ${{ if eq(resources.repositories['self'].ref, resources.repositories['self'].defaultBranch) }}:
- script: dir
displayName: 'Run my script (injected from decorator)'
可以开始查看此扩展点的强大功能。 使用当前作业的上下文在运行时有条件地注入步骤。 使用 YAML 表达式 来决定要注入的步骤和时间。 有关可用数据的完整列表,请参阅 管道修饰器表达式上下文 。
我们需要考虑另一种情况:如果用户已包含病毒扫描步骤,该怎么办?
我们不应该浪费时间再次运行它。
在此简单示例中,我们将假装作业中找到的任何 script 任务都运行病毒扫描程序。
(在实际实现中,你需要一个自定义任务来检查该任务。)
脚本任务的 ID 为 d9bafed4-0b18-4f58-968d-86655b4d2ce9。
如果看到另一个脚本任务,则不应注入我们的任务。
my-decorator.yml (最终版本)
steps:
- ${{ if and(eq(resources.repositories['self'].ref, resources.repositories['self'].defaultBranch), not(containsValue(job.steps.*.task.id, 'd9bafed4-0b18-4f58-968d-86655b4d2ce9'))) }}:
- script: dir
displayName: 'Run my script (injected from decorator)'
指定目标任务
可以指定目标 任务 ID,并在此目标任务之前或之后注入任务。 若要指定目标任务,可以修改 vss-extension.json 清单文件,如下所示:
vss-extension.json
{
"contributions": [
{
"id": "my-required-task",
"type": "ms.azure-pipelines.pipeline-decorator",
"targets": [
"ms.azure-pipelines-agent-job.pre-task-tasks",
"ms.azure-pipelines-agent-job.post-task-tasks"
],
"properties": {
"template": "my-decorator.yml",
"targettask": "target-task-id"
}
}
],
...
}
通过设置“targettask”属性,可以指定目标任务的 ID。 任务将在指定目标任务的所有实例之前/之后注入。
指定目标任务的输入注入
可以指定要作为注入任务输入的目标任务的输入列表。
此功能旨在处理 自定义管道任务。 它不打算通过管道变量提供对目标管道任务输入的访问。
为了访问具有 target_ 前缀) 的目标管道任务输入 (输入,注入的管道任务应使用 来自 azure-pipelines-tasks-task-lib 的方法,而不是管道变量,例如 const inputString = tl.getInput('target_targetInput')) 。
为此,可以创建自己的自定义管道 任务 并使用目标输入。 如果需要现装任务之一的功能,例如 CmdLine@2,可以创建 CmdLine@2任务 的副本,并使用修饰器扩展发布它。
注意
此功能仅适用于在目标任务之前或之后注入的任务。
若要指定此输入列表,可以修改 vss-extension.json 清单文件,如下所示:
vss-extension.json (注入的任务输入版本)
{
"contributions": [
{
"id": "my-required-task",
"type": "ms.azure-pipelines.pipeline-decorator",
"targets": [
"ms.azure-pipelines-agent-job.pre-task-tasks",
"ms.azure-pipelines-agent-job.post-task-tasks"
],
"properties": {
"template": "my-decorator.yml",
"targettask": "target-task-id",
"targettaskinputs": ["target-task-input", "target-task-second-input"]
}
}
],
...
}
通过设置“targettaskinputs”属性,可以指定要注入的输入列表。
这些输入将注入到带有前缀“target_”的任务中,并将在注入的任务中可用,如下所示 target_target-task-input。
注意:使用变量获取机密值或从其他任务获取机密值的目标任务输入不会注入。
调试
创作管道修饰器时,可能需要调试。 你可能还希望查看上下文中可用的数据。
可以在对管道进行排队时将 system.debugContext 变量设置为该变量 true 。
然后,查看管道摘要页。
会看到类似于下图的内容:

选择任务以查看日志,其中报告可用上下文和运行时值。
有用的链接
详细了解 YAML 表达式语法。