// Copyright Epic Games, Inc. All Rights Reserved.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
namespace BuildAgent.Issues
{
///
/// Information about a particular issue
///
[DataContract]
class Issue
{
///
/// The issue id in the database. -1 for issues that have not been posted yet.
///
[DataMember(Order = 0, IsRequired = true)]
public long Id = -1;
///
/// Project that this belongs to
///
[DataMember(Order = 1, IsRequired = true)]
public string Project;
///
/// Type common to all diagnostics within this issue.
///
[DataMember(Order = 2, IsRequired = true)]
public string Category;
///
/// The initial job that this error was seen on. Allows other issues from the same job to be merged.
///
[DataMember(Order = 3, IsRequired = true)]
public string InitialJobUrl;
///
/// List of strings to display in the details panel for this job
///
[DataMember(Order = 4, IsRequired = true)]
public List Diagnostics = new List();
///
/// List of files associated with this issue
///
[DataMember(Order = 5)]
public HashSet FileNames = new HashSet();
///
/// List of messages associated with this issue
///
[DataMember(Order = 6)]
public SortedSet Identifiers = new SortedSet();
///
/// Other arbitrary references to assets or files
///
[DataMember(Order = 7)]
public SortedSet References = new SortedSet();
///
/// The last posted issue summary. Will be updated if it changes.
///
[DataMember(Order = 20)]
public string PostedSummary;
///
/// Whether we've posted an update to the resolved flag to the server
///
[DataMember(Order = 22)]
public bool bPostedResolved;
///
/// The time at which the issue was closed. Issues will be retained for 24 hours after they are closed, in case the same issue appears in another stream and to prevent the issue being added again.
///
[DataMember(Order = 23)]
public DateTime? ResolvedAt;
///
/// Map of stream name -> step name -> history for builds exhibiting this issue
///
[DataMember(Order = 30, IsRequired = true)]
public Dictionary> Streams = new Dictionary>();
///
/// Set of changes which may have caused this issue. Used to de-duplicate issues between streams.
///
[DataMember(Order = 31)]
public HashSet SourceChanges = new HashSet();
///
/// List of possible causers
///
[DataMember(Order = 32)]
public HashSet Watchers = new HashSet();
///
/// Set of causers that have yet to be added to the possible causers list
///
[DataMember(Order = 33)]
public HashSet PendingWatchers = new HashSet();
///
/// Constructor
///
/// Category of this issue
/// Url of the initial job that this error was seen with
///
public Issue(string Project, string Category, string InitialJobUrl, IssueDiagnostic Diagnostic)
{
this.Project = Project;
this.Category = Category;
this.InitialJobUrl = InitialJobUrl;
this.Diagnostics.Add(Diagnostic);
}
///
/// Determines whether the issue can be closed
///
/// True if the issue can be closed
public bool IsResolved()
{
return Streams.Values.All(x => x.Values.All(y => y.NextSuccessfulBuild != null));
}
///
/// Finds all the steps which are related to this issue
///
/// Set of step names
public SortedSet GetStepNames()
{
return new SortedSet(Streams.Values.SelectMany(x => x.Keys));
}
///
/// Format the issue for the debugger
///
/// String representation of the issue
public override string ToString()
{
StringBuilder Result = new StringBuilder();
if(Id == -1)
{
Result.Append("[New] ");
}
else
{
Result.AppendFormat("[{0}] ", Id);
}
Result.AppendFormat("Errors in {0}", String.Join(", ", GetStepNames()));
return Result.ToString();
}
}
}