Search code examples
tfs-2015tfs-sdkazure-devops-rest-api

TFS2015 REST API Build definition update


I'm trying to update a build definition through REST API with PowerShell.

The script used is:

$url = "http://tfs:8080/tfs/collection/project/_apis/build/definitions/$($buildId)?api-version=2.0"
$obj = Invoke-RestMethod -Uri $url2 -Method Get -ContentType "application/json" -UseDefaultCredentials
$json = ConvertTo-Json $obj
Invoke-RestMethod -Uri $url -Method Put -Body $json -ContentType "application/json" -UseDefaultCredentials

First I've tried with a new empty definition and I've got the below error:

The collection must contain at least one element.Parameter name: definition.Options.Inputs

So I added an extra code to remove the "options" part from the returned json:

if($obj.options -ne $null){
    $obj.options = $null }

and the update worked. But when I'm using the code on an "real" existing build definition that is in production then I get another error:

The collection must contain at least one element. Parameter name: definition.RetentionRules.Rule.Branches.Filter

I'm using TFS2015 Update 3.

Why is not working a simple update (without any modification) of a build definition via REST API?


Solution

  • The line $json = ConvertTo-Json $obj needs changed to include the -Depth argument with a minimum value of 3. The default is 2 and because of the nesting the values are lost when converted from an object to Json. More specifically what happens is the values get converted from an array to a simple string.

    How to tell this is happening in the Json

    Without the depth parameter

    "retentionRules":  [
                               {
                                   "branches":  "+refs/heads/*",
                                   "artifacts":  "build.SourceLabel",
                                   "daysToKeep":  10,
                                   "minimumToKeep":  1,
                                   "deleteBuildRecord":  true,
                                   "deleteTestResults":  true
                               }
                           ]
    

    With the depth parameter

    "retentionRules":  [
                               {
                                   "branches":  [
                                                    "+refs/heads/*"
                                                ],
                                   "artifacts":  [
                                                     "build.SourceLabel"
                                                 ],
                                   "daysToKeep":  10,
                                   "minimumToKeep":  1,
                                   "deleteBuildRecord":  true,
                                   "deleteTestResults":  true
                               }
                           ]
    

    You will see that the the branches and artifacts values change from a string to an array with the proper depth value.

    What your example code should be

    $url = "http://tfs:8080/tfs/collection/project/_apis/build/definitions/$($buildId)?api-version=2.0"
    $obj = Invoke-RestMethod -Uri $url2 -Method Get -ContentType "application/json" -UseDefaultCredentials
    $json = ConvertTo-Json $obj -Depth 3
    Invoke-RestMethod -Uri $url -Method Put -Body $json -ContentType "application/json" -UseDefaultCredentials