问题
I'm attempting to update my build definitions in Azure DevOps using the REST API via a PowerShell script...
$header = @{Authorization = 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$($personalAccessToken)"))}
$definitions = Invoke-RestMethod -Uri "https://devops.domain.com/Collection/Project/_apis/build/definitions" -Method GET -Header $header
$branchNames = 'master', 'feature'
ForEach ($definition in $definitions.value) {
$definition | Add-Member -NotePropertyName triggers -NotePropertyValue (@{ triggerType = 'continuousIntegration'; branchFilters = $branchNames | % {"+refs/heads/$_/*"} }) -Force
$body = $definition | ConvertTo-Json
Write-Host $body
Invoke-RestMethod -Uri "https://devops.domain.com/Collection/Project/_apis/build/definitions/$($definition.id)?api-version=5.0" -Method PUT -ContentType application/json -Body $body -Header $header
}
It's not particularly clear from the Azure DevOps documentation how I should update the build definition using this method, but the above results in the following error:
Invoke-RestMethod : {"$id":"1","innerException":null,"message":"Value cannot be null.\r\nParameter name: definition.Repository","typeName":"System.ArgumentNullException, mscorlib","typeKey":"ArgumentNullException","errorCode":0,"eventId":0}
This is where I'm wondering if I'm barking up the wrong tree as this should surely be simpler (I found a simple solution on SO here for creating a new build definition). In fact, all I want to do is update the trigger branch filters.
How do I achieve this using PowerShell and the REST API?
回答1:
The triggers
is array so you can't just edit it, you need to edit the triggers[0]
, the same thing it's the branchFilters
, you need to edit the branchFilters[0]
. also, you don't need to touch in the triggerType
.
All the above it's assuming that there is already a trigger in the build and you want to edit it, not add a new trigger section.
There is also a tricky thing in the branchFilters
array, if you have only 1 branch (master
for example) and you want to add another branch you need to add it to the array and not just edit the branchFilters[0]
value.
Last thing that should be fixed is the branches value, it should be +refs/heads/branchName
and not just the branch name.
So, I have a pipeline with test
branch trigger and I succeeded to edit the trigger to master
and feature/*
with this script:
# I get only one definition and update him, not iterate all my definitions
$definition = Invoke-RestMethod -Uri $url -Method Get
# Change the branch trigger from "test" to "master"
$definition.triggers[0].branchFilters[0] = "+refs/heads/master"
# Add another branch trigger - "feature/*"
$definition.triggers[0].branchFilters[0] += "+refs/heads/feature/*"
$body = $definition | ConvertTo-Json -Depth 10
Write-Host $body
Invoke-RestMethod -Uri $url -Method Put -ContentType application/json -Body $body
回答2:
Here is slide correction that works for me,
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$token = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$($personalAccessToken)"))
$headers.Add("Authorization", "Basic $token")
$headers.Add("Content-Type", "application/json")
$definitions = Invoke-RestMethod -Uri "https://devops.domain.com/Collection/Project/_apis/build/definitions" -Method GET -Headers $headers
ForEach ($definition in $definitions.value) {
$definition.triggers = (@{ triggerType = 'continuousIntegration'; branchFilters = 'master', 'feature/*' })
$definition.revision++
$body = $definition | ConvertTo-Json
Write-Host $body
Invoke-RestMethod -Uri "https://devops.domain.com/Collection/Project/_apis/build/definitions/$($definition.id)?api-version=5.0" -Method PUT -ContentType application/json -Body $body -Headers $headers
}
回答3:
It appears that the definitions received from the list method cannot be used directly with the update method. This is quite clear in the list response type BuildDefinitionReference which doesn't include properties such as triggers
. The definitions must be obtained from the get method using the definition IDs from the list method. This returns a BuildDefinition which does indeed have the triggers
property. This can then be modified and passed to the update method.
This is the working code:
$header = @{Authorization = 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$($personalAccessToken)"))}
$definitions = Invoke-RestMethod -Uri "https://devops.domain.com/Collection/Project/_apis/build/definitions" -Method GET -Header $header
$branchNames = 'master', 'feature'
ForEach ($definition in $definitions.value) {
$definitionToUpdate = Invoke-RestMethod -Uri "$($collection)$($project.name)/_apis/build/definitions/$($definition.id)" -Method GET -Header $header
$trigger = $definitionToUpdate.triggers | Where {$_.triggerType -eq 'continuousIntegration'}
if ($trigger) {
$trigger.branchFilters = $branchNames | % {"+refs/heads/$_/*"}
Invoke-RestMethod -Uri "https://devops.domain.com/Collection/Project/_apis/build/definitions/$($definition.id)?api-version=5.0" -Method PUT -ContentType application/json -Body ($definitionToUpdate | ConvertTo-Json -Depth 10) -Header $header
}
}
The code checks that the CI trigger exists before updating its branch filters.
来源:https://stackoverflow.com/questions/56855732/update-build-definition-using-azure-devops-rest-api-in-powershell