Search code examples
azure-devopsazure-pipelinesazure-pipelines-yaml

Azure Devops pipeline yaml create variable conditionally


I am trying to accomplish as follows in a variable.yml file (separate form pipeline file)

- name: environment
    value: $[ stageDependencies.StartStage.StartJob.outputs['StartJobVariables.environment'] ]
- name: serviceConnectionName
    ${{ if eq( variables.environment, 'dev' ) }}: 
      value: $[ stageDependencies.StartStage.StartJob.outputs['StartJobVariables.devServiceConnectionName'] ] 
    ${{ if eq( variables.environment, 'qa' ) }}: 
      value: $[ stageDependencies.StartStage.StartJob.outputs['StartJobVariables.qaServiceConnectionName'] ] 
    ${{ if eq( variables.environment, 'prod' ) }}: 
      value: $[ stageDependencies.StartStage.StartJob.outputs['StartJobVariables.prodServiceConnectionName'] ] 

so practically I would like to create a variable conditionally based on the value of another variable. How would I do this properly?


Solution

  • Service Connections are one of the few properties that cannot be set with a variable that is computed at runtime. The pipeline-run-sequence expands all templates out at compile-time in order to evaluate permissions and approvals. The only exception to this is if the variable is defined in the pipeline.yml at compile time.

    However, if you wanted to conditionally construct a variable there are a few options:

    Coalesce

    Based on the presence of other variables, the coalesce function will evaluate one or more values and take the first non-null value:

    variables:
    - name: environmentName
      value: $[ coalesce( variables['one'], variables['two'], variables['three']) ]
    
    - name: one
      value: $[ stageDependencies.myStage.myJob.outputs['myTask.myVarOne'] ]
    
    - name: two
      value: $[ stageDependencies.myStage.myJob.outputs['myTask.myVarTwo'] ]
    
    - name: three
      value: $[ stageDependencies.myStage.myJob.outputs['myTask.myVarThree'] ]
    

    Dynamic variable name

    The variables collection is a dictionary which you can access by name. If your variables follow a convention, simply construct the name of the variable using the format function:

    variables:
    # assuming the possible output variables are either:
    #  - devServiceConnection
    #  - stgServiceConnection
    #  - prdServiceConnection
    - name: myVariable
      value: $[ stageDependencies.MyStage.MyJob.outputs[format('MyTask.{0}ServiceConnection', variables['environment'))] ]
    

    Nested Replace

    There is no if( true, true-value, false-value) function, but you can emulate it by nesting replace statements. If you need to do more than two conditions, it can get really confusing to look at, but it works.

    variable:
      # assume variables['envName'] can be dev, stg, or prd
      development: 'one'
      staging: 'two'
      production: 'three'
      
      # replace syntax ( original-value, search-string, replace-value)
      myName: $[ 
         replace(
           replace(
             replace( variables['envName'], 'dev', variables['development'])),
             'stg', variables['staging'])
           , 'prd', variables['myStg'])
        ]