Справочник по использованию шаблона

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

Шаблоны позволяют определять повторное использование содержимого, логики и параметров в конвейерах YAML. Для эффективной работы с шаблонами вам потребуется базовое представление о ключевых понятиях Azure Pipelines, таких как этапы , шаги и задания.

Шаблоны помогут ускорить разработку. Например, в шаблоне можно выполнить ряд одних и тех же задач, а затем включить шаблон несколько раз в разные этапы конвейера YAML.

Шаблоны также помогают защитить конвейер. Когда шаблон управляет допустимым в конвейере, шаблон определяет логику, которую должен следовать другой файл. Например, может потребоваться ограничить выполнение задач. В этом сценарии можно использовать шаблон, чтобы предотвратить успешное выполнение задачи, которая нарушает политики безопасности организации.

Существует два типа шаблонов: включает и расширяет.

  • Включает шаблоны , позволяющие вставлять повторно используемый контент с помощью шаблона. Если шаблон используется для включения содержимого, он работает как директива include во многих языках программирования. Содержимое из одного файла вставляется в другой файл.
  • Расширяет элемент управления шаблоном , разрешенный в конвейере. При расширении элементов управления шаблоном, разрешенных в конвейере, шаблон определяет логику, которую должен следовать другой файл.

Чтобы воспользоваться всеми преимуществами шаблонов, следует также использовать выражения шаблонов и параметры шаблона.

Введенные ограничения

Шаблоны и выражения шаблонов могут привести к значительному увеличению размера и сложности конвейера. Чтобы предотвратить рост запуска, Azure Pipelines накладывает следующие ограничения:

  • Может быть включено не более 100 отдельных файлов YAML (напрямую или косвенно)
  • Допускается не более 20 уровней вложенности шаблонов (шаблонов, включающих другие шаблоны)
  • При анализе YAML не более 10 мб памяти (на практике это обычно составляет от 600 КБ до 2 МБ из YAML на диске в зависимости от используемых функций).

Используйте шаблоны, чтобы определить логику один раз, а затем повторно использовать ее несколько раз. Шаблоны объединяют содержимое нескольких файлов YAML в один конвейер. Параметры можно передать в шаблон из родительского конвейера.

Расширение из шаблона

Чтобы повысить безопасность, можно применить применение конвейера из определенного шаблона. Файл start.yml определяет параметр buildSteps, который затем используется в конвейере azure-pipelines.yml. В start.ymlслучае, если buildStep возвращается шаг скрипта, он отклоняется и сборка конвейера завершается сбоем. При расширении из шаблона можно повысить безопасность, добавив необходимое утверждение шаблона.

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

Расширение из шаблона с ресурсами

Вы также можете использовать extends для расширения из шаблона в конвейере Azure, который содержит ресурсы.

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

Вставка шаблона

Вы можете скопировать содержимое из одного YAML и повторно использовать его в другом YAML. Копирование содержимого из одного YAML в другое сохраняет необходимость вручную включать одну логику в нескольких местах. Шаблон include-npm-steps.yml файла содержит шаги, которые повторно используются.azure-pipelines.yml

Примечание.

Файлы шаблонов должны существовать в файловой системе в начале выполнения конвейера. Вы не можете ссылаться на шаблоны в артефакте.

# 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

Повторное использование шага

Вы можете вставить шаблон для повторного использования одного или нескольких шагов в нескольких заданиях. Помимо шагов из шаблона, каждое задание может определить дополнительные шаги.

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

Повторное использование задания

Как и шаги, задания можно повторно использовать с помощью шаблонов.

# 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

При работе с несколькими заданиями не забудьте удалить имя задания в файле шаблона, чтобы избежать конфликта.

# 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

Повторное использование этапа

Этапы также можно повторно использовать с помощью шаблонов.

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

pool:
  vmImage: 'ubuntu-latest'

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

Шаблоны заданий, этапов и шагов с параметрами

В следующих шаблонах:

  • templates/npm-with-params.yml определяет два параметра: name и vmImage создает задание с параметром name для имени задания и параметра vmImage для образа виртуальной машины.
  • Конвейер (azure-pipelines.yml) ссылается на шаблон три раза, каждый из которых имеет разные значения параметров, ссылающиеся на имена операционной системы и образов виртуальной машины.
  • Встроенный конвейер выполняется на другом образе виртуальной машины и называется в соответствии с указанной ОС. Каждое задание выполняет действия установки npm и тестов npm.
# File: templates/npm-with-params.yml

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

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

При использовании шаблона в конвейере укажите значения параметров шаблона.

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

Шаблоны этапов с несколькими параметрами

В следующих шаблонах:

  • Шаблон stage-template.yml определяет четыре параметра: stageName, jobNamevmImage, и scriptPathвсе строки типа. Шаблон создает этап с помощью stageName параметра для задания имени этапа, определяет задание с jobNameи включает шаг для запуска скрипта.
  • Конвейер, azure-pipeline.ymlа затем динамически определяют этапы и задания с помощью параметров и запуска задания, выполняющего скрипт, build-script.sh.
# stage-template.yml

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

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

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

Шаблоны с шагами и параметрами

Также можно использовать параметры с шаблонами шагов или этапов.

В следующих шаблонах:

  • Шаблон (templates/steps-with-params.yml) определяет параметр с именем runExtendedTests по умолчанию со значением false.
  • Конвейер (azure-pipelines.yml) выполняется npm test и npm test --extended потому, что runExtendedTests параметр имеет значение true.
# File: templates/steps-with-params.yml

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

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

При использовании шаблона в конвейере укажите значения параметров шаблона.

# File: azure-pipelines.yml

steps:
- script: npm install

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

Примечание.

Скалярные параметры без указанного типа обрабатываются как строки. Например, возвращается, eq(true, parameters['myparam']) даже если myparam параметр является словомfalse, если myparam оно не сделано booleanявным trueобразом. Непустые строки привязываются к true логическому контексту. Это выражение может быть перезаписано для явного сравнения строк: eq(parameters['myparam'], 'true')

Параметры не ограничиваются скалярными строками. См. список типов данных. Например, используя object тип:

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


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

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

Повторное использование переменной

Переменные можно определить в одном YAML и включить в другой шаблон. Это может быть полезно, если вы хотите хранить все переменные в одном файле. Если вы используете шаблон для включения переменных в конвейер, включенный шаблон можно использовать только для определения переменных. Вы можете использовать шаги и более сложную логику при расширении из шаблона. Используйте параметры вместо переменных, если требуется ограничить тип.

В этом примере переменная favoriteVeggie включена в 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 }}.

Шаблоны переменных с параметром

Параметры можно передавать в переменные с помощью шаблонов. В этом примере параметр передается DIRECTORY переменной RELEASE_COMMAND .

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

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

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

При использовании шаблона в конвейере укажите значения параметров шаблона.

# 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

Расширение от шаблона и использование шаблона включения с переменными

Один из распространенных сценариев заключается в наличии конвейера с этапами разработки, тестирования и рабочей среды, которая использует как шаблон для переменных, так и шаблон расширения для этапов или заданий.

В следующем примере variables-template.yml определяет набор переменных виртуальной машины, которые затем используются в azure-pipeline.yml.

# variables-template.yml

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

Следующий файл stage-template.yml определяет конфигурацию для повторно используемых этапов с тремя параметрами (name, vmImage, ) stepsи заданием с именем Build.

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

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

Следующий конвейер, azure-pipelines.ymlимпортирует переменные из variables-template.yml, а затем использует stage-template.yml шаблон для каждого этапа. Каждый этап (Dev, Test, Prod) определяется с одним и тем же шаблоном, но с различными параметрами, что приводит к согласованности между этапами, позволяя настраивать. Этап Prod включает переменную среды в качестве примера того, что вы можете использовать для проверки подлинности.

# azure-pipelines.yml
trigger:
- main

variables:
- template: variables-template.yml

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

Пути к шаблону ссылок

Пути к шаблону могут быть абсолютным путем в репозитории или относительно файла, который выполняет включение.

Чтобы использовать абсолютный путь, путь шаблона должен начинаться с /. Все остальные пути считаются относительными.

Ниже приведен пример вложенной иерархии.

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

Затем вы fileA.yml можете ссылаться fileB.yml и fileC.yml вроде этого.

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

Если fileC.yml это ваша отправная точка, вы можете включить fileA.yml и fileB.yml , как это.

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

Когда fileB.yml вы начинаете свою точку, вы можете включить fileA.yml и fileC.yml , как это.

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

Кроме того, fileB.yml можно ссылаться на fileA.yml абсолютные пути и fileC.yml использовать такие пути.

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

Использование других репозиториев

Вы можете сохранить шаблоны в других репозиториях. Например, предположим, что у вас есть основной конвейер, который требуется использовать всем конвейерам приложений. Вы можете поместить шаблон в основной репозиторий, а затем ссылаться на него из каждого репозитория приложения:

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

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

Теперь этот шаблон можно повторно использовать в нескольких конвейерах. Используйте спецификацию resources , чтобы указать расположение основного репозитория. Если вы ссылаетесь на основной репозиторий, используйте @ и имя, в который вы предоставили его 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'

Для type: githubэтого name используется <identity>/<repo> как в приведенных выше примерах. Для type: git (Azure Repos) name используется <project>/<repo>. Если этот проект находится в отдельной организации Azure DevOps, необходимо настроить подключение службы типа Azure Repos/Team Foundation Server с доступом к проекту и включить его в YAML:

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

Репозитории разрешаются только один раз при запуске конвейера. После этого тот же ресурс используется в течение срока конвейера. Используются только файлы шаблонов. После полного развертывания шаблонов конечный конвейер запускается, как если бы он был определен полностью в исходном репозитории. Это означает, что вы не можете использовать скрипты из репозитория шаблона в конвейере.

Если вы хотите использовать определенную исправленную версию шаблона, обязательно закрепите ее ref. Являются refs ветвями (refs/heads/<name>) или тегами (refs/tags/<name>). Если вы хотите закрепить определенную фиксацию, сначала создайте тег, указывающий на эту фиксацию, а затем закрепление этого тега.

Примечание.

Если значение не ref указано, конвейер по умолчанию будет использовать refs/heads/main.

Вы также можете закрепить определенную фиксацию в Git со значением SHA для ресурса репозитория. Значение SHA — это хэш контрольной суммы 40 символов, который однозначно идентифицирует фиксацию.

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

Вы также можете использовать @self для ссылки на репозиторий, где найден исходный конвейер. Это удобно для использования в extends шаблонах, если вы хотите вернуться к содержимому в репозитории расширения конвейера. Например:

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

Вопросы и ответы

Как использовать переменные в шаблонах?

Бывают случаи, когда может быть полезно задать для параметров значения на основе переменных. Параметры развертываются рано при обработке запуска конвейера, поэтому не все переменные доступны. Дополнительные сведения см. в статье Использование предопределенных переменных.

В этом примере предопределенные переменные Build.SourceBranch и Build.Reason используются в условиях в 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