Introduction
The recent addition to Azure DevOps of the StringList
parameter type can be really useful to dynamically create parallel stages or jobs in an Azure DevOps YAML pipeline.
A StringList
parameter can be used to present a list of values to the user queuing a pipeline run, thus allowing the selection of one or more values that can be accessed using a YAML expression loop.
This can be combined with YAML templates, where the StringList
is passed into a template as an Object
. Noting that you can’t use the StringList
type for a parameter type in the template definition. However, this is not a problem as there is a dynamic conversion from StringList
to Object
e.g.
# Azure-Pipeline.yml
parameters:
- name: environments
type: stringList
default:
- dev
values:
- dev
- test
- prod
trigger: none
extends:
template: template.yml
parameters:
environments: ${{parameters.environments }}
# template.yml
parameters:
- name: environments
type: object
stages:
- stage: Deploy
pool:
vmImage: ubuntu-latest
jobs:
- job: DeployJob
steps:
- checkout: none
- ${{ each value in parameters.environments }}:
- script: |
echo "Selected environments: ${{ value }}"
The Problem
Whilst implementing this new parameter type on an existing pipeline we got a very strange set of error messages ‘Unexpected a mapping’, ‘Unexpected at least one-value pair in the mapping’ and ‘Unexpected state while attempting t read the mapping end state’
After much experimentation we found the issue was the indenting of a steps
block later in the YAML. When the new loop expression was added only part of the jobs block was correctly indented.
The indenting was
jobs:
- ${{ each environment in parameters.Environments }}:
- job: build_${{ environment }}
steps:
...
When it should have been
jobs:
- ${{ each environment in parameters.Environments }}:
- job: build_${{ environment }}
steps:
...
So as usual when you get an unexpected and unclear error in Azure DevOps YAML, assume the problem is due to whitespace.