Criar um decorador de pipeline

Azure DevOps Services | Azure DevOps Server 2022

Os decoradores de pipeline permitem que você adicione etapas ao início e ao fim de cada trabalho. O processo de criação de um decorador de pipeline é diferente de adicionar etapas a uma única definição, pois se aplica a todos os pipelines em uma organização.

Suponha que sua organização exija a execução de um scanner de vírus em todas as saídas de compilação que podem ser liberadas. Os autores do pipeline não precisam se lembrar de adicionar essa etapa. Criamos um decorador que injeta automaticamente o passo. Nosso decorador de pipeline injeta uma tarefa personalizada que faz a varredura de vírus no final de cada trabalho de pipeline.

Dica

Confira nossa documentação mais recente sobre o desenvolvimento de extensão usando o SDK da Extensão do Azure DevOps.

1. Adicionar contribuições a uma extensão

O exemplo a seguir pressupõe que você esteja familiarizado com os modelos de contribuição.

  1. Crie uma extensão. Depois que sua extensão for criada, você terá um vss-extension.json arquivo.
  2. Adicione contribuições ao arquivo para o vss-extension.json nosso novo decorador de pipeline.

vss-extensão.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"
        }
    ]
}

Opções de contribuição

Vamos dar uma olhada nas propriedades e para que elas são usadas:

Propriedade Descrição
id Identificador de contribuição. Deve ser único entre as contribuições nesta extensão.
type Especifica que essa contribuição é um decorador de pipeline. Deve ser a cadeia de caracteres ms.azure-pipelines.pipeline-decorator.
targets Os decoradores podem executar antes do seu trabalho/tarefa especificada, depois ou ambos. Consulte a tabela a seguir para obter as opções disponíveis.
properties.template (Obrigatório) O modelo é um arquivo YAML incluído em sua extensão, que define as etapas para o decorador de pipeline. É um caminho relativo da raiz da pasta de extensão.
properties.targettask A ID da tarefa de destino usada para ms.azure-pipelines-agent-job.pre-task-tasks ou ms.azure-pipelines-agent-job.post-task-tasks destinos. Deve ser uma cadeia de caracteres GUID como 89b8ac58-8cb7-4479-a362-1baaacc6c7ad

Destinos

Destino Descrição
ms.azure-pipelines-agent-job.pre-job-tasks Execute antes de outras tarefas em uma compilação clássica ou pipeline YAML. Devido a diferenças em como o check-out do código-fonte acontece, esse destino é executado após o check-out em um pipeline YAML, mas antes do check-out em um pipeline de compilação clássico.
ms.azure-pipelines-agent-job.post-checkout-tasks Execute após a última checkout tarefa em uma compilação clássica ou pipeline YAML.
ms.azure-pipelines-agent-job.post-job-tasks Execute após outras tarefas em uma compilação clássica ou pipeline YAML.
ms.azure-pipelines-agent-job.pre-task-tasks Execute antes da tarefa especificada em uma compilação clássica ou pipeline YAML.
ms.azure-pipelines-agent-job.post-task-tasks Executar após a tarefa especificada em uma compilação clássica ou pipeline YAML.
ms.azure-release-pipelines-agent-job.pre-task-tasks Executar antes da tarefa especificada em um pipeline RM clássico.
ms.azure-release-pipelines-agent-job.post-task-tasks Executar após a tarefa especificada em um pipeline RM clássico.
ms.azure-release-pipelines-agent-job.pre-job-tasks Executar antes de outras tarefas em um pipeline RM clássico.
ms.azure-release-pipelines-agent-job.post-job-tasks Executar após outras tarefas em um pipeline RM clássico.

Observação

Os trabalhos de implantação em um pipeline YAML oferecem suporte ms.azure-pipelines-agent-job.pre-job-tasks e ms.azure-pipelines-agent-job.post-job-tasks destinos apenas. Os trabalhos oferecem suporte a todos os destinos de pipeline YAML.

Neste exemplo, usamos ms.azure-pipelines-agent-job.post-job-tasks porque queremos executar no final de todos os trabalhos de compilação.

Esta extensão contribui com um decorador de tubulação. Em seguida, criamos um arquivo YAML modelo para definir o comportamento do decorador.

2. Crie um arquivo YAML decorador

Nas propriedades da extensão, escolhemos o nome "my-decorator.yml". Crie esse arquivo na raiz da sua contribuição. Ele contém o conjunto de etapas a serem executadas após cada trabalho. Começamos com um exemplo básico e trabalhamos até a tarefa completa.

my-decorator.yml (versão inicial)

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

Observação

As tarefas do decorador de pipeline com uso de conexão de serviço não são suportadas para pipelines de versão clássicos.

3. Instale o decorador

Para adicionar um decorador de pipeline à sua organização, você deve instalar uma extensão. Apenas extensões privadas podem contribuir com decoradores de tubulação. A extensão deve ser criada e compartilhada com sua organização antes de poder ser usada.

Depois que a extensão tiver sido compartilhada com sua organização, procure a extensão e instale-a.

Salve o arquivo, compile e instale a extensão. Crie e execute um pipeline básico. O decorador injeta automaticamente nosso dir roteiro no final de cada trabalho. Uma execução de pipeline é semelhante ao exemplo a seguir.

Pipeline decorator running a simple script

Observação

O decorador executa todos os trabalhos em todos os pipelines da organização. Em etapas posteriores, adicionamos lógica para controlar quando e como o decorador funciona.

4. Condições de injeção

Em nosso exemplo, só precisamos executar o scanner de vírus se as saídas de compilação puderem ser liberadas para o público. Digamos que apenas compilações da ramificação padrão (normalmente main) sejam lançadas. Devemos limitar o decorador a trabalhos executados na ramificação padrão.

O arquivo atualizado tem a seguinte aparência:

my-decorator.yml (versão revisada)


steps:
- ${{ if eq(resources.repositories['self'].ref, resources.repositories['self'].defaultBranch) }}:
  - script: dir
    displayName: 'Run my script (injected from decorator)'

Você pode começar a ver o poder desse ponto de extensibilidade. Use o contexto do trabalho atual para injetar condicionalmente etapas em tempo de execução. Use expressões YAML para tomar decisões sobre quais etapas injetar e quando. Consulte o contexto de expressão do decorador de pipeline para obter uma lista completa de dados disponíveis.

Há outra condição que precisamos considerar: e se o usuário já tiver incluído a etapa de verificação de vírus? Não devemos perder tempo a executá-lo novamente. Neste exemplo simples, vamos fingir que qualquer script tarefa encontrada no trabalho está executando o scanner de vírus. (Em uma implementação real, você teria uma tarefa personalizada para verificar isso.)

A ID da tarefa de script é d9bafed4-0b18-4f58-968d-86655b4d2ce9. Se virmos outra tarefa de script, não devemos injetar a nossa.

my-decorator.yml (versão final)


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. Especifique uma tarefa de destino

Você pode especificar a ID da tarefa de destino e injetar tarefas antes ou depois dessa tarefa de destino. Para especificar a tarefa de destino, você pode modificar o arquivo de manifesto vss-extension.json como no exemplo a seguir.

vss-extensão.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"
            }
        }
    ],
    ...
}

Ao configurar a propriedade 'targettask', você pode especificar a ID de uma tarefa de destino. As tarefas serão injetadas antes/depois de todas as instâncias da tarefa de destino especificada.

Especificar a injeção de entradas da tarefa de destino

Você pode especificar uma lista de entradas da tarefa de destino que deseja injetar como entradas para a tarefa injetada.

Esse recurso foi projetado para funcionar com tarefas de pipeline personalizadas. Ele não se destina a fornecer acesso a entradas de tarefas de pipeline de destino por meio de variáveis de pipeline.

Para obter acesso às entradas da tarefa de pipeline de destino (entradas com o prefixotarget_), a tarefa de pipeline injetada deve usar métodos do azure-pipelines-tasks-task-lib, e não as variáveis de pipeline, por exemploconst inputString = tl.getInput('target_targetInput')).

Para fazer isso, você pode criar sua própria tarefa de pipeline personalizada e usar as entradas de destino lá. Se você precisar da funcionalidade de uma das tarefas prontas para uso, como CmdLine@2, você pode criar uma cópia da tarefa CmdLine@2 e publicá-la com sua extensão de decorador.

Observação

Essa funcionalidade só está disponível para tarefas que são injetadas antes ou depois da tarefa de destino.

Para especificar essa lista de entradas, você pode modificar o arquivo de manifesto vss-extension.json como no exemplo a seguir.

vss-extension.json (versão de entradas de tarefa injetada)

{
    "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"]
            }
        }
    ],
    ...
}

Ao configurar a propriedade 'targettaskinputs', você pode especificar a lista de entradas que devem ser injetadas. Essas entradas serão injetadas na tarefa com o prefixo ""target_ e estarão disponíveis na tarefa injetada como target_target-task-input.

Observação

As entradas de tarefas de destino que obtêm valores secretos com variáveis ou os obtêm de outras tarefas não serão injetadas.

Depurar

Talvez seja necessário depurar ao criar seu decorador. Você também pode querer ver quais dados você tem disponíveis no contexto.

Você pode definir a system.debugContext variável para true quando você enfileirar um pipeline. Em seguida, examine a página de resumo do pipeline.

Você vê algo semelhante à imagem a seguir.

View pipeline decorator context

Selecione a tarefa para ver os logs, que mostram valores de tempo de execução e que o contexto está disponível.