创作管道修饰器

Azure DevOps Services | Azure DevOps Server 2022

管道修饰器允许向每个作业的开头和结尾添加步骤。 创作管道修饰器的过程不同于向单个定义添加步骤,因为它适用于组织中的所有管道。

假设你的组织需要在可以释放的所有生成输出上运行病毒扫描程序。 管道作者无需记住添加该步骤。 我们将创建一个自动注入步骤的修饰器。 管道修饰器会注入一个自定义任务,该任务会在每个管道作业结束时执行病毒扫描。

提示

查看有关使用 Azure DevOps 扩展 SDK 进行扩展开发的最新文档。

1. 向扩展添加贡献

以下示例假定你熟悉 贡献模型

  1. 创建扩展。 创建扩展后,你有一个 vss-extension.json 文件。
  2. 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"
        }
    ]
}

贡献选项

让我们看看属性及其用途:

properties 说明
id 贡献标识符。 此扩展中的贡献必须是唯一的。
type 指定此贡献是管道修饰器。 必须是字符串 ms.azure-pipelines.pipeline-decorator
targets 修饰器可以在作业/指定任务之前、之后或同时运行。 有关可用选项,请参阅下表。
properties.template (必需)该模板是扩展中包含的 YAML 文件,用于定义管道修饰器的步骤。 它是扩展文件夹根目录中的相对路径。
properties.targettask 用于 ms.azure-pipelines-agent-job.pre-task-tasksms.azure-pipelines-agent-job.post-task-tasks 目标的目标任务 ID。 必须是 GUID 字符串,如下所示 89b8ac58-8cb7-4479-a362-1baaacc6c7ad

目标

目标 说明
ms.azure-pipelines-agent-job.pre-job-tasks 在经典生成或 YAML 管道中的其他任务之前运行。 由于源代码检查输出方式存在差异,此目标在 YAML 管道中的检查out之后运行,但在经典生成管道中检查out之前运行。
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 管道中运行其他任务。

注意

YAML 管道中的部署作业 仅支持 ms.azure-pipelines-agent-job.pre-job-tasksms.azure-pipelines-agent-job.post-job-tasks 目标。 作业 支持所有 YAML 管道目标。

在此示例中,我们使用 ms.azure-pipelines-agent-job.post-job-tasks 是因为我们想要在所有生成作业结束时运行。

此扩展提供管道修饰器。 接下来,我们将创建一个模板 YAML 文件来定义修饰器的行为。

2.创建修饰器 YAML 文件

在扩展的属性中,我们选择了名称“my-decorator.yml”。 在贡献的根目录中创建该文件。 它保存每个作业后要运行的步骤集。 我们从一个基本示例开始,并完成完整的任务。

my-decorator.yml (初始版本)

steps:
- task: CmdLine@2
  displayName: 'Run my script (injected from decorator)'
  inputs:
    script: dir

注意

经典发布管道不支持具有服务连接使用情况的管道修饰器任务。

3.安装修饰器

若要向组织添加管道修饰器,必须 安装扩展只有专用扩展可以参与管道修饰器。 必须先创作扩展并将其与组织共享,然后才能使用它。

扩展与组织共享后, 搜索该扩展 并安装它。

保存该文件,然后 生成并安装扩展。 创建并运行基本管道。 修饰器在每个作业结束时自动注入脚本 dir 。 管道运行类似于以下示例。

Pipeline decorator running a simple script

注意

修饰器在组织中每个管道中的每个作业上运行。 在后面的步骤中,我们将添加逻辑来控制修饰器运行的时间和方式。

4. 注入条件

在我们的示例中,仅当生成输出可能发布到公共时,我们只需运行病毒扫描程序。 假设仅发布来自默认分支(通常)main的内部版本。 应将修饰器限制为针对默认分支运行的作业。

更新的文件如下所示:

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)'

5. 指定目标任务

可以指定目标 任务 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 。 然后,查看管道摘要页。

你会看到类似于下图的内容。

View pipeline decorator context

选择任务以查看日志,其中显示了运行时值以及上下文可用。