Utilização de tipos de modelo &

Serviços do Azure DevOps | Azure DevOps Server 2022 - Azure DevOps Server 2019

Os modelos permitem definir conteúdo reutilizável, lógica e parâmetros. Os modelos funcionam de duas formas. Pode inserir conteúdo reutilizável com um modelo ou pode utilizar um modelo para controlar o que é permitido num pipeline. A segunda abordagem é útil para criar pipelines seguros com modelos.

Se um modelo for utilizado para incluir conteúdo, funciona como uma diretiva de inclusão em muitas linguagens de programação. O conteúdo de um ficheiro é inserido noutro ficheiro. Quando um modelo controla o que é permitido num pipeline, o modelo define a lógica que outro ficheiro tem de seguir.

Utilize modelos para definir a lógica uma vez e, em seguida, reutilizá-la várias vezes. Os modelos combinam o conteúdo de múltiplos ficheiros YAML num único pipeline. Pode transmitir parâmetros para um modelo a partir do pipeline principal.

Parâmetros

Pode especificar parâmetros e os respetivos tipos de dados num modelo e referenciar esses parâmetros num pipeline. Com templateContext, também pode transmitir propriedades para fases, passos e trabalhos que são utilizados como parâmetros num modelo.

Também pode utilizar parâmetros fora dos modelos. Só pode utilizar literais para valores predefinidos de parâmetros.

Transmitir parâmetros

Os parâmetros têm de conter um nome e um tipo de dados. Em azure-pipelines.yml, quando o parâmetro yesNo é definido como um valor booleano, a compilação é bem-sucedida. Quando yesNo está definida para uma cadeia, como apples, a compilação 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 no runtime

Pode chamar modelos diferentes a partir de um YAML de pipeline, consoante uma condição. Neste exemplo, o experimental.yml YAML será executado quando o parâmetro experimentalTemplate for verdadeiro.

#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âmetros

Tipo de dados Notas
string string
number pode ser restringido a values:, caso contrário, qualquer cadeia de carateres semelhante a um número é aceite
boolean true ou false
object qualquer estrutura YAML
step um único passo
stepList sequência de passos
job uma única tarefa
jobList sequência de tarefas
deployment uma única tarefa de implementação
deploymentList sequência de tarefas de implementação
stage uma única fase
stageList sequência de fases

Todos os tipos de dados stepList, job, jobList, deployment, deploymentList, stage e stageList utilizam o formato de esquema YAML padrão. Este exemplo inclui cadeia, número, booleano, objeto, passo 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 }}

Pode iterar através de um objeto e imprimir cada cadeia no objeto.

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

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

Além disso, pode iterar através de elementos aninhados dentro de 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 }}

Expandir a partir de um modelo

Para aumentar a segurança, pode impor que um pipeline se expanda a partir de um modelo específico. O ficheiro start.yml define o parâmetro buildSteps, que é depois utilizado no pipeline azure-pipelines.yml. No start.yml, se um buildStep for transmitido com um passo de script, será rejeitado e a compilação do pipeline falhará. Ao expandir a partir de um modelo, pode aumentar a segurança ao adicionar 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"

Expandir a partir de um modelo com recursos

Também pode utilizar extends para expandir a partir de um modelo no 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"

Utilizar templateContext para transmitir propriedades a modelos

Pode utilizar templateContext para transmitir propriedades adicionais para fases, passos e trabalhos que são utilizados como parâmetros num modelo. Especificamente, pode especificar templateContext no jobListtipo de dados , deploymentListou stageList parâmetro.

Pode utilizar templateContext para facilitar a configuração de ambientes ao processar cada tarefa. Ao agrupar uma tarefa e o respetivo objeto de propriedades de ambiente, templateContext pode ajudá-lo a ter um YAML mais fácil de manter e compreender.

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 com a palavra-chave cada. Em seguida, o modelo referencia o testJob.templateContext.expectedHTTPResponseCode, que é definido e azure-pipeline.yml passado para o modelo.

Quando o código de resposta é 200, o modelo faz um pedido REST. Quando o código de resposta é 500, o modelo produz 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

Pode copiar conteúdo de um YAML e reutilizá-lo num YAML diferente. Copiar conteúdo de um YAML para outro impede-o de ter de incluir manualmente a mesma lógica em vários locais. O include-npm-steps.yml modelo de ficheiro contém passos que são reutilizados no azure-pipelines.yml.

Nota

Os ficheiros de modelo têm de existir no sistema de ficheiros no início de uma execução de pipeline. Não pode referenciar modelos num 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

Reutilização de passos

Pode inserir um modelo para reutilizar um ou mais passos em várias tarefas. Além dos passos do modelo, cada tarefa pode definir mais passos.

# 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 da tarefa

Tal como os passos, as tarefas podem ser reutilizadas 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árias tarefas, lembre-se de remover o nome da tarefa no ficheiro de modelo, de modo a 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 fase

As fases também podem ser reutilizadas 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 tarefas, fases e passos 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

Quando consumir o modelo no pipeline, especifique valores para os parâmetros do 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'

Também pode utilizar parâmetros com modelos de fase ou passo. Por exemplo, passos 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

Quando consumir o modelo no pipeline, especifique valores para os parâmetros do modelo.

# File: azure-pipelines.yml

steps:
- script: npm install

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

Nota

Os parâmetros escalares sem um tipo especificado são tratados como cadeias. Por exemplo, eq(true, parameters['myparam']) irá devolver true, mesmo que o myparam parâmetro seja a palavra false, se myparam não for explicitamente efetuada boolean. As cadeias não vazias são convertidas true num contexto booleano. Essa expressão pode ser reescrita para comparar explicitamente cadeias: eq(parameters['myparam'], 'true').

Os parâmetros não estão limitados a cadeias escalares. Veja a lista de tipos de dados. Por exemplo, com 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 variável

As variáveis podem ser definidas num YAML e incluídas noutro modelo. Isto pode ser útil se quiser armazenar todas as suas variáveis num único ficheiro. Se estiver a utilizar um modelo para incluir variáveis num pipeline, o modelo incluído só pode ser utilizado para definir variáveis. Pode utilizar passos e lógica mais complexa ao expandir a partir de um modelo. Utilize 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

Pode transmitir parâmetros para variáveis com modelos. Neste exemplo, está a transmitir 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}'  

Quando consumir o modelo no pipeline, especifique valores para os parâmetros do 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 dos modelos devem ser relativos ao ficheiro que faz a inclusão. Eis um exemplo de hierarquia aninhada.

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

Em seguida, fileA.yml pode referenciar fileB.yml e fileC.yml desta forma.

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

Se fileC.yml for o seu ponto de partida, pode incluir fileA.yml e fileB.yml desta forma.

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

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

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

Utilizar outros repositórios

Pode manter os seus modelos noutros repositórios. Por exemplo, suponha que tem um pipeline principal que pretende que todos os pipelines da sua aplicação utilizem. Pode colocar o modelo num repositório principal e, em seguida, fazer referência ao mesmo a partir de cada um dos repositórios de aplicações:

# 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 pode reutilizar este modelo em vários pipelines. Utilize a resources especificação para fornecer a localização do repositório principal. Quando se referir ao repositório principal, utilize @ e o nome que deu 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 (Repositórios do Azure), name é <project>/<repo>. Se esse projeto estiver numa organização separada do Azure DevOps, terá de configurar uma ligaçã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, é utilizado o mesmo recurso durante o pipeline. Apenas os ficheiros de modelo são utilizados. Assim que os modelos estiverem totalmente expandidos, o pipeline final é executado como se tivesse sido definido inteiramente no repositório de origem. Isto significa que não pode utilizar scripts do repositório de modelos no seu pipeline.

Se quiser utilizar uma versão fixa específica do modelo, certifique-se de que afixa a um ref. São refs ramos (refs/heads/<name>) ou etiquetas (refs/tags/<name>). Se quiser afixar uma consolidação específica, crie primeiro uma etiqueta que aponte para essa consolidação e, em seguida, afixe a essa etiqueta.

Nota

Se não ref for especificado, o pipeline terá a predefinição de utilizar refs/heads/main.

Também pode utilizar @self para fazer referência ao repositório onde o pipeline original foi encontrado. Isto é conveniente para utilização em extends modelos se quiser voltar a consultar conteúdos no repositório do pipeline de expansã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

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

As expressões de modelo podem expandir parâmetros de modelo e também variáveis. Pode utilizar parâmetros para influenciar a forma como um modelo é expandido. O parameters objeto funciona como o variables objeto numa expressão. Apenas as variáveis predefinidas podem ser utilizadas em expressões de modelo.

Nota

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

Por exemplo, 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, referencia o modelo e transmite-lhe o parâmetro opcional solution :

# File: azure-pipelines.yml

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

Contexto

Numa expressão de modelo, tem acesso ao parameters contexto que contém os valores dos parâmetros transmitidos. Além disso, tem acesso ao variables contexto que contém todas as variáveis especificadas no ficheiro YAML e muitas das variáveis predefinidas (indicadas em cada variável nesse tópico). Importante, não tem variáveis de runtime, como as armazenadas no pipeline ou fornecidas quando inicia uma execução. A expansão do modelo ocorre no início da execução, pelo que essas variáveis não estão disponíveis.

Parâmetros necessários

Pode adicionar um passo de validação no início do modelo para verificar se existem os parâmetros necessários.

Eis um exemplo que verifica o parâmetro com o solution Bash (que lhe permite trabalhar 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 falha se 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

Pode utilizar funções gerais nos seus modelos. Também pode utilizar algumas funções de expressão de modelo.

formato

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

coalesce

  • É avaliado como o primeiro argumento de cadeia não vazio e não nulo
  • Parâmetros min: 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

Pode utilizar expressões de modelo para alterar a estrutura de um pipeline YAML. Por exemplo, para inserir numa 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 numa matriz, a matriz aninhada é achatada.

Para inserir num mapeamento, utilize 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 quiser inserir condicionalmente numa sequência ou mapeamento num modelo, utilize inserções e avaliação de expressões. Também pode utilizar if instruções fora dos modelos , desde que utilize a sintaxe do modelo.

Por exemplo, para inserir numa sequência num 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 num mapeamento num 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

Também pode utilizar a inserção condicional para variáveis. Neste exemplo, start imprime sempre e this is a test só imprime quando a foo variável é igual a test.

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 numa sequência YAML (matriz) ou mapeamento (pares chave-valor).

Por exemplo, pode moldar os passos de cada tarefa com outros pré e pós-passos:

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

Também pode manipular as propriedades do que estiver a iterar. 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.

Escapar a um valor

Se precisar de escapar a um valor que contém ${{literalmente , embrulhe o valor numa cadeia de expressão. Por exemplo, ${{ 'my${{value' }} ou ${{ 'my${{value with a '' single quote too' }}

Limites impostos

Os modelos e as expressões de modelos podem causar um crescimento explosivo do tamanho e complexidade de um pipeline. Para ajudar a evitar o crescimento em fuga, o Azure Pipelines impõe os seguintes limites:

  • Não podem ser incluídos mais de 100 ficheiros YAML separados (direta ou indiretamente)
  • Não podem existir mais de 20 níveis de aninhamento de modelos (modelos, incluindo outros modelos)
  • Não são consumidos mais de 10 megabytes de memória ao analisar o YAML (na prática, isto é normalmente entre 600 KB e 2 MB de YAML no disco, dependendo das funcionalidades específicas utilizadas)

Parâmetros do modelo

Pode transmitir parâmetros para modelos. A parameters secção define que parâmetros estão disponíveis no modelo e os respetivos valores predefinidos. Os modelos são expandidos pouco antes da execução do pipeline para que os valores rodeados sejam ${{ }} substituídos pelos parâmetros que recebe do pipeline de colocação em curso. Como resultado, apenas as variáveis predefinidas podem ser utilizadas em parâmetros.

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

Modelos de tarefas, fases e passos 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

Quando consumir o modelo no pipeline, especifique valores para os parâmetros do 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'

Também pode utilizar parâmetros com modelos de fase ou passo. Por exemplo, passos 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

Quando consumir o modelo no pipeline, especifique valores para os parâmetros do modelo.

# File: azure-pipelines.yml

steps:
- script: npm install

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

Nota

Os parâmetros escalares são sempre tratados como cadeias. Por exemplo, eq(parameters['myparam'], true) devolverá quase sempre true, mesmo que o myparam parâmetro seja a palavra false. As cadeias não vazias são convertidas true num contexto booleano. Essa expressão pode ser reescrita para comparar explicitamente cadeias: eq(parameters['myparam'], 'true').

Os parâmetros não estão limitados a cadeias escalares. Desde que o local onde o parâmetro se expanda espere um mapeamento, o parâmetro pode ser um mapeamento. Da mesma forma, as sequências podem ser transmitidas 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 }}

Utilizar outros repositórios

Pode manter os seus modelos noutros repositórios. Por exemplo, suponha que tem um pipeline principal que pretende que todos os pipelines de aplicação utilizem. Pode colocar o modelo num repositório principal e, em seguida, fazer referência ao mesmo a partir de cada um dos seus repositórios de aplicações:

# 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 pode reutilizar este modelo em vários pipelines. Utilize a resources especificação para fornecer a localização do repositório principal. Quando fizer referência ao repositório principal, utilize @ e o nome que atribuiu 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 (Repositórios do Azure), name é <project>/<repo>. O projeto tem de estar na mesma organização; As referências entre organizações não são suportadas.

Os repositórios são resolvidos apenas uma vez, quando o pipeline é iniciado. Depois disso, é utilizado o mesmo recurso durante o pipeline. Só são utilizados os ficheiros de modelo. Assim que os modelos estiverem totalmente expandidos, o pipeline final é executado como se estivesse totalmente definido no repositório de origem. Isto significa que não pode utilizar scripts do repositório de modelos no seu pipeline.

Se quiser utilizar uma versão fixa específica do modelo, certifique-se de que afixa a um ref. Os refs são ramos (refs/heads/<name>) ou etiquetas (refs/tags/<name>). Se quiser afixar uma consolidação específica, crie primeiro uma etiqueta que aponte para essa consolidação e, em seguida, afixe a essa etiqueta.

Expressions (Expressões)

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

As expressões de modelo podem expandir parâmetros de modelo e também variáveis. Pode utilizar parâmetros para influenciar a forma como um modelo é expandido. O parameters objeto funciona como o variables objeto numa expressão.

Por exemplo, 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, referencia o modelo e transmite-lhe o parâmetro opcional solution :

# File: azure-pipelines.yml

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

Contexto

Numa expressão de modelo, tem acesso ao parameters contexto, que contém os valores dos parâmetros transmitidos. Além disso, tem acesso ao variables contexto, que contém todas as variáveis especificadas no ficheiro YAML e as variáveis de sistema. É importante que não tenha variáveis de runtime, como as que estão armazenadas no pipeline ou fornecidas quando inicia uma execução. A expansão do modelo ocorre no início da execução, pelo que essas variáveis não estão disponíveis.

Parâmetros necessários

Pode adicionar um passo de validação no início do modelo para verificar os parâmetros de que precisa.

Eis um exemplo que verifica o parâmetro com o solution Bash (que lhe permite trabalhar 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 falha se 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

Pode utilizar funções gerais nos seus modelos. Também pode utilizar algumas funções de expressão de modelo.

formato

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

coalesce

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

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

Inserção

Pode utilizar expressões de modelo para alterar a estrutura de um pipeline YAML. Por exemplo, para inserir numa 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 numa matriz, a matriz aninhada é aplanada.

Para inserir num mapeamento, utilize 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 quiser inserir condicionalmente numa sequência ou mapeamento, utilize inserções e avaliação de expressões.

Por exemplo, para inserir numa 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 num 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 numa sequência YAML (matriz) ou mapeamento (pares chave-valor).

Por exemplo, pode encapsular os passos de cada tarefa com pré e pós-passos adicionais:

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

Também pode manipular as propriedades do que estiver a iterar. 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.

A fugir

Se precisar de escapar a um valor que contém ${{literalmente , embrulhe o valor numa cadeia de expressão. Por exemplo, ${{ 'my${{value' }} ou ${{ 'my${{value with a '' single quote too' }}

Limites

Os modelos e as expressões de modelos podem causar um crescimento explosivo do tamanho e complexidade de um pipeline. Para ajudar a evitar o crescimento em execução, o Azure Pipelines impõe os seguintes limites:

  • Não podem ser incluídos mais de 50 ficheiros YAML separados (direta ou indiretamente)
  • Não existem mais de 10 megabytes de memória consumida ao analisar o YAML (na prática, isto é normalmente entre 600 KB e 2 MB de YAML no disco, dependendo das funcionalidades específicas utilizadas)
  • Não são permitidos mais de 2000 carateres por expressão de modelo

FAQ

Como posso utilizar variáveis em modelos?

Por vezes, pode ser útil definir parâmetros como valores baseados em variáveis. Os parâmetros são expandidos no início do processamento de uma execução de pipeline, pelo que nem todas as variáveis estarão disponíveis. Para ver que variáveis predefinidas estão disponíveis nos modelos, veja Utilizar variáveis predefinidas.

Neste exemplo, as variáveis predefinidas e Build.Reason são utilizadas Build.SourceBranch 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