Uso de tipos de modelo &

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

Os modelos permitem definir o conteúdo reutilizável, a lógica e os parâmetros. Os modelos funcionam de duas maneiras. É possível inserir conteúdo reutilizável com um modelo ou usar um modelo para controlar o que é permitido em um pipeline. A segunda abordagem é útil para criar pipelines seguros com modelos.

Se um modelo for usado para incluir conteúdo, ele funcionará como uma diretiva include em muitas linguagens de programação. O conteúdo de um arquivo é inserido em outro arquivo. Quando um modelo controla o que é permitido em um pipeline, o modelo define a lógica que outro arquivo deve seguir.

Use modelos para definir sua lógica uma vez e reutilizá-la várias vezes. Os modelos combinam o conteúdo de vários arquivos YAML em um único pipeline. Você pode passar parâmetros para um modelo do pipeline pai.

Parâmetros

Você pode especificar parâmetros e seus tipos de dados em um modelo e referenciar esses parâmetros em um pipeline. Com templateContext, você também pode passar propriedades para estágios, etapas e trabalhos que são usados como parâmetros em um modelo.

Você também pode usar parâmetros fora dos modelos. Você só pode usar literais para valores padrão de parâmetro.

Passando parâmetros

Os parâmetros devem conter um nome e um tipo de dados. Em azure-pipelines.yml, quando o parâmetro yesNo é definido como um valor booliano, o build é bem-sucedido. Quando yesNo é definido como uma cadeia de caracteres como apples, o build falha.

# File: simple-param.yml
parameters:
- name: yesNo # name of the parameter; required
  type: boolean # data type of the parameter; required
  default: false

steps:
- script: echo ${{ parameters.yesNo }}
# File: azure-pipelines.yml
trigger:
- main

extends:
  template: simple-param.yml
  parameters:
      yesNo: false # set to a non-boolean value to have the build fail

Parâmetros para selecionar um modelo em runtime

Você pode chamar modelos diferentes de um YAML de pipeline dependendo de uma condição. Neste exemplo, o experimental.yml YAML será executado quando o parâmetro experimentalTemplate for true.

#azure-pipeline.yml
parameters:
- name: experimentalTemplate
  displayName: 'Use experimental build process?'
  type: boolean
  default: false

steps:
- ${{ if eq(parameters.experimentalTemplate, true) }}:
  - template: experimental.yml
- ${{ if not(eq(parameters.experimentalTemplate, true)) }}:
  - template: stable.yml

Tipos de dados de parâmetro

Tipo de dados Observações
string string
number pode ser restrito a values:, caso contrário, qualquer cadeia de caracteres semelhante a número é aceita
boolean true ou false
object qualquer estrutura YAML
step uma única etapa
stepList sequência de etapas
job um único trabalho
jobList sequência de trabalhos
deployment um único trabalho de implantação
deploymentList sequência de trabalhos de implantação
stage um único estágio
stageList sequência de estágios

Os tipos de dados step, stepList, job, jobList, deployment, deploymentList, stage e stageList usam o formato de esquema YAML padrão. Este exemplo inclui cadeia de caracteres, número, booliano, objeto, etapa e stepList.

parameters:
- name: myString
  type: string
  default: a string
- name: myMultiString
  type: string
  default: default
  values:
  - default
  - ubuntu
- name: myNumber
  type: number
  default: 2
  values:
  - 1
  - 2
  - 4
  - 8
  - 16
- name: myBoolean
  type: boolean
  default: true
- name: myObject
  type: object
  default:
    foo: FOO
    bar: BAR
    things:
    - one
    - two
    - three
    nested:
      one: apple
      two: pear
      count: 3
- name: myStep
  type: step
  default:
    script: echo my step
- name: mySteplist
  type: stepList
  default:
    - script: echo step one
    - script: echo step two

trigger: none

jobs: 
- job: stepList
  steps: ${{ parameters.mySteplist }}
- job: myStep
  steps:
    - ${{ parameters.myStep }}

Você pode iterar por meio de um objeto e imprimir cada cadeia de caracteres no objeto .

parameters:
- name: listOfStrings
  type: object
  default:
  - one
  - two

steps:
- ${{ each value in parameters.listOfStrings }}:
  - script: echo ${{ value }}

Além disso, você pode iterar por meio de elementos aninhados em um objeto .

parameters:
- name: listOfFruits
  type: object
  default:
  - fruitName: 'apple'
    colors: ['red','green']
  - fruitName: 'lemon'
    colors: ['yellow']

steps:
- ${{ each fruit in parameters.listOfFruits }} :
  - ${{ each fruitColor in fruit.colors}} :
    - script: echo ${{ fruit.fruitName}} ${{ fruitColor }}

Estender de um modelo

Para aumentar a segurança, você pode impor que um pipeline se estenda de um modelo específico. O arquivo start.yml define o parâmetro buildSteps, que é usado no pipeline azure-pipelines.yml. No start.yml, se um buildStep for passado com uma etapa de script, ele será rejeitado e o build do pipeline falhará. Ao estender de um modelo, você pode aumentar a segurança adicionando uma aprovação de modelo necessária.

# 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"

Estender de um modelo com recursos

Você também pode usar extends para estender de um modelo em seu pipeline do Azure que contém 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"

Usar templateContext para passar propriedades para modelos

Você pode usar templateContext para passar propriedades adicionais para estágios, etapas e trabalhos que são usados como parâmetros em um modelo. Especificamente, você pode especificar templateContext dentro do tipo de dados de jobListparâmetro , deploymentListou stageList .

Você pode usar templateContext para facilitar a configuração de ambientes ao processar cada trabalho. Ao agrupar um trabalho e seu objeto de propriedades de ambiente, templateContext você pode ajudar você a ter um YAML mais mantenedível e mais fácil de entender.

Neste exemplo, o parâmetro testSet em testing-template.yml tem o tipo jobListde dados . O modelo testing-template.yml cria uma nova variável testJob usando cada palavra-chave. Em seguida, o modelo faz referência ao testJob.templateContext.expectedHTTPResponseCode, que é definido em azure-pipeline.yml e passado para o modelo.

Quando o código de resposta é 200, o modelo faz uma solicitação REST. Quando o código de resposta é 500, o modelo gera todas as variáveis de ambiente para depuração.

templateContext pode conter propriedades.

#testing-template.yml

parameters: 
- name: testSet
  type: jobList

jobs:
- ${{ each testJob in parameters.testSet }}:
  - ${{ if eq(testJob.templateContext.expectedHTTPResponseCode, 200) }}:
    - job:
      steps: 
      - powershell: 'Invoke-RestMethod -Uri https://blogs.msdn.microsoft.com/powershell/feed/ | Format-Table -Property Title, pubDate'
      - ${{ testJob.steps }}    
  - ${{ if eq(testJob.templateContext.expectedHTTPResponseCode, 500) }}:
    - job:
      steps:
      - powershell: 'Get-ChildItem -Path Env:\'
      - ${{ testJob.steps }}
#azure-pipeline.yml

trigger: none

pool:
  vmImage: ubuntu-latest

extends:
  template: testing-template.yml
  parameters:
    testSet:
    - job: positive_test
      templateContext:
        expectedHTTPResponseCode: 200
      steps:
      - script: echo "Run positive test" 
    - job: negative_test
      templateContext:
        expectedHTTPResponseCode: 500
      steps:
      - script: echo "Run negative test" 

Inserir um modelo

Você pode copiar o conteúdo de um YAML e reutilizá-lo em um YAML diferente. Copiar conteúdo de um YAML para outro evita que você precise incluir manualmente a mesma lógica em vários lugares. O include-npm-steps.yml modelo de arquivo contém etapas reutilizados em azure-pipelines.yml.

Observação

Os arquivos de modelo precisam existir no sistema de arquivos no início de uma execução de pipeline. Você não pode referenciar modelos em um artefato.

# 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

Reutilização da etapa

Você pode inserir um modelo para reutilizar uma ou mais etapas em vários trabalhos. Além das etapas do modelo, cada trabalho pode definir mais etapas.

# 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.

Reutilização do trabalho

Assim como as etapas, os trabalhos podem ser reutilizados com modelos.

# 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

Ao trabalhar com vários trabalhos, lembre-se de remover o nome do trabalho no arquivo de modelo, para evitar conflitos

# 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

Reutilização de estágio

Estágios também podem ser reutilizados com modelos.

# 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: templates/stages2.yml

Modelos de trabalho, estágio e etapa com parâmetros

# 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

Ao consumir o modelo em seu pipeline, especifique valores para os parâmetros de modelo.

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

Você também pode usar parâmetros com modelos de etapa ou estágio. Por exemplo, etapas com parâmetros:

# 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

Ao consumir o modelo em seu pipeline, especifique valores para os parâmetros de modelo.

# File: azure-pipelines.yml

steps:
- script: npm install

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

Observação

Parâmetros escalares sem um tipo especificado são tratados como cadeias de caracteres. Por exemplo, eq(true, parameters['myparam']) retornará true, mesmo que o myparam parâmetro seja a palavra false, se myparam não for explicitamente feito boolean. Cadeias de caracteres não vazias são convertidas true em em um contexto booliano. Essa expressão pode ser reescrita para comparar explicitamente cadeias de caracteres: eq(parameters['myparam'], 'true').

Os parâmetros não estão limitados a cadeias de caracteres escalares. Consulte a lista de tipos de dados. Por exemplo, usando o object tipo :

# 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 }}

Reutilização de variável

As variáveis podem ser definidas em um YAML e incluídas em outro modelo. Isso pode ser útil se você quiser armazenar todas as variáveis em um arquivo. Se você estiver usando um modelo para incluir variáveis em um pipeline, o modelo incluído só poderá ser usado para definir variáveis. Você pode usar etapas e lógica mais complexa ao estender de um modelo. Use parâmetros em vez de variáveis quando quiser restringir o tipo.

Neste exemplo, a variável favoriteVeggie está incluída em 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 }}.

Modelos de variáveis com parâmetro

Você pode passar parâmetros para variáveis com modelos. Neste exemplo, você está passando o DIRECTORY parâmetro para uma RELEASE_COMMAND variável.

# 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}'  

Ao consumir o modelo em seu pipeline, especifique valores para os parâmetros de modelo.

# 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

Caminhos de modelo de referência

Os caminhos de modelo devem ser relativos ao arquivo que faz a inclusão. Aqui está um exemplo de hierarquia aninhada.

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

Em seguida, em fileA.yml , você pode referenciar fileB.yml e fileC.yml assim.

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

Se fileC.yml for seu ponto de partida, você poderá incluir fileA.yml e fileB.yml curtir isso.

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

Quando fileB.yml é o ponto de partida, você pode incluir fileA.yml e fileC.yml assim.

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

Usar outros repositórios

Você pode manter seus modelos em outros repositórios. Por exemplo, suponha que você tenha um pipeline principal que deseja que todos os pipelines de aplicativo usem. Você pode colocar o modelo em um repositório principal e, em seguida, fazer referência a ele de cada um dos seus repositórios de aplicativos:

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

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

Agora você pode reutilizar esse modelo em vários pipelines. Use a resources especificação para fornecer o local do repositório principal. Quando você se referir ao repositório principal, use @ e o nome que você deu a ele em 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 é <identity>/<repo> como nos exemplos acima. Para type: git (Azure Repos), name é <project>/<repo>. Se esse projeto estiver em uma organização separada do Azure DevOps, você precisará configurar uma conexão de serviço do tipo Azure Repos/Team Foundation Server com acesso ao projeto e incluí-la no YAML:

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

Os repositórios são resolvidos apenas uma vez, quando o pipeline é iniciado. Depois disso, o mesmo recurso é usado durante o pipeline. Somente os arquivos de modelo são usados. Depois que os modelos forem totalmente expandidos, o pipeline final será executado como se tivesse sido definido inteiramente no repositório de origem. Isso significa que você não pode usar scripts do repositório de modelos em seu pipeline.

Se você quiser usar uma versão fixa específica do modelo, certifique-se de fixar em um ref. Os refs são branches (refs/heads/<name>) ou marcas (refs/tags/<name>). Se você quiser fixar uma confirmação específica, primeiro crie uma marca apontando para essa confirmação e, em seguida, fixe nessa marca.

Observação

Se nenhum ref for especificado, o pipeline usará por padrão refs/heads/main.

Você também pode usar @self para se referir ao repositório em que o pipeline original foi encontrado. Isso é conveniente para uso em extends modelos se você quiser fazer referência ao conteúdo no repositório do pipeline de extensão. Por exemplo:

# 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: []

Expressões de modelo

Use expressões de modelo para especificar como os valores são resolvidos dinamicamente durante a inicialização do pipeline. Encapsule sua expressão de modelo dentro desta sintaxe: ${{ }}.

As expressões de modelo podem expandir parâmetros de modelo e também variáveis. Você pode usar parâmetros para influenciar como um modelo é expandido. O parameters objeto funciona como o variables objeto em uma expressão. Somente variáveis predefinidas podem ser usadas em expressões de modelo.

Observação

As expressões são expandidas apenas para stages, jobs, stepse containers (dentro resourcesde ). Você não pode, por exemplo, usar uma expressão dentro trigger ou um recurso como repositories. Além disso, no Azure DevOps 2020 RTW, você não pode usar expressões de modelo dentro containersde .

Por exemplo, você define um modelo:

# File: steps/msbuild.yml

parameters:
- name: 'solution'
  default: '**/*.sln'
  type: string

steps:
- task: msbuild@1
  inputs:
    solution: ${{ parameters['solution'] }}  # index syntax
- task: vstest@2
  inputs:
    solution: ${{ parameters.solution }}  # property dereference syntax

Em seguida, você faz referência ao modelo e passa o parâmetro opcional solution para ele:

# File: azure-pipelines.yml

steps:
- template: steps/msbuild.yml
  parameters:
    solution: my.sln

Contexto

Em uma expressão de modelo, você tem acesso ao parameters contexto que contém os valores dos parâmetros passados. Além disso, você tem acesso ao variables contexto que contém todas as variáveis especificadas no arquivo YAML, além de muitas das variáveis predefinidas (indicadas em cada variável nesse tópico). É importante ressaltar que ele não tem variáveis de runtime, como aquelas armazenadas no pipeline ou fornecidas quando você inicia uma execução. A expansão do modelo ocorre no início da execução, portanto, essas variáveis não estão disponíveis.

Parâmetros obrigatórios

Você pode adicionar uma etapa de validação no início do modelo para marcar para os parâmetros necessários.

Aqui está um exemplo que verifica o parâmetro usando Bash solution (que permite que ele funcione em qualquer plataforma):

# File: steps/msbuild.yml

parameters:
- name: 'solution'
  default: ''
  type: string

steps:
- bash: |
    if [ -z "$SOLUTION" ]; then
      echo "##vso[task.logissue type=error;]Missing template parameter \"solution\""
      echo "##vso[task.complete result=Failed;]"
    fi
  env:
    SOLUTION: ${{ parameters.solution }}
  displayName: Check for required parameters
- task: msbuild@1
  inputs:
    solution: ${{ parameters.solution }}
- task: vstest@2
  inputs:
    solution: ${{ parameters.solution }}

Para mostrar que o modelo falhará se ele não tiver o parâmetro necessário:

# File: azure-pipelines.yml

# This will fail since it doesn't set the "solution" parameter to anything,
# so the template will use its default of an empty string
steps:
- template: steps/msbuild.yml

Funções de expressão de modelo

Você pode usar funções gerais em seus modelos. Você também pode usar algumas funções de expressão de modelo.

format

  • Substituição de token de cadeia de caracteres simples
  • Parâmetros mínimos: 2. Parâmetros máximos: N
  • Exemplo: ${{ format('{0} Build', parameters.os) }}'Windows Build'

coalesce

  • É avaliado como o primeiro argumento de cadeia de caracteres não vazia e não nula
  • Parâmetros mínimos: 2. Parâmetros máximos: N
  • Exemplo:
parameters:
- name: 'restoreProjects'
  default: ''
  type: string
- name: 'buildProjects'
  default: ''
  type: string

steps:
- script: echo ${{ coalesce(parameters.foo, parameters.bar, 'Nothing to see') }}

Inserção

Você pode usar expressões de modelo para alterar a estrutura de um pipeline YAML. Por exemplo, para inserir em uma sequência:

# File: jobs/build.yml

parameters:
- name: 'preBuild'
  type: stepList
  default: []
- name: 'preTest'
  type: stepList
  default: []
- name: 'preSign'
  type: stepList
  default: []

jobs:
- job: Build
  pool:
    vmImage: 'windows-latest'
  steps:
  - script: cred-scan
  - ${{ parameters.preBuild }}
  - task: msbuild@1
  - ${{ parameters.preTest }}
  - task: vstest@2
  - ${{ parameters.preSign }}
  - script: sign
# File: .vsts.ci.yml

jobs:
- template: jobs/build.yml
  parameters:
    preBuild:
    - script: echo hello from pre-build
    preTest:
    - script: echo hello from pre-test

Quando uma matriz é inserida em uma matriz, a matriz aninhada é nivelada.

Para inserir em um mapeamento, use a propriedade ${{ insert }}especial .

# Default values
parameters:
- name: 'additionalVariables'
  type: object
  default: {}

jobs:
- job: build
  variables:
    configuration: debug
    arch: x86
    ${{ insert }}: ${{ parameters.additionalVariables }}
  steps:
  - task: msbuild@1
  - task: vstest@2
jobs:
- template: jobs/build.yml
  parameters:
    additionalVariables:
      TEST_SUITE: L0,L1

Inserção condicional

Se você quiser inserir condicionalmente em uma sequência ou mapeamento em um modelo, use inserções e avaliação de expressão. Você também pode usar if instruções fora dos modelos , desde que use a sintaxe de modelo.

Por exemplo, para inserir em uma sequência em um modelo:

# File: steps/build.yml

parameters:
- name: 'toolset'
  default: msbuild
  type: string
  values:
  - msbuild
  - dotnet

steps:
# msbuild
- ${{ if eq(parameters.toolset, 'msbuild') }}:
  - task: msbuild@1
  - task: vstest@2

# dotnet
- ${{ if eq(parameters.toolset, 'dotnet') }}:
  - task: dotnet@1
    inputs:
      command: build
  - task: dotnet@1
    inputs:
      command: test
# File: azure-pipelines.yml

steps:
- template: steps/build.yml
  parameters:
    toolset: dotnet

Por exemplo, para inserir em um mapeamento em um modelo:

# File: steps/build.yml

parameters:
- name: 'debug'
  type: boolean
  default: false

steps:
- script: tool
  env:
    ${{ if eq(parameters.debug, true) }}:
      TOOL_DEBUG: true
      TOOL_DEBUG_DIR: _dbg
steps:
- template: steps/build.yml
  parameters:
    debug: true

Você também pode usar a inserção condicional para variáveis. Neste exemplo, start sempre imprime e this is a test apenas imprime quando a variável é testigual a foo .

variables:
  - name: foo
    value: test

pool:
  vmImage: 'ubuntu-latest'

steps:
- script: echo "start" # always runs
- ${{ if eq(variables.foo, 'test') }}:
  - script: echo "this is a test" # runs when foo=test

Inserção iterativa

A each diretiva permite a inserção iterativa com base em uma sequência YAML (matriz) ou mapeamento (pares chave-valor).

Por exemplo, você pode encapsular as etapas de cada trabalho com outras pré e pós-etapas:

# job.yml
parameters:
- name: 'jobs'
  type: jobList
  default: []

jobs:
- ${{ each job in parameters.jobs }}: # Each job
  - ${{ each pair in job }}:          # Insert all properties other than "steps"
      ${{ if ne(pair.key, 'steps') }}:
        ${{ pair.key }}: ${{ pair.value }}
    steps:                            # Wrap the steps
    - task: SetupMyBuildTools@1       # Pre steps
    - ${{ job.steps }}                # Users steps
    - task: PublishMyTelemetry@1      # Post steps
      condition: always()
# azure-pipelines.yml
jobs:
- template: job.yml
  parameters:
    jobs:
    - job: A
      steps:
      - script: echo This will get sandwiched between SetupMyBuildTools and PublishMyTelemetry.
    - job: B
      steps:
      - script: echo So will this!

Você também pode manipular as propriedades do que estiver iterando. Por exemplo, para adicionar mais dependências:

# job.yml
parameters:
- name: 'jobs'
  type: jobList
  default: []

jobs:
- job: SomeSpecialTool                # Run your special tool in its own job first
  steps:
  - task: RunSpecialTool@1
- ${{ each job in parameters.jobs }}: # Then do each job
  - ${{ each pair in job }}:          # Insert all properties other than "dependsOn"
      ${{ if ne(pair.key, 'dependsOn') }}:
        ${{ pair.key }}: ${{ pair.value }}
    dependsOn:                        # Inject dependency
    - SomeSpecialTool
    - ${{ if job.dependsOn }}:
      - ${{ job.dependsOn }}
# azure-pipelines.yml
jobs:
- template: job.yml
  parameters:
    jobs:
    - job: A
      steps:
      - script: echo This job depends on SomeSpecialTool, even though it's not explicitly shown here.
    - job: B
      dependsOn:
      - A
      steps:
      - script: echo This job depends on both Job A and on SomeSpecialTool.

Escape de um valor

Se você precisar escapar de um valor que contém ${{literalmente , em seguida, encapsule o valor em uma cadeia de caracteres de expressão. Por exemplo, ${{ 'my${{value' }} ou ${{ 'my${{value with a '' single quote too' }}

Limites impostos

Modelos e expressões de modelo podem causar um crescimento explosivo do tamanho e da complexidade de um pipeline. Para ajudar a evitar o crescimento descontrolado, o Azure Pipelines impõe os seguintes limites:

  • Não mais de 100 arquivos YAML separados podem ser incluídos (direta ou indiretamente)
  • Não mais do que 20 níveis de aninhamento de modelos (modelos incluindo outros modelos)
  • Não mais do que 10 megabytes de memória consumidos durante a análise do YAML (na prática, isso normalmente está entre 600 KB e 2 MB de YAML no disco, dependendo dos recursos específicos usados)

Parâmetros de modelo

Você pode passar parâmetros para modelos. A parameters seção define quais parâmetros estão disponíveis no modelo e seus valores padrão. Os modelos são expandidos pouco antes da execução do pipeline para que os valores cercados por ${{ }} sejam substituídos pelos parâmetros recebidos do pipeline delimitador. Como resultado, somente variáveis predefinidas podem ser usadas em parâmetros.

Para usar parâmetros em vários pipelines, confira como criar um grupo de variáveis.

Modelos de trabalho, estágio e etapa com parâmetros

# File: templates/npm-with-params.yml

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

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

Ao consumir o modelo em seu pipeline, especifique valores para os parâmetros de modelo.

# 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-10.13'

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

Você também pode usar parâmetros com modelos de etapa ou estágio. Por exemplo, etapas com parâmetros:

# File: templates/steps-with-params.yml

parameters:
  runExtendedTests: 'false'  # defaults for any parameters that aren't specified

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

Ao consumir o modelo em seu pipeline, especifique valores para os parâmetros de modelo.

# File: azure-pipelines.yml

steps:
- script: npm install

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

Observação

Parâmetros escalares são sempre tratados como cadeias de caracteres. Por exemplo, eq(parameters['myparam'], true) quase sempre retornará true, mesmo que o myparam parâmetro seja a palavra false. Cadeias de caracteres não vazias são convertidas true em em um contexto booliano. Essa expressão pode ser reescrita para comparar explicitamente cadeias de caracteres: eq(parameters['myparam'], 'true').

Os parâmetros não estão limitados a cadeias de caracteres escalares. Desde que o local em que o parâmetro se expanda espere um mapeamento, o parâmetro pode ser um mapeamento. Da mesma forma, as sequências podem ser passadas onde as sequências são esperadas. Por exemplo:

# 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:
  pool: {}

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

Usando outros repositórios

Você pode manter seus modelos em outros repositórios. Por exemplo, suponha que você tenha um pipeline principal que deseja que todos os pipelines de aplicativo usem. Você pode colocar o modelo em um repositório principal e, em seguida, fazer referência a ele de cada um dos repositórios do aplicativo:

# Repo: Contoso/BuildTemplates
# File: common.yml
parameters:
  vmImage: 'ubuntu 16.04'

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

Agora você pode reutilizar esse modelo em vários pipelines. Use a resources especificação para fornecer o local do repositório principal. Quando você se referir ao repositório principal, use @ e o nome que você deu a ele em 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 é <identity>/<repo> como nos exemplos acima. Para type: git (Azure Repos), name é <project>/<repo>. O projeto deve estar na mesma organização; Não há suporte para referências entre organizações.

Os repositórios são resolvidos apenas uma vez, quando o pipeline é iniciado. Depois disso, o mesmo recurso é usado durante o pipeline. Somente os arquivos de modelo são usados. Depois que os modelos forem totalmente expandidos, o pipeline final será executado como se tivesse sido definido inteiramente no repositório de origem. Isso significa que você não pode usar scripts do repositório de modelos em seu pipeline.

Se você quiser usar uma versão fixa específica do modelo, certifique-se de fixar em um ref. Refs são branches (refs/heads/<name>) ou marcas (refs/tags/<name>). Se você quiser fixar um commit específico, primeiro crie uma marca apontando para essa confirmação e fixe nessa marca.

Expressões

Use expressões de modelo para especificar como os valores são resolvidos dinamicamente durante a inicialização do pipeline. Encapsule sua expressão de modelo dentro dessa sintaxe: ${{ }}.

As expressões de modelo podem expandir parâmetros de modelo e também variáveis. Você pode usar parâmetros para influenciar como um modelo é expandido. O parameters objeto funciona como o variables objeto em uma expressão.

Por exemplo, você define um modelo:

# File: steps/msbuild.yml

parameters:
  solution: '**/*.sln'

steps:
- task: msbuild@1
  inputs:
    solution: ${{ parameters['solution'] }}  # index syntax
- task: vstest@2
  inputs:
    solution: ${{ parameters.solution }}  # property dereference syntax

Em seguida, você faz referência ao modelo e passa o parâmetro opcional solution para ele:

# File: azure-pipelines.yml

steps:
- template: steps/msbuild.yml
  parameters:
    solution: my.sln

Contexto

Dentro de uma expressão de modelo, você tem acesso ao parameters contexto , que contém os valores dos parâmetros passados. Além disso, você tem acesso ao variables contexto , que contém todas as variáveis especificadas no arquivo YAML mais as variáveis do sistema. É importante ressaltar que ele não tem variáveis de runtime, como aquelas armazenadas no pipeline ou fornecidas quando você inicia uma execução. A expansão do modelo ocorre no início da execução, portanto, essas variáveis não estão disponíveis.

Parâmetros obrigatórios

Você pode adicionar uma etapa de validação no início do modelo para marcar para os parâmetros necessários.

Aqui está um exemplo que verifica o parâmetro usando Bash solution (que permite que ele funcione em qualquer plataforma):

# File: steps/msbuild.yml

parameters:
  solution: ''

steps:
- bash: |
    if [ -z "$SOLUTION" ]; then
      echo "##vso[task.logissue type=error;]Missing template parameter \"solution\""
      echo "##vso[task.complete result=Failed;]"
    fi
  env:
    SOLUTION: ${{ parameters.solution }}
  displayName: Check for required parameters
- task: msbuild@1
  inputs:
    solution: ${{ parameters.solution }}
- task: vstest@2
  inputs:
    solution: ${{ parameters.solution }}

Para mostrar que o modelo falhará se ele não tiver o parâmetro necessário:

# File: azure-pipelines.yml

# This will fail since it doesn't set the "solution" parameter to anything,
# so the template will use its default of an empty string
steps:
- template: steps/msbuild.yml

Funções de expressão de modelo

Você pode usar funções gerais em seus modelos. Você também pode usar algumas funções de expressão de modelo.

format

  • Substituição de token de cadeia de caracteres simples
  • Parâmetros mínimos: 2. Parâmetros máximos: N
  • Exemplo: ${{ format('{0} Build', parameters.os) }}'Windows Build'

coalesce

  • É avaliado como o primeiro argumento de cadeia de caracteres não nula e não nulo
  • Parâmetros mínimos: 2. Parâmetros máximos: N
  • Exemplo:
parameters:
  restoreProjects: ''
  buildProjects: ''

steps:
- script: echo ${{ coalesce(parameters.foo, parameters.bar, 'Nothing to see') }}

Inserção

Você pode usar expressões de modelo para alterar a estrutura de um pipeline YAML. Por exemplo, para inserir em uma sequência:

# File: jobs/build.yml

parameters:
  preBuild: []
  preTest: []
  preSign: []

jobs:
- job: Build
  pool:
    vmImage: 'windows-latest'
  steps:
  - script: cred-scan
  - ${{ parameters.preBuild }}
  - task: msbuild@1
  - ${{ parameters.preTest }}
  - task: vstest@2
  - ${{ parameters.preSign }}
  - script: sign
# File: .vsts.ci.yml

jobs:
- template: jobs/build.yml
  parameters:
    preBuild:
    - script: echo hello from pre-build
    preTest:
    - script: echo hello from pre-test

Quando uma matriz é inserida em uma matriz, a matriz aninhada é nivelada.

Para inserir em um mapeamento, use a propriedade ${{ insert }}especial .

# Default values
parameters:
  additionalVariables: {}

jobs:
- job: build
  variables:
    configuration: debug
    arch: x86
    ${{ insert }}: ${{ parameters.additionalVariables }}
  steps:
  - task: msbuild@1
  - task: vstest@2
jobs:
- template: jobs/build.yml
  parameters:
    additionalVariables:
      TEST_SUITE: L0,L1

Inserção condicional

Se você quiser inserir condicionalmente em uma sequência ou mapeamento, use inserções e avaliação de expressão.

Por exemplo, para inserir em uma sequência:

# File: steps/build.yml

parameters:
  toolset: msbuild

steps:
# msbuild
- ${{ if eq(parameters.toolset, 'msbuild') }}:
  - task: msbuild@1
  - task: vstest@2

# dotnet
- ${{ if eq(parameters.toolset, 'dotnet') }}:
  - task: dotnet@1
    inputs:
      command: build
  - task: dotnet@1
    inputs:
      command: test
# File: azure-pipelines.yml

steps:
- template: steps/build.yml
  parameters:
    toolset: dotnet

Por exemplo, para inserir em um mapeamento:

# File: steps/build.yml

parameters:
  debug: false

steps:
- script: tool
  env:
    ${{ if eq(parameters.debug, 'true') }}:
      TOOL_DEBUG: true
      TOOL_DEBUG_DIR: _dbg
steps:
- template: steps/build.yml
  parameters:
    debug: true

Inserção iterativa

A each diretiva permite a inserção iterativa com base em uma sequência yaml (matriz) ou mapeamento (pares chave-valor).

Por exemplo, você pode encapsular as etapas de cada trabalho com pré e pós-etapas extras:

# job.yml
parameters:
  jobs: []

jobs:
- ${{ each job in parameters.jobs }}: # Each job
  - ${{ each pair in job }}:          # Insert all properties other than "steps"
      ${{ if ne(pair.key, 'steps') }}:
        ${{ pair.key }}: ${{ pair.value }}
    steps:                            # Wrap the steps
    - task: SetupMyBuildTools@1       # Pre steps
    - ${{ job.steps }}                # Users steps
    - task: PublishMyTelemetry@1      # Post steps
      condition: always()
# azure-pipelines.yml
jobs:
- template: job.yml
  parameters:
    jobs:
    - job: A
      steps:
      - script: echo This will get sandwiched between SetupMyBuildTools and PublishMyTelemetry.
    - job: B
      steps:
      - script: echo So will this!

Você também pode manipular as propriedades do que estiver iterando. Por exemplo, para adicionar mais dependências:

# job.yml
parameters:
  jobs: []

jobs:
- job: SomeSpecialTool                # Run your special tool in its own job first
  steps:
  - task: RunSpecialTool@1
- ${{ each job in parameters.jobs }}: # Then do each job
  - ${{ each pair in job }}:          # Insert all properties other than "dependsOn"
      ${{ if ne(pair.key, 'dependsOn') }}:
        ${{ pair.key }}: ${{ pair.value }}
    dependsOn:                        # Inject dependency
    - SomeSpecialTool
    - ${{ if job.dependsOn }}:
      - ${{ job.dependsOn }}
# azure-pipelines.yml
jobs:
- template: job.yml
  parameters:
    jobs:
    - job: A
      steps:
      - script: echo This job depends on SomeSpecialTool, even though it's not explicitly shown here.
    - job: B
      dependsOn:
      - A
      steps:
      - script: echo This job depends on both Job A and on SomeSpecialTool.

Escape

Se você precisar escapar de um valor que contém ${{literalmente , em seguida, encapsule o valor em uma cadeia de caracteres de expressão. Por exemplo, ${{ 'my${{value' }} ou ${{ 'my${{value with a '' single quote too' }}

Limites

Modelos e expressões de modelo podem causar um crescimento explosivo do tamanho e da complexidade de um pipeline. Para ajudar a evitar o crescimento descontrolado, o Azure Pipelines impõe os seguintes limites:

  • Não mais de 50 arquivos YAML separados podem ser incluídos (direta ou indiretamente)
  • Não mais do que 10 megabytes de memória consumidos durante a análise do YAML (na prática, isso normalmente está entre 600 KB e 2 MB de YAML no disco, dependendo dos recursos específicos usados)
  • Não são permitidos mais de 2.000 caracteres por expressão de modelo

Perguntas frequentes

Como posso usar variáveis dentro de modelos?

Há momentos em que pode ser útil definir parâmetros para valores com base em variáveis. Os parâmetros são expandidos no início do processamento de uma execução de pipeline para que nem todas as variáveis estejam disponíveis. Para ver quais variáveis predefinidas estão disponíveis em modelos, confira Usar variáveis predefinidas.

Neste exemplo, as variáveis Build.SourceBranch predefinidas e Build.Reason são usadas em condições em 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