Automation, Azure, Azure DevOps, Professional, YAML Pipelines

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

       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:

- deployment: deploy_${{ parameters.environmentName }}
  displayName: Deploy ${{ parameters.environmentName }}
  - ${{ 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
  - 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

            environmentName: ${{ environmentObject.environmentName}}
            regionAbrvs: ${{ environmentObject.regionAbrvs }}

Then we may use this information to parse through the region object in the next template:

      - ${{ each regionAbrv in parameters.regionAbrvs }} :
        - template:deploy_job.yml@YAMLTemplates
            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.