Search code examples
azure-devopsazure-pipelinesazure-powershell

I have a problem setting and accessing variables in devops pipeline (yaml)


I have a Azure DevOps pipeline template that is used for deploying a Arm template. Its also meant to parse the ARM template outputs into Devops variables that should be accessible throughout the pipeline run. But i have problem with setting the variable and accessing it.

Here is a print from the run where we can see the output from the template. It's an array containing strings.

Print from pipeline run showing the variable we are trying to use

When i attempt to access it in azure powershell script i do this and everything works well.

$outputJson = $deployment.outputs | ConvertTo-Json
Write-Host "print: $output"


Print output after converting to Json

So im able to print the output. But after that i want to set a variable that i can use in the pipeline run:

Here is my problem, im trying to set the variable here like this: (Tried some different ways)

Write-Output "##vso[task.setvariable variable=outputTest;isOutput=true]$outputJson"

Here is some examples of my syntax when trying to access the variable.

Write-Host "print var test1: $outputTest"
Write-Host "print var test2: $(outputTest)"
Write-Host "print var test3: ${{ $variables.outputTest }}"
Write-Host "print var test4: '${{ $variables.outputTest }}'"

but what ever i do i do the printed output is empty. I feel so stupid.. haha Any ideas?

Additional information:

This is the structure of the yaml file where the commands take place


steps:
  - script: |
      echo parameters.serviceconnection - ${{parameters.serviceconnection}}
      echo resourceGroup - ${{parameters.resourceGroup}}
      echo resourceGroupLocation - ${{parameters.resourceGroupLocation}}
      echo overrideParameters - ${{parameters.overrideParameters}}
    displayName: 'arm-template.yml - Variable list'

task: AzurePowerShell@5
    displayName: "PowerShell template deploy"
    inputs:
      azureSubscription: ${{parameters.serviceConnection}}
      scriptType: InlineScript
      azurePowerShellVersion: LatestVersion
      inline: |
    "my code"

Solution

  • If not mistaken, the reason you are not seeing the variable is because when you are using isOutput=true the task/step itself would need to be referenced.

    This flag is important for passing variables/data between stages & jobs, but can be skipped for tasks within the same job.

    I will give you 2 alternatives on how you should be able to solve it.

    Option 1

    Remove the isOutput=true from Write-Output "##vso[task.setvariable variable=outputTest;isOutput=true]$outputJson"

    This should make it into a regular variable and can there after be called by $(outputTest).

    Please note that this variable only exists within the same job and is only known for the agent running the job. It can be referenced within the same job, but it cannot be referenced/called anywhere else thereafter.

    Option 2

    If you keep isOutput=true you would need a way to reference the task itself:

    - task: AzurePowerShell@5
        displayName: "PowerShell template deploy"
        name: NameOfMyTask
        inputs:
          azureSubscription: ${{parameters.serviceConnection}}
          scriptType: InlineScript
          azurePowerShellVersion: LatestVersion
          inline: |
           "your code"
    

    By adding name: NameOfMyTask while keeping isOutput=true you should be able to reference it by $(NameOfMyTask.outputTest)

    Passing it to another job

    With isOutput=true it can also be referenced in another job using the following example:

    - job: MySecondJob
      dependsOn: [MyFirstJob] # This is your job where you set the variable with isOutput=true
      variables:
        myOutput: $[ dependencies.MyFirstJob.outputs['NameOfMyTask.outputTest'] ]
    
      steps:
    
      - pwsh: |
          Write-Output $(myOutput)
    

    With isOutput=true it can also be referenced in another stage using the following example:

    Passing it to another stage

    - stage: MySecondStage
      dependsOn: [MyFirstStage] # This is your stage where you set the variable with isOutput=true
      variables:
        myOutput: $[ stageDependencies.MyFirstStage.MyFirstJob.outputs['NameOfMyTask.outputTest'] ]
      
      jobs:
    
      - job: MySecondJob
    
        steps:
    
        - pwsh: |
            Write-Output $(myOutput)
    

    The reason the dependsOn is needed is because $[] is a runtime expression, and if it would not await the first stage/job/step to be completed and hence the variable set, it would lead to an empty value/null for the variable.

    Hope you can solve it using the provided information, good luck!