通过其余 api 创建新的 VSTS 版本时 ReleaseStartMetadata 合同中的必填字段

Required fields in ReleaseStartMetadata contract when creating a new VSTS release via the rest api

我正在尝试编写一个 powershell 脚本来创建并启动一个基于现有版本定义的新版本。我在构建 POST 请求正文所需的 ReleaseStartMetadata 对象时遇到问题。文档 here, here, and here 没有说明哪些字段是必需的,哪些是可选的,并且在某些情况下 (BuildVersion) 根本没有解释字段的含义以及在哪里可以找到填充它们的值。

我使用的发布定义取决于两组工件。一个是构建工件,一个是源工件。发布定义被配置为默认为两者的最新工件版本,但我无法通过其余 api 找到任何方法来指定仅使用默认(最新)工件。所以我假设我需要明确指定要使用的工件版本。我在网上找到的所有示例都展示了如何使用构建工件创建发布,但我找不到使用源工件的示例。我猜 BuildVersion 合同上的 "sourceVersion" 字段应该是变更集 ID,但我不知道在哪里可以找到要为 "sourceBranch"、"sourceRepositoryId" 和 [=33= 指定的值].

这是我目前的脚本:

$authinfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("my@email.com:blahblahtokenvalueblahblahblah"))
$headers = @{}
$headers.Add('Authorization', ("Basic {0}" -f $authinfo))
$headers.Add('Content-Type', 'application/json')

$uri = 'https://my-account.visualstudio.com/DefaultCollection/MyProject/_apis/build/builds?api-version=2.0&definitions=16'
$buildsResponse = Invoke-RestMethod -Method 'Get' -Uri $uri -Headers $headers
$build = $buildsResponse | Select -Expand value | Sort -Property id | Select -Last 1
$buildId = $build | Select -Expand id
$buildNumber = $build | Select -Expand buildNumber
Write-Host "Found latest build.  BuildId: $buildId, BuildNumber: $buildNumber"

$uri = 'https://my-account.visualstudio.com/DefaultCollection/MyProject/_apis/tfvc/changesets?api-version=1.0&searchCriteria.itemPath=$/MyProject'
$changesetsResponse = Invoke-RestMethod -Method 'Get' -Uri $uri -Headers $headers
$changeset = $changesetsResponse | Select -Expand value | Sort -Property changesetId | Select -Last 1
$changesetId = $changeset | Select -Expand changesetId
Write-Host "Found latest changeset.  ChangesetId: $changesetId"

$uri = 'https://my-account.vsrm.visualstudio.com/MyProject/_apis/release/releases?api-version=4.0-preview.4'
$body = @{
    definitionId = 3
    description = 'Testing release via Rest API'
    isDraft = $FALSE
    reason = 'none'
    manualEnvironments = $NULL
    artifacts = @(
        @{
            alias = 'My Build Artifact'
            instanceReference = @{
                id = "$buildId"
                name = $buildNumber
            }
        },
        @{
            alias = 'My Source Artifact'
            instanceReference = @{
                sourceBranch = "Dev"
                sourceRepositoryId = $NULL
                sourceRepositoryType = $NULL
                sourceVersion = "$changesetId"
            }
        }
    )
    properties = $NULL
}
$createResponse = Invoke-RestMethod -Method 'Post' -Uri $uri -Headers $headers -Body $body
$releaseId = $createResponse | Select id
Write-Host "Release Created: $releaseId"

当我 运行 这样做时,前两个请求工作正常,我得到了预期的值,但是 POST 请求失败并出现以下异常:

Invoke-RestMethod : {
    "$id":"1",
    "innerException":null,
    "message":"VS402903: The specified value is not convertible to type ReleaseStartMetadata. Make sure it is convertible to type eleaseStartMetadata and try again.",
    "typeName":"Microsoft.VisualStudio.Services.ReleaseManagement.Data.Exceptions.InvalidRequestException, Microsoft.VisualStudio.Services.ReleaseManagement2.Data",
    "typeKey":"InvalidRequestException",
    "errorCode":0,
    "eventId":3000
}
At C:\dev\PShell\MyScript.ps1:49 char:19
+ ... eResponse = Invoke-RestMethod -Method 'Post' -Uri $uri -Headers $head ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

即使我为 sourceRepositoryId 和 sourceRepository 类型填写了一些虚假值,我也会得到同样的错误。所以现在我有两个问题:

  1. 我在哪里可以找到值来填充源工件的 BuildVersion 合同上的所有源*字段?
  2. 我的数据结构还有什么问题导致它无法正确解析为 ReleaseStartMetadata 对象?

如果您使用 Git 源作为工件,则 instanceReference id 是提交 id,但您使用的是 TFVC REST API,因此它是不正确的。

样本:

{
"definitionId":1,
"isDraft":false,
"description":"",
"manualEnvironments":[],
"artifacts":
[
{
"alias":"Asp.netVnext",
"instanceReference":
{
"id":"6459",
"name":"null"
}
},
{
"alias":"WebAPI",
"instanceReference":{
"id":"26e0df34d57fc68ce1706f230eee03c4166d24d0",
"name":"null",
"sourceBranch":"dev"
}
}
]
}

如果您使用 TFVC 源作为工件,则 instanceReference id 是变更集 id,但没有 sourceBranch、sourcerepositoryId parameters/keys,只有 id 和名称。

样本:

{
"definitionId":1
,"isDraft":false,
"description":"",
"manualEnvironments":[],
"artifacts":[
{
"alias":"ScrumStarain2",
"instanceReference":{
"id":"1705",
"name":"Changeset 1705"
}
}
]}

像往常一样,在我发布问题后不久,我偶然发现了一篇文章,最终引导我找到了我需要的答案。

对于问题 1,答案是 BuildVersion 合同中唯一实际需要的字段是 "id"。

  • 对于构建工件,这应该是 buildId。
  • 对于 TFVC 源项目,这应该是 changesetId。
  • 正如 starian chen-MSFT 在他的回答中提到的,对于 Git 源工件,这应该是提交 ID。

对于问题 2,我遗漏的部分是通过将“| ConvertTo-Json 100”附加到 $body 定义来将我的 @-notation 对象转换为 json。

作为一些额外的奖励信息,如果其他人对 "Sets list of environments to manual as condition." 的含义感到困惑(来自 ReleaseStartMetadata 合同的文档),如果您的发布定义配置为新发布在任何时间自动启动它的环境,您可以通过在 manualEnvironments 字段中列出这些环境来在创建发布时禁用自动启动。我必须这样做以防止我的新版本(用于我们的自动化测试环境)自动开始部署到开发环境。

所以我最终的工作 $body 定义如下所示:

$body = @{
    definitionId = 3
    description = 'Testing release via Rest API'
    isDraft = $FALSE
    reason = 'none'
    manualEnvironments = @('Development')
    artifacts = @(
        @{
            alias = 'My Build Artifact'
            instanceReference = @{
                id = "$buildId"
            }
        },
        @{
            alias = 'My Source Artifact'
            instanceReference = @{
                id = "$changesetId"
            }
        }
    )
    properties = $NULL
} | ConvertTo-Json -Depth 100