在使用模板的相当复杂的 YAML 设置中,我尝试定义一个参数对象,其中包含环境级别的一些默认服务设置和可选覆盖,如下所示:
extends:
template: YAML/pipeline.yml@templates
parameters:
DefaultSettings:
Service1:
Setting1: Value1
Setting2: Value2
Service2:
Setting1: Value1
Environments:
Development:
Settings:
Service1:
Setting2: OtherValue2
Service2:
Setting1: OtherValue1
[...]
Test:
Settings:
Service2:
Setting1: OtherValue1
这个想法是定义一次常用的环境设置,并且仅在存在差异的地方进行覆盖。这些设置按服务分组,因为稍后在模板中,每个服务都会单独处理。
在
YAML/pipeline.yml@templates
中,我正在迭代环境:
stages:
- ${{ each environment in parameters.Environments }}:
- template: environment.yml
parameters:
Environment: ${{ environment.Value }}
DefaultSettings: ${{ parameters.DefaultSettings }}
在
environment.yml
中,我尝试将默认值和覆盖组合到最终的 Settings
对象中,以便进一步传递到执行实际工作的模板中。我正在根据 DefaultSettings
的结构重建这个对象:
stages:
- template: environment-stages.yml
parameters:
Settings:
${{ each service in parameters.DefaultSettings }}:
${{ service.Key }}:
${{ each setting in service.Value }}:
${{ setting.Key }}: ${{ coalesce(parameters.Environment.Settings[service.Key][setting.Key], setting.Value) }}
问题是,当我尝试运行此管道时,Azure DevOps 在上面的最后一行抛出错误,这并没有真正帮助:
Encountered error(s) while parsing pipeline YAML:
/YAML/environment.yml@templates (Line: 16, Col: 33): Unable to convert the object to a template token. Actual type 'System.Collections.Generic.List`1[[System.Collections.Generic.KeyValuePair`2[[Microsoft.TeamFoundation.DistributedTask.Pipelines.Yaml.ObjectTemplating.Tokens.ScalarToken, Microsoft.TeamFoundation.DistributedTask.Pipelines.Yaml, Version=19.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a],[Microsoft.TeamFoundation.DistributedTask.Pipeline[...]
我猜它不喜欢
parameters.Environment.Settings[service.Key][setting.Key]
的语法,但我没有其他想法。
你是吗?
根据您共享的yaml文件进行测试,我没有遇到相同的错误,并且管道工作正常。
azure-pipelines.yml:
trigger:
- none
pool:
vmImage: ubuntu-latest
extends:
template: pipeline.yml
parameters:
DefaultSettings:
Service1:
Setting1: Value1
Setting2: Value2
Service2:
Setting1: Value1
Environments:
Development:
Settings:
Service1:
Setting2: DevelopmentValue2
Service2:
Setting1: DevelopmentValue1
Test:
Settings:
Service2:
Setting1: TestValue1
管道.yml:
parameters:
- name: DefaultSettings
type: object
default: []
- name: Environments
type: object
default: []
stages:
- stage: Pipeline
jobs:
- job: job
steps:
- script: |
echo "ENVIRONMENTS: ${ENVIRONMENTS}"
echo "DEFAULTSETTINGS: ${DEFAULTSETTINGS}"
env:
ENVIRONMENTS: ${{ convertToJson(parameters.Environments) }}
DEFAULTSETTINGS: ${{ convertToJson(parameters.DefaultSettings) }}
- ${{ each environment in parameters.Environments }}:
- template: environment.yml
parameters:
Environment: ${{ environment.Value }}
DefaultSettings: ${{ parameters.DefaultSettings }}
环境.yml:
parameters:
- name: Environment
type: object
default: []
- name: DefaultSettings
type: object
default: []
stages:
- stage:
jobs:
- job: job
steps:
- script: |
echo "ENVIRONMENT: ${ENVIRONMENT}"
echo "DEFAULTSETTINGS: ${DEFAULTSETTINGS}"
env:
ENVIRONMENT: ${{ convertToJson(parameters.Environment) }}
DEFAULTSETTINGS: ${{ convertToJson(parameters.DefaultSettings) }}
- template: environment-stages.yml
parameters:
Settings:
${{ each service in parameters.DefaultSettings }}:
${{ service.Key }}:
${{ each setting in service.Value }}:
${{ setting.Key }}: ${{ coalesce(parameters.Environment.Settings[service.Key][setting.Key], setting.Value) }}
环境阶段.yml:
parameters:
- name: Settings
type: object
default: []
stages:
- stage:
jobs:
- job: job
steps:
- script: |
echo "Settings: ${SETTINGS}"
env:
SETTINGS: ${{ convertToJson(parameters.Settings) }}
结果: