Advanced Azure DevOps YAML Objects
Updated: Check out my presentation to the Omaha Azure User Group that covers these in action!
Update 2: Check out my GitHub repo TheYAMLPipelineOne for examples leveraging this method.
Sometimes the need to do some advanced templating requires the use of YAML objects in Azure DevOps. Here a couple of quick ways I’ve used some more advanced YAM objects. I have omitted the actual YAML templates as this focuses more on the advanced usage of YAML objects.
First let’s say we are deploying to multiple environments. Instead of copying and pasting each environment what if we could store our environment names in an object and just loop through? We would declare the object like:
- name: environmentNames
type: object
default: ['dev','uat', 'prod']
And then loop through our template like:
- ${{ each environmentName in parameters.environmentNames }} :
- template: stages/terraform_deploy_env_stage.yml
parameters:
environmentName: ${{ environmentName}}
This loop will go through each object and we can see just by using ${{ environmentName}}
we are referring to the instance of ${{envornmentNames}}
.
Then inside the job we can load environment specific variables for each like:
jobs:
- deployment: deploy_${{ parameters.environmentName }}
displayName: Deploy ${{ parameters.environmentName }}
variables:
- ${{ parameters.environmentName }}.yml
This process will save from having to define the same stage/job multiple times and we can call specific variables scoped to the necessary stage/job.
Let’s take this concept a step further and say we have a scenario where our dev is deployed to one region while uat environment might be deployed to multiple. In this scenario the region is a property of the environment. This may look like:
- name: environmentObjects
type: object
default:
- environmentName: 'dev'
regionAbrvs: ['eus']
- environmentName: 'uat'
regionAbrvs: ['eus', 'cus']
And then the passing to our template look like:
- ${{ each environmentObject in parameters.environmentObjects }} :
- template: deploy_env_stage.yml
parameters:
environmentName: ${{ environmentObject.environmentName}}
regionAbrvs: ${{ environmentObject.regionAbrvs }}
Then we may use this information to parse through the region object in the next template:
jobs:
- ${{ each regionAbrv in parameters.regionAbrvs }} :
- template:deploy_job.yml@YAMLTemplates
parameters:
environmentName: ${{ parameters.environmentName}}
regionAbrv: ${{ regionAbrv }
So, now we can deploy to different environments and different regions just by using the correct syntax and structuring the YAML templates appropriately.
If interested in this topic check out my other posts: Introduction to the Joy of Azure DevOps MultiStage YAML Pipelines, What to Do When Azure DevOps YAML Pipelines Fail, Leveraging YAML Pipelines: The New Deployment Architecture, Testing YAML Pipeline Changes.
https://github.com/JFolberth/TheYAMLPipelineOne/blob/main/tasks/ado_copy_files_task.yml#L14
just in case, I found a mistake in the file
Thanks, I will get that updated.
Quick note for those who may be struggling to pass objects as parameters. I found that you absolutely need to declare the parameters in the templates you call in some circumstances (I don’t have a great understanding of when they are required and not). I started experimenting with a simple object and I didn’t have to declare the parameters at the start of the template. I later tried using a complex object and my pipeline was throwing errors, after lots of experimentation I declared the parameters and it started to work just fine.
Curious and would like to understand more. Are you referring to variables vs parameters or defining the schema for nested parameter objects?
Hey John, I was inspired by your post above and restructured all of our Production pipelines based on this, Thank you!, Pipelines are much quicker and less error prone!. I’ve built upon above quite a bit and tailored to Bicep. I don’t have a blog yet, but just about to start one, would you mind if i used a bit of you blog content, whilst also adding my own additions? i would of course give credit and link to this page?
Absolutely. Would be happy to help and see what you have. Feel free to reach out on LinkedIn, happy to hear what others are doing in this space!