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

Til*_* F. 6 continuous-integration build-triggers pull-request azure-devops

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

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

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

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

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

这个问题已经作为一个问题发布在这里,但我在回复中找不到令人满意的答案(例如,分支过滤器和命名策略不能解决问题)。

Til*_* F. 3

我已经按照 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
}
Run Code Online (Sandbox Code Playgroud)

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