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

Posted

技术标签:

【中文标题】如何使用 Azure DevOps REST Api 编写构建计划脚本?【英文标题】:How to script build schedule using Azure DevOps REST Api? 【发布时间】:2020-02-21 09:11:58 【问题描述】:

这个问题是我另一个问题的延续 - 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

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

    主体应该是一个标量对象,而不是一个数组。所以,我将 $BuildDefinition 而不是 @($BuildDefinition) 转换为 json。 我使用 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】:

如果您的意思是使用 REST API 设置构建计划,那么您可以使用 Definitions - Update

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

回到你的要求:

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

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

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

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

    How to schedule a Batch File to run automatically in Windows

    Run a task every x-minutes with Windows Task Scheduler

    在脚本中硬编码,打开控制台以任意方式运行脚本 可以访问 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:

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

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"
    
]

更新 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)

【讨论】:

请参阅EDIT 1 @mark 要设置构建计划,您需要在请求正文中附加计划属性,请参阅更新后的答案。 计划触发器架构记录在哪里? @mark 其他属性等没有具体示例,但文档中确实提到了。详情请查看BuildTrigger 和DefinitionTriggerType。因此,我们可以从现有的构建定义中获取响应以检查架构。 @mark 好吧,我写了一个 PowerShell 脚本来启用或更新构建计划触发器,请查看更新后的答案。

以上是关于如何使用 Azure DevOps REST Api 编写构建计划脚本?的主要内容,如果未能解决你的问题,请参考以下文章

Azure DevOps REST API - 选项列表如何与字段关联?

如何从 azure devops rest api 获得 n 个工作项的交互

尝试使用 Azure DevOps Rest API 创建发布定义时出错

Azure devops Server 2019中的Analytics Widget-寻找Rest api和class libraby用于Analytics Widget

Azure DevOps REST API - 创建工作项 - “需要一个值”

使用 DevOps Release REST API 确定发布完成的时间