1
votes

I have an Azure Devops release pipeline (using the Classic Editor rather than yaml) and am having trouble setting a variable in an inline powershell script. The relevant part of the script is this:

Write-Host "Web is $web"
Write-Host "App is $app"

Write-Host "##vso[task.setvariable variable=MyWebEnv;]$web"
Write-Host "Set Web to $($MyWebEnv)"

Write-Host "##vso[task.setvariable variable=MyAppEnv;]$app"
Write-Host "Set App to $(MyAppEnv)" 

The log files indicate that my $web and $app variables hold the correct values, however the setting is not working.

I've tried writing out the value in both the $($env:MyWebEnv) and $(MyWebEnv) formats and both formats indicate that the ADO variable has not been set correctly.

My variable is defined in the variables tab on the pipeline. It is set to Settable at queue time. I have tried with no value set in the definition and an initial value and I can see that the initial value does not get overwritten.

I've tried running this on both a self-hosted agent and an Azure Pipelines Hosted agent - same results. I have another release pipeline that does something similar without issues.

I'm trying to use the variable in a subsequent Stage.

I don't want to write the variable to a file or anything as I want to use the variable to control whether the stage even runs.

Edit: Based on Levi's comment I tried adding isOutput=true and inspecting the variable in a subsequent step in the same stage - it's not visible even within a subsequent step:

pipeline output

========================================================================= Edit 2: I must have had a non visible character somewhere. I was composing the powershell in an external editor (just so I had more space) and pasting into the inline textbox in ADO - when I typed in the exact same thing I had into the editor it started working - sort of.

I can set the variable now and it's appearing in the task below, but what I really want is to use it in the next stages - in the IIS deployment group to control that IIS server A runs, but IIS server B doesn't. I'm attempting to do this in the Additional Options Run Expression.

I've tried and(succeeded(), eq(variables['MyWebEnv'], 'myvalue')

or (where MyOutput. is the name given to my output reference when setting the variable) and(succeeded(), eq(variables['MyOutpub.MyWebEnv'], 'myvalue') or and(succeeded(), eq(variables['MyOutpub_MyWebEnv'], 'myvalue')

To clarify, I'm doing this on the IIS Deployment Group itself, and not on any of the tasks within that group.

I keep seeing that the deployment is skipped due to: Evaluating: eq(variables['MyOutput,MyWebEnv'], 'myvalue') Expanded: eq(Null, 'myvalue') Result: False

2
Have you heard about Json to Variable extension? It helped me sometimes with variables across multiple stages.Rogerson Nazário

2 Answers

3
votes

As Levi Lu mentioned you can access pipeline variables in the next step. So if you set variables like this here:

enter image description here

$web ="some-web"
$app ="some-app"

Write-Host "##vso[task.setvariable variable=MyWebEnv;]$web"
Write-Host "##vso[task.setvariable variable=MyAppEnv;]$app"

then you can read them in this way:

enter image description here

Write-Host "Set Web to $(MyWebEnv)"
Write-Host "Set App to $(MyAppEnv)" 

enter image description here

And if you want to access them via env variables you should use this syntax:

Write-Host "Set Web to $($env:MYWEBENV)"
Write-Host "Set App to $($env:MYAPPENV)" 

Answer for EDIT 2:

What you actually need is output cross stage variables which is supported in YAML but not in classic pipelines. Please check this topics. You can overcome this but it requires an extra effort as it shown here. However, please remember that you can't publish an artifact from release pipeline.

Here you have docs for cross stage variables but as above, it works on YAML.

2
votes

The variable you were trying to set in the powershell task will only take effect in the following tasks, which means if you echo out the variable in its own powershell task, it will not output the overriden value. See here.

To set a variable from a script, you use the task.setvariable logging command. This doesn't update the environment variables, but it does make the new variable available to downstream steps within the same job.

So you can only refer to it in the downstream tasks by wrapping it around $(). See below:

steps:
- powershell: |
  
   Write-Host "##vso[task.setvariable variable=MyWebEnv]$web"

- powershell: |
     Write-Host "Set Web to $(MyWebEnv)"   

If you want to use it in a subsequent stage. You will have to make the variable to be an output variable by using isOutput=true. See here

- powershell: |
      
       Write-Host "##vso[task.setvariable variable=MyWebEnv;isOutput=true]$web"
  name: MyVariable

- powershell: echo "$(MyVariable.MyWebEnv)"

You should also give this powershell task a name in order to refer to it in the following stages. See here to learn how to refer to multiple stage output variables.

variables:
   web: $[stageDependencies.stageName.jobName.outputs['stepName.variableName']]

You also need add dependency on this stage for the following stages.

See below example:

stages:
- stage: VariableStage
  jobs:
  - job: VariableJob
    steps:
    - powershell: |
         $web = "---"
         Write-Host "##vso[task.setvariable variable=MyWebEnv;isOutput=true]$web"
      name: MyVariable

- stage:
  dependsOn: VariableStage
  variables:
    web: $[stageDependencies.VariableStage.VariableJob.outputs['MyVariable.MyWebEnv']]
  jobs:
  - job:
    steps:
    - powershell: echo "$(web)"