Crear un decorador de canalización

Azure DevOps Services | Azure DevOps Server 2022

Los decoradores de canalización permiten agregar pasos al principio y al final de cada trabajo. El proceso de creación de un decorador de canalización es diferente de agregar pasos a una sola definición porque se aplica a todas las canalizaciones de una organización.

Supongamos que su organización requiere ejecutar un analizador de virus en todas las salidas de compilación que se podrían liberar. No es necesario que los autores de canalizaciones recuerden agregar ese paso. Creamos un decorador que inserta automáticamente el paso. Nuestro decorador de canalización inserta una tarea personalizada que realiza el examen de virus al final de cada trabajo de canalización.

Sugerencia

Consulte nuestra documentación más reciente sobre el desarrollo de extensiones mediante el SDK de extensión de Azure DevOps.

1. Agregar contribuciones a una extensión

En el ejemplo siguiente se supone que está familiarizado con los modelos de contribución.

  1. Cree una extensión. Una vez creada la extensión, tiene un vss-extension.json archivo.
  2. Agregue contribuciones al archivo para nuestro vss-extension.json nuevo decorador de canalización.

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"
        }
    ]
}

Opciones de contribución

Echemos un vistazo a las propiedades y a lo que se usan para:

Propiedad Descripción
id Identificador de contribución. Debe ser único entre las contribuciones de esta extensión.
type Especifica que esta contribución es un decorador de canalización. Debe ser la cadena ms.azure-pipelines.pipeline-decorator.
targets Los decoradores se pueden ejecutar antes de que el trabajo o la tarea especificada, después o ambos. Consulte la tabla siguiente para ver las opciones disponibles.
properties.template (Obligatorio) La plantilla es un archivo YAML incluido en la extensión, que define los pasos para el decorador de canalización. Es una ruta de acceso relativa de la raíz de la carpeta de extensión.
properties.targettask Identificador de tarea de destino que se usa para ms.azure-pipelines-agent-job.pre-task-tasks los destinos o ms.azure-pipelines-agent-job.post-task-tasks . Debe ser una cadena GUID como 89b8ac58-8cb7-4479-a362-1baaacc6c7ad

Targets

Destino Descripción
ms.azure-pipelines-agent-job.pre-job-tasks Ejecute antes de otras tareas en una compilación clásica o una canalización YAML. Debido a las diferencias en la forma en que se produce la desprotección del código fuente, este destino se ejecuta después de la finalización de la compra en una canalización de YAML, pero antes de la desprotección en una canalización de compilación clásica.
ms.azure-pipelines-agent-job.post-checkout-tasks Ejecute después de la última checkout tarea en una canalización de YAML o compilación clásica.
ms.azure-pipelines-agent-job.post-job-tasks Ejecute después de otras tareas en una canalización de YAML o compilación clásica.
ms.azure-pipelines-agent-job.pre-task-tasks Ejecute antes de la tarea especificada en una canalización de compilación o YAML clásica.
ms.azure-pipelines-agent-job.post-task-tasks Ejecute después de la tarea especificada en una canalización de compilación o YAML clásica.
ms.azure-release-pipelines-agent-job.pre-task-tasks Ejecute antes de la tarea especificada en una canalización de RM clásica.
ms.azure-release-pipelines-agent-job.post-task-tasks Ejecute después de la tarea especificada en una canalización de RM clásica.
ms.azure-release-pipelines-agent-job.pre-job-tasks Ejecute antes de otras tareas en una canalización de RM clásica.
ms.azure-release-pipelines-agent-job.post-job-tasks Ejecute después de otras tareas en una canalización de RM clásica.

Nota:

Los trabajos de implementación en una canalización YAML solo admiten ms.azure-pipelines-agent-job.pre-job-tasks y ms.azure-pipelines-agent-job.post-job-tasks destinos. Los trabajos admiten todos los destinos de canalización de YAML.

En este ejemplo, se usa ms.azure-pipelines-agent-job.post-job-tasks porque queremos ejecutar al final de todos los trabajos de compilación.

Esta extensión contribuye a un decorador de canalización. A continuación, creamos un archivo YAML de plantilla para definir el comportamiento del decorador.

2. Crear un archivo YAML decorador

En las propiedades de la extensión, elegimos el nombre "my-decorator.yml". Cree ese archivo en la raíz de la contribución. Contiene el conjunto de pasos que se van a ejecutar después de cada trabajo. Empezamos con un ejemplo básico y trabajamos hasta la tarea completa.

my-decorator.yml (versión inicial)

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

Nota:

Las tareas de decorador de canalización con uso de conexión de servicio no se admiten para canalizaciones de versión clásicas.

3. Instalar el decorador

Para agregar un decorador de canalización a su organización, debe instalar una extensión. Solo las extensiones privadas pueden contribuir a decoradores de canalización. La extensión debe crearse y compartirse con su organización para poder usarla.

Una vez que la extensión se haya compartido con su organización, busque la extensión e instálela.

Guarde el archivo y, a continuación , compile e instale la extensión. Cree y ejecute una canalización básica. El decorador inserta automáticamente nuestro dir script al final de cada trabajo. Una ejecución de canalización es similar al ejemplo siguiente.

Pipeline decorator running a simple script

Nota:

El decorador se ejecuta en cada trabajo de cada canalización de la organización. En pasos posteriores, agregamos lógica para controlar cuándo y cómo se ejecuta el decorador.

4. Inyección de condiciones

En nuestro ejemplo, solo es necesario ejecutar el detector de virus si es posible que las salidas de compilación se publiquen al público. Supongamos que solo se publican compilaciones a partir de la rama predeterminada (normalmente main). Debemos limitar el decorador a los trabajos que se ejecutan en la rama predeterminada.

El archivo actualizado tiene este aspecto:

my-decorator.yml (versión revisada)


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

Puede empezar a ver la potencia de este punto de extensibilidad. Use el contexto del trabajo actual para insertar condicionalmente los pasos en tiempo de ejecución. Use expresiones YAML para tomar decisiones sobre los pasos que se deben insertar y cuándo. Consulte contexto de expresión del decorador de canalización para obtener una lista completa de los datos disponibles.

Hay otra condición que debemos tener en cuenta: ¿qué ocurre si el usuario ya ha incluido el paso de detección de virus? No deberíamos perder tiempo ejecutándolo de nuevo. En este ejemplo sencillo, se pretenderá que cualquier script tarea que se encuentre en el trabajo ejecute el detector de virus. (En una implementación real, tendría una tarea personalizada para comprobarlo en su lugar).

El identificador de la tarea de script es d9bafed4-0b18-4f58-968d-86655b4d2ce9. Si vemos otra tarea de script, no deberíamos insertar la nuestra.

my-decorator.yml (versión 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. Especificar una tarea de destino

Puede especificar el identificador de tarea de destino e insertar tareas antes o después de esta tarea de destino. Para especificar la tarea de destino, puede modificar el archivo de manifiesto vss-extension.json como en el ejemplo siguiente.

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

Al configurar la propiedad "targettask", puede especificar el identificador de una tarea de destino. Las tareas se insertarán antes o después de todas las instancias de la tarea de destino especificada.

Especificación de la inserción de entradas de la tarea de destino

Puede especificar una lista de entradas de la tarea de destino que desea insertar como entradas en la tarea insertada.

Esta característica está diseñada para trabajar con tareas de canalización personalizadas. No está pensado para proporcionar acceso a las entradas de la tarea de canalización de destino a través de variables de canalización.

Para obtener acceso a las entradas de la tarea de canalización de destino (entradas con el target_ prefijo), la tarea de canalización insertada debe usar métodos de azure-pipelines-tasks-task-lib y no de las variables de canalización, por ejemplo const inputString = tl.getInput('target_targetInput')).

Para ello, puede crear su propia tarea de canalización personalizada y usar las entradas de destino allí. Si necesita la funcionalidad de una de las tareas integradas, como CmdLine@2, puede crear una copia de la tarea CmdLine@2 y publicarla con la extensión de decorador.

Nota:

Esta funcionalidad solo está disponible para las tareas que se insertan antes o después de la tarea de destino.

Para especificar esta lista de entradas, puede modificar el archivo de manifiesto vss-extension.json como en el ejemplo siguiente.

vss-extension.json (versión de entradas de tareas insertadas)

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

Al configurar la propiedad "targettaskinputs", puede especificar la lista de entradas que se espera que se inserten. Estas entradas se insertarán en la tarea con el prefijo "target_" y estarán disponibles en la tarea insertada como target_target-task-input.

Nota:

Las entradas de tarea de destino que obtienen valores secretos con variables u obtenerlos de otras tareas no se insertarán.

Depurar

Es posible que tenga que depurar al crear el decorador. También es posible que desee ver qué datos tiene disponibles en el contexto.

Puede establecer la system.debugContext variable en true al poner en cola una canalización. A continuación, examine la página de resumen de la canalización.

Verá algo similar a la imagen siguiente.

View pipeline decorator context

Seleccione la tarea para ver los registros, que muestran los valores en tiempo de ejecución y que el contexto está disponible.