variablesazure-devopsazure-pipelinesazure-pipelines-yaml

Passing Variables between Stages in Azure DevOps Pipeline


I am trying to pass a variable from one stage to another but somehow its is not working, I did check the other answers here on Stackoverflow but it didnt work (or maybe I am doing something wrong)

I am trying to pass the Variable $NEW_VERSION to the Cleanup Stage but in the output is empty:

enter image description here

This is my .yaml pipeline:

stages:
  - stage: ImageDeployment
    jobs:
      - job: NewImageDeployment
        timeoutInMinutes: 180
        pool:
          vmImage: 'ubuntu-latest'
        steps:
          - task: AzureKeyVault@2
            displayName: 'Fetch Secrets'
            inputs:
              connectedServiceName: '$(GLOBAL_SERVICE_CONNECTION)'
              keyVaultName: $(GLOBAL_KV_NAME)
              secretsFilter: "Packer-Secret"
              runAsPreJob: false

          - task: AzureCLI@2
            displayName: 'Check image version'
            retryCountOnTaskFailure: 0
            inputs:
              azureSubscription: '$(GLOBAL_SERVICE_CONNECTION)'
              scriptType: 'bash'
              scriptLocation: 'inlineScript'
              inlineScript: |
                while IFS=$'\t' read -a arr_image_versions; do
                  version=${arr_image_versions[0]}
                  date=${arr_image_versions[1]}
                  if [[ $date > $old_date ]]; then
                    last_version=$version
                  fi
                  old_date=$date
                done <<< "$(az sig image-version list --gallery-image-definition xxxxxxx --gallery-name xxxxxxxx --resource-group xxxxxxxxx --query "[].[name, publishingProfile.publishedDate]" -o tsv)"
                echo "Last image version: $last_version"
                echo "##vso[task.setvariable variable=last_version]$last_version"
            
          - task: Bash@3
            name: CheckImageVersion
            displayName: 'Increment image version'
            inputs:
              targetType: 'inline'
              script: |
                IFS='.' read -ra VERSION_PARTS <<< "$(last_version)"
                PATCH_VERSION=${VERSION_PARTS[2]}
                PATCH_VERSION=$((PATCH_VERSION + 1))
                NEW_VERSION="${VERSION_PARTS[0]}.${VERSION_PARTS[1]}.$PATCH_VERSION"
                echo "New image version: $NEW_VERSION"
                echo "##vso[task.setvariable variable=NEW_VERSION;isOutput=true]$NEW_VERSION"


  - template: tests/build_functionapp_testcase2.yaml@self

  - template: tests/datafactory_testcase3.yaml@self

  - stage: Cleanup
    condition: failed()
    jobs:
      - job: DeleteImage
        pool:
          vmImage: 'ubuntu-latest'
        variables:
          NEW_VERSION: $[ stageDependencies.ImageDeployment.NewImageDeployment.outputs['CheckImageVersion.NEW_VERSION'] ]
        steps:
          - script: |
              echo "NEW_VERSION in Cleanup stage: $(NEW_VERSION)"
          - task: AzureCLI@2
            displayName: 'Delete Packer Image'
            inputs:
              azureSubscription: '$(GLOBAL_SERVICE_CONNECTION)'
              scriptType: 'bash'
              scriptLocation: 'inlineScript'
              inlineScript: |
                echo "Deleting image version: $(NEW_VERSION)"
                az sig image-version delete --gallery-image-definition xxxxxxxxxxxxxxxxxxxxxxx

Solution

  • On stage "Cleanup", you missed the option "dependsOn" to let stage "Cleanup" to depend on stage "ImageDeployment".

    The "dependsOn" relationship also will ensure the stage "Cleanup" runs after the stage "ImageDeployment".

    stages:
    - stage: ImageDeployment
    
    . . .
    
    - stage: Cleanup
      dependsOn: ImageDeployment
    

    If not set the "dependsOn" relationship, stage "Cleanup" cannot fetch the output from stage "ImageDeployment" when there are some other stages also are consuming the output from stage "ImageDeployment".

    Related documentations:


    EDIT:

    From the YAML you provided, I noticed you are using two fixed templates. If the names of stages defined in the templates also are fixed, on the stage "Cleanup", you can directly provide a list of stage names to the "dependsOn" option.

    stages:
    - stage: ImageDeployment
    
    . . .
    # Some stages from templates.
    . . .
    
    - stage: Cleanup
      dependsOn:
        - ImageDeployment
        - <name of stage_1 defined in templates>
        - <name of stage_2 defined in templates>
        . . .
        - <name of stage_N defined in templates>
      condition: failed()