TFS 2010 API:队列同步构建并获取每个排队构建的状态:“在代理上运行(等待构建代理)”

是否可以同步排队构建?

我试过这样的事情:

CodeActivity:

[BuildActivity(HostEnvironmentOption.Agent)] public sealed class QueueNewBuild : CodeActivity { // The Team Project that the build definition belongs to. [RequiredArgument] public InArgument BuildDetail { get; set; } // The build definition to queue [RequiredArgument] public InArgument BuildDefinition { get; set; } protected override BuildResult Execute(CodeActivityContext context) { // Obtain the runtime value of the input arguments var buildDefinitionName = context.GetValue(BuildDefinition); var buildDetail = context.GetValue(BuildDetail); // Obtain the Team Project for the current build definition. var tfsProject = buildDetail.BuildDefinition.TeamProject; var configurationServerUri = buildDetail.BuildServer.TeamProjectCollection.Uri.ToString(); var server = new TfsTeamProjectCollection(new Uri(configurationServerUri)); server.EnsureAuthenticated(); var buildServer = server.GetService(); var buildDefinition = buildServer.GetBuildDefinition(tfsProject, buildDefinitionName); var queuedBuild = buildServer.QueueBuild(buildDefinition); var buildStatusWatcher = new BuildStatusWatcher(queuedBuild.Id); buildStatusWatcher.Connect(buildServer, tfsProject); do { } while (buildStatusWatcher.Status != QueueStatus.Completed && buildStatusWatcher.Status != QueueStatus.Canceled); buildStatusWatcher.Disconnect(); return new BuildResult { WasSuccessfully = buildStatusWatcher.Build.CompilationStatus == BuildPhaseStatus.Succeeded, BuildDetail = buildStatusWatcher.Build }; } } 

BuildResult:

 public class BuildResult { public bool WasSuccessfully { get; set; } public IBuildDetail BuildDetail { get; set; } } 

BuildStatusWatcher:

 public class BuildStatusWatcher { private IQueuedBuildsView _queuedBuildsView; private readonly int _queueBuildId; private QueueStatus _status; private IBuildDetail _build; public BuildStatusWatcher(int queueBuildId) { _queueBuildId = queueBuildId; } public IBuildDetail Build { get { return _build; } } public QueueStatus Status { get { return _status; } } public void Connect(IBuildServer buildServer, string tfsProject) { _queuedBuildsView = buildServer.CreateQueuedBuildsView(tfsProject); _queuedBuildsView.StatusChanged += QueuedBuildsViewStatusChanged; _queuedBuildsView.Connect(10000, null); } public void Disconnect() { _queuedBuildsView.Disconnect(); } private void QueuedBuildsViewStatusChanged(object sender, StatusChangedEventArgs e) { if (e.Changed) { var queuedBuild = _queuedBuildsView.QueuedBuilds.FirstOrDefault(x => x.Id == _queueBuildId); if (queuedBuild != null) { _status = queuedBuild.Status; _build = queuedBuild.Build; } } } } 

所以我试图等待构建完成或取消,但这不起作用,因为子构建的构建代理正在等待整个时间。

我有一个主构建过程(在代理1上运行),它调用13个子构建过程(全部在代理2上运行)。 我想等待每个子构建过程,以便在子构建过程失败时我可以中止主构建过程。

有任何想法吗?

更新:

服务’XXX – Agent1’有一个例外:exception消息:操作未在分配的超时00:00:30内完成。 分配给此操作的时间可能是较长超时的一部分。 (输入FaultException`1)

exception堆栈跟踪:在Microsoft.TeamFoundation.Build.Machine.BuildAgentService.TerminateWorkflow(TerminatingException ex)

工作流程:

在此处输入图像描述

由于您只拥有一个额外的构建代理,我认为使用这样一个复杂的模块并不会给您带来太多帮助。

我会实施两个单独的活动:
一个Activity将BuildDetailBuildDefinition作为输入,在新构建排队后退出。
我会在XAML的循环中调用此活动。 这会将构建代理#2中的所有构建排队。

第二个活动将检查构建代理#2的状态并等待代理再次变为空闲。
一旦它这样做,我会检查应该在Agent#2中成功运行的每个构建定义,如下所示:
if(buildDefinition.LastGoodBuildUri != buildDefinition.LastBuildUri)

这种方法看起来有点不利,事实上构建不会在第一次打破“子”构建时失败/停止。
在我看来,这实际上是一个优势:如果不止一个失败,你会马上知道。

我创建了一个特殊的模板,用于按顺序启动构建。 基本模板:

获取构建,QueueBuild,MonitorBuild

获取构建是默认模板中的活动。 它是我模板中的第一个活动,只在开始时调用一次。

QueueBuild是在codeplex从TFSExtensions获得的活动。 我创建了一个包含IQueueBuild对象的变量,该对象是我计划启动的每个构建的QueueBuild活动的结果。 我将Result设置为此变量。 我打电话给我的是CurrentQueueBuild。 在每个QueueBuild活动启动构建之后,此变量将由活动更新到当前构建队列。

MonitorBuild是我创建的一个序列,它执行大部分“同步”:

首先是一个检查CurrentQueueBuild是否为null的活动(CurrentQueueBuild Is Nothing)。 如果它是我抛出exception,因为我不能拥有它。

其次是While活动(称为’while building’)。 它的条件是’CurrentQueueBuild.Status = BuildStatus.InProgress’。 在While的主体中,我有另一个包含InvokeMethod活动的序列(TargetObject = CurrentQueueBuild,MethodName = Refresh,我添加了QueryOptions类型的In参数设置为QueryOptions.All)。 我按照InvokeMethod设置延迟活动设置为等待5秒。

最后,我写了一条构建消息来记录状态。 这显然是可选的。

总而言之 ,我有5个构建我开始,每个我有一个QueueBuild活动,然后是如上所述放在一起的Monitor Build活动。

希望这有助于某人。