Uso de tipos de modelo &

Azure DevOps Services | Azure DevOps Server | 2020 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 usar um modelo para controlar o que é permitido num oleoduto. A segunda abordagem é útil para a construção de oleodutos seguros com modelos.

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

Use modelos para definir a sua lógica uma vez e, em seguida, reutilizá-la várias vezes. Os modelos combinam o conteúdo de vários ficheiros YAML num único oleoduto. Pode passar parâmetros para um modelo a partir do seu oleoduto principal.

Parâmetros

Pode especificar os parâmetros e os seus tipos de dados num modelo e passar esses parâmetros para um pipeline. Também pode usar parâmetros fora dos modelos. Só pode utilizar literais para valores padrão de parâmetros.

Parâmetros de passagem

Os parâmetros devem conter um nome e um tipo de dados. Em azure-pipelines.yml, quando o parâmetro yesNo é definido para um valor boolean, a construção tem sucesso. Quando yesNo está definida para uma cadeia como apples, a construçã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 tempo de execução

Pode chamar modelos diferentes de um pipeline YAML dependendo de uma condição. Neste exemplo, o experimental.yml YAML funcionará 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 , caso contrário qualquer cadeia semelhante a values:número é aceite
boolean true ou false
object qualquer estrutura YAML
step um único passo
stepList sequência de passos
job um único trabalho
jobList sequência de empregos
deployment um único trabalho de implantação
deploymentList sequência de postos de trabalho de implantação
stage um único estágio
stageList sequência de estágios

Os tipos de dados step, stepList, job, jobList, deploymentList, stage e stageList utilizam todos os tipos de esquemas YAML padrão. Este exemplo inclui string, número, boolean, 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 corda no objeto.

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

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

Estender a partir de um modelo

Para aumentar a segurança, pode impor que um oleoduto se estenda a partir de um determinado modelo. O ficheiro start.yml define o parâmetro buildSteps, que é depois utilizado no gasoduto azure-pipelines.yml. Em start.yml, se um buildStep é passado com um passo de script, então é rejeitado e a construção do gasoduto falha. Ao estender-se a partir de um modelo, 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 a partir de um modelo com recursos

Também pode usar extends para se estender a partir de um modelo no seu pipeline 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"

Insira um modelo

Pode copiar conteúdo de um YAML e reutilizá-lo num YAML diferente. Copiar conteúdo de um YAML para outro evita que tenha 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 em azure-pipelines.yml.

Nota

Os ficheiros de modelos precisam de existir no seu sistema de ficheiros no início de uma execução do pipeline. Não se pode fazer referência a 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ários trabalhos. Além dos passos do modelo, cada trabalho 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 de emprego

Tal como os passos, 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 do 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 palco

As etapas 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 trabalho, estágio e passo 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 seu pipeline, especifique os 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 passo ou fase. 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 seu pipeline, especifique os 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 escalar sem um tipo especificado são tratados como cordas. Por exemplo, eq(true, parameters['myparam']) regressará true, mesmo que o myparam parâmetro seja a palavra false, se myparam não for explicitamente feito boolean. As cordas não vazias são lançadas num true contexto booleano. Esta expressão pode ser reescrita para comparar explicitamente as cordas: eq(parameters['myparam'], 'true').

Os parâmetros não se limitam a cordas escalar. Consulte a lista de tipos de dados. Por exemplo, utilizando 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 só ficheiro. Se estiver a usar um modelo para incluir variáveis num oleoduto, o modelo incluído só pode ser usado para definir variáveis. Pode usar passos e lógica mais complexa quando se está a estender a partir de um modelo. Utilize parâmetros em vez de variáveis quando pretende 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 variáveis com parâmetro

Pode passar parâmetros para variáveis com modelos. Neste exemplo, está a passar 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 seu pipeline, especifique os 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 do modelo de referência

Os caminhos do modelo devem ser relativos ao ficheiro que faz o incluindo. Aqui está um exemplo de hierarquia aninhada.

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

Então, podes fileA.yml fazer referência fileB.yml e fileC.yml assim.

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

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

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

Use outros repositórios

Pode manter os seus modelos em outros repositórios. Por exemplo, suponha que tem um pipeline de núcleo que deseja que todos os seus oleodutos de aplicações usem. Pode colocar o modelo num repo de núcleo e, em seguida, encaminhá-lo a partir de cada um dos seus repos de aplicação:

# 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 oleodutos. Utilize a resources especificação para fornecer a localização do repo do núcleo. Quando se refere ao repo central, use @ e o nome em resourcesque o deu.

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

Pois type: github, name está <identity>/<repo> como nos exemplos acima. Para type: git (Azure Repos), name é <project>/<repo>. Se esse projeto estiver numa organização separada da Azure DevOps, você precisará configurar uma ligação de serviço do tipo Azure Repos/Team Foundation Server com acesso ao projeto e incluí-lo em YAML:

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

Os repositórios só são resolvidos uma vez, quando o gasoduto começa. Depois disso, utiliza-se o mesmo recurso durante a duração do gasoduto. Apenas os ficheiros de modelo são utilizados. Uma vez que os modelos são totalmente expandidos, o gasoduto final funciona como se fosse definido inteiramente no repo de origem. Isto significa que não pode usar scripts a partir do repo do modelo no seu oleoduto.

Se quiser utilizar uma versão específica e fixa do modelo, certifique-se de fixar a ref. São refs ramos (refs/heads/<name>) ou tags (refs/tags/<name>). Se quiser fixar um compromisso específico, primeiro crie uma etiqueta que indique esse compromisso e, em seguida, pina para essa etiqueta.

Nota

Se não ref for especificado, o gasoduto não será utilizado refs/heads/mainpor defeito .

Pode também utilizar @self para se referir ao repositório onde o gasoduto principal foi encontrado. Isto é conveniente para ser usado em extends modelos se você quiser remeter para o 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

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

As expressões do modelo podem expandir os parâmetros do modelo, e também as 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 variáveis predefinidas podem ser usadas em expressões de modelo.

Nota

As expressões só são expandidas parastages, stepsjobs, e containers (dentroresources). Não é possível, por exemplo, utilizar uma expressão no interior trigger ou um recurso como repositories. Além disso, em Azure DevOps 2020 RTW, não pode usar expressões de modelo no interior containers.

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

# 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 ficheiro YAML mais muitas das variáveis predefinidas (notadas em cada variável nesse tópico). Importante, não tem variáveis de tempo de execução, como as armazenadas no oleoduto ou dadas quando começa a correr. A expansão do modelo acontece muito cedo na execução, por isso essas variáveis não estão disponíveis.

Parâmetros necessários

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

Aqui está um exemplo que verifica o solution parâmetro usando 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 faltar 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 usar algumas funções de expressão de modelo.

formato

  • Substituição simples de símbolo de corda
  • Min parâmetros: 2. Parâmetros max: N
  • Exemplo: ${{ format('{0} Build', parameters.os) }}'Windows Build'

coalesce

  • Avalia para o primeiro argumento de corda não vazio e não nulo
  • Min parâmetros: 2. Parâmetros max: 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 oleoduto 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 num mapeamento num modelo, utilize inserções e faça uma avaliação de expressão. Também pode usar if declarações fora dos modelos , desde que utilize sintaxe de 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 inserção condicional para variáveis. Neste exemplo, start imprime sempre e this is a test só imprime quando a foo variável é testigual.

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 de valores-chave).

Por exemplo, pode embrulhar os passos de cada trabalho com outros passos 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 imutar. 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 de um valor

Se precisar de escapar a um valor que literalmente contenha ${{, embrulhe o valor numa corda 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 crescimento explosivo ao tamanho e complexidade de um oleoduto. Para ajudar a prevenir o crescimento em fuga, a Azure Pipelines impõe os seguintes limites:

  • Não podem ser incluídos mais de 100 ficheiros YAML separados (direta ou indiretamente)
  • Não mais de 20 níveis de nidificação de modelo (modelos incluindo outros modelos)
  • Não mais de 10 megabytes de memória consumidas durante a análise do YAML (na prática, isto é tipicamente entre 600 KB - 2 MB de YAML on-disk, dependendo das características específicas utilizadas)

Parâmetros do modelo

Pode passar parâmetros para modelos. A parameters secção define quais os parâmetros disponíveis no modelo e os seus valores predefinidos. Os modelos são expandidos pouco antes do gasoduto ser executado de modo a que os valores rodeados por ${{ }} sejam substituídos pelos parâmetros que recebe do gasoduto de encerramento. Como resultado, apenas variáveis predefinidas podem ser usadas em parâmetros.

Para utilizar parâmetros em vários oleodutos, veja como criar um grupo variável.

Modelos de trabalho, estágio e passo 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 seu pipeline, especifique os 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 passo ou fase. 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 seu pipeline, especifique os 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 escalar são sempre tratados como cordas. Por exemplo, eq(parameters['myparam'], true) voltará quase sempre true, mesmo que o myparam parâmetro seja a palavra false. As cordas não vazias são lançadas num true contexto booleano. Esta expressão pode ser reescrita para comparar explicitamente as cordas: eq(parameters['myparam'], 'true').

Os parâmetros não se limitam a cordas escalar. Enquanto o local onde o parâmetro se expande espera um mapeamento, o parâmetro pode ser um mapeamento. Da mesma forma, as sequências podem ser passadas onde se esperam sequências. 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

Pode manter os seus modelos em outros repositórios. Por exemplo, suponha que tem um pipeline de núcleo que deseja que todos os seus oleodutos de aplicações usem. Pode colocar o modelo num repo de núcleo e, em seguida, encaminhá-lo a partir de cada um dos seus repos de aplicação:

# 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 oleodutos. Utilize a resources especificação para fornecer a localização do repo do núcleo. Quando se refere ao repo central, use @ e o nome em resourcesque o deu.

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

Pois type: github, name está <identity>/<repo> como nos exemplos acima. Para type: git (Azure Repos), name é <project>/<repo>. O projeto deve ser na mesma organização; as referências da organização cruzada não são apoiadas.

Os repositórios só são resolvidos uma vez, quando o gasoduto começa. Depois disso, o mesmo recurso é utilizado durante o gasoduto. Apenas os ficheiros de modelo são utilizados. Uma vez que os modelos são totalmente expandidos, o gasoduto final funciona como se fosse definido inteiramente no repo de origem. Isto significa que não pode usar scripts a partir do repo do modelo no seu oleoduto.

Se pretender utilizar uma versão determinada e fixa do modelo, certifique-se de fixar num árbitro. Os árbitros são ou ramos (refs/heads/<name>) ou tags (refs/tags/<name>). Se quiser fixar um compromisso específico, primeiro crie uma etiqueta que indique esse compromisso e, em seguida, pina para essa etiqueta.

Expressions (Expressões)

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

As expressões do modelo podem expandir os parâmetros do modelo, e também as 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-se 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ê referencia o modelo e passa-lhe o parâmetro opcional solution :

# 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 ficheiro YAML mais as variáveis do sistema. Importante, não tem variáveis de tempo de execução, como as armazenadas no oleoduto ou dadas quando começa a correr. A expansão do modelo acontece no início da corrida, por isso essas variáveis não estão disponíveis.

Parâmetros necessários

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

Aqui está um exemplo que verifica o solution parâmetro usando 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 faltar 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 usar algumas funções de expressão de modelo.

formato

  • Substituição simples de símbolo de corda
  • Min parâmetros: 2. Parâmetros max: N
  • Exemplo: ${{ format('{0} Build', parameters.os) }}'Windows Build'

coalesce

  • Avalia para o primeiro argumento de corda não vazio e não nulo
  • Min parâmetros: 2. Parâmetros max: 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 oleoduto 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 é achatada.

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 num mapeamento, utilize inserções e uma avaliação de expressão.

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 de valores-chave).

Por exemplo, pode embrulhar os passos de cada trabalho com passos extra pré e pós-passos:

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

Escapando

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

Limites

Modelos e expressões de modelo podem causar crescimento explosivo ao tamanho e complexidade de um oleoduto. Para ajudar a prevenir o crescimento em fuga, a Azure Pipelines impõe os seguintes limites:

  • Não podem ser incluídos mais de 50 ficheiros YAML separados (direta ou indiretamente)
  • Não mais de 10 megabytes de memória consumidas durante a análise do YAML (na prática, isto é tipicamente entre 600 KB - 2 MB de YAML on-disk, dependendo das características específicas utilizadas)
  • Não são permitidos mais de 2000 caracteres por expressão de modelo