首页 > 解决方案 > 如何使用 Azure DevOps REST Api 编写构建计划脚本?

问题描述

这个问题是我的另一个问题的延续 -如何安排本地 Azure DevOps 构建每 5 分钟运行一次?

我无法弄清楚如何编写构建计划的脚本。我应该使用什么 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

使用建议的解决方案有效。这是我的代码,基于提供的答案。我不得不改变两件事:

  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 没有给出任何错误指示。

标签: azure-devops-rest-api

解决方案


如果您的意思是使用 REST API 设置构建计划,那么您可以使用定义 - 更新

从 UI 设置计划时,您还可以在浏览器中按 F12 来跟踪 API。

回到您的要求:

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

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

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

  1. 编写一个脚本来调用队列构建 REST API,然后在客户端机器上定期运行它,我们可以使用 Windows 任务计划程序进行设置。参考下面的博客来做到这一点:

  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 )
    }

更新1:

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

通过调用 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"
    }
]

更新2:

好吧,您可以使用下面的 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)

推荐阅读