不要为 Azure DevOps 中已有拉取请求的分支触发构建

发布于 2025-01-14 15:07:46 字数 565 浏览 5 评论 0原文

我们使用 Azure DevOps 进行持续集成。管道配置为每当将更改推送到功能分支时就运行构建。这是快速反馈所需要的。

此外,我们对主分支有一个政策,即在合并功能分支之前需要成功的验证构建。现在,当为功能分支创建拉取请求 (PR) 时,Azure DevOps 会自动触发相应的验证构建。

所有这些都很好,但有一个逆境:如果已经创建了 PR 并且更新了功能分支,则会触发两个构建(一个单独用于功能分支,另一个用于功能分支的结果)合并,即验证构建)。

我知道有些人可能想要两个构建,但在我们的情况下(可能在每个正常情况下),如果仅触发验证构建会更好。

问题:有没有办法告诉 Azure DevOps 它应该忽略任何已拥有 PR 的分支的分支触发器?当然,也欢迎具有等效结果的解决方法。

该问题已作为问题发布在此处,但我无法在回复中找到满意的答案(例如,分支过滤器和命名策略不能解决问题)。

We use Azure DevOps for continuous integration. The pipeline is configured to run a build whenever a change is pushed to a feature branch. This is desired for quick feedback.

Additionally, we have the policy for the master branch that a successful validation build is required before a feature branch can be merged. Azure DevOps now automatically triggers the corresponding validation build when a pull request (PR) is created for a feature branch.

All of this is fine, but there is an adversity: if a PR is already created and the feature branch is updated, two builds are triggered (one for the feature branch alone and one for the outcome of the merge, i.e., the validation build).

I understand that some people might want both builds, but in our case (an probably in every normal case) it would be better if only the validation build was triggered.

Question: Is there a way to tell Azure DevOps that it should ignore branch triggers for any branch that already has a PR? Workarounds with an equivalent outcome are also welcome, of course.

The question has already been posted as an issue here, but I could not find a satisfying answer in the replies (e.g., branch filters and a naming strategy do not solve the problem).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

甜`诱少女 2025-01-21 15:07:46

我已经按照 Shamrai 的建议解决了这个问题。我将其添加为共享我的代码的另一个答案。

将以下 PowerShell 代码添加到管道开头的步骤。它使用 Azure DevOps REST API 检查当前分支的现有 PR。如果没有这样的 PR 或者当前构建已手动排队,或者 PR 尚未准备好合并(例如冲突),则构建将照常继续。否则,将被取消。

$BaseApiUri_Builds   = "https://my.tfs.server.com/MyCollection/MyProject/_apis/build/builds"
$BaseApiUri_GitRepos = "https://my.tfs.server.com/MyCollection/MyProject/_apis/git/repositories"
$AuthenicationHeader = @{ Authorization = "Bearer ${env:System_AccessToken}" }

# Cancels the current build
function Cancel-This-Build()
{
    Cancel-Build -BuildId ${env:Build_BuildId}
}

# Cancels the given build
function Cancel-Build([String] $BuildId)
{
    Write-Host "Cancelling build ${BuildId}..."
    
    $BuildApiUri = "${BaseApiUri_Builds}/${BuildId}?api-version=5.1"
    $CancelBody = @{ status = "cancelling" } | ConvertTo-Json
    Invoke-RestMethod -Uri $BuildApiUri -Method PATCH -ContentType application/json -Body $CancelBody -Header $AuthenicationHeader
}

# Detects if a validation build is queued for the given branch. This is the case if an active PR exists that does not have merge conflicts.
function Check-For-Validation-Build([String] $BranchName)
{
    Write-Host "Checking for validation builds of branch '${BranchName}' in repository ${env:Build_Repository_ID}..."
    
    $GetPRsApiUri = "${BaseApiUri_GitRepos}/${env:Build_Repository_ID}/pullrequests?api-version=5.1&searchCriteria.sourceRefName=${BranchName}"
    $PRs = Invoke-RestMethod -Uri $GetPRsApiUri -Method GET -Header $AuthenicationHeader
    
    ForEach($PR in $PRs.Value)
    {
        Write-Host "Found PR $($PR.pullRequestId) '$($PR.title)': isDraft=$($PR.isDraft), status=$($PR.status), mergeStatus=$($PR.mergeStatus)"
        
        if (!$PR.isDraft -and ($PR.mergeStatus -eq "succeeded") -and ($PR.status -eq "active"))
        {
            Write-Host "Validation build is queued for branch '${BranchName}'."
            return $true
        }
    }
    
    Write-Host "No validation build is queued for branch '${BranchName}'."
    return $false
}

# Check if a valid PR exists. If so, cancel this build, because a validation build is also queued. 
$HasValidationBuild = Check-For-Validation-Build -BranchName ${env:Build_SourceBranch}
if (($HasValidationBuild -eq $true) -and (${env:Build_Reason} -ne "Manual") -and !${env:Build_SourceBranch}.EndsWith('/merge'))
{
    Cancel-This-Build
}

请注意,必须使 System.AccessToken 环境变量可见,脚本才能正常工作。

I have solved the issue like suggested by Shamrai. I'm adding this as another answer to share my code.

Add the following PowerShell code to a step at the beginning of the pipeline. It uses the Azure DevOps REST API to check for an existing PR of the current branch. If there is no such PR or if the current build was manually queued, or if the PR is not ready to be merged (e.g. conflicts), the build continues as normal. Otherwise, it is cancelled.

$BaseApiUri_Builds   = "https://my.tfs.server.com/MyCollection/MyProject/_apis/build/builds"
$BaseApiUri_GitRepos = "https://my.tfs.server.com/MyCollection/MyProject/_apis/git/repositories"
$AuthenicationHeader = @{ Authorization = "Bearer ${env:System_AccessToken}" }

# Cancels the current build
function Cancel-This-Build()
{
    Cancel-Build -BuildId ${env:Build_BuildId}
}

# Cancels the given build
function Cancel-Build([String] $BuildId)
{
    Write-Host "Cancelling build ${BuildId}..."
    
    $BuildApiUri = "${BaseApiUri_Builds}/${BuildId}?api-version=5.1"
    $CancelBody = @{ status = "cancelling" } | ConvertTo-Json
    Invoke-RestMethod -Uri $BuildApiUri -Method PATCH -ContentType application/json -Body $CancelBody -Header $AuthenicationHeader
}

# Detects if a validation build is queued for the given branch. This is the case if an active PR exists that does not have merge conflicts.
function Check-For-Validation-Build([String] $BranchName)
{
    Write-Host "Checking for validation builds of branch '${BranchName}' in repository ${env:Build_Repository_ID}..."
    
    $GetPRsApiUri = "${BaseApiUri_GitRepos}/${env:Build_Repository_ID}/pullrequests?api-version=5.1&searchCriteria.sourceRefName=${BranchName}"
    $PRs = Invoke-RestMethod -Uri $GetPRsApiUri -Method GET -Header $AuthenicationHeader
    
    ForEach($PR in $PRs.Value)
    {
        Write-Host "Found PR $($PR.pullRequestId) '$($PR.title)': isDraft=$($PR.isDraft), status=$($PR.status), mergeStatus=$($PR.mergeStatus)"
        
        if (!$PR.isDraft -and ($PR.mergeStatus -eq "succeeded") -and ($PR.status -eq "active"))
        {
            Write-Host "Validation build is queued for branch '${BranchName}'."
            return $true
        }
    }
    
    Write-Host "No validation build is queued for branch '${BranchName}'."
    return $false
}

# Check if a valid PR exists. If so, cancel this build, because a validation build is also queued. 
$HasValidationBuild = Check-For-Validation-Build -BranchName ${env:Build_SourceBranch}
if (($HasValidationBuild -eq $true) -and (${env:Build_Reason} -ne "Manual") -and !${env:Build_SourceBranch}.EndsWith('/merge'))
{
    Cancel-This-Build
}

Note that the System.AccessToken environment variable must be made visible for the script to work.

月下客 2025-01-21 15:07:46

“开箱即用”——你不能。但是,作为解决方法,您可以使用 REST API 来检查活动的拉取请求,如果它们存在,则会导致您不需要的构建失败:

  1. 获取拉取请求- 定位特定分支
  2. 使用构建管道中的系统访问令牌访问存储库、工件和其他资源
  3. 使用 Powershell 从构建中退出:exit 1

"Out-of-box" - you can not. However as a workaround, you can use rest API to check active pull requests and if they exist just fail your unneeded build:

  1. Get Pull Requests - Targeting a specific branch
  2. Use the system access token from your build pipeline. Access repositories, artifacts, and other resources
  3. Exit with Powershell from a build: exit 1
温柔一刀 2025-01-21 15:07:46

因为这就是设计,因此,两个构建都会被触发,但您可以尝试使用 follow 方法来避免构建同时排队。

在构建验证策略中 - 禁用自动排队。或者将 PR 标记为草稿,同时进行更改。在此更改之后,任何更改都只会触发 CI 构建/管道,准备好后只需发布 PR 或手动对 PR 进行排队。

Because that's the design, thus, both build will be triggered but you could have try with follow method to avoid the build queued at the same time.

In the build validation policy - disable automatic queuing. Or mark the PR as draft, while changes are being worked on. After this change any of the changes will only trigger CI build/pipeline, and when ready just publish the PR or queue the PR manually.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文