我们正在使用持续集成作为构建自动化的一部分。对于每次签入,tfs构建服务器构建项目并成功部署到我们的Web服务器。
当构建失败时,它会自动创建一个新Bug,其中包含构建失败的详细信息。
由于CI和服务器上的活动,在构建开始成功之前,这可能会导致10或20个失败工作项。
所以,我有两个选择。我想让构建过程看看是否已存在构建失败的开放工作项,只是添加详细信息;或者,我希望构建服务器在它再次开始工作时自动关闭所有构建失败项。
有什么想法吗?
答案 0 :(得分:2)
您可以创建MSBuild任务来执行其中任一选项。以下是我用来启动您的类似代码,但由于我不知道您的工作项或流程的详细信息,因此您必须对其进行更改。
此代码获取与构建关联的所有工作项并更新其状态。
如果选择第一个选项,则只需更改UpdateWorkItemStatus方法并更新任何现有的WI。对于第二种方法,您需要做更多的工作,因为您需要查找先前的构建而不是将其作为输入。
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Build.Utilities;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using Microsoft.Build.Framework;
using Microsoft.TeamFoundation.Build;
using Microsoft.TeamFoundation.Build.Client;
namespace Nowcom.TeamBuild.Tasks
{
public class UpdateWorkItemState: Task
{
private IBuildDetail _Build;
private void test()
{
TeamFoundationServerUrl = "Teamserver";
BuildUri = "vstfs:///Build/Build/1741";
Execute();
}
public override bool Execute()
{
bool result = true;
try
{
TeamFoundationServer tfs = TeamFoundationServerFactory.GetServer(TeamFoundationServerUrl, new UICredentialsProvider());
tfs.EnsureAuthenticated();
WorkItemStore store = (WorkItemStore)tfs.GetService(typeof(WorkItemStore));
IBuildServer buildServer = (IBuildServer)tfs.GetService(typeof(IBuildServer));
_Build = buildServer.GetAllBuildDetails(new Uri(BuildUri));
//add build step
IBuildStep buildStep = InformationNodeConverters.AddBuildStep(_Build, "UpdateWorkItemStatus", "Updating Work Item Status");
try
{
Log.LogMessageFromText(string.Format("Build Number: {0}", _Build.BuildNumber), MessageImportance.Normal);
List<IWorkItemSummary> assocWorkItems = InformationNodeConverters.GetAssociatedWorkItems(_Build);
// update work item status
UpdateWorkItemStatus(store, assocWorkItems, "Open", "Resolved");
SaveWorkItems(store, assocWorkItems);
}
catch (Exception)
{
UpdateBuildStep(buildStep, false);
throw;
}
UpdateBuildStep(buildStep, result);
}
catch (Exception e)
{
result = false;
BuildErrorEventArgs eventArgs;
eventArgs = new BuildErrorEventArgs("", "", BuildEngine.ProjectFileOfTaskNode, BuildEngine.LineNumberOfTaskNode, BuildEngine.ColumnNumberOfTaskNode, 0, 0, string.Format("UpdateWorkItemState failed: {0}", e.Message), "", "");
BuildEngine.LogErrorEvent(eventArgs);
throw;
}
return result;
}
private static void SaveWorkItems(WorkItemStore store, List<IWorkItemSummary> assocWorkItems)
{
foreach (IWorkItemSummary w in assocWorkItems)
{
WorkItem wi = store.GetWorkItem(w.WorkItemId);
if (wi.IsDirty)
{
wi.Save();
}
}
}
// check in this routine if the workitem is a bug created by your CI process. Check by title or assigned to or description depending on your process.
private void UpdateWorkItemStatus(WorkItemStore store, List<IWorkItemSummary> assocWorkItems, string oldState, string newState)
{
foreach (IWorkItemSummary w in assocWorkItems)
{
Log.LogMessageFromText(string.Format("Updating Workitem Id {0}", w.WorkItemId), MessageImportance.Normal);
WorkItem wi = store.GetWorkItem(w.WorkItemId);
if (wi.Fields.Contains("Microsoft.VSTS.Build.IntegrationBuild") && wi.State != "Resolved")
{
wi.Fields["Microsoft.VSTS.Build.IntegrationBuild"].Value =_Build.BuildNumber;
}
if (wi.State == oldState)
{
wi.State = newState;
foreach (Field field in wi.Fields)
{
if (!field.IsValid)
{
break;
}
}
}
if (wi.IsDirty)
{
wi.Save();
}
}
}
private void UpdateBuildStep(IBuildStep step, bool result)
{
step.Status = result ? BuildStepStatus.Succeeded : BuildStepStatus.Failed;
step.FinishTime = DateTime.Now;
step.Save();
}
[Required]
public string BuildUri { get; set; }
[Required]
public string TeamFoundationServerUrl {get; set;}
}
}
< UpdateWorkItemState
TeamFoundationServerUrl="$(TeamFoundationServerUrl)"
BuildUri="$(BuildUri)"
ContinueOnError="false"/>