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

如何用Azure DevOps C#客户端获取PR关联构建状态并完成PR?

获取Azure DevOps PR关联构建状态并自动完成PR的正确方式

一、解决构建状态为空的问题:正确获取PR关联构建状态

默认调用GetPullRequestByIdAsync时,不会返回PR的关联状态(包括构建任务),必须指定PullRequestExpand.Statuses扩展参数才能加载这部分数据。

方法1:通过GitHttpClient获取PR的构建状态

using Microsoft.TeamFoundation.SourceControl.WebApi;
using Microsoft.VisualStudio.Services.WebApi;

// 初始化已有的GitHttpClient实例
var gitClient = connection.GetClient<GitHttpClient>();

// 查询PR时指定扩展参数,加载状态集合
var pullRequest = await gitClient.GetPullRequestByIdAsync(
    repositoryId: repoId,
    pullRequestId: pullRequestId,
    expand: PullRequestExpand.Statuses // 关键:指定加载状态数据
);

// 从Statuses中筛选出构建类型的状态条目
var buildStatuses = pullRequest.Statuses
    .Where(s => s.Context.Type == "build")
    .ToList();

// 遍历检查每个构建的状态
foreach (var buildStatus in buildStatuses)
{
    // buildStatus.State 表示构建状态:NotSet、Pending、Succeeded、Failed等
    // buildStatus.Description 包含构建ID、结果等详细信息
    Console.WriteLine($"构建状态:{buildStatus.State}, 详情:{buildStatus.Description}");
}

方法2:通过BuildHttpClient直接查询关联PR的构建

如果需要更完整的构建信息(如执行时间、日志链接),可以用BuildHttpClient根据PR ID筛选关联构建:

using Microsoft.TeamFoundation.Build.WebApi;

// 初始化BuildHttpClient实例
var buildClient = connection.GetClient<BuildHttpClient>();

// 查询关联当前PR的所有构建任务
var builds = await buildClient.GetBuildsAsync(
    project: projectName,
    repositoryId: repoId,
    sourcePullRequestId: pullRequestId // 用PR ID过滤构建
);

// 检查每个构建的执行结果
foreach (var build in builds)
{
    bool isBuildSuccess = build.Status == BuildStatus.Completed && build.Result == BuildResult.Succeeded;
    Console.WriteLine($"构建ID {build.Id}: 状态={build.Status}, 结果={build.Result}, 是否成功={isBuildSuccess}");
}

二、判断所有构建成功后完成PR

结合你的需求,完整流程是循环检查构建状态→确认全部成功→调用更新接口完成PR。注意用异步调用替代.Result避免线程阻塞,同时确保用户拥有绕过分支策略的权限。

完整示例代码:

using System.Threading.Tasks;

public async Task CompletePrWhenBuildsSucceedAsync(VssConnection connection, Guid repoId, int pullRequestId, string projectName)
{
    var gitClient = connection.GetClient<GitHttpClient>();
    var buildClient = connection.GetClient<BuildHttpClient>();
    
    // 循环检查构建状态(可根据需求调整重试间隔和次数)
    bool allBuildsSucceeded = false;
    int retryCount = 0;
    const int maxRetries = 20;
    const int retryIntervalSeconds = 30;

    while (!allBuildsSucceeded && retryCount < maxRetries)
    {
        // 获取关联PR的所有构建
        var builds = await buildClient.GetBuildsAsync(
            project: projectName,
            repositoryId: repoId,
            sourcePullRequestId: pullRequestId
        );

        // 判断是否所有构建都已完成且成功
        allBuildsSucceeded = builds.All(b => 
            b.Status == BuildStatus.Completed && 
            b.Result == BuildResult.Succeeded);

        if (!allBuildsSucceeded)
        {
            await Task.Delay(TimeSpan.FromSeconds(retryIntervalSeconds));
            retryCount++;
        }
    }

    if (allBuildsSucceeded)
    {
        // 完成PR(基于你的代码调整为异步调用)
        var updatedPr = new GitPullRequest()
        {
            Status = PullRequestStatus.Completed,
            CompletionOptions = new GitPullRequestCompletionOptions() 
            { 
                SquashMerge = true, 
                DeleteSourceBranch = true, 
                BypassPolicy = true 
            }
        };

        var completedPr = await gitClient.UpdatePullRequestAsync(updatedPr, repoId, pullRequestId);
        Console.WriteLine($"PR {pullRequestId} 已成功完成");
    }
    else
    {
        Console.WriteLine($"超时:PR {pullRequestId} 的关联构建未全部成功");
    }
}

关键注意点

  • 必须指定PullRequestExpand.Statuses,否则GitHttpClient返回的Statuses集合为空。
  • 使用BuildHttpClient时,sourcePullRequestId参数必须准确关联目标PR。
  • 异步操作优先用await,避免.Result导致的线程阻塞或死锁。
  • BypassPolicy=true生效的前提是当前用户拥有"绕过分支策略"的权限。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 04:17:19