【问题标题】:TFS 2015 Queue new build using REST Api - Set Demands使用 REST Api 的 TFS 2015 队列新构建 - 设置需求
【发布时间】:2018-02-14 17:26:10
【问题描述】:

我正在尝试使用 TFS 2015.3 REST API 对新构建进行排队,我关注了许多文章但无法使其正常工作。

我在 PowerShell 中执行此操作,标准队列新构建调用仅在传递定义 ID 时有效,但传递除 id 之外的任何其他内容似乎都不起作用。

我的代码:

$buildDef = Invoke-RestMethod -Method Get -UseDefaultCredentials -Uri "$($tfsRoot)/_apis/build/definitions?api-version=2.0&name=$buildDefintionName"        

        $detailedResults = Invoke-RestMethod -Uri $buildDef.Value[0].Url -Method Get -ContentType "application/json" -UseDefaultCredentials

        if ($buildDef.Value[0].Id)
        {
            $agentDemandString = "Agent.Name -equals $agent"
            $demands = $detailedResults.Demands

            $json = "definition: { id:$($buildDef.Value[0].Id) }, demands: $demands" 
            $bodyjson = $json | ConvertTo-Json
            Write-Host "Queuing build $buildDefintionName on agent $agent with parameters $json"
            $build = Invoke-RestMethod -Method Post -UseDefaultCredentials -ContentType application/json -Uri "$($tfsRoot)/_apis/build/builds?api-version=2.0" -Body $bodyjson
        }

我尝试了许多不同的传递要求的变体,但看起来它甚至没有达到那一点,因为它抱怨“构建”参数。

Invoke-RestMethod : {"$id":"1","innerException":null,"message":"值不能为空。\r\n参数名称: build","typeName":"System.ArgumentNullException , mscorlib, 版本=4.0.0.0, 文化=中性

如果我是对的,构建参数包含要执行的构建步骤。这让我认为排队构建正在删除所有现有配置并试图仅依赖于 JsonBody 中传递的内容,这当然不是我想要的。

我应该传递什么以及如何传递才能将新构建排队但有更新/额外的需求。

【问题讨论】:

    标签: tfs


    【解决方案1】:

    尝试设置深度:

    $bodyjson = $json | ConvertTo-Json -Depth 3

    【讨论】:

    • 谢谢,但这并不能解决问题。我不认为深度是问题,因为我创建的设置没有那么深。
    【解决方案2】:

    $json = "definition: { id:$($buildDef.Value[0].Id) }, demands: $demands" 不会是有效的 JSON——例如,它不会被包裹在花括号中。

    我建议创建一个可以正确转换为有效 JSON 的关联数组。 documentation 中提供的 JSON 示例为:

    {
      "definition": {
        "id": 25
      },
      "sourceBranch": "refs/heads/master",
      "parameters": "{\"system.debug\":\"true\",\"BuildConfiguration\":\"debug\",\"BuildPlatform\":\"x64\"}"
    }
    

    所以这会生成一个合适的 JSON 对象:

    $body = @{
        definition = @{ id=25 }
        sourceBranch = 'refs/heads/master'
        parameters = '{\"system.debug\":\"true\",\"BuildConfiguration\":\"debug\",\"BuildPlatform\":\"x64\"}'
    } 
    
    $body | convertto-json
    

    或者,如果您想更加花哨并消除内部 JSON-as-a-string 位:

    $body = @{
        definition = @{ id=25 }
        sourceBranch = 'refs/heads/master'
        parameters = (@{'system.debug' = $true; BuildConfiguration='debug'; BuildPlatform='x64'}) | convertto-json -Compress
    } 
    
    $body | convertto-json
    

    【讨论】:

    • 感谢 Daniel,我尝试了各种编写 json 的方法,我猜在上一个版本中弄错了。但是对于您的版本,我仍然会遇到相同的错误。值不能为空。\r\n参数名称: build
    【解决方案3】:

    根据我的测试,我们无法直接使用队列构建 REST Api 设置需求。

    构建仍将使用定义中设置的代理,即使我们在对构建进行排队时指定了具有“需求”集的其他代理。您可以使用 REST API 检查这一点,下面的屏幕截图供您参考。

    并使用 REST API 进行构建,例如:

    GET http://SERVER:8080/tfs/CollectionLC/6debd6ea-fa97-4ea2-b0c0-3cbbc4afa802/_apis/build/Builds/1071/
    

    您可以看到,响应中不包含“需求”。它仅出现在构建定义响应中。

    实际上,“需求”是在构建定义中设置的,它只是针对构建定义。当使用 REST API 对构建进行排队时,它只会触发构建定义。因此,如果您想使用 REST API 触发特定代理的构建,您需要先更新定义(设置需求),然后触发构建定义。

    要更新定义,请使用 REST API:请参阅 Update a build definition

    PUT https://{instance}/DefaultCollection/{project}/_apis/build/definitions/{definitionId}?api-version={version}
    

    因此,您可以编写脚本来更新构建定义,然后使用构建定义 ID 触发构建。

    【讨论】:

    • 在更改之后您需要撤消更新我猜?或者有没有办法使用替代配置将构建排队 1 次?我们希望能够同时在 10 个代理上排队(重新)构建,并确保它已在所有这些代理上运行,确保这一点的唯一方法是通过其名称限制代理过滤器。我可以使用可以工作的临时配置对构建进行排队,但是保存和回滚更改会很痛苦。我们能否通过 C# API 更好地实现这一目标?
    • @Nico 我认为最好的方法是创建 10 个构建定义分别为它们设置代理,然后编写脚本来触发它们。
    • 不行,因为它们将在自己的工作区中运行。我们需要重建在每个代理的原始工作区中运行,以确保工作区被重建和清理。 TFS自己是怎么做的,通过webUI可以在排队构建的时候添加需求..
    • @Nico 每个代理都会在自己的工作区中运行,代理会首先从 TFS 获取源到本地代理服务器。您可以为此检查构建日志。因此,除非您使用相同的代理进行构建,否则如果您想使用其他代理进行构建,它们将单独获取源代码并在自己的工作区中运行。无论是 webUI 还是 REST API。因此,您只需要将构建定义克隆 10 次,然后更改需求以指定每个特定的代理。
    • 不,我不是这个意思。我们有 1 个构建定义,可以在 10 个不同的代理上运行,显然都在它们自己的工作区中。所有这些构建都是增量和运行测试。在某些时候,我们需要清理工作空间,运行一个干净的构建,因为工作空间中出现了问题。为此,我们希望在所有代理上为该定义排队构建,并确保它已在那里运行。这样做的唯一方法是强制 10 个排队的构建中的每一个在不同的代理上运行。所以我们需要使用 Agent.Name -equals 需求的正常构建定义。
    【解决方案4】:

    我终于在一些帮助下让它工作了。接受 Demands 属性。 由于带有 Json 转换的 powerShell 代码,它似乎无法正常工作。如果我在下面使用并且不将其转换为 Json,它可以工作!

    Function queuebuild{ 
    
          $uri="$($tfsRoot)/_apis/build/builds?api-version=2.0"
    
          $body='{
                     "definition": {
                     "id": 1061
                     },
                        "sourceBranch": "$/Project/Branch",
                        "demands":["Demand1", "Agent.Name -equals Computer2-E-A2"]
                     }';
    
            $result=Invoke-RestMethod -Uri $uri -Method Post -ContentType "application/json" -UseDefaultCredentials -Body $body
    

    }

    【讨论】:

      猜你喜欢
      • 2016-07-19
      • 2016-11-13
      • 2017-05-12
      • 1970-01-01
      • 2016-09-03
      • 1970-01-01
      • 1970-01-01
      • 2017-10-15
      • 2013-08-23
      相关资源
      最近更新 更多