Azure DevOps 管道中的动态变量组

Dynamic variable group in Azure DevOps pipeline

我希望能够根据生成的名称在 Azure DevOps Pipeline 中使用变量组。

像这样:(其中 dtapName 是一个像 dt 这样的字母。)

variables:
- group: 'project-${{ dtapName }}'

我已经看到它在其他管道中有效,但我自己创建一个管道很痛苦。

我目前的流水线如下: 变量组“global-d”包含一个变量'dtapName',值为'd'。 变量组“project-t”包含 URL 等特定于我们的 'develop' 景观。

文件“管道-infra.yaml”:

trigger:
  branches:
    include:
    - main
    - develop
  paths:
    include:
    - Project/pipelines

stages:
- stage: Develop
  displayName: Develop deployment of Project
  variables:
  - name: environmentName
    value: 'develop-o'
  - group: 'global-o'
  jobs:
  - deployment: 'Debug_001'
    environment: ${{ variables.environmentName }}
    strategy:
      runOnce:
        deploy:
          steps:
            - script: echo [Testing job]
            - script: echo v.environment = ${{ variables.environmentName }} # Does work
            - script: echo v.dtapName = ${{ variables.dtapName }} #❗Fails, why? It is defined in the variable group 'global-o'
            # script: echo environment = ${{ environmentName }} #❗Failed, why does it work in the template call below?
            # script: echo dtapName = ${{ dtapName }} #❗Failed, why does it work in the template call below?
            - script: echo env ENVIRONMENTNAME = $ENVIRONMENTNAME # Does work
            - script: echo env DTAPNAME = $DTAPNAME  # Does work

  - template: pipeline-infra.extra.yaml
    parameters:
      environment: $(environmentName)
      dtapName: $(dtapName)

文件“管道-infra.extra.yaml”

parameters:
- name: environment
  type: string
- name: dtapName
  type: string

jobs:
- deployment: 'Debug_002'
# environment: ${{ parameters.environment }} #❗Fails with: Environment $(environmentName) could not be found.  WHY?
  environment: 'develop-o'
  pool:
    vmImage: 'ubuntu-latest'
  variables:
  - name: placeholder
    value: 'none'
# - group: 'project-${{ parameters.dtapName }}' #❗Fails with: Variable group 'project-$(dtapName)' could not be found. How to do this?
  strategy: 
    runOnce:
      deploy:
        steps:
        - script: echo [ pipeline-infra.extra.yaml ]
        - script: echo Environment = ${{ parameters.environment }} # WORKS
        - script: echo "Environment (v) = ${{ variables.environmentName }}" #❗FAILS, this variable is declare on the stage of this job... why can't it be accessed?
        - script: echo Parameter = ${{ parameters.dtapName }} # WORKS
        - script: echo PARAMETER = $DTAPNAME # WORKS
        - script: echo Variable  = ${{ variables.dtapName }} #❗FAILS, would think this comes available when the problem in the calling stage is fixed
        - task: Bash@3
          displayName: VariableListing 2
          inputs:
            targetType: inline
            script: 'env | sort'

任何人都可以向我解释(或指出描述)为什么会出现这些问题吗? 我已阅读(大部分)Define variables 和从此处链接的文档。 应该是小事,不过这两天没看到。

您的主 yaml 中有两个错误:

  1. cannot 使用模板表达式 ${{ variables.var }} 从变量组调用变量。模板变量在编译时处理,并在运行时开始前被替换。它cannot从组中获取变量值,它可以从预定义变量中获取值。
  2. 模板表达式的格式应为 ${{ variables.var }} 而不是 ${{ var }}.

请查看文档:Understand variable syntax 了解详细信息。我在下面添加对您的 yaml 的评论:

trigger:
  branches:
    include:
    - main
    - develop
  paths:
    include:
    - Project/pipelines

stages:
- stage: Develop
  displayName: Develop deployment of Project
  variables:
  - name: environmentName
    value: 'develop-o'
  - group: 'global-o'
  jobs:
  - deployment: 'Debug_001'
    environment: ${{ variables.environmentName }}
    strategy:
      runOnce:
        deploy:
          steps:
            - script: echo [Testing job]
            - script: echo v.environment = ${{ variables.environmentName }} # Does work, it use template expression syntax and can get the value as it's predefined variable.
            - script: echo v.dtapName = ${{ variables.dtapName }} #❗Not work, Template variables are processed at compile time, and are replaced before runtime starts, it cannot get the Test Group variable value, should use macro syntax $(dtapName).
            # script: echo environment = ${{ environmentName }} #❗Failed, syntax error, should be ${{ variables.environmentName }} or $(environmentName)
            # script: echo dtapName = ${{ dtapName }} #❗Failed, syntax error, should be $(dtapName)
            - script: echo env ENVIRONMENTNAME = $ENVIRONMENTNAME # Does work, the variable is set as environment value, you can use it with syntax $NAME.
            - script: echo env DTAPNAME = $DTAPNAME  # Does work,the variable is set as environment value, you can use it with syntax $NAME.

  - template: pipeline-infra.extra.yaml
    parameters:
      environment: $(environmentName) # Environment creation happens at compile time, if you pass marco syntax to template, it will cause the error, should use template expreesion ${{ variables.environmentName }}.
      dtapName: $(dtapName)  # not work here, should define it out of variable group, and transfer with parameter expression same as above.

对于您的模板 yaml:

  1. 环境创建发生在编译期,所以如果你在主yaml中为模板定义$(environmentName),它无法获取值,你应该在main中使用模板表达式${{ variables.environmentName }} yaml 传输值。
  2. 模板中没有定义变量,你cannot使用${{ variables.var }},你应该使用参数表达式${{ parameters.var }}.
parameters:
- name: environment
  type: string
- name: dtapName
  type: string

jobs:
- deployment: 'Debug_002'
# environment: ${{ parameters.environment }} #❗Fails, should use ${{ variables.environmentName }} in main yaml for template.
  environment: 'develop-o'
  pool:
    vmImage: 'ubuntu-latest'
  variables:
  - name: placeholder
    value: 'none'
# - group: 'project-${{ parameters.dtapName }}' #❗Fails, same as above, it cannot get the value 
  strategy: 
    runOnce:
      deploy:
        steps:
        - script: echo [ pipeline-infra.extra.yaml ]
        - script: echo Environment = ${{ parameters.environment }} # WORKS
        - script: echo "Environment (v) = ${{ variables.environmentName }}" #❗FAILS, should use parameter expression as no variable defined.
        - script: echo Parameter = ${{ parameters.dtapName }} # WORKS
        - script: echo PARAMETER = $DTAPNAME # WORKS
        - script: echo Variable  = ${{ variables.dtapName }} #❗FAILS, same as above.
        - task: Bash@3
          displayName: VariableListing 2
          inputs:
            targetType: inline
            script: 'env | sort'