Search code examples
azureazure-devopsazure-pipelines

Assigning run time variable from different stage to a template parameter


I'm trying to set the variable dynamically in a task in one stage and then pass it to template(that has multiple other stages) as a parameter. But this is not working for me. Can you let me know if I'm doing something wrong here?

stages:  
  - ${{ if eq(variables['Build.Reason'], 'ResourceTrigger') }}:
    - stage: StageA
      jobs:
      - job: JobA
        steps:
        - checkout: self
        - task: DownloadPipelineArtifact@2    
          inputs:
            buildType: 'specific'
            project: 'Project'
            artifactName: 'Environment.properties'
            targetPath: $(Build.SourcesDirectory)/Configurations/
            pipeline: 'test'
            runVersion: 'latest'
            
        - task: Bash@3
          displayName: Reset Environment details 
          name: SetEnv
          inputs:
            targetType: 'inline'
            script: |
              wrapper_environment=$(cat $(Build.SourcesDirectory)/Configurations/Environment.properties | grep Environment= | head -1 | cut -d '=' -f 2)
              wrapper_environment_for_services=$(cat $(Build.SourcesDirectory)/Configurations/Environment.properties | grep EnvSer= | head -1 | cut -d '=' -f 2)
              echo $wrapper_environment
              echo $wrapper_environment_for_services
              echo "##vso[task.setvariable variable=wrapper_environment;isOutput=true;]$wrapper_environment"
              echo "##vso[task.setvariable variable=wrapper_environment_for_services;isOutput=true]$wrapper_environment_for_services"
              cat $(Build.SourcesDirectory)/Configurations/Environment.properties
 
        
    - template: run/run_tests_template.yml@tests 
      parameters: 
        variable_group_name:  Sanity_variablegroup
        environment: $[ stageDependencies.StageA.JobA.outputs['SetEnv.wrapper_environment']]
        environment_for_services: $[ stageDependencies.StageA.JobA.outputs['wrapper_environment_for_services']]
        screenshot_required: $(screenshot_required)
        grid: $(grid)
        gridURL: $(gridURL)
        desktopBrowser: $(desktop_browser)
        # Testing only - delete later
        publish_test_results: true
        delete_pod : true
        download_property: true

Solution

  • Output variables are runtime variables. However, parameters are expanded just before the pipeline runs so that the value of the output variables can't be passed to the parameters.

    It's suggested that you use variables in your template and map the output variables to variables in your template.

    Consider the following example for a more intuitive understanding.

    main.yml: Define output variable wrapper_environment.

    stages:  
    - stage: StageA
      jobs:
      - job: JobA
        steps:
          - task: Bash@3
            displayName: Reset Environment details 
            name: SetEnv
            inputs:
              targetType: 'inline'
              script: |
                echo "##vso[task.setvariable variable=wrapper_environment;isOutput=true;]dev"
    
    - template: template.yml
      parameters:
        environment: $[ stageDependencies.StageA.JobA.outputs['SetEnv.wrapper_environment']]
    
    

    template.yml: Map the output variable to a stage-level variable myNewEnvironment.

    parameters:
    - name: environment
      displayName: environment
      type: string
      default: 'test'
    
    stages:
    - stage: StageB
      dependsOn: StageA
      variables:
        myNewEnvironment: $[stageDependencies.StageA.JobA.outputs['SetEnv.wrapper_environment']]
      jobs:
      - job: jobB
        steps:
        - script: |
            echo 'the value of parameter.environment is ${{ parameters.environment}}'
            echo 'the value of myNewEnvironment is $(myNewEnvironment)'
    

    The values of the variable myNewEnvironment and parameter environment are shown as below.

    enter image description here