You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure Pipeline自动创建PR需求及相关技术问题咨询

实现分支X自动创建/更新到分支Y的ADO PR流水线

核心方案

通过Azure Pipeline YAML结合Azure DevOps REST API,实现分支X变更触发后,自动检测是否存在从X到Y的开启状态PR,再根据结果执行创建PR(含审阅人、工作项关联)或更新现有PR(追加审阅人、关联新工作项)的操作。

具体实现步骤

1. 流水线触发配置

限定仅分支X有变更时触发流水线,YAML配置如下:

trigger:
  branches:
    include:
      - refs/heads/X  # 替换为你的分支X名称
  paths:
    exclude:
      - README.md  # 可选,排除无需触发的文件路径

2. 配置流水线权限

  • 为流水线服务账号分配仓库Contributor权限,用于创建/更新PR
  • 确保服务账号拥有项目级读取工作项权限,用于关联工作项
  • 在流水线代理作业设置中勾选允许脚本访问OAuth令牌,让脚本能调用ADO API

3. 检测现有开启状态的PR

用PowerShell脚本调用ADO REST API,查询是否存在从X到Y的活跃PR,并将结果存入流水线变量:

$orgName = "$(System.TeamFoundationCollectionUri)"
$projectName = "$(System.TeamProject)"
$repoName = "$(Build.Repository.Name)"
$sourceBranch = "refs/heads/X"
$targetBranch = "refs/heads/Y"

# 查询活跃PR
$prUrl = "$orgName/$projectName/_apis/git/repositories/$repoName/pullrequests?sourceRefName=$sourceBranch&targetRefName=$targetBranch&status=active&api-version=7.1-preview.1"
$prResponse = Invoke-RestMethod -Uri $prUrl -Headers @{Authorization = "Bearer $(System.AccessToken)"} -Method Get

# 输出PR ID到流水线变量
if ($prResponse.count -gt 0) {
  Write-Host "##vso[task.setvariable variable=ExistingPrId;]$($prResponse.value[0].pullRequestId)"
  Write-Host "找到已存在的活跃PR: $($prResponse.value[0].pullRequestId)"
} else {
  Write-Host "未找到从X到Y的活跃PR"
}

4. 提取变更作者与关联工作项

4.1 获取提交作者

提取当前触发提交的作者邮箱(去重),存入变量供后续添加审阅人使用:

$orgName = "$(System.TeamFoundationCollectionUri)"
$projectName = "$(System.TeamProject)"
$repoName = "$(Build.Repository.Name)"

# 获取当前提交的作者信息
$commitsUrl = "$orgName/$projectName/_apis/git/repositories/$repoName/commits?searchCriteria.fromCommitId=$(Build.SourceVersion)&searchCriteria.toCommitId=$(Build.SourceVersion)&api-version=7.1-preview.1"
$commits = Invoke-RestMethod -Uri $commitsUrl -Headers @{Authorization = "Bearer $(System.AccessToken)"} -Method Get
$authors = $commits.value | Select-Object -ExpandProperty author -Unique | Select-Object -ExpandProperty email
Write-Host "##vso[task.setvariable variable=PrReviewers;]$($authors -join ',')"

4.2 获取关联工作项

提取当前构建关联的工作项ID,存入变量供PR关联使用:

$orgName = "$(System.TeamFoundationCollectionUri)"
$projectName = "$(System.TeamProject)"

# 获取构建关联的工作项
$workItemsUrl = "$orgName/$projectName/_apis/build/builds/$(Build.BuildId)/workitems?api-version=7.1-preview.2"
$workItems = Invoke-RestMethod -Uri $workItemsUrl -Headers @{Authorization = "Bearer $(System.AccessToken)"} -Method Get
$workItemIds = $workItems.value | Select-Object -ExpandProperty id | ForEach-Object { "`"$_`"" }
$workItemIdsStr = "[$($workItemIds -join ',')]"
Write-Host "##vso[task.setvariable variable=LinkedWorkItems;]$workItemIdsStr"

5. 创建或更新PR

根据ExistingPrId变量的值,分支执行创建PR或更新现有PR的操作:

$orgName = "$(System.TeamFoundationCollectionUri)"
$projectName = "$(System.TeamProject)"
$repoName = "$(Build.Repository.Name)"
$sourceBranch = "refs/heads/X"
$targetBranch = "refs/heads/Y"

if (-not $(ExistingPrId)) {
  # 创建新PR
  $reviewersList = $(PrReviewers) -split ',' | ForEach-Object { @{id = $_ } }
  $workItemsList = $(LinkedWorkItems) | ConvertFrom-Json | ForEach-Object { @{id = $_ } }

  $createPrBody = @{
    sourceRefName = $sourceBranch
    targetRefName = $targetBranch
    title = "Auto-merge branch X to Y"
    description = "Automatically created by pipeline $(Build.BuildNumber)"
    reviewers = $reviewersList
    workItemRefs = $workItemsList
  } | ConvertTo-Json -Depth 3

  $createPrUrl = "$orgName/$projectName/_apis/git/repositories/$repoName/pullrequests?api-version=7.1-preview.1"
  Invoke-RestMethod -Uri $createPrUrl -Headers @{Authorization = "Bearer $(System.AccessToken)"} -Method Post -Body $createPrBody -ContentType "application/json"
  Write-Host "成功创建从X到Y的PR"
} else {
  # 添加新审阅人
  $reviewersBody = $(PrReviewers) -split ',' | ForEach-Object { @{id = $_ } } | ConvertTo-Json
  $addReviewerUrl = "$orgName/$projectName/_apis/git/repositories/$repoName/pullrequests/$(ExistingPrId)/reviewers?api-version=7.1-preview.1"
  Invoke-RestMethod -Uri $addReviewerUrl -Headers @{Authorization = "Bearer $(System.AccessToken)"} -Method Post -Body $reviewersBody -ContentType "application/json"

  # 关联新工作项
  $workItemsBody = $(LinkedWorkItems) | ConvertFrom-Json | ForEach-Object { @{id = $_ } } | ConvertTo-Json
  $linkWorkItemUrl = "$orgName/$projectName/_apis/git/repositories/$repoName/pullrequests/$(ExistingPrId)/workitems?api-version=7.1-preview.1"
  Invoke-RestMethod -Uri $linkWorkItemUrl -Headers @{Authorization = "Bearer $(System.AccessToken)"} -Method Post -Body $workItemsBody -ContentType "application/json"

  # 更新PR描述
  $updatePrBody = @{
    description = "Updated by pipeline $(Build.BuildNumber). Latest commit: $(Build.SourceVersion)"
  } | ConvertTo-Json
  $updatePrUrl = "$orgName/$projectName/_apis/git/repositories/$repoName/pullrequests/$(ExistingPrId)?api-version=7.1-preview.1"
  Invoke-RestMethod -Uri $updatePrUrl -Headers @{Authorization = "Bearer $(System.AccessToken)"} -Method Patch -Body $updatePrBody -ContentType "application/json"

  Write-Host "成功更新现有PR: $(ExistingPrId)"
}

优化建议

  • 去重审阅人:更新PR前调用GET /pullrequests/{prId}/reviewers接口,对比现有审阅人后再添加,避免重复
  • 动态PR标题:从提交信息中提取主题作为PR标题,提升可读性
  • 重试机制:给REST API调用添加Retry-Command逻辑,应对网络波动
  • 通知触发:添加发送通知的任务,告知相关人员PR已创建/更新

内容的提问来源于stack exchange,提问作者Walter Svenddal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 10:25:41