Azure DevOps API: не удается десериализовать основное значение

#powershell #azure-devops-rest-api

#powershell #azure-devops-rest-api

Вопрос:

Я пытаюсь добавить сохранение для запуска сборки через API (https://docs.microsoft.com/en-us/rest/api/azure/devops/build/leases/add?view=azure-devops-rest-6.0 ) с помощью PowerShell.

В приведенном ниже коде показаны 3 мои попытки добавить сохранение в сборку:

 $base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $User, $Token))) #Encrypt token
$Head = @{Authorization = ("Basic {0}" -f $base64AuthInfo)}
$uri = "https://dev.azure.com/$myorg/$myproject/_apis/build/retention/leases?api-version=6.0-preview.1"
    
$BodyJson = '{
    "daysValid":"5",
    "DefinitionID":"12706",
    "ownerId":"dashboard",
    "protectPipeline":"true",
    "runId":"2971238"
}'

$BodyConvertTo = @{
    daysValid = "5"
    DefinitionID= "12706"
    ownerId = "dashboard"
    protectPipeline = "true"
    runId = "2971238"
} | ConvertTo-Json

$BodyObj = @{
    daysValid = "5"
    DefinitionID= "12706"
    ownerId = "dashboard"
    protectPipeline = "true"
    runId = "2971238"
}

#BodyJson
Invoke-RestMethod -Uri $uri -Method POST -Headers $Head -Body $BodyJson -ContentType "application/json" -verbose

#BodyConvertTo
Invoke-RestMethod -Uri $uri -Method POST -Headers $Head -Body $BodyConvertTo -ContentType "application/json" -verbose

#BodyObj
Invoke-RestMethod -Uri $uri -Method POST -Headers $Head -Body $BodyObj -ContentType "application/json" -verbose
 

Результаты:

$BodyJson:

 Invoke-RestMethod : {"$id":"1","innerException":null,"message":"This request expects an object in the request body, but the supplied data could not be 
deserialized.","typeName":"Microsoft.TeamFoundation.Build.WebApi.RequestContentException, Microsoft.TeamFoundation.Build2.WebApi","typeKey":"RequestContentException","errorCode":0,"eventId":3000}
 

$BodyConvertTo:

 Invoke-RestMethod : {"$id":"1","innerException":null,"message":"This request expects an object in the request body, but the supplied data could not be 
deserialized.","typeName":"Microsoft.TeamFoundation.Build.WebApi.RequestContentException, Microsoft.TeamFoundation.Build2.WebApi","typeKey":"RequestContentException","errorCode":0,"eventId":3000}
 

$BodyObj:

 Invoke-RestMethod : {"$id":"1","innerException":null,"message":"TF400898: An Internal Error Occurred. Activity Id: 5b090138-3392-4d76-8ebb-99d9968959c9.","typeName":"Newtonsoft.Json.JsonReaderException, 
Newtonsoft.Json","typeKey":"JsonReaderException","errorCode":0,"eventId":0}
 

Итак, мне интересно, ему не нужны ни Json, ни PSObject, что я должен отправить в body, чтобы заставить его работать?

Комментарии:

1. Вы устанавливаете все свойства в виде строк, заключая их в двойные кавычки. Здесь это объясняется daysValid definitionId и runId должно быть целыми числами. protectPipeline должно быть логическое значение: "protectPipeline": true не строка "protectPipeline": "true" . Можете ли вы попробовать это?

2. Пробовал, не повезло. В приведенном ниже ответе есть решение, спасибо всем!

Ответ №1:

Попробуйте следующий код:

 $base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $User, $Token))) #Encrypt token
$Head = @{Authorization = ("Basic {0}" -f $base64AuthInfo)}
$uri = "https://dev.azure.com/$myorg/$myproject/_apis/build/retention/leases?api-version=6.0-preview.1"
    
$Body = @(
        @{
            "definitionId" = "129"
            "runId" = "2758"
            "ownerId" = "User:32861cf9-xxxx-xxxx-xxxx-6f90c41bf1a6"
            "daysValid" = "365000"
            "protectPipeline" = "false"
         }
    
    )

$BodyJson = ConvertTo-Json $Body

#BodyJson
Invoke-RestMethod -Uri $uri -Method POST -Headers $Head -Body $BodyJson -ContentType "application/json" -verbose
 

Комментарии:

1. Было бы неплохо, если бы вы могли уточнить это. Почему тело json должно быть массивом?

2. @Theo В документации говорится, что тело запроса newRetentionLease[] должно быть массивом. Ссылка: docs.microsoft.com/en-us/rest/api/azure/devops/build/leases /…

Ответ №2:

Используя оболочку, это можно сделать, как показано ниже. Здесь мы создаем строку JSON с помощью утилиты jq, мы используем период хранения 365 дней и защищаем конвейер от случайного удаления

 $ RETENTION_LEASE_JSON_STRING=$(jq -cn --arg days 365 
   --arg defId <build definition id> 
   --arg owner <org owner id> 
   --arg protect true 
   --arg runIdVal <build id> '[{ daysValid: $days, definitionId: $defId, ownerId: 
   $owner, protectPipeline: $protect, runId: $runIdVal }]')
$ curl -u <username>:<password> -H "Content-Type: application/json" -d $RETENTION_LEASE_JSON_STRING  https://****.azure.com/{org-name}/{project-name}/_apis/build/retention/leases?api-version=6.0-preview.1