通过嵌套模板传递参数(或声明变量的IF条件)

时间:2020-06-03 06:40:12

标签: azure-devops yaml azure-pipelines

我希望能够一直通过我的YAML管道传递管道参数,而不必在每个YAML文件中都定义参数。

基本上,我有一个主要的YAML文件,该文件称为阶段YAML,该文件具有多个嵌套作业YAML,而该嵌套作业又称为嵌套步骤YAML;实质上是按照我应该使用的模板来构建我的管道:https://docs.microsoft.com/en-us/azure/devops/pipelines/process/templates?view=azure-devops

这是一个树形列表示例文件夹;

E:.
├───01_stage (many files per folder)
├───02_jobs (many files per folder)
├───03_steps (many files per folder)
└───...main pipeline files

理想情况下,我想根据管道是PROD还是NON-PROD在签出存储库时运行IF条件。我可以将其定义为参数很好,但也可以将其定义为变量。 据我所知;您不能对变量使用IF条件。

这很好

- ${{ if eq(parameters.pester, true) }}:     # or even as variables['pester']
  - name: pester
    value: yes

这不好

- ${{ if eq(variables.pester, true) }}:     # or even as variables['pester']
  - name: pester
    value: yes

我想让它运行的条件是嵌套在许多模板下面,而必须重新编码所有内容以确认在每个文件中声明并传递的参数值绝对是痛苦的。

这是我想要的地方:

steps:

- ${{ if eq(parameters['masterTagged'], 'true') }}:   # here
  - checkout: masterTagged
    displayName: Repo Tagged

- ${{ if ne(parameters['masterTagged'], 'true') }}:   # here
  - checkout: self
    displayName: Repo Self

- template: /.pipelines/03_steps/ssh_install.yml

- template: /.pipelines/03_steps/tf_install.yml
  parameters:
    terraformVersion: ${{ parameters['terraformVersion'] }}

- ...many more templates

这是我的主要YAML管道文件:

parameters:
- name: artifactory_base
  type: boolean
  default: true

# ...many more params

- name: pester
  type: boolean
  default: true

- name: planDeploy
  type: boolean
  default: true

- name: useBackupAgent
  type: boolean
  default: false

- name: masterTagged  # key param
  type: boolean
  default: true


name: Team2

pr: none
resources:
  repositories:
  - repository: masterTagged
    endpoint: nationwide-ccoe
    name: my-github-org/my-github-repo
    type: github
    ref: refs/tags/v2.0.3
trigger: none
variables:
- template: /.pipelines/config/sub-asdfasdf.config.yml
- template: /.pipelines/config/namingstd.config.yml
- ${{ if eq(parameters.artifactory_base, true) }}:
  - name: artifactory_base
    value: yes
# ...many more conditions
- ${{ if eq(parameters.pester, true) }}:
  - name: pester
    value: yes
- ${{ if eq(parameters.planDeploy, true) }}:
  - name: planDeploy
    value: yes

stages:
- template: /.pipelines/01_stage/lz_deploy.yml
  parameters:
    ${{ if eq(parameters.useBackupAgent, false) }}:
      pool:
        vmImage: Ubuntu 18.04
    ${{ if eq(parameters.useBackupAgent, true) }}:
      pool:
        name: backupAgents
    terraformVersion: $(TERRAFORM_VERSION)

是否可以设置此masterTagged参数并对其进行向下过滤,而不必每次都声明?

也;是否有可能以这种方式使用变量而不是参数(我知道参数会在变量之前扩展):

- ${{ if eq(variables.pester, true) }}:     # or even as variables['pester']
  - name: pester
    value: yes

...如果是,我一直都在做错事吗?

注意:

我了解您可以在结帐任务上使用标准任务条件(如下所示);但是,在两个任务上执行“切换”操作将破坏检出存储库的文件夹路径。即使我们只检查存储库,它也会向$ SYSTEM_DEFAULTWORKINGDIRECTORY添加另一个文件夹级别。以这种方式进行操作将需要对YAML管道的当前结构进行更多的重新编码。

- checkout: masterTagged
  condition: eq(variables['masterTagged'], 'true')
  displayName: Repo Tagged

- checkout: self
  condition: ne(variables['masterTagged'], 'true')
  displayName: Repo Self

如果可以,但我知道这是不可能的(从其他人的请求中可以看出),我可以在存储库引用中启用参数或变量:

resources:
  repositories:
  - repository: masterTagged
    endpoint: nationwide-ccoe
    name: my-github-org/my-github-repo
    type: github
    ref: ${{ parameters.repoRef }}    # here

1 个答案:

答案 0 :(得分:0)

是否可以设置此masterTagged参数并对其进行向下过滤,而不必每次都声明?

否,因为参数“作用域”到定义它们的文件。这是由于在第一次编译管道时它们被扩展了。 (请参阅> Pipeline run sequence

您可以在变量上使用IF条件,但是不能在模板内部的变量上使用模板表达式(用{{}}包裹),因为变量不存在/在模板扩展时尚未填充。 / p>

一个选择就是按照您建议的方式使用签出任务中的条件,并将额外的文件夹级别处理为默认工作目录。我不得不做一些类似的事情,我们的解决方案是将repo文件夹的内容复制到默认的工作目录中。

您的另一个选择是在顶级管道文件中进行检出。这样一来,您就可以使用参数来模板化结帐步骤,而不必完全将其传递给文件。我建议使用此选项,因为您不必处理第一个选项的文件夹结构问题。

这看起来像这样:

parameters:
  - name: masterTagged
    default: true
    type: boolean

resources:
  repositories:
    - repository: masterTagged
      endpoint: nationwide-ccoe
      name: my-github-org/my-github-repo
      type: github
      ref: refs/tags/v2.0.3

steps:
  - ${{ if eq(parameters.masterTagged, true) }}:
    - checkout: masterTagged
  - ${{ if eq(parameters.masterTagged, false) }}:
    - checkout: self

  - template: ./path/to/template.yml

我希望这能回答您的问题。