Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019
模板用于 YAML 管道中可重用的内容、逻辑和参数。 需要了解
Azure Pipelines 关键概念
(如阶段、步骤和工作等)的基础知识才能有效地利用好模板。
模板可帮助你加快开发速度。 例如,可以在模板中包含一系列相同的任务,然后在 YAML 管道的不同阶段多次包含模板。
模板还可以帮助你确保管道的安全。 当模板控制管道中允许的内容时,该模板则定义另一个文件必须遵循的逻辑。 例如,你可能想要限制允许运行哪些任务。 此类情况下,可以使用模板阻止某人成功运行违反组织安全策略的任务。
有两种类型的模板:包含和扩展。
包含模板
支持在模板中插入可重用的内容。 如果使用模板来包含内容,它的作用类似于许多编程语言中的 include 指令。 一个文件中的内容会插入到另一个文件中。
扩展模板
可以控制管道中允许的内容。 当扩展模板控制管道中允许的内容时,该模板则定义另一个文件必须遵循的逻辑。
还应使用
模板表达式
和
模板参数
来充分利用模板。
使用模板,定义一次逻辑即可供多次重用。 模板将多个 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 复制到另一个 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
带参数的作业、阶段和步骤模板
# 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'
还可以将参数与步骤模板或阶段模板一起使用。
例如,带参数的步骤:
# 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'
没有指定类型的标量参数被视为字符串。
例如,如果 myparam
未显式设置为 boolean
,eq(true, parameters['myparam'])
将返回 true
,即使 myparam
参数是单词 false
。
非空字符串在布尔上下文中强制转换为 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
引用模板路径
模板路径可以是存储库中的绝对路径,也可以是相对于包含的文件的绝对路径。
若要使用绝对路径,模板路径必须以 /
开头。 所有其他路径都被视为相对路径。
下面是一个嵌套层次结构示例。
+-- 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
。
还可以使用存储库资源的 SHA 值固定到 Git 中的特定提交。 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