azure devops release pipeline , bulk edit - powershell

$Organization = "y"
$Project = "x"
$DefinitionID = "81"
$url = "https://dev.azure.com/$Organization/$Project/_apis/build/definitions/$DefinitionID?api-version=6.0"
Write-Host "URL: $url"
$pipeline = Invoke-RestMethod -Uri $url -Headers #{
Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
}
Write-Host "Pipeline = $($pipeline | ConvertTo-Json -Depth 100)"
$pipeline.variables.v1030.value = "xyz"
####****************** 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 Varialbe 'v1030' is updated to"
$updatedef.variables.v1030.value
error:
2022-03-17T13:05:24.9981259Z Invoke-RestMethod : {"$id":"1","innerException":null,"message":"Build pipeline
2022-03-17T13:05:24.9982421Z 81 was not found.","typeName":"Microsoft.TeamFoundation.Build.WebApi.Definition
2022-03-17T13:05:24.9982939Z NotFoundException, Microsoft.TeamFoundation.Build2.WebApi","typeKey":"Definitio
2022-03-17T13:05:24.9983313Z nNotFoundException","errorCode":0,"eventId":3000}
Hi I get this error in Logs,
I think I can not find the release pipeline number
The $ DefinitionID
I want to do it on 100 releases pipelines I'll wrap it with 'for' later, but first I want to see I can do on one

Related

Create annotated tag with build user

I have powershell script which is creating annotated tag for commit in azure repos, but when I run this script in azure release pipeline I got error: "The combination of parameters is either not valid or not complete." When I make call from Postman with my credentials. its working. I also set repo permission Create Tag to Allow. Which permission I need for creating annotated tags with build user?
$createTagUrl= "$($env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI)$env:SYSTEM_TEAMPROJECT/_apis/git/repositories/$($env:BUILD_REPOSITORY_ID)/annotatedtags?api-version=6.0-preview.1"
Write-Host "createTagUrl=" $createTagUrl
$jsonObject = #"
{
"name": "$($env:RELEASE_RELEASENAME)-$(ENVIRONMENT)",
"taggedObject":{
"objectId": "$($env:BUILD_BUILDID)"
},
"message": "test"
}
"#
Write-Host "JsonObject: " $jsonObject
$json = #($jsonObject) | ConvertTo-Json -Depth 99
$createdTag = Invoke-RestMethod -Uri $createTagUrl -Method Post -Body $json -ContentType "application/json" -Headers #{Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"}
I can reproduce your issue:
The root cause is the code on your side is wrong.
This should works:
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Authorization", "Basic <PAT>")
$headers.Add("Content-Type", "application/json")
$body = "{
`n `"name`": `"xxx`",
`n `"message`": `"xxx`",
`n `"taggedObject`": {
`n `"objectId`": `"<object id>`"
`n }
`n}"
$response = Invoke-RestMethod 'https://dev.azure.com/<Organization Name>/<Project Name>/_apis/git/repositories/<Repo Name>/annotatedtags?api-version=4.1-preview.1' -Method 'POST' -Headers $headers -Body $body
$response | ConvertTo-Json

Update Azure Devops Build Pipeline Variable with Rest API

I have an Azure Devops YAML based Build (Not Release) Pipeline. I have defined a variable called Department. My Requirement is that this variable to be updated at the end of the build using the rest API. I'm using this code.
How to modify Azure DevOps release definition variable from a release task?
The API call works fine. But I'm not sure whether this is the correct API to call. The Department will change for each build. According to the output HTTP method put is not supported.
Note: I have actually defined 5 variables including Department, Department being the last one. When the API is called it only outputs first 3 variables only.
$Department = getDepartment.ps1
$url = "https://dev.azure.com/xxx/xxx/_apis/pipelines/$(System.DefinitionId)/runs?api-version=6.0-preview.1"
$pipeline = Invoke-RestMethod -Uri $url -Headers #{
Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
}
Write-Host "Pipeline = $($pipeline | ConvertTo-Json -Depth 100)"
$pipeline.variables.Department.value = $Department
$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 Variable 'Department' is updated to $( $updatedef.variables.Department.value)"
write-host "=========================================================="
The Department will change for each build. According to the output HTTP method put is not supported.
According to the document Pipelines:
It does not provide a method for update pipeline with PUT.
To resolve this issue, you still need use the REST API Build Definitions - Update:
PUT https://dev.azure.com/{organization}/{project}/_apis/build/definitions/{definitionId}?api-version=6.0
The code sample:
$url = "https://dev.azure.com/{organization}/{project}/_apis/build/definitions/{definitionId}?api-version=6.0"
Write-Host "URL: $url"
$pipeline = Invoke-RestMethod -Uri $url -Headers #{
Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
}
Write-Host "Pipeline = $($pipeline | ConvertTo-Json -Depth 100)"
$pipeline.variables.Test.value = "$Department"
####****************** 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 Varialbe 'Test' is updated to" $updatedef.variables.Test.value
The test result:
When you start the pipeline using the API, you can add the values of the parameters that should be different from the default values, to the payload of the call. So you're not updating the definition, but just the value of the variables for that instance of the pipeline run.
Payload
$JSON = #"
{
"definition": {
"id":"207"
},
"parameters": "{ \"ENVIRONMENT\":\"$($config.testEnvironmentName)\", \"API_CLIENT_SECRET\":\"$($config.testEnvironmentApiClientSecret)\" }"
}
"#
Note that the 'parameters' property has a value as an escaped json string.
This is the API that I use to start the pipeline.
/_apis/build/builds?api-version=7.1-preview
Use a 'POST' method and send the json as the body of the request (content-type application/json).

Updating release def results in error VS402903: The specified value is not convertible to type ReleaseDefinition

I am updating release definitions using the onpremise Azure DevOps API using the following powershell script:
$listurl="https://onpremdomain/{ogr}/{proj}/_apis/release/definitions?api-version=6.0"
$PAT="Personal access token"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($PAT)"))
#get the releases' ids.
$result = Invoke-RestMethod -Uri $listurl -Headers #{Authorization = "Basic {0}" -f $base64AuthInfo} -Method get
#loop the ids to get each release's definition
foreach($release in $result.value){
#get each release's definition
$definitionurl="https://onpremdomain/{ogr}/{proj}/_apis/release/definitions/$($release.id)?&api-version=6.0"
$releaseDefinition = Invoke-RestMethod -Uri $definitionurl-Headers #{Authorization = "Basic {0}" -f $base64AuthInfo} -Method get
#loop through each stage
foreach( $environment in $releaseDefinition.environments){
#loop through each tasks to find the task group
foreach($task in $environment.deployPhases.workflowTasks){
# change the 'taskId' to the taskId of your task group
if($task.taskId -eq "{taskId}"){
$task.version = "2.*" # update the taskgroup version to the newest version
}
}
}
$updateurl="https://onpremdomain/{ogr}/{proj}/_apis/release/definitions?api-version=6.0"
# update the release definition
Invoke-RestMethod -Uri $updateurl -Headers #{Authorization = "Basic {0}" -f $base64AuthInfo} -ContentType "application/json" -Method PUT -Body (convertto-json $releaseDefinition -Depth 100)
}
When Invoke-RestMethod in the last line is called I get the following error:
Invoke-RestMethod : {"$id":"1","innerException":null,"message":"VS402903: The specified value is not convertible to type ReleaseDefinition. Make sure it is convertible to type ReleaseDefinition and
try again.","typeName":"Microsoft.VisualStudio.Services.ReleaseManagement.Data.Exceptions.InvalidRequestException, Microsoft.VisualStudio.Services.ReleaseManagement2.Data","typeKey":"InvalidRequestE
xception","errorCode":0,"eventId":3000}
Any idea why this error occurs?
REST API doc:
Get a list of release definitions.
Get a release definition.
Update a release definition.
Power shell script
$listurl="https://vsrm.dev.azure.com/{Org name}/{Project name}/_apis/release/definitions?api-version=6.0"
$PAT="{PAT}"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($PAT)"))
#get the releases' ids.
$result = Invoke-RestMethod -Uri $listurl -Headers #{Authorization = "Basic {0}" -f $base64AuthInfo} -Method get
write-host $result.value.id
#loop the ids to get each release's definition
foreach($release in $result.value){
#get each release's definition
$definitionurl="https://vsrm.dev.azure.com/{Org name}/{Project name}/_apis/release/definitions/$($release.id)?api-version=6.0"
#write-host $definitionurl
$releaseDefinition = Invoke-RestMethod -Uri $definitionurl -Headers #{Authorization = "Basic {0}" -f $base64AuthInfo} -Method get
#loop through each stage
foreach( $environment in $releaseDefinition.environments){
#loop through each tasks to find the task group
foreach($task in $environment.deployPhases.workflowTasks){
write-host $task.taskId
# change the 'taskId' to the taskId of your task group
if($task.taskId -eq "e213ff0f-5d5c-4791-802d-52ea3e7be1f1"){
write-host $task.version
$task.version = "1.*" # update the taskgroup version to the newest version
write-host $task.version
}
}
}
$updateurl="https://vsrm.dev.azure.com/{Org name}/{project name}/_apis/release/definitions?api-version=6.0"
# update the release definition
Invoke-RestMethod -Uri $updateurl -Headers #{Authorization = "Basic {0}" -f $base64AuthInfo} -ContentType "application/json" -Method PUT -Body (convertto-json $releaseDefinition -Depth 100)
}
Update
I found the issue, the second Invoke-RestMethod method is missing the space before the -Headers parameter, and the issue should be Invoke-RestMethod : A positional parameter cannot be found that accepts argument 'System.Collections.Hashtable'.
After adding a space before the parameter, it works, you could check the pic below.

Scheduling a Azure DevOps release using Powershell

I am able to trigger a Azure DevOps release using Rest API call. But when i tried to do it by adding the scheduling it is not working. The code i used is given below:
$PATtoken= 'PAT'
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($PATtoken)"))
$header=#{authorization= "Basic $token" }
$defurl = "https://vsrm.dev.azure.com/Orgnization/Project/_apis/release/definitions/13?api-version=5.1"
$definition = Invoke-RestMethod -Uri $defurl -Method Get -Headers $header
$triggers = '
[{
"schedule": {
"timeZoneId": "India Standard Time",
"startHours": 20,
"startMinutes": 40,
"daysToRelease": 31
}
}]'
$definition | Add-Member -NotePropertyName "triggers" -NotePropertyValue (Convertfrom-Json $triggers) -Force
$json = #($definition) | ConvertTo-Json -Depth 99
$updatedef = Invoke-RestMethod -Uri $defurl -Method Put -Body $json -ContentType "application/json" -Headers $header
Write-Host ($updatedef.triggers | ConvertTo-Json -Depth 99)
But unfortunately the scheduling or triggering is not happening.
You can do it in this way:
...
$definition = Invoke-RestMethod -Uri $defurl -Method Get -Headers $header
$hash = #(
#{ triggerType="schedule";
schedule = #{"daysToRelease"="31";"timeZoneId"="India Standard Time";"startHours"="20";"startMinutes"="40"}
}
)
$definition.triggers = $hash
$json = $definition | ConvertTo-Json -Depth 99
Invoke-RestMethod -Uri $defurl -Method Put -Body $json -ContnetType application/json -Headers $header
You should not add schedule into triggers to configure the release pipeline schedule execute.
You can use Postman as test. See below pic:
Even I have configure the schedule script in request body, the response body still has no content in the trigger.
To set the schedule, you need apply above schedule script to schedules which is nested under environment. Also, you could using Fiddler to capture the records to confirm this by configuring the schedule release from UI.

Getting Unauthorised error while triggering TFS build from release definition

I need to trigger a build after successful deployment of a release. I have tried using below code in Powershell in the release definition.
After executing, I get this error - Access is denied due to invalid credentials
$url = "http://abc:8080/tfs/GlobalCollection/Project/_apis/build/builds?
api-version=2.0"
$body = "{ 'definition' : { 'id' : 1} }"
$type = "application/json"
$headers = #{
Authorization = "Basic d3JlblxzcsampleTIzNA=="
}
Write-Host "URL: $url"
$definition = Invoke-RestMethod -Uri $url -Body $body -ContentType $type -
Method Post -Headers $headers
Write-Host "Definition = $($definition | ConvertTo-Json -Depth 1000)"`
Based on my test, you can use -UseDefaultCredentials :
$type = "application/json"
$url = "http://abc:8080/tfs/GlobalCollection/Project/_apis/build/builds?api-version=2.0"
$body = "{ 'definition' : { 'id' : 56} }"
Write-Host "URL: $url"
$definition = Invoke-RestMethod -Uri $url -Body $body -ContentType $type -Method Post -UseDefaultCredentials
Write-Host "Definition = $($definition | ConvertTo-Json -Depth 1000)"
Alternatively provide the specific Credential:
$user = "username"
$password = "password"
# Base64-encodes the Personal Access Token (PAT) appropriately
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$password)))
$headers = #{Authorization=("Basic {0}" -f $base64AuthInfo)}
$type = "application/json"
$url = "http://abc:8080/tfs/GlobalCollection/Project/_apis/build/builds?api-version=2.0"
$body = "{ 'definition' : { 'id' : 56} }"
Write-Host "URL: $url"
$definition = Invoke-RestMethod -Uri $url -Body $body -ContentType $type -Method Post -Headers $headers
Write-Host "Definition = $($definition | ConvertTo-Json -Depth 1000)"