Referencia de uso de la plantilla

Azure DevOps Services | Azure DevOps Server 2022 | Azure DevOps Server 2019

Las plantillas permiten definir el contenido reutilizable, la lógica y los parámetros reutilizables en la canalización YAML. Para trabajar con plantillas de forma eficaz, debe tener conocimientos básicos de los conceptos clave de Azure Pipelines, como fases, pasos y trabajos.

Las plantillas pueden ayudarle a acelerar el desarrollo. Por ejemplo, puede tener una serie de las mismas tareas en una plantilla y, a continuación, incluir la plantilla varias veces en distintas fases de la canalización de YAML.

Las plantillas también pueden ayudarle a proteger la canalización. Cuando una plantilla controla lo que se permite en una canalización, la plantilla define la lógica que debe seguir otro archivo. Por ejemplo, puede restringir qué tareas se pueden ejecutar. En ese escenario, puede usar una plantilla para evitar que alguien ejecute correctamente una tarea que infrinja las directivas de seguridad de la organización.

Existen dos tipos de plantillas: incluye y extiende.

  • Incluye plantillas que permiten insertar contenido reutilizable con una plantilla. Si se usa una plantilla para incluir contenido, funciona como una directiva include en muchos lenguajes de programación. El contenido de un archivo se inserta en otro archivo.
  • Extiende el control de plantilla lo que se permite en una canalización. Cuando una plantilla extends controla lo que se permite en una canalización, la plantilla define la lógica que debe seguir otro archivo.

Para aprovechar al máximo las plantillas, también debe usar expresiones de plantilla y parámetros de plantilla.

Límites impuestos

Las plantillas y las expresiones de plantilla pueden provocar un crecimiento explosivo en el tamaño y la complejidad de una canalización. Para ayudar a evitar el crecimiento descontrolada, Azure Pipelines impone los siguientes límites:

  • No se pueden incluir más de 100 archivos YAML independientes (directa o indirectamente)
  • No más de 20 niveles de anidamiento de plantillas (plantillas incluidas otras plantillas)
  • No se consumen más de 10 megabytes de memoria al analizar el YAML (en la práctica, suele estar entre 600 KB y 2 MB de YAML en disco, según las características específicas usadas)

Use plantillas para definir la lógica una vez y, a continuación, reutilícela varias veces. Combinan el contenido de varios archivos YAML en una sola canalización. Se pueden pasar parámetros a una plantilla de la canalización principal.

Extensión desde una plantilla

Para aumentar la seguridad, puede aplicar que una canalización se extienda desde una plantilla determinada. El archivo start.yml define el parámetro buildSteps, que luego se usa en la canalización azure-pipelines.yml. En start.yml, si buildStep se pasa con un paso de script, se rechaza y se produce un error en la compilación de canalización. Al extender desde una plantilla, puede aumentar la seguridad agregando una aprobación de plantilla necesaria.

# File: start.yml
parameters:
- name: buildSteps # the name of the parameter is buildSteps
  type: stepList # data type is StepList
  default: [] # default value of buildSteps
stages:
- stage: secure_buildstage
  pool:
    vmImage: windows-latest
  jobs:
  - job: secure_buildjob
    steps:
    - script: echo This happens before code 
      displayName: 'Base: Pre-build'
    - script: echo Building
      displayName: 'Base: Build'

    - ${{ each step in parameters.buildSteps }}:
      - ${{ each pair in step }}:
          ${{ if ne(pair.value, 'CmdLine@2') }}:
            ${{ pair.key }}: ${{ pair.value }}       
          ${{ if eq(pair.value, 'CmdLine@2') }}: 
            # Step is rejected by raising a YAML syntax error: Unexpected value 'CmdLine@2'
            '${{ pair.value }}': error         

    - script: echo This happens after code
      displayName: 'Base: Signing'
# File: azure-pipelines.yml
trigger:
- main

extends:
  template: start.yml
  parameters:
    buildSteps:  
      - bash: echo Test #Passes
        displayName: succeed
      - bash: echo "Test"
        displayName: succeed
      # Step is rejected by raising a YAML syntax error: Unexpected value 'CmdLine@2'
      - task: CmdLine@2
        inputs:
          script: echo "Script Test"
      # Step is rejected by raising a YAML syntax error: Unexpected value 'CmdLine@2'
      - script: echo "Script Test"

Extensión desde una plantilla con recursos

También puede usar extends para ampliar desde una plantilla de la canalización de Azure que contenga recursos.

# File: azure-pipelines.yml
trigger:
- none

extends:
  template: resource-template.yml
# File: resource-template.yml
resources:
  pipelines:
  - pipeline: my-pipeline 
    source: sourcePipeline

steps:
- script: echo "Testing resource template"

Insertar una plantilla

Puede copiar contenido de un YAML y reutilizarlo en otro YAML. Copiar contenido de un YAML a otro le ahorra tener que incluir manualmente la misma lógica en varios lugares. La plantilla de archivo include-npm-steps.yml contiene pasos que se reutilizan en azure-pipelines.yml.

Nota:

Los archivos de plantilla deben existir en el sistema de archivos al principio de una ejecución de canalización. No se puede hacer referencia a plantillas en un artefacto.

# File: templates/include-npm-steps.yml

steps:
- script: npm install
- script: yarn install
- script: npm run compile
# File: azure-pipelines.yml

jobs:
- job: Linux
  pool:
    vmImage: 'ubuntu-latest'
  steps:
  - template: templates/include-npm-steps.yml  # Template reference
- job: Windows
  pool:
    vmImage: 'windows-latest'
  steps:
  - template: templates/include-npm-steps.yml  # Template reference

Reutilización de pasos

Puede insertar una plantilla para reutilizar uno o varios pasos en varios trabajos. Además de los pasos de la plantilla, cada trabajo puede definir más pasos.

# File: templates/npm-steps.yml
steps:
- script: npm install
- script: npm test
# File: azure-pipelines.yml

jobs:
- job: Linux
  pool:
    vmImage: 'ubuntu-latest'
  steps:
  - template: templates/npm-steps.yml  # Template reference

- job: macOS
  pool:
    vmImage: 'macOS-latest'
  steps:
  - template: templates/npm-steps.yml  # Template reference

- job: Windows
  pool:
    vmImage: 'windows-latest'
  steps:
  - script: echo This script runs before the template's steps, only on Windows.
  - template: templates/npm-steps.yml  # Template reference
  - script: echo This step runs after the template's steps.

Reutilización de trabajos

Al igual que los pasos, los trabajos se pueden reutilizar con plantillas.

# File: templates/jobs.yml
jobs:
- job: Ubuntu
  pool:
    vmImage: 'ubuntu-latest'
  steps:
  - bash: echo "Hello Ubuntu"

- job: Windows
  pool:
    vmImage: 'windows-latest'
  steps:
  - bash: echo "Hello Windows"
# File: azure-pipelines.yml

jobs:
- template: templates/jobs.yml  # Template reference

Al trabajar con varios trabajos, recuerde quitar el nombre del trabajo en el archivo de plantilla para evitar conflictos

# File: templates/jobs.yml
jobs:
- job: 
  pool:
    vmImage: 'ubuntu-latest'
  steps:
  - bash: echo "Hello Ubuntu"

- job:
  pool:
    vmImage: 'windows-latest'
  steps:
  - bash: echo "Hello Windows"
# File: azure-pipelines.yml

jobs:
- template: templates/jobs.yml  # Template reference
- template: templates/jobs.yml  # Template reference
- template: templates/jobs.yml  # Template reference

Reutilización de fases

Las fases también se pueden reutilizar con plantillas.

# File: templates/stages1.yml
stages:
- stage: Angular
  jobs:
  - job: angularinstall
    steps:
    - script: npm install angular
# File: templates/stages2.yml
stages:
- stage: Build
  jobs:
  - job: build
    steps:
    - script: npm run build
# File: azure-pipelines.yml
trigger:
- main

pool:
  vmImage: 'ubuntu-latest'

stages:
- stage: Install
  jobs: 
  - job: npminstall
    steps:
    - task: Npm@1
      inputs:
        command: 'install'
- template: templates/stages1.yml # Template reference
- template: templates/stages2.yml # Template reference

Plantillas de trabajo, fases y pasos con parámetros

En las plantillas siguientes:

  • templates/npm-with-params.yml define dos parámetros: name y vmImage crea un trabajo con el parámetro name para el nombre del trabajo y el parámetro vmImage para la imagen de máquina virtual.
  • La canalización (azure-pipelines.yml) hace referencia a la plantilla tres veces, cada una con valores de parámetros diferentes que hacen referencia a los nombres de imagen de máquina virtual y del sistema operativo.
  • La canalización compilada se ejecuta en una imagen de máquina virtual diferente y se denomina según el sistema operativo especificado. Cada trabajo realiza los pasos de prueba de npm install y npm.
# File: templates/npm-with-params.yml

parameters:
- name: name  # defaults for any parameters that aren't specified
  default: ''
- name: vmImage
  default: ''

jobs:
- job: ${{ parameters.name }}
  pool: 
    vmImage: ${{ parameters.vmImage }}
  steps:
  - script: npm install
  - script: npm test

Al consumir la plantilla en la canalización, especifique valores para los parámetros de plantilla.

# File: azure-pipelines.yml

jobs:
- template: templates/npm-with-params.yml  # Template reference
  parameters:
    name: Linux
    vmImage: 'ubuntu-latest'

- template: templates/npm-with-params.yml  # Template reference
  parameters:
    name: macOS
    vmImage: 'macOS-latest'

- template: templates/npm-with-params.yml  # Template reference
  parameters:
    name: Windows
    vmImage: 'windows-latest'

Plantillas de fase con varios parámetros

En las plantillas siguientes:

  • La plantilla stage-template.yml define cuatro parámetros: stageName, jobName, vmImage y scriptPath, todos de tipo cadena. La plantilla crea una fase mediante el parámetro stageName para establecer el nombre de la fase, define un trabajo con jobName e incluye un paso para ejecutar un script.
  • A continuación, la canalización azure-pipeline.yml define dinámicamente fases y trabajos mediante parámetros y ejecuta un trabajo que ejecuta un script, build-script.sh.
# stage-template.yml

parameters:
  - name: stageName
    type: string
  - name: jobName
    type: string
  - name: vmImage
    type: string
  - name: scriptPath
    type: string

stages:
  - stage: ${{ parameters.stageName }}
    jobs:
      - job: ${{ parameters.jobName }}
        pool:
          vmImage: ${{ parameters.vmImage }}
        steps:
          - script: ./${{ parameters.scriptPath }}
# azure-pipelines.yml
trigger:
- main

stages:
- template: stage-template.yml
  parameters:
    stageName: 'BuildStage'
    jobName: 'BuildJob'
    scriptPath: 'build-script.sh' # replace with script in your repository
    vmImage: 'ubuntu-latest'

Plantillas con pasos y parámetros

También puede usar parámetros con plantillas de paso o fase.

En las plantillas siguientes:

  • La plantilla (templates/steps-with-params.yml) define un parámetro denominado runExtendedTests con un valor predeterminado de false.
  • La canalización (azure-pipelines.yml) ejecuta npm test y npm test --extended porque el parámetro runExtendedTests es true.
# File: templates/steps-with-params.yml

parameters:
- name: 'runExtendedTests'  # defaults for any parameters that aren't specified
  type: boolean
  default: false

steps:
- script: npm test
- ${{ if eq(parameters.runExtendedTests, true) }}:
  - script: npm test --extended

Al consumir la plantilla en la canalización, especifique valores para los parámetros de plantilla.

# File: azure-pipelines.yml

steps:
- script: npm install

- template: templates/steps-with-params.yml  # Template reference
  parameters:
    runExtendedTests: 'true'

Nota:

Los parámetros escalares sin un tipo especificado se tratan como cadenas. Por ejemplo, eq(true, parameters['myparam']) devolverá true, incluso si el parámetro myparam es la palabra false, si myparam no se hace explícitamente boolean. Las cadenas no vacías se convierten en true en un contexto booleano. Esa expresión se podría reescribir para comparar explícitamente cadenas: eq(parameters['myparam'], 'true').

Los parámetros no se limitan a las cadenas escalares. Consulte la lista de tipos de datos. Por ejemplo, con el tipo object:

# azure-pipelines.yml
jobs:
- template: process.yml
  parameters:
    pool:   # this parameter is called `pool`
      vmImage: ubuntu-latest  # and it's a mapping rather than a string


# process.yml
parameters:
- name: 'pool'
  type: object
  default: {}

jobs:
- job: build
  pool: ${{ parameters.pool }}

Reutilización de variables

Las variables se pueden definir en un YAML e incluirse en otra plantilla. Esto podría ser útil si desea almacenar todas las variables en un archivo. Si usa una plantilla para incluir variables en una canalización, la plantilla incluida solo se puede usar para definir variables. Puede usar pasos y lógica más compleja al extender desde una plantilla. Use parámetros en lugar de variables cuando desee restringir el tipo.

En este ejemplo, la variable favoriteVeggie se incluye en azure-pipelines.yml.

# File: vars.yml
variables:
  favoriteVeggie: 'brussels sprouts'
# File: azure-pipelines.yml

variables:
- template: vars.yml  # Template reference

steps:
- script: echo My favorite vegetable is ${{ variables.favoriteVeggie }}.

Plantillas de variables con parámetro

Puede pasar parámetros a variables con plantillas. En este ejemplo, va a pasar el parámetro DIRECTORY a una variable RELEASE_COMMAND.

# File: templates/package-release-with-params.yml

parameters:
- name: DIRECTORY 
  type: string
  default: "." # defaults for any parameters that specified with "." (current directory)

variables:
- name: RELEASE_COMMAND
  value: grep version ${{ parameters.DIRECTORY }}/package.json | awk -F \" '{print $4}'  

Al consumir la plantilla en la canalización, especifique valores para los parámetros de plantilla.

# File: azure-pipelines.yml

variables: # Global variables
  - template: package-release-with-params.yml # Template reference
    parameters:
      DIRECTORY: "azure/checker"

pool:
  vmImage: 'ubuntu-latest'

stages:
- stage: Release_Stage 
  displayName: Release Version
  variables: # Stage variables
  - template: package-release-with-params.yml  # Template reference
    parameters:
      DIRECTORY: "azure/todo-list"
  jobs: 
  - job: A
    steps: 
    - bash: $(RELEASE_COMMAND) #output release command

Ampliar a partir de una plantilla y usar una plantilla de inclusión con variables

Lo normal es tener una canalización con fases de desarrollo, pruebas y producción que usen una plantilla para variables y una plantilla de ampliación para fases o trabajos.

En el ejemplo siguiente, variables-template.yml define un grupo de variables de máquina virtual que se usan en azure-pipeline.yml.

# variables-template.yml

variables:
- name: devVmImage
  value: 'ubuntu-latest'
- name: testVmImage
  value: 'ubuntu-latest'
- name: prodVmImage
  value: 'ubuntu-latest'

El siguiente archivo, stage-template.yml, define una configuración de fase reutilizable con tres parámetros (name, vmImage, steps) y una tarea denominada Build.

# stage-template.yml
parameters:
- name: name
  type: string
  default: ''
- name: vmImage
  type: string
  default: ''
- name: steps
  type: stepList
  default: []

stages:
- stage: ${{ parameters.name }}
  jobs:
  - job: Build
    pool:
      vmImage: ${{ parameters.vmImage }}
    steps: ${{ parameters.steps }}

La siguiente canalización, azure-pipelines.yml, importa variables de variables-template.yml y luego usa la plantilla stage-template.yml para cada fase. Cada fase (Desarrollo, Prueba, Producción) se define con la misma plantilla, pero con parámetros diferentes, lo que hace que haya uniformidad entre fases, a la vez que permite la personalización. La fase de producción incluye una variable de entorno como ejemplo de algo que podría usar para la autenticación.

# azure-pipelines.yml
trigger:
- main

variables:
- template: variables-template.yml

stages:
- template: stage-template.yml
  parameters:
    name: Dev
    vmImage: ${{ variables.devVmImage }}
    steps:
      - script: echo "Building in Dev"
- template: stage-template.yml
  parameters:
    name: Test
    vmImage: ${{ variables.testVmImage }}
    steps:
      - script: echo "Testing in Test"
- template: stage-template.yml
  parameters:
    name: Prod
    vmImage: ${{ variables.prodVmImage }}
    steps:
      - script: echo "Deploying to Prod"
        env:
          SYSTEM_ACCESSTOKEN: $(System.AccessToken)

Trazado de plantilla de referencia

Las rutas de acceso de plantilla pueden ser una ruta de acceso absoluta dentro del repositorio o en relación con el archivo que realiza la inclusión.

Para usar una ruta de acceso absoluta, la ruta de acceso de plantilla debe comenzar con /. Todas las demás rutas de acceso se consideran relativas.

Este es un ejemplo de jerarquía anidada.

|
+-- fileA.yml
|
+-- dir1/
     |
     +-- fileB.yml
     |
     +-- dir2/
          |
          +-- fileC.yml

A continuación, en fileA.yml puede hacer referencia a fileB.yml y fileC.yml así.

steps:
- template: dir1/fileB.yml
- template: dir1/dir2/fileC.yml

Si fileC.yml es el punto de partida, puede incluir fileA.yml y fileB.yml así.

steps:
- template: ../../fileA.yml
- template: ../fileB.yml

Cuando fileB.yml es el punto de partida, puede incluir fileA.yml y fileC.yml así.

steps:
- template: ../fileA.yml
- template: dir2/fileC.yml

Como alternativa, fileB.yml podría hacer referencia a fileA.yml y fileC.yml usar rutas de acceso absolutas como esta.

steps:
- template: /fileA.yml
- template: /dir1/dir2/fileC.yml

Uso de otros repositorios

Puede mantener las plantillas en otros repositorios. Por ejemplo, supongamos que tiene una canalización principal que quiere que usen todas las canalizaciones de la aplicación. Puede colocar la plantilla en un repositorio principal y, a continuación, hacer referencia a ella desde cada uno de los repositorios de aplicaciones:

# Repo: Contoso/BuildTemplates
# File: common.yml
parameters:
- name: 'vmImage'
  default: 'ubuntu-22.04'
  type: string

jobs:
- job: Build
  pool:
    vmImage: ${{ parameters.vmImage }}
  steps:
  - script: npm install
  - script: npm test

Ahora puede reutilizar esta plantilla en varias canalizaciones. Use la especificación resources para proporcionar la ubicación del repositorio principal. Al hacer referencia al repositorio principal, use @ y el nombre que le proporcionó en resources.

# Repo: Contoso/LinuxProduct
# File: azure-pipelines.yml
resources:
  repositories:
    - repository: templates
      type: github
      name: Contoso/BuildTemplates

jobs:
- template: common.yml@templates  # Template reference
# Repo: Contoso/WindowsProduct
# File: azure-pipelines.yml
resources:
  repositories:
    - repository: templates
      type: github
      name: Contoso/BuildTemplates
      ref: refs/tags/v1.0 # optional ref to pin to

jobs:
- template: common.yml@templates  # Template reference
  parameters:
    vmImage: 'windows-latest'

Para type: github, name es <identity>/<repo> como en los ejemplos anteriores. Para type: git (Azure Repos), name es <project>/<repo>. Si ese proyecto está en una organización de Azure DevOps independiente, deberá configurar una conexión de servicio de tipo Azure Repos/Team Foundation Server con acceso al proyecto e incluirlo en YAML:

resources:
  repositories:
  - repository: templates
    name: Contoso/BuildTemplates
    endpoint: myServiceConnection # Azure DevOps service connection
jobs:
- template: common.yml@templates

Los repositorios solo se resuelven una vez cuando se inicia la canalización. Después, se usa el mismo recurso durante la canalización. Solo se usan los archivos de plantilla. Una vez que las plantillas se expandan por completo, la canalización final se ejecuta como si estuviera definida completamente en el repositorio de origen. Esto significa que no puede usar scripts del repositorio de plantillas de la canalización.

Si desea usar una versión determinada y fija de la plantilla, asegúrese de anclar a ref. Las refs son ramas (refs/heads/<name>) o etiquetas (refs/tags/<name>). Si desea anclar una confirmación específica, cree primero una etiqueta que apunte a esa confirmación y, a continuación, ancle a esa etiqueta.

Nota:

Si no se especifica ref, la canalización usará de forma predeterminada refs/heads/main.

También puede anclar a una confirmación específica en Git con el valor SHA de un recurso de repositorio. El valor SHA es una suma de comprobación hash de 40 caracteres que identifica de forma única la confirmación.

resources:
  repositories:
    - repository: templates
      type: git
      name: Contoso/BuildTemplates
      ref: 1234567890abcdef1234567890abcdef12345678

También puede usar @self para hacer referencia al repositorio donde se encontró la canalización original. Esto es cómodo para su uso en plantillas extends si desea volver a hacer referencia al contenido en el repositorio de la canalización de extensión. Por ejemplo:

# Repo: Contoso/Central
# File: template.yml
jobs:
- job: PreBuild
  steps: []

  # Template reference to the repo where this template was
  # included from - consumers of the template are expected
  # to provide a "BuildJobs.yml"
- template: BuildJobs.yml@self

- job: PostBuild
  steps: []
# Repo: Contoso/MyProduct
# File: azure-pipelines.yml
resources:
  repositories:
    - repository: templates
      type: git
      name: Contoso/Central

extends:
  template: template.yml@templates
# Repo: Contoso/MyProduct
# File: BuildJobs.yml
jobs:
- job: Build
  steps: []

Preguntas más frecuentes

¿Cómo puedo usar variables dentro de plantillas?

Hay ocasiones en las que puede ser útil establecer parámetros en valores basados en variables. Los parámetros se expanden al principio del procesamiento de una ejecución de canalización, por lo que no todas las variables estarán disponibles. Para ver qué variables predefinidas están disponibles en las plantillas, consulte Uso de variables predefinidas.

En este ejemplo, las variables predefinidas Build.SourceBranch y Build.Reason se usan en condiciones en template.yml.

# File: azure-pipelines.yml
trigger:
- main

extends:
  template: template.yml
# File: template.yml
steps:
- script: echo Build.SourceBranch = $(Build.SourceBranch) # outputs refs/heads/main
- script: echo Build.Reason = $(Build.Reason) # outputs IndividualCI
- ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/main') }}: 
  - script: echo I run only if Build.SourceBranch = refs/heads/main 
- ${{ if eq(variables['Build.Reason'], 'IndividualCI') }}: 
  - script: echo I run only if Build.Reason = IndividualCI 
- script: echo I run after the conditions