How to use an array in a condition for Azure DevOps YAML

Viewed 4024

I have a template that defines an array of branches for each environment, so that I can control which branches cause a deploy to a particular environment. For example, the only branch I want deployed to production is master, but for UAT I want release, hotfix, and master. I've set-up a parent template that calls downstream templates in an 'each' loop. Inside the deploy template, I want to compare the array of allowed branches against the current branch to determine whether to proceed or not. Here's part of the parent template that passes the branches arrays:

- template: pipeline-templates/environment-pipeline.yml
  parameters:
    envs: 
      - name: devtest
        branches: 
        - 'refs/heads/master'
        - 'refs/heads/develop'
        - 'refs/heads/hotfix/'
        - 'refs/heads/release/'
      - name: nightly
        branches: 
        - 'refs/heads/master'
        - 'refs/heads/develop'
        - 'refs/heads/hotfix/'
        - 'refs/heads/release/'
      - name: qa
        branches: 
        - 'refs/heads/master'
        - 'refs/heads/hotfix/'
        - 'refs/heads/release/'
      - name: prod
        branches: 
        - 'refs/heads/master'

The environment-pipeline.yml below then calls the deploy template for each environment.

parameters:
  - name: envs # collection of environments to create/deploy
    type: object
    default:
      env:
        name: ''
        branches: []

stages:
- ${{ each env in parameters.envs }}:
  - template: deploy.yml
    parameters:
      environmentName: ${{ env.name }}
      onlyForBranches: ${{ env.branches }}

The above all works fine (note, I've deleted a lot of the YAML to simplify the example). The next stage is to use a condition with the array of branches in the deploy template. This is how I was hoping it would work, but doesn't.

parameters:
  environmentName: ''
  onlyForBranches: []

stages:
  - stage: branch_gate
    condition: and(succeeded(), in(variables['Build.SourceBranch'], ${{ parameters.onlyForBranches }}))

# then the deploy stages go here if above condition passes

This results in the following error:

Unable to convert from Array to String.

Is there some way to make this work, or should I use a different approach?

2 Answers

in is not the function to use. It takes n arguments and is true if the first argument equals any of the rest: in('B', 'A', 'B', 'C') => true

Try containsvalue instead:

condition: and(succeeded(), containsvalue(${{ parameters.onlyForBranches }}, variables['Build.SourceBranch']))

I agree with schummar on the use of containsValue, however the suggested approach did not work for me either.

Instead try this:

condition: and(succeeded(), ${{ containsValue(parameters.onlyForBranches, variables['Build.SourceBranch']) }})

Related