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

时间:2018-04-02 16:21:46

标签: powershell azure-devops azure-pipelines-release-pipeline azure-devops-rest-api

我正在尝试编写一个PowerShell脚本,以根据现有版本定义创建和启动新版本。我在构建POST请求正文所需的ReleaseStartMetadata对象时遇到了问题。文档hereherehere没有说明哪些字段是必需的,哪些字段是可选的,在某些情况下(BuildVersion)根本没有说明什么是字段意味着在哪里找到填充它们的值。

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

这是我到目前为止的剧本:

$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合约上的所有source *字段?
  2. 我的数据结构还有什么问题导致它无法正确解析为ReleaseStartMetadata对象?

2 个答案:

答案 0 :(得分:1)

如果您使用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参数/键,只是id和name。

样品:

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

答案 1 :(得分:0)

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

对于问题1,答案是BuildVersion合同中唯一的实际必填字段是“id”。

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

对于问题2,我缺少的那篇文章是通过将“| ConvertTo-Json 100”附加到$ body定义来将我的@ -notation对象转换为json。

作为一些额外的奖励信息,如果其他人对“将环境列表设置为手动作为条件”的内容感到困惑。表示(来自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