在 VSTS 合并请求中获取真实的源代码分支名称
Get real source branch name in VSTS Pull Request
我们正在使用 Visual Studio Team Systems 和 Git 以及 Team System Build(以前的 Build vNext)。
当我们执行 Pull Request 时,会触发一个新的构建,用于 运行 单元测试并部署到一个隔离的测试系统。
要执行到隔离系统的部署,我需要在构建过程中获取真实的源分支名称。
然而 Build.SourceBranchName
变量总是 "merge",
例如:
将请求从源 FOO 拉取到目标 BAR
Build.SourceBranch
是 "refs/pull/1/merge",因此 Build.SourceBranchName
是 "merge"。
但是我需要以某种方式让 "FOO" 到 运行 我的 Power Shell 脚本来配置系统。
有没有办法在 VSTS 中的 Git 拉取请求中获取真实的源分支名称?
这里没有任何变量,但您可以创建一个 power-shell 脚本来通过 Rest API.
获取它
[String]$projecturi = "$env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"
[String]$sourcebranch = "$env:BUILD_SOURCEBRANCH"
[String]$repoid = "$env:BUILD_REPOSITORY_ID"
$username="alternativeusername"
$password="alternativepassword"
$basicAuth= ("{0}:{1}"-f $username,$password)
$basicAuth=[System.Text.Encoding]::UTF8.GetBytes($basicAuth)
$basicAuth=[System.Convert]::ToBase64String($basicAuth)
$headers= @{Authorization=("Basic {0}"-f $basicAuth)}
#get pull request ID via regex
$pullrequest = "refs/pull/+(?<pullnumber>\w+?)/merge+"
if($sourcebranch -match $pullrequest){
$pullrequestid = $Matches.pullnumber;
}
else { write-host "Cannot find pull request ID" }
#get pull request information via API
$url= $projecturi + "_apis/git/repositories/" + $repoid + "/pullRequests/" + $pullrequestid + "?api-version=1.0-preview.1"
Write-Host $url
$getpullrequest = Invoke-RestMethod -Uri $url -headers $headers -Method Get
#get sourcebranch and targetbranch
$sourceref = $getpullrequest.sourceRefName
$targetref = $getpullrequest.targetRefName
如果在构建任务内部使用,此脚本将从环境变量中读取参数,如果在构建任务外部使用,则使用提供的参数。变量 $sourcebranch 将被设置为在以后的构建任务中使用。
[CmdletBinding()]
param (
[Parameter(Mandatory=$false)][string]$projectUri = "$env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI",
[Parameter(Mandatory=$false)][string]$branch = "$env:BUILD_branch",
[Parameter(Mandatory=$false)][string]$repositoryName = "$env:BUILD_REPOSITORY_NAME",
[Parameter(Mandatory=$false)][string]$projectName = "$env:SYSTEM_TEAMPROJECT",
[Parameter(Mandatory=$false)][string]$oAuthToken = "$env:SYSTEM_ACCESSTOKEN",
[Parameter(Mandatory=$false)][string]$username,
[Parameter(Mandatory=$false)][string]$password
)
#check all parameters
if(!$oAuthToken) {
if(!$username -or !$password) {
throw "You must either supply an OAuth Token or a username and a password. You can supply the token via the environment variable SYSTEM_ACCESSTOKEN"
}
$basicAuth= ("{0}:{1}"-f $username,$password)
$basicAuth=[System.Text.Encoding]::UTF8.GetBytes($basicAuth)
$basicAuth=[System.Convert]::ToBase64String($basicAuth)
$headers= @{Authorization=("Basic {0}"-f $basicAuth)}
}
else {
$headers= @{Authorization="Bearer $oAuthToken"}
}
if(!$projectUri) {
throw "You must supply a project uri or set the Environment variable SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"
}
if(!$branch) {
throw "You must supply a branch or set the Environment variable BUILD_branch"
}
if(!$repositoryName) {
throw "You must supply a repository name or set the Environment variable BUILD_REPOSITORY_NAME"
}
if(!$projectName) {
throw "You must supply a project name or set the Environment variable SYSTEM_TEAMPROJECT"
}
#get pull request ID via regex
$pullrequest = "refs/pull/+(?<pullnumber>\w+?)/merge+"
if($branch -match $pullrequest) {
$pullrequestid = $Matches.pullnumber;
Write-Output "Pull request ID is $pullrequestid"
}
else {
Write-Output "Cannot find pull request ID"
}
#get pull request information via API
$url= $projectUri + "DefaultCollection/$projectName/_apis/git/repositories/$repositoryName/pullRequests/$pullrequestid\?api-version=1.0-preview.1"
Write-Output "Getting info from $url"
$getpullrequest = Invoke-RestMethod -Uri $url -headers $headers -Method Get
#get sourcebranch and targetbranch ref
$sourceref = $getpullrequest.sourceRefName
$targetref = $getpullrequest.targetRefName
#get the branch name via regex
$branchref = "refs/heads/(?<realBranchname>.*)"
if($sourceref -match $branchref) {
$sourcebranch = $Matches.realBranchname;
Write-Output "Real source branch is $sourcebranch"
}
else {
Write-Output "Cannot find real source branch"
}
if($targetref -match $branchref) {
$targetbranch = $Matches.realBranchname;
Write-Output "Real target branch is $targetbranch"
}
else {
Write-Output "Cannot find real target branch"
}
#set a variable "sourcebranch" to use it in another build task
Write-Output "##vso[task.setvariable variable=sourcebranch;]$sourcebranch"
VSTS 现在有 System.PullRequest.SourceBranch
和 System.PullRequest.TargetBranch
变量。
这应该可以解决您的问题而无需编写任何自定义脚本
您可以创建一个 bash 脚本,将较短的分支名称分配给变量。
# Bash script
BRANCH_NAME=$(echo "$(System.PullRequest.TargetBranch)" | awk -F/ '{print $NF}')
echo "##vso[task.setvariable variable=PullRequest_Target_Branch;]$BRANCH_NAME"
然后您可以在管道中引用 $(PullRequest_Target_Branch)
如果没有此错误,您仍然无法在构建定义中将 $(System.PullRequest.SourceBranch)
用于 BuildNumberFormat
:
The build number format string $(BuildDefinitionName)-$(System.PullRequest.SourceBranch)-$(Date:yyyyMMdd)$(Rev:.r)
generated a build number "MyBuildName-refs/heads/myBranch-20190831.1" which contains invalid character(s), is too long, or ends with '.'.
好像现在可以用Build.SourceBranchName
The name of the branch in the triggering repo the build was queued for.
Git repo branch or pull request: The last path segment in the ref. For example, in refs/heads/master
this value is master
. In refs/heads/feature/tools
this value is tools
.
我们正在使用 Visual Studio Team Systems 和 Git 以及 Team System Build(以前的 Build vNext)。
当我们执行 Pull Request 时,会触发一个新的构建,用于 运行 单元测试并部署到一个隔离的测试系统。
要执行到隔离系统的部署,我需要在构建过程中获取真实的源分支名称。
然而 Build.SourceBranchName
变量总是 "merge",
例如:
将请求从源 FOO 拉取到目标 BAR
Build.SourceBranch
是 "refs/pull/1/merge",因此 Build.SourceBranchName
是 "merge"。
但是我需要以某种方式让 "FOO" 到 运行 我的 Power Shell 脚本来配置系统。
有没有办法在 VSTS 中的 Git 拉取请求中获取真实的源分支名称?
这里没有任何变量,但您可以创建一个 power-shell 脚本来通过 Rest API.
获取它[String]$projecturi = "$env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"
[String]$sourcebranch = "$env:BUILD_SOURCEBRANCH"
[String]$repoid = "$env:BUILD_REPOSITORY_ID"
$username="alternativeusername"
$password="alternativepassword"
$basicAuth= ("{0}:{1}"-f $username,$password)
$basicAuth=[System.Text.Encoding]::UTF8.GetBytes($basicAuth)
$basicAuth=[System.Convert]::ToBase64String($basicAuth)
$headers= @{Authorization=("Basic {0}"-f $basicAuth)}
#get pull request ID via regex
$pullrequest = "refs/pull/+(?<pullnumber>\w+?)/merge+"
if($sourcebranch -match $pullrequest){
$pullrequestid = $Matches.pullnumber;
}
else { write-host "Cannot find pull request ID" }
#get pull request information via API
$url= $projecturi + "_apis/git/repositories/" + $repoid + "/pullRequests/" + $pullrequestid + "?api-version=1.0-preview.1"
Write-Host $url
$getpullrequest = Invoke-RestMethod -Uri $url -headers $headers -Method Get
#get sourcebranch and targetbranch
$sourceref = $getpullrequest.sourceRefName
$targetref = $getpullrequest.targetRefName
如果在构建任务内部使用,此脚本将从环境变量中读取参数,如果在构建任务外部使用,则使用提供的参数。变量 $sourcebranch 将被设置为在以后的构建任务中使用。
[CmdletBinding()]
param (
[Parameter(Mandatory=$false)][string]$projectUri = "$env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI",
[Parameter(Mandatory=$false)][string]$branch = "$env:BUILD_branch",
[Parameter(Mandatory=$false)][string]$repositoryName = "$env:BUILD_REPOSITORY_NAME",
[Parameter(Mandatory=$false)][string]$projectName = "$env:SYSTEM_TEAMPROJECT",
[Parameter(Mandatory=$false)][string]$oAuthToken = "$env:SYSTEM_ACCESSTOKEN",
[Parameter(Mandatory=$false)][string]$username,
[Parameter(Mandatory=$false)][string]$password
)
#check all parameters
if(!$oAuthToken) {
if(!$username -or !$password) {
throw "You must either supply an OAuth Token or a username and a password. You can supply the token via the environment variable SYSTEM_ACCESSTOKEN"
}
$basicAuth= ("{0}:{1}"-f $username,$password)
$basicAuth=[System.Text.Encoding]::UTF8.GetBytes($basicAuth)
$basicAuth=[System.Convert]::ToBase64String($basicAuth)
$headers= @{Authorization=("Basic {0}"-f $basicAuth)}
}
else {
$headers= @{Authorization="Bearer $oAuthToken"}
}
if(!$projectUri) {
throw "You must supply a project uri or set the Environment variable SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"
}
if(!$branch) {
throw "You must supply a branch or set the Environment variable BUILD_branch"
}
if(!$repositoryName) {
throw "You must supply a repository name or set the Environment variable BUILD_REPOSITORY_NAME"
}
if(!$projectName) {
throw "You must supply a project name or set the Environment variable SYSTEM_TEAMPROJECT"
}
#get pull request ID via regex
$pullrequest = "refs/pull/+(?<pullnumber>\w+?)/merge+"
if($branch -match $pullrequest) {
$pullrequestid = $Matches.pullnumber;
Write-Output "Pull request ID is $pullrequestid"
}
else {
Write-Output "Cannot find pull request ID"
}
#get pull request information via API
$url= $projectUri + "DefaultCollection/$projectName/_apis/git/repositories/$repositoryName/pullRequests/$pullrequestid\?api-version=1.0-preview.1"
Write-Output "Getting info from $url"
$getpullrequest = Invoke-RestMethod -Uri $url -headers $headers -Method Get
#get sourcebranch and targetbranch ref
$sourceref = $getpullrequest.sourceRefName
$targetref = $getpullrequest.targetRefName
#get the branch name via regex
$branchref = "refs/heads/(?<realBranchname>.*)"
if($sourceref -match $branchref) {
$sourcebranch = $Matches.realBranchname;
Write-Output "Real source branch is $sourcebranch"
}
else {
Write-Output "Cannot find real source branch"
}
if($targetref -match $branchref) {
$targetbranch = $Matches.realBranchname;
Write-Output "Real target branch is $targetbranch"
}
else {
Write-Output "Cannot find real target branch"
}
#set a variable "sourcebranch" to use it in another build task
Write-Output "##vso[task.setvariable variable=sourcebranch;]$sourcebranch"
VSTS 现在有 System.PullRequest.SourceBranch
和 System.PullRequest.TargetBranch
变量。
这应该可以解决您的问题而无需编写任何自定义脚本
您可以创建一个 bash 脚本,将较短的分支名称分配给变量。
# Bash script
BRANCH_NAME=$(echo "$(System.PullRequest.TargetBranch)" | awk -F/ '{print $NF}')
echo "##vso[task.setvariable variable=PullRequest_Target_Branch;]$BRANCH_NAME"
然后您可以在管道中引用 $(PullRequest_Target_Branch)
如果没有此错误,您仍然无法在构建定义中将 $(System.PullRequest.SourceBranch)
用于 BuildNumberFormat
:
The build number format string
$(BuildDefinitionName)-$(System.PullRequest.SourceBranch)-$(Date:yyyyMMdd)$(Rev:.r)
generated a build number "MyBuildName-refs/heads/myBranch-20190831.1" which contains invalid character(s), is too long, or ends with '.'.
好像现在可以用Build.SourceBranchName
The name of the branch in the triggering repo the build was queued for. Git repo branch or pull request: The last path segment in the ref. For example, in
refs/heads/master
this value ismaster
. Inrefs/heads/feature/tools
this value istools
.