Revisiting ADO YAML Objects and Looping
Introduction
My own experience has evolved since initially posting Advanced Azure DevOps YAML Objects two years ago! Thus thought a post revisiting ADO YAML Objects and Looping was warranted. This initial post is still widely popular and still one of the top results when looking for Azure DevOps and YAML Objects. There is nothing wrong with the initial posting, just a recognition that my skills as a blogger has grown and the information from Microsoft on YAML Pipelines as grown.
The Use Case
Suppose you are working in YAML Pipelines and would like to create an object. Inside that object say you have a need to a list of values. Typically I run into this when defining either an environment with multiple regions or a deployment with multiple projects.
Microsoft’s documentation was a little weak on what to do past defining an object and potentially looping through said object…until recently and more on that later.
Variable/Parameter Structure
The variable or parameters being used to loop through should follow a fairly straight forward syntax. In my TheYAMLPipelineOne, I have examples being read in as parameters with a default value.
parameters:
- name: environmentObjects
type: object
default:
- environmentName: 'dev'
regionAbrvs: ['cus']
- environmentName: 'tst'
regionAbrvs: ['cus','eus']
Looping
Azure DevOps YAML Pipelines does offer some looping functionality through the each
keyword. I have a submitted a Pull Request to have the documentation updated to include the following:
parameters:
- name: listOfFruits
type: object
default:
- fruitName: 'apple'
colors: ['red','green']
- fruitName: 'lemon'
colors: ['yellow']
steps:
- ${{ each fruit in parameters.listOfFruits }} :
- ${{ each fruitColor in fruit.colors}} :
- script: echo ${{ fruit.fruitName}} ${{ fruitColor }}
The basis of this is understanding the each
loop will go through and pull the listOfFruits
instance and store it in the fruit object. The second each
statement will go through the array of values for the colors
on each instance of listOfFruits
. We will echo the fruitName
from the first each
with each fruitColor
being iterated through the second each
.
In ADO this will look like:
2022-12-28T16:15:33.2955122Z Script contents:
2022-12-28T16:15:33.2957273Z echo apple red
.....
2022-12-28T16:15:33.9862565Z Script contents:
2022-12-28T16:15:33.9863692Z echo apple green
.....
2022-12-28T16:15:34.6171924Z Generating script.
2022-12-28T16:15:34.6183737Z Script contents:
2022-12-28T16:15:34.6185339Z echo lemon yellow
Updating Documentation/Additional Content
Part of this revisit is inspired of continuously viewing documentation that did not illustrate this. In addition to the pull request mentioned on Azure Pipelines each keyword I have also had PRs merged into Parameter Data Types to help show this example to a wider audiance.
If wanting to also learn more on how to use this one can watch my YouTube video on YAML Deployment Pipelines, TheYamlPipelineOne repository, or check out my series on Azure DevOps Pipelines on Microsoft’s Tech Community Platform
Conclusion
There it is. A simple look at revisiting ADO YAML Objects and Looping. This concept took me a while to discover and afterward made more advanced items like templating and multi-stage pipelines easier. Hopefully it does the same for you.
Hi John, thanks for this nice article.
You say “one can easily do this with variables as well”. Were you able to loop over a variable ? I have a use case where I need to create a list dynamically and would like to iterate over it later in the pipeline to invoke a given task multiple times.
As I understand it, variables are only strings and cannot be typed of something else. And the documentation also says the “each” keyword is only for parameters.
And given that my use case is rather dynamic, I think it’s not feasible. But it woud be nice to have your opinion on this.
Thanks.
Hey Matthew,
You are correct. I will update the article accordingly as this is something I overlooked. Variables can only be strings; however, I typically leverage templates to pass in parameter objects to the templates. Alternatively if need be I would have a variable template file with the appropriate values and then have that template scoped to the appropriate stage/job. If these are dynamic then this may not work for you.
If you wouldn’t mind sharing more would be happy to provide input. Some suggestions off the bat would be to consider how the variables would be scoped or alternatively dynamically create ADO variables in your pipelineto be used later on.