In Azure DevOps I needed to determine a variable in one deployment stage, and use it in another. I remember finding and implementing this solution before but couldn’t figure out how I did things, so this post is for me to find it easier next time 😉.
For example, in a stage I want to set a variable with the name ReleaseVariableName to a value. Searching online points you to an example on how to do this with for example the PowerShell command below. You first create a variable in the variable tab and then set/overwrite its value:
Write-Host "##vso[task.setvariable variable=ReleaseVariableName;]Value1.0"
Get hands-on experience on Azure DevOps from live experts at DevOps Online Training
Note that you don’t necessarily need to create variable, Azure DevOps does that for you. But it helps in figuring out what is happening later on.
The issue
Testing the code above will prove that this works, but that the variable values are reset in a new Agent Job or another Stage. This stems from the fact that each job or stage can be run on a different Agent (and even in parallel) and that the values are not synced across.
The fix: use the REST API for Azure DevOps
The only way I found to update the variable value is to use the REST API for Azure DevOps, find the current release we’re in and then overwrite the variable value there. Then the next Stage / Job will pick up the new value and you can continue.
Do note that this updated value will not be available with this in the same stage as you’re updating it in! Handle that separately.
#region variables
$ReleaseVariableName = 'StageVar'
$releaseurl = ('{0}{1}/_apis/release/releases/{2}?api-version=5.0' -f $($env:SYSTEM_TEAMFOUNDATIONSERVERURI), $($env:SYSTEM_TEAMPROJECTID), $($env:RELEASE_RELEASEID) )
#endregion
#region Get Release Definition
Write-Host "URL: $releaseurl"
$Release = Invoke-RestMethod -Uri $releaseurl -Headers @{
Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
}
#endregion
#region Output current Release Pipeline
Write-Output ('Release Pipeline variables output: {0}' -f $($Release.variables | ConvertTo-Json -Depth 10))
#endregion
#region Update StageVar with new value
Write-Host "Updating release variable with name [$(ReleaseVariableName)] with new value [$(ReleaseVariableValue)]"
$release.variables.$(ReleaseVariableName).value = "$(ReleaseVariableValue)"
#endregion
#region update release pipeline
Write-Output ('Updating Release Definition')
$json = @($release) | ConvertTo-Json -Depth 99
Invoke-RestMethod -Uri $releaseurl -Method Put -Body $json -ContentType "application/json" -Headers @{Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN" }
#endregion
#region Get updated Release Definition
Write-Output ('Get updated Release Definition')
Write-Host "URL: $releaseurl"
$Release = Invoke-RestMethod -Uri $releaseurl -Headers @{
Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
}
#endregion
#region Output Updated Release Pipeline
Write-Output ('Updated Release Pipeline variables output: {0}' -f $($Release.variables | ConvertTo-Json -Depth 10))
#endregion
Note: you will need to set the Job you are running this in to have access to the OAuth Access Token:

Even easier, download the Task Group definition
Making implementing this even easier, you can download my exported Task Group here and import it (after reviewing it for security issues of course!) into your own environment.
Authorization for the Service account you are using
Good to note that you need Manage Releases with the service you are running the deployment pipeline with, otherwise you will run into an error like this:
VS402904: Access denied: User Project Collection Build Service (AzDoServiceAccountName) does not have manage releases permission. Contact your release manager.
Future Azure DevOps update
There is a new update for Azure DevOps on its way to make this even easier as noted by the Azure DevOps team here. You can see that the initial issues was created in 2017 and the solution is rolling out in 2020 😄.
Update for yaml pipelines
After reading this blog post, Sebastian Schütze new about another way to fix this issue in a yaml pipeline: you have the option there to upload an artefact from the pipeline that can be downloaded in any subsequent stage/job.Sebastian Schütze @RazorSPoint
Get hands -on experience on YAML Files at DevOps Online Course
Recreation in Classic Pipeline
I wanted to check to see if I could replicate the behavior in a classic pipeline and it all seemed good: there is a Publish Pipeline Artifact task available that is meant just for cases like this.

You can then retrieve the file in the next stage/job and read it back in…. Or so was the plan:


The Upload Artifact task cannot be run in a release pipeline! 😠💩 It has been added to the documentation, but why they then show the task as being available and all, is beyond me. There have been more people who want this to work, as you can find in this GitHub issue.
There is an option to upload a file to the release pipeline, but then you cannot download it again:
Write-Host "##vso[task.uploadfile]$($file.FullName)"
Know more information from live experts at DevOps Training