如何使用Azure DevOps REST Api编写构建计划脚本?

时间:2019-10-25 02:19:16

标签: azure-devops-rest-api

这个问题是我其他问题的延续-How to schedule an on-premise Azure DevOps build to run every 5 minutes?

我不知道如何编写构建时间表的脚本。我应该使用什么API?

编辑1

我想强调-我不想每5分钟将构建队列排队。我想编写一个生成时间表。因此,我正在使用定义更新REST Api-https://docs.microsoft.com/en-us/rest/api/azure/devops/build/definitions/update?view=azure-devops-rest-5.1,但仍然不知道如何更新构建定义的时间表。打开Fiddler和反向工程API的建议使我认为这没有记录。这是否意味着我基于流量分析实现的功能在下一个版本中可能会被破坏?

编辑2

使用建议的解决方案。这是我的代码,基于提供的答案。我必须更改2件事:

  1. 主体应该是标量对象,而不是数组。因此,我将$BuildDefinition而不是@($BuildDefinition)转换为json。
  2. 我使用Windows身份验证,因为我们有一台本地Azure DevOps服务器。

$BuildDefinition | Add-Member triggers $triggers -Force

$json = ConvertTo-Json $BuildDefinition -Depth 99 

$Url = $BuildDefinition.url -replace '(.+)\?.+',"`$1?api-version=5.0"
Invoke-RestMethod -Uri $url -Method Put -Body $json -ContentType "application/json" -UseDefaultCredentials

但是,构建定义对象必须通过GET API而不是LIST API获得。后者返回构建定义的简化版本,该版本不能用于更新。

编辑3

使用完整的符号(即refs/heads/master而不是master指定分支非常重要。使用后者似乎有效-创建了时间表,分支过滤器看上去正确,但是不起作用。问题在于GUI并未给出任何错误提示。

1 个答案:

答案 0 :(得分:3)

如果您要使用REST API设置构建计划,则可以使用Definitions - Update

通过UI设置时间表后,您还可以在浏览器中按F12键跟踪API。

返回您的要求:

  

如何安排本地Azure DevOps构建每5分钟运行一次?

就像您提到的那样,当前本地Azure DevOps Server不支持YAML中的计划。而且,用于定义基于时间的构建触发器的UI不够灵活。 因此,我们无法实现内置功能那样的功能。

但是我们可以每5分钟调用queue build REST API来排队构建,我们有两种方法可以做到:

  1. 编写脚本以调用队列构建REST API,然后运行它 定期在客户端计算机上,我们可以使用Windows Task进行设置 调度程序。为此,请参考下面的博客:

  2. 在脚本中进行了硬编码,请打开控制台以在任何脚本中运行脚本 客户端,可以访问Azure DevOps服务器(PowerShell下) 脚本适合我):

示例:

Param(
       [string]$collectionurl = "https://server/DefaultCollection",
       [string]$projectName = "ProjectName",
       [string]$BuildDefinitionId = "11",
       [string]$user = "username",
       [string]$token = "password/PAT"
    )

    # Base64-encodes the Personal Access Token (PAT) appropriately
    $base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))

    function CreateJsonBody
    {

        $value = @"
      {
      "definition": {
        "id": $BuildDefinitionId
      }

    }
    "@

     return $value
    }

    $json = CreateJsonBody

    $uri = "$($collectionurl)/$($projectName)/_apis/build/builds?api-version=5.1"


    $EndTime = Get-Date
    while($true) {
        $EndTime = $EndTime.AddMinutes(5)

        ###Queue build###
        $result = Invoke-RestMethod -Uri $uri -Method Post -Body $json -ContentType "application/json" -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)}


        Start-Sleep -Seconds $( [int]( New-TimeSpan -End $EndTime ).TotalSeconds )
    }

UPDATE1:

要在启用计划触发器的情况下更新构建定义,我们需要在请求正文中附加触发器属性。

GET build definition,方法是调用REST API,将响应用作请求正文。

在响应请求正文中添加触发器属性:

"triggers": [
    {
        "schedules": [
            {
                "branchFilters": [
                    "+refs/heads/master"
                ],
                "timeZoneId": "UTC",
                "startHours": 5,
                "startMinutes": 20,
                "daysToBuild": 31,
                "scheduleJobId": "5e8e3663-2d1c-482e-bb4d-91f804755010",
                "scheduleOnlyWithChanges": true
            }
        ],
        "triggerType": "schedule"
    }
]

UPDATE2:

好吧,您可以使用以下PowerShell脚本通过更新构建定义来启用/更新构建计划触发器:

Param(
   [string]$collectionurl = "https://server/DefaultCollection",
   [string]$project = "projectname",
   [string]$definitionid = "183",
   [string]$user = "username",
   [string]$token = "password/PAT"
)

# Base64-encodes the Personal Access Token (PAT) appropriately
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))

$ErrorActionPreference = 'SilentlyContinue' 

#Get resonse of the build definition
$defurl = "$collectionurl/$project/_apis/build/definitions/$($definitionid)?api-version=5.1"            
$definition = Invoke-RestMethod -Uri $defurl -Method Get -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)}

#Set trigger array


 $triggers =  ' 
        [{
            "schedules": [
                {
                    "branchFilters": [
                        "+refs/heads/master"
                    ],
                    "timeZoneId": "UTC",
                    "startHours": 9,
                    "startMinutes": 40,
                    "daysToBuild": 31,
                    "scheduleOnlyWithChanges": true
                }
            ],
            "triggerType": "schedule"
        }]'


 cls
#Add a trigger block to the response body

$definition | Add-Member -NotePropertyName "triggers" -NotePropertyValue (Convertfrom-Json $triggers) -Force

Remove-TypeData System.Array  # Remove the redundant ETS-supplied .Count and values property

#Convert the response body to Json
$json = @($definition) | ConvertTo-Json -Depth 99 

#Update build definition
$updatedef = Invoke-RestMethod  -Uri $defurl  -Method Put -Body $json -ContentType "application/json" -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)}

Write-Host ($updatedef.triggers | ConvertTo-Json -Depth 99)