3

我有一个自托管虚拟机池(MyTestPool),其中一半专用于安装和测试“开启”构建(打开的功能很少)和“关闭”构建(这是默认安装)。我所有的测试代理虚拟机都具有“全部”作为用户定义的功能。其中一半也被标记为“开”,另一半被标记为“关”。

现在我有两个称为 DEPLOYOFF 和 DEPLOYON 的阶段,如果变量组变量“skipDeployOffStage”或“skipDeployOnStage”设置为 true,则可以跳过这些阶段。如果只测试 ON/OFF,我想做的是使用“ALL”作为代理需求。如果要同时测试 ON 和 OFF,则适当的阶段将要求它们各自的“ON”或“OFF”VM。

问题:${{ if }} 不起作用。

trigger: none
pr: none


pool: 'MyBuildPool'

variables:
  - group: TEST_IF_VARIABLE_GROUP
  - name: subPool
    value: 'ON'
  - name: useAllPool
    value: $[ or(eq( variables.skipDeployOnStage, true), eq( variables.skipDeployOffStage, true)) ]
    
stages:
- stage: DEPLOYOFF
  condition: ne(variables['skipDeployOffStage'], 'true')

  variables:
    # The test stage's subpool
    ${{ if variables.useAllPool }}:
      subPool: 'ALL'
    ${{ if not(variables.useAllPool)  }}:
      subPool: 'OFF'

  pool: 
    name: 'MyTestPool'
    demands: 
      - ${{ variables.subPool }}

  jobs:
  - job:

    steps:
    - checkout: none
    - pwsh: |
        Write-Host ("Value of useAllPool is: {0}" -f '$(useAllPool)')
        Write-Host ("Value of VG variable 'skipDeployOnStage' is {0} and 'skipDeployOffStage' is {1}" -f '$(skipDeployOnStage)', '$(skipDeployOffStage)')
        Write-Host ("Subpool is {0}" -f '$(subPool)')
      displayName: 'Determined SubPool'

标志之一为假时的输出:

2020-08-02T18:39:05.5849160Z Value of useAllPool is: True
2020-08-02T18:39:05.5854283Z Value of VG variable 'skipDeployOnStage' is true and 'skipDeployOffStage' is false 
2020-08-02T18:39:05.5868711Z Subpool is ALL

两者都为假时的输出:

2020-08-02T18:56:40.5371875Z Value of useAllPool is: False
2020-08-02T18:56:40.5383258Z Value of VG variable 'skipDeployOnStage' is false and 'skipDeployOffStage' is false
2020-08-02T18:56:40.5386626Z Subpool is ALL

我错过了什么?

4

2 回答 2

4

有两个问题会导致您的代码运行不正确:

1.The ${{if}}: 你写的方式${{if}}不对,正确的脚本是:

${{ if eq(variables['useAllPool'], true)}}:
   subPool: 'ALL'
${{ if ne(variables['useAllPool'], true)}}:
   subPool: 'OFF'

2. variables.useAllPool 的定义:你使用了一个运行时表达式($[ <expression> ]),所以当${{if}}运行时,的值variables.useAllPool'$[ or(eq( variables.skipDeployOnStage, true), eq( variables.skipDeployOffStage, true)) ]'而不是trueor false

要解决此问题,您需要使用编译时表达式${{ <expression> }}

但是,当使用编译时表达式时,它不能包含来自变量组的变量。skipDeployOnStage因此,您需要将变量skipDeployOffStage从变量组移动到 YAML 文件。

因此,您可以通过以下步骤解决问题:

1.从变量组中删除变量skipDeployOnStage和。skipDeployOffStageTEST_IF_VARIABLE_GROUP

2.修改YAML文件:

trigger: none
pr: none
 
 
pool: 'MyBuildPool'
 
variables:
  - group: TEST_IF_VARIABLE_GROUP
  - name: subPool
    value: 'ON'
  - name: skipDeployOnStage
    value: true
  - name: skipDeployOffStage
    value: false
  - name: useAllPool
value: ${{ or(eq( variables.skipDeployOnStage, true), eq( variables.skipDeployOffStage, true)) }}
    
stages:
- stage: DEPLOYOFF
  condition: ne(variables['skipDeployOffStage'], 'true')
 
  variables:
    # The test stage's subpool
    ${{ if eq(variables['useAllPool'], true)}}:
      subPool: 'ALL'
    ${{ if ne(variables['useAllPool'], true)}}:
      subPool: 'OFF'
  pool: 
    name: 'MyTestPool'
    demands: 
      - ${{ variables.subPool }}
 
  jobs:
  - job:
 
    steps:
    - checkout: none
    - pwsh: |
        Write-Host ("Value of useAllPool is: {0}" -f '$(useAllPool)')
        Write-Host ("Value of VG variable 'skipDeployOnStage' is {0} and 'skipDeployOffStage' is {1}" -f '$(skipDeployOnStage)', '$(skipDeployOffStage)')
        Write-Host ("Subpool is {0}" -f '$(subPool)')
      displayName: 'Determined SubPool'

您可以修改YAML 文件中skipDeployOnStage和的值,以测试该方案是否有效。skipDeployOffStage

于 2020-08-03T10:11:58.963 回答
1

我的要求:

  • 有一个自托管的虚拟机池,比如 20 台机器
  • 其中 10 个具有“OFF”作为用户功能(名称为 OFF,值为空白)其中 10 个具有
  • “ON”作为用户功能(名称为 ON,值为空白)
  • 它们都具有“ALL”作为附加用户功能
  • 管道基本上安装了产品的 2 个变体,并在池中的指定机器上运行测试(开/关)
  • 当用户想要同时运行 OFF 和 ON 部署时,我有需要 OFF 或 ON 运行的阶段
  • 我想要做的是当用户只想要 ON 或 OFF 部署时,为了节省时间,我想使用所有 20 台机器,部署和测试,这样我就可以减少整体测试时间。

我试图在运行时替换池需求是徒劳的,因为我不想在每次运行之前更新 20-50 个 VM 的用户功能。如果使用传统的需求语法,这就是我必须做的:

  pool: 
    name: 'MyTestPool'
    demands: 
      # There's no OR or other syntax supported here
      # LVALUE must be a built-in variable such as Agent.Name OR a User capability
      # I will have to manually change the DeploymentType before the pipeline is run
      - DeploymentType -equals $(subPool)  

因此,我试图在运行时确定 subPool 的值并使用以下语法,因此我不必在运行前手动配置用户功能。

pool:
  name: ${{ parameters.pool }}
  demands:
    - ${{ parameters.subPool}}

这是我的研究:

您绝对可以混合编译和运行时表达式。编译时表达式的计算结果是编译时的值。如果它是表达式或变量(而不是常量),则整个表达式或变量将被替换为 Jane Ma-MSFT 注释。

例如,我已经能够在编译时表达式中使用队列时间变量而没有问题。例如,我使用了哪个池作为队列时间变量,然后将其传递给模板,该模板对该值使用编译时语法。

parameters:
  - name: pool
    type: string  

jobs:
  - job: ExecAllPrerequisitesJob
    displayName: 'Run Stage prerequisites one time from a Single agent'

    pool:
      name: ${{ parameters.pool }}

但是,真正的问题是您在哪里使用编译时表达式。本质上,在上面,整个 ${{ parameters.pool }} 被 $(buildPool) 替换,这是一个编译时的队列时间变量。但是,池支持使用变量作为池名称。在您可以使用表达式、变量(编译或运行)以及您必须使用常量的地方,这是如此令人费解且未记录在案。

一个这样的例子:

jobs:
- job: SliceItFourWays
  strategy:
    parallel: 4  # $[ variables['noOfVMs'] ] is the ONLY syntax that works to replace 4

在某些地方,例如 Pool 需求,微软的 YAML 解析器尽职尽责地替换了变量。但是,运行时不支持自定义变量作为 LVALUE。

它仅支持在需求的 RVALUE 部分中评估自定义运行时变量。

  pool: 
    name: ${{ parameters.buildPool }} # Run time supports variables here
    demands: 
      - ${{ parameters.subPool }}  # LVALUE: Must be resolved to a CONSTANT at compile time
      - poolToRunOn -equals '${{ parameters.subPool }}'  # RVALUE... custom user capability.  This evaluates and applies the demand correctly.

结论:

微软的 YAML 实现很糟糕!

于 2020-08-19T02:51:21.723 回答