Updating Azure DevOps Release Pipeline Variable During Release - azure

I have a classic Release Pipeline that has a few custom variables set that are used periodically throughout the release.
The first two steps in the release are two PowerShell scripts. In the first one, I basically take one of the variables, and assign a value to it. I then output what the variable was updated to so I can make sure it is correct (it always is). The second script does basically the same thing but to a different variable, and when I output the value, it is always correct.
Now, as the release is going, if I switch to the Variables tab, I can see the variable was never updated. It is still set at the value from the previous release. This is a major issue for me because about half way down the release, I have a "Copy Files" step, where it copies files to a folder path that is created from those variables. Since the variables are from the previous release, they are put into an improperly named folder path.
After the release pipeline is completed finished and succeeds, the Pipeline Variables are then correctly updated on the Variables tab.
Is there a way that I can update these variables DURING the release, instead of them updating after the release has completed? I would prefer to update them properly in my PowerShell scripts, or as a setting in the pipeline.
This is basically what my scripts looks like:
$url = "$($env:SYSTEM_TEAMFOUNDATIONSERVERURI)$env:SYSTEM_TEAMPROJECTID/_apis/Release/definitions/$($env:RELEASE_DEFINITIONID)?api-version=5.0-preview.3"
$pipeline = Invoke-RestMethod -Uri $url -Headers #{Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"}
Write-Host "Pipeline = $($pipeline | ConvertTo-Json -Depth 100)"
$buildNumber = $env:BUILD_BUILDNUMBER
$pipeline.variables.ReleaseVersion.value = $buildNumber
####****************** update the modified object **************************
$json = #($pipeline) | ConvertTo-Json -Depth 99
$updatedef = Invoke-RestMethod -Uri $url -Method Put -Body $json -ContentType "application/json" -Headers #{Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"}
write-host "================================="
write-host "The value of ReleaseVersion updated to " $updatedef.variables.ReleaseVersion.value
write-host "================================="
My variable (ReleaseVersion in the script above) is set in the Variables tab, it's scope is 'Release', and 'Settable at release time' is checked. I have also tried using Write-Host '##vso[task.setvariable variable=ReleaseVersion]$(Build.BuildNumber)' to set my variable, but I get the same outcome.
UPDATE
ADDING NEW SCRIPT AND LOG DESCRIPTION
So I just pushed new code through my pipeline. The build was numbered v2.1.0.16 (which is correct). I have the build number set to the branch name, plus a (:.rev) variable at the end.
The first script in the pipeline sets a custom pipeline variable called ReleaseVersion. It is set to the build number. This is the script:
$url = "https://vsrm.dev.azure.com/{organization}/$env:SYSTEM_TEAMPROJECTID/_apis/Release/definitions/$($env:RELEASE_DEFINITIONID)?api-version=5.0-preview.3"
$pipeline = Invoke-RestMethod -Uri $url -Headers #{Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"}
Write-Host "Pipeline = $($pipeline | ConvertTo-Json -Depth 100)"
$buildNumber = $env:BUILD_BUILDNUMBER
$pipeline.variables.ReleaseVersion.value = $buildNumber
####****************** update the modified object **************************
$json = #($pipeline) | ConvertTo-Json -Depth 99
$updatedef = Invoke-RestMethod -Uri $url -Method Put -Body $json -ContentType "application/json" -Headers #{Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"}
write-host "================================="
write-host "The value of ReleaseVersion updated to " $updatedef.variables.ReleaseVersion.value
write-host "================================="
and my output:
2020-05-11T03:02:21.5631557Z "id": #,
2020-05-11T03:02:21.5632209Z "name": "#",
2020-05-11T03:02:21.5632816Z "path": "#",
2020-05-11T03:02:21.5633410Z "projectReference": null,
2020-05-11T03:02:21.5634223Z "url": "https://vsrm.dev.azure.com/{organization}/{project}/_apis/Release/definitions/{definitionId}",
2020-05-11T03:02:21.5635058Z "_links": {
2020-05-11T03:02:21.5635643Z "self": {
2020-05-11T03:02:21.5636500Z "href": "https://vsrm.dev.azure.com/{organization}/{project}/_apis/Release/definitions/{definitionId}"
2020-05-11T03:02:21.5637445Z },
2020-05-11T03:02:21.5641618Z "web": {
2020-05-11T03:02:21.5643197Z "href": "https://vsrm.dev.azure.com/{organization}/{project}/_apis/Release/definitions/{definitionId}"
2020-05-11T03:02:21.5644085Z }
2020-05-11T03:02:21.5647518Z }
2020-05-11T03:02:21.5648322Z }
2020-05-11T03:02:22.4291104Z =================================
2020-05-11T03:02:22.4456531Z The value of ReleaseVersion updated to v2.1.0.15
2020-05-11T03:02:22.4483349Z =================================
2020-05-11T03:02:23.0643676Z ##[section]Finishing: Update Release Version
It says the value has been updated to v2.1.0.15, which is one revision behind the current build. I then have a script to make a folder path based on the above variable. It checks for a folder with that name (v2.1.0.15 for example), and will attach a -1 if it was already found, and a -2 if the -1 was already found, and so-on. It sets that folder name to a custom pipeline variable called RootDirectory. This is the script:
$url = "https://vsrm.dev.azure.com/{organization}/$env:SYSTEM_TEAMPROJECTID/_apis/Release/definitions/$($env:RELEASE_DEFINITIONID)?api-version=5.0-preview.3"
$pipeline = Invoke-RestMethod -Uri $url -Headers #{Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"}
write-host "Pipeline = $($pipeline | ConvertTo-Json -Depth 100)"
$rootDirectory = $pipeline.variables.BuildDirectory.value + "\" + $pipeline.variables.ReleaseVersion.value
if (test-path $rootDirectory) {
$newDirectory=$rootDirectory
$index=0
while (test-path $newDirectory) {
$index += 1
$newDirectory=$rootDirectory + "-" + $index
}
}
$pipeline.variables.RootDirectory.value = $newDirectory
####****************** update the modified object **************************
$json = #($pipeline) | ConvertTo-Json -Depth 99
$updatedef = Invoke-RestMethod -Uri $url -Method Put -Body $json -ContentType "application/json" -Headers #{Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"}
write-host "================================="
write-host "The value of Root Directory updated to " $updatedef.variables.RootDirectory.value
write-host "================================="
The BuildDirectory variable is a hardcoded variable that never changes. And it's output:
2020-05-11T15:32:45.7255688Z "id": #,
2020-05-11T15:32:45.7255852Z "name": "#",
2020-05-11T15:32:45.7256001Z "path": "#",
2020-05-11T15:32:45.7256166Z "projectReference": null,
2020-05-11T15:32:45.7256379Z "url": "https://vsrm.dev.azure.com/{organization}/{project}/_apis/Release/definitions/{definitionId}",
2020-05-11T15:32:45.7256556Z "_links": {
2020-05-11T15:32:45.7256698Z "self": {
2020-05-11T15:32:45.7256903Z "href": "https://vsrm.dev.azure.com/{organization}/{project}/_apis/Release/definitions/{definitionId}"
2020-05-11T15:32:45.7257174Z },
2020-05-11T15:32:45.7257331Z "web": {
2020-05-11T15:32:45.7257537Z "href": "https://vsrm.dev.azure.com/{organization}/{project}/_apis/Release/definitions/{definitionId}"
2020-05-11T15:32:45.7257721Z }
2020-05-11T15:32:45.7257862Z }
2020-05-11T15:32:45.7258016Z }
2020-05-11T15:32:46.6474274Z =================================
2020-05-11T15:32:46.6481861Z The value of Root Directory updated to
2020-05-11T15:32:46.6491120Z =================================
2020-05-11T15:32:46.7209281Z ##[section]Finishing: Create Root Directory
Notice how the output of that script is blank, it does not show what the variable was updated to.
A few steps later in my pipeline, is where I actually use those variables. It is in a "Copy files" pipeline task. The target folder is set to $(RootDirectory)/Debug, but since the RootDirectory variable isn't updated, it just copies the files to the root c: drive.

When I used code above with REST API ReleaseVersion remained the same as it was. However, I used logging command Write-Host '##vso[task.setvariable variable=ReleaseVersion]$(Build.BuildNumber)' and ReleaseVersion was updated but a new value was available in next step. So the new value should be available in Copy Files as it is a next step.

Updating Azure DevOps Release Pipeline Variable During Release
First, the reason why the logging command not work for you is that:
The variable set by the logging command can only be used inside the current agent, and will not modify the value of the web potral variable.
So, we could use the set variable in the next task, but if you want to update the variable on the Variables tab, you could use the REST API (Definitions - Update) to update the value of the release definition variable from a release pipeline:
PUT https://vsrm.dev.azure.com/{organization}/{project}/_apis/release/definitions/{definitionId}?api-version=5.0
Then, I have checked your scripts, it is close to the correct answer. The reason why it doesn't work for you is that you use variable $($env:SYSTEM_TEAMFOUNDATIONSERVERURI) in your url.
The default value of that variable is https://dev.azure.com/YourOrganization/. However, the API we use is that https://vsrm.dev.azure.com/{organization}, missing vsrm in the Url.
You could check my previous thread for some more details.
Hope this helps.

Related

How can I query for the yaml filepath for all pipelines in our dev azure project?

I want to list all the yaml files in use in any devops pipeline. I can do:
az pipelines show --project ProjectName --query '{pipeline:name,repo:repository.name,yml:process.yamlFilename}' --output table --name PipelineName
and get the right result:
Pipeline Repo Yml
------------- ------------- ---------------------------------------
PipelineName RepoName path/to/azure-pipeline.yaml
but if I list instead of show -- I want all of them, not one at a time -- list doesn't return the same level of detail. It doesn't give me repository and process data, so I can't list the repo name or the yaml path.
How can I get repo name and yaml path for all my pipelines?
To get repo name and yaml path for all your pipeline, you could use REST API to list all your pipeline, and get each pipeline details, then, according to result to get repository. Finally, generate a file with pipeline name, repository name and path. Here is the PowerShell script for the whole process. Please replace with your own PAT, organization name, project name and the path you want to store the file. Here set the path=null for classic pipeline.
$PAT ="<PAT>"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($PAT)"))
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Authorization", "Basic $base64AuthInfo")
$response = Invoke-RestMethod "https://dev.azure.com/<orgName>/<ProjectName>/_apis/pipelines?api-version=6.0-preview.1" -Method 'GET' -Headers $headers
$response | ConvertTo-Json
foreach ($value in $response.value)
{
$mid=$value.id
$url = "https://dev.azure.com/<orgName>/<ProjectName>/_apis/pipelines/"+$mid+"?api-version=7.1-preview.1"
$pipeline = Invoke-RestMethod $url -Method 'GET' -Headers $headers
$pipeline | ConvertTo-Json
$pipelinename = $pipeline.name
if ($pipeline.configuration.path)
{
$path=$pipeline.configuration.path
$repositoryid=$pipeline.configuration.repository.id
$url = "https://dev.azure.com/<orgName>/<ProjectName>/_apis/git/repositories/"+$repositoryid+"?api-version=6.0"
$repositorydetails = Invoke-RestMethod $url -Method 'GET' -Headers $headers
$repositorydetails | ConvertTo-Json
$repositoryName=$repositorydetails.name
}
else
{
$path="null"
$repositoryname=$pipeline.configuration.designerJson.repository.name
}
Write-Output "$pipelinename, $repositoryName, $path" >> C:\workspace1\new1\test.txt
}

how to list all NPM package and its version available in azure feed?

I have requested to list out all the NPM packages available in the Azure Artifact location.
Able to list from project scoped feed and unable to list NPM packages from Organization scoped feeds. Please help
As per this MSDoc - Get Packages
To list out all the packages available in the Azure Artifact location, use the below REST API
GET https://feeds.dev.azure.com/{organization}/{project}/_apis/packaging/Feeds/{feedId}/packages?api-version=6.0-preview.1
As per this MSDoc - Get Package Versions
To get the list of Package Versions, use the below API
GET https://feeds.dev.azure.com/{organization}/{project}/_apis/packaging/Feeds/{feedId}/Packages/{packageId}/versions/{packageVersionId}?api-version=6.0-preview.1
To get the list of npm packages Version, use
GET https://pkgs.dev.azure.com/{organization}/{project}/_apis/packaging/feeds/{feedId}/npm/{packageName}/versions/{packageVersion}?api-version=6.0-preview.1
Please refer Artifacts - Npm for more information
Below PowerShell script helped me to pull the list using PAT.
function GetUrl() {
param(
[string]$orgUrl,
[hashtable]$header,
[string]$AreaId
)
# Area ids
# https://learn.microsoft.com/en-us/azure/devops/extend/develop/work-with-urls?view=azure-devops&tabs=http&viewFallbackFrom=vsts#resource-area-ids-reference
# Build the URL for calling the org-level Resource Areas REST API for the RM APIs
$orgResourceAreasUrl = [string]::Format("{0}/_apis/resourceAreas/{1}?api-preview=5.0-preview.1", $orgUrl, $AreaId)
# Do a GET on this URL (this returns an object with a "locationUrl" field)
$results = Invoke-RestMethod -Uri $orgResourceAreasUrl -Headers $header
# The "locationUrl" field reflects the correct base URL for RM REST API calls
if ("null" -eq $results) {
$areaUrl = $orgUrl
}
else {
$areaUrl = $results.locationUrl
}
return $areaUrl
}
$orgUrl = "https://dev.azure.com/myorg"
$personalToken = "mytoken"
Write-Host "Initialize authentication context" -ForegroundColor Yellow
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($personalToken)"))
$header = #{authorization = "Basic $token"}
DEMO 1 List of projects
Write-Host "Project List"
#packaging ID refer https://learn.microsoft.com/en-us/azure/devops/extend/develop/work-with-urls?view=azure-devops&tabs=http&viewFallbackFrom=vsts
$coreAreaId = "7ab4e64e-c4d8-4f50-ae73-5ef2e21642a5"
$tfsBaseUrl = GetUrl -orgUrl $orgUrl -header $header -AreaId $coreAreaId
https://learn.microsoft.com/en-us/rest/api/azure/devops/core/projects/list?view=azure-devops-rest-5.1
project name should be specified for project based feed
#$projectsUrl = "$($tfsBaseUrl)Project/_apis/packaging/Feeds/{FeedName}/packages?api-version=6.0-preview.1"
#$projectsUrl = "$($tfsBaseUrl)/_apis/packaging/Feeds/platform-template/packages?includeAllVersions=True&api-version=6.0-preview.1"
No project name should be specified for Organization based feed
$projectsUrl = "$($tfsBaseUrl)/_apis/packaging/Feeds/{FeedName}/packages?api-version=6.0-preview.1"
$projects = Invoke-RestMethod -Uri $projectsUrl -Method Get -ContentType "application/json" -Headers $header
$projects.value | ForEach-Object {
write-output "Package Name:" $.name | Out-File "D:\File.txt" -Append
$projects2Url = "https://feeds.dev.azure.com/pdidev/apis/packaging/Feeds/{FeedName}/Packages/$($.id)/versions?api-version=6.0-preview.1"
$project2s = Invoke-RestMethod -Uri $projects2Url -Method Get -ContentType "application/json" -Headers $header
$project2s.value | ForEach-Object {
write-output $.version `n| Out-File "D:\file.txt" -Append
}
}

Azure devops release edit bulk 110

Hello I have 145 releases
And I have to do an equal action for everyone for example add a certain variable and edit a certain line.
Is there a way to control everyone with a script?
I checked for a template, but it creates the release from 0 and does not edit it.
Can a script in PS or Python be a solution? I did not find any information on Google about it, other than an export release template.
Azure devops release edit bulk 110
You could use the REST API Definitions - Update to update the release pipeline:
PUT https://vsrm.dev.azure.com/{organization}/{project}/_apis/release/definitions/{DefinitionsId}?api-version=6.0
And if we want to batch modify the release pipeline, we need to get each ID of the release pipeline with REST API Definitions - List:
GET https://vsrm.dev.azure.com/{organization}/{project}/_apis/release/definitions?api-version=6.0
Then we could iterate through each Rlease ID obtained.
I provide a rough code for your better reading:
$connectionToken="PAT"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($connectionToken)"))
$ReleasePipelineUrl = "https://vsrm.dev.azure.com/{organization}/{project}/_apis/release/definitions?api-version=6.0"
Write-Host "URL: $ReleasePipelineUrl"
$ReleasePipelines = (Invoke-RestMethod -Uri $PipelineUrl -Method Get -UseDefaultCredential -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)})
$ReleasePipelinesId = $ReleasePipelines.value.id
Write-Host "ReleasePipelinesId = $ReleasePipelinesId"
ForEach ($Pt in $ReleasePipelinesId)
{
$baseUrl = "https://vsrm.dev.azure.com/{organization}/{project}/_apis/release/definitions/$($Pt)?api-version=6.0"
$pipeline = (Invoke-RestMethod -Uri $baseUrl -Method Get -UseDefaultCredential -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)})
Write-Host "URL: $baseUrl"
$pipeline.variables.TestValue.value = "$buildNumber"
####****************** update the modified object **************************
$json = #($pipeline) | ConvertTo-Json -Depth 99
Write-Host "URL: $json "
$updatedef = Invoke-RestMethod -Uri $url -Method Put -Body $json -ContentType "application/json" -Headers #{Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"}
write-host "=========================================================="
Write-host "The value of Varialbe 'TestValue' is updated to" $updatedef.variables.TestValue.value
}

Output variables in Azure DevOps release pipeline gates

How do I use output variables in Azure DevOps release pipeline gates?
I would like to output a variable equal to the value of something in the response of the HTTP request.
e.g. The http request will return { success: true, userId: 12345 }. I would like to set a variable for userId which I can use in the next HTTP request gate.
As of this time, however, outputting variables in Invoke REST API in gates is not supported.
The output variables section cannot output the custom defined variables, but only the variables defined by the task.
Unfortunately, this task does not define an output variable. You can see it in the screenshot:
There are no output variables associated with this task.
Maybe this isn't what you are looking for, but you can use Azure Powershell to invoke HTTP Request and output the value of response that way to a pipeline variable for use in subsequent steps.
Refer to this Stack Overflow Post: How to access the response of the InvokeRestAPI task from another job in an Azure DevOps pipeline?
$url = "https://vsrm.dev.azure.com/thecodemanual/$env:SYSTEM_TEAMPROJECTID/_apis/Release/definitions/$($env:RELEASE_DEFINITIONID)?api-version=5.0"
$pipeline = Invoke-RestMethod -Uri $url -Headers #{Authorization = "Bearer
$env:SYSTEM_ACCESSTOKEN"}
Write-Host "Pipeline = $($pipeline | ConvertTo-Json -Depth 100)"
$buildNumber = $env:BUILD_BUILDNUMBER
$pipeline.variables.ReleaseVersion.value = $buildNumber
####****************** update the modified object **************************
$json = #($pipeline) | ConvertTo-Json -Depth 99
$updatedef = Invoke-RestMethod -Uri $url -Method Put -Body $json -ContentType "application/json" -Headers #{Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"}

Change variable group value of Azure Pipeline

I have a Variable Group in Azure Pipeline(below attached),
I want to change the value of isPOS to False through below mentioned conditions,
$angular = (Get-Content "$(system.defaultworkingdirectory)/amaze-commerce/angular.json" -Raw) | ConvertFrom-Json
if ($angular.defaultProject -ne "ecomm-ac-ecomm"){
// Please add your code here
}
Can you please guide me to change the Variable group value and i want to use the same in Release Pipeline.
In order to change the value of a variable group use Azure DevOps Api.
An example of how to update a variable group:
Variablegroups - Get Variable Groups - filtered by {groupName}
$pat ="<your-tfs-security-token>"
$read = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes(":$pat"))
$variableGroupName = "Check for angular.json"
$variableGroupId = ((Invoke-RestMethod -Method Get -Headers #{'Authorization' = "Basic $read" } -Uri "https://{instance}/{collection}/{project}/_apis/distributedtask/variablegroups?groupName=${variableGroupName}").Value).id
Variablegroups - Update
$body =#"
{
"variables": {
"isPOS": {
"value": $false
}
},
"type": "Vsts",
"name": "${variableGroupName}",
"description": "Updated variable group"
}
"#
$response= (Invoke-RestMethod -Uri "https://{instance}/{collection}/{project}/_apis/distributedtask/variablegroups/${variableGroupId}?api-version=5.0-preview.1" -Method Put -Headers #{'Authorization' = "Basic $read" } -ContentType "application/json" -Body $body)

Resources