/// <summary> /// Export the build graph to a Json file for parsing by Horde /// </summary> /// <param name="File">Output file to write</param> public void ExportForHorde(FileReference File) { DirectoryReference.CreateDirectory(File.Directory); using (JsonWriter JsonWriter = new JsonWriter(File.FullName)) { JsonWriter.WriteObjectStart(); JsonWriter.WriteArrayStart("Groups"); foreach (Agent Agent in Agents) { JsonWriter.WriteObjectStart(); JsonWriter.WriteArrayStart("Nodes"); foreach (Node Node in Agent.Nodes) { JsonWriter.WriteObjectStart(); JsonWriter.WriteValue("Name", Node.Name); JsonWriter.WriteValue("Group", Agent.Name); JsonWriter.WriteValue("RunEarly", Node.bRunEarly); JsonWriter.WriteValue("Exclusive", true); JsonWriter.WriteArrayStart("InputDependencies"); foreach (string InputDependency in Node.GetDirectInputDependencies().Select(x => x.Name)) { JsonWriter.WriteValue(InputDependency); } JsonWriter.WriteArrayEnd(); JsonWriter.WriteArrayStart("OrderDependencies"); foreach (string OrderDependency in Node.GetDirectOrderDependencies().Select(x => x.Name)) { JsonWriter.WriteValue(OrderDependency); } JsonWriter.WriteArrayEnd(); JsonWriter.WriteObjectEnd(); } JsonWriter.WriteArrayEnd(); JsonWriter.WriteObjectEnd(); } JsonWriter.WriteArrayEnd(); JsonWriter.WriteObjectEnd(); } }
/// <summary> /// Print the contents of the graph /// </summary> /// <param name="CompletedNodes">Set of nodes which are already complete</param> /// <param name="PrintOptions">Options for how to print the graph</param> public void Print(HashSet <Node> CompletedNodes, GraphPrintOptions PrintOptions) { // Print the options if ((PrintOptions & GraphPrintOptions.ShowCommandLineOptions) != 0) { // Get the list of messages List <string> Messages = new List <string>(); foreach (GraphOption Option in Options) { StringBuilder Message = new StringBuilder(); Message.AppendFormat("-set:{0}=... {1}", Option.Name, Option.Description); if (!String.IsNullOrEmpty(Option.DefaultValue)) { Message.AppendFormat(" (Default: {0})", Option.DefaultValue); } Messages.Add(Message.ToString()); } // Format them to the log if (Messages.Count > 0) { CommandUtils.LogInformation(""); CommandUtils.LogInformation("Options:"); CommandUtils.LogInformation(""); foreach (string Line in CommandUtils.FormatParams(Messages, 4, 24)) { CommandUtils.LogInformation(Line); } } } // Get a list of all the triggers, including the null global one List <ManualTrigger> AllTriggers = new List <ManualTrigger>(); AllTriggers.Add(null); AllTriggers.AddRange(NameToTrigger.Values.OrderBy(x => x.QualifiedName)); // Output all the triggers in order CommandUtils.LogInformation(""); CommandUtils.LogInformation("Graph:"); foreach (ManualTrigger Trigger in AllTriggers) { // Filter everything by this trigger Dictionary <Agent, Node[]> FilteredAgentToNodes = new Dictionary <Agent, Node[]>(); foreach (Agent Agent in Agents) { Node[] Nodes = Agent.Nodes.Where(x => x.ControllingTrigger == Trigger).ToArray(); if (Nodes.Length > 0) { FilteredAgentToNodes[Agent] = Nodes; } } // Skip this trigger if there's nothing to display if (FilteredAgentToNodes.Count == 0) { continue; } // Print the trigger name CommandUtils.LogInformation(" Trigger: {0}", (Trigger == null)? "None" : Trigger.QualifiedName); if (Trigger != null && PrintOptions.HasFlag(GraphPrintOptions.ShowNotifications)) { foreach (string User in Trigger.NotifyUsers) { CommandUtils.LogInformation(" notify> {0}", User); } } // Output all the agents for this trigger foreach (Agent Agent in Agents) { Node[] Nodes; if (FilteredAgentToNodes.TryGetValue(Agent, out Nodes)) { CommandUtils.LogInformation(" Agent: {0} ({1})", Agent.Name, String.Join(";", Agent.PossibleTypes)); foreach (Node Node in Nodes) { CommandUtils.LogInformation(" Node: {0}{1}", Node.Name, CompletedNodes.Contains(Node)? " (completed)" : Node.bRunEarly? " (early)" : ""); if (PrintOptions.HasFlag(GraphPrintOptions.ShowDependencies)) { HashSet <Node> InputDependencies = new HashSet <Node>(Node.GetDirectInputDependencies()); foreach (Node InputDependency in InputDependencies) { CommandUtils.LogInformation(" input> {0}", InputDependency.Name); } HashSet <Node> OrderDependencies = new HashSet <Node>(Node.GetDirectOrderDependencies()); foreach (Node OrderDependency in OrderDependencies.Except(InputDependencies)) { CommandUtils.LogInformation(" after> {0}", OrderDependency.Name); } } if (PrintOptions.HasFlag(GraphPrintOptions.ShowNotifications)) { string Label = Node.bNotifyOnWarnings? "warnings" : "errors"; foreach (string User in Node.NotifyUsers) { CommandUtils.LogInformation(" {0}> {1}", Label, User); } foreach (string Submitter in Node.NotifySubmitters) { CommandUtils.LogInformation(" {0}> submitters to {1}", Label, Submitter); } } } } } } CommandUtils.LogInformation(""); // Print out all the non-empty aggregates string[] AggregateNames = AggregateNameToNodes.Where(x => x.Value.Length > 0).Select(x => x.Key).OrderBy(x => x).ToArray(); if (AggregateNames.Length > 0) { CommandUtils.LogInformation("Aggregates:"); foreach (string AggregateName in AggregateNames) { CommandUtils.LogInformation(" {0}", AggregateName); } CommandUtils.LogInformation(""); } }
/// <summary> /// Export the build graph to a Json file, for parallel execution by the build system /// </summary> /// <param name="File">Output file to write</param> /// <param name="Trigger">The trigger whose nodes to run. Null for the default nodes.</param> /// <param name="CompletedNodes">Set of nodes which have been completed</param> public void Export(FileReference File, ManualTrigger Trigger, HashSet <Node> CompletedNodes) { // Find all the nodes which we're actually going to execute. We'll use this to filter the graph. HashSet <Node> NodesToExecute = new HashSet <Node>(); foreach (Node Node in Agents.SelectMany(x => x.Nodes)) { if (!CompletedNodes.Contains(Node) && Node.IsBehind(Trigger)) { NodesToExecute.Add(Node); } } // Open the output file using (JsonWriter JsonWriter = new JsonWriter(File.FullName)) { JsonWriter.WriteObjectStart(); // Write all the agents JsonWriter.WriteArrayStart("Groups"); foreach (Agent Agent in Agents) { Node[] Nodes = Agent.Nodes.Where(x => NodesToExecute.Contains(x) && x.ControllingTrigger == Trigger).ToArray(); if (Nodes.Length > 0) { JsonWriter.WriteObjectStart(); JsonWriter.WriteValue("Name", Agent.Name); JsonWriter.WriteArrayStart("Agent Types"); foreach (string AgentType in Agent.PossibleTypes) { JsonWriter.WriteValue(AgentType); } JsonWriter.WriteArrayEnd(); JsonWriter.WriteArrayStart("Nodes"); foreach (Node Node in Nodes) { JsonWriter.WriteObjectStart(); JsonWriter.WriteValue("Name", Node.Name); JsonWriter.WriteValue("DependsOn", String.Join(";", Node.GetDirectOrderDependencies().Where(x => NodesToExecute.Contains(x) && x.ControllingTrigger == Trigger))); JsonWriter.WriteValue("RunEarly", Node.bRunEarly); JsonWriter.WriteObjectStart("Notify"); JsonWriter.WriteValue("Default", String.Join(";", Node.NotifyUsers)); JsonWriter.WriteValue("Submitters", String.Join(";", Node.NotifySubmitters)); JsonWriter.WriteValue("Warnings", Node.bNotifyOnWarnings); JsonWriter.WriteObjectEnd(); JsonWriter.WriteObjectEnd(); } JsonWriter.WriteArrayEnd(); JsonWriter.WriteObjectEnd(); } } JsonWriter.WriteArrayEnd(); // Write all the badges JsonWriter.WriteArrayStart("Badges"); foreach (Badge Badge in Badges) { Node[] Dependencies = Badge.Nodes.Where(x => NodesToExecute.Contains(x) && x.ControllingTrigger == Trigger).ToArray(); if (Dependencies.Length > 0) { // Reduce that list to the smallest subset of direct dependencies HashSet <Node> DirectDependencies = new HashSet <Node>(Dependencies); foreach (Node Dependency in Dependencies) { DirectDependencies.ExceptWith(Dependency.OrderDependencies); } JsonWriter.WriteObjectStart(); JsonWriter.WriteValue("Name", Badge.Name); if (!String.IsNullOrEmpty(Badge.Project)) { JsonWriter.WriteValue("Project", Badge.Project); } if (Badge.Change != 0) { JsonWriter.WriteValue("Change", Badge.Change); } JsonWriter.WriteValue("AllDependencies", String.Join(";", Agents.SelectMany(x => x.Nodes).Where(x => Dependencies.Contains(x)).Select(x => x.Name))); JsonWriter.WriteValue("DirectDependencies", String.Join(";", DirectDependencies.Select(x => x.Name))); JsonWriter.WriteObjectEnd(); } } JsonWriter.WriteArrayEnd(); // Write all the triggers and reports. JsonWriter.WriteArrayStart("Reports"); foreach (Report Report in NameToReport.Values) { Node[] Dependencies = Report.Nodes.Where(x => NodesToExecute.Contains(x) && x.ControllingTrigger == Trigger).ToArray(); if (Dependencies.Length > 0) { // Reduce that list to the smallest subset of direct dependencies HashSet <Node> DirectDependencies = new HashSet <Node>(Dependencies); foreach (Node Dependency in Dependencies) { DirectDependencies.ExceptWith(Dependency.OrderDependencies); } JsonWriter.WriteObjectStart(); JsonWriter.WriteValue("Name", Report.Name); JsonWriter.WriteValue("AllDependencies", String.Join(";", Agents.SelectMany(x => x.Nodes).Where(x => Dependencies.Contains(x)).Select(x => x.Name))); JsonWriter.WriteValue("DirectDependencies", String.Join(";", DirectDependencies.Select(x => x.Name))); JsonWriter.WriteValue("Notify", String.Join(";", Report.NotifyUsers)); JsonWriter.WriteValue("IsTrigger", false); JsonWriter.WriteObjectEnd(); } } foreach (ManualTrigger DownstreamTrigger in NameToTrigger.Values) { if (DownstreamTrigger.Parent == Trigger) { // Find all the nodes that this trigger is dependent on HashSet <Node> Dependencies = new HashSet <Node>(); foreach (Node NodeToExecute in NodesToExecute) { if (NodeToExecute.IsBehind(DownstreamTrigger)) { Dependencies.UnionWith(NodeToExecute.OrderDependencies.Where(x => x.ControllingTrigger == Trigger)); } } // Reduce that list to the smallest subset of direct dependencies HashSet <Node> DirectDependencies = new HashSet <Node>(Dependencies); foreach (Node Dependency in Dependencies) { DirectDependencies.ExceptWith(Dependency.OrderDependencies); } // Write out the object JsonWriter.WriteObjectStart(); JsonWriter.WriteValue("Name", DownstreamTrigger.Name); JsonWriter.WriteValue("AllDependencies", String.Join(";", Agents.SelectMany(x => x.Nodes).Where(x => Dependencies.Contains(x)).Select(x => x.Name))); JsonWriter.WriteValue("DirectDependencies", String.Join(";", Dependencies.Where(x => DirectDependencies.Contains(x)).Select(x => x.Name))); JsonWriter.WriteValue("Notify", String.Join(";", DownstreamTrigger.NotifyUsers)); JsonWriter.WriteValue("IsTrigger", true); JsonWriter.WriteObjectEnd(); } } JsonWriter.WriteArrayEnd(); JsonWriter.WriteObjectEnd(); } }
/// <summary> /// Print the contents of the graph /// </summary> /// <param name="NodeToState">Mapping of node to its current state</param> /// <param name="Options">Options for how to print the graph</param> public void Print(HashSet <Node> CompletedNodes, GraphPrintOptions Options) { // Get a list of all the triggers, including the null global one List <ManualTrigger> AllTriggers = new List <ManualTrigger>(); AllTriggers.Add(null); AllTriggers.AddRange(NameToTrigger.Values.OrderBy(x => x.QualifiedName)); // Output all the triggers in order CommandUtils.Log(""); CommandUtils.Log("Graph:"); foreach (ManualTrigger Trigger in AllTriggers) { // Filter everything by this trigger Dictionary <AgentGroup, Node[]> FilteredGroupToNodes = new Dictionary <AgentGroup, Node[]>(); foreach (AgentGroup Group in Groups) { Node[] Nodes = Group.Nodes.Where(x => x.ControllingTrigger == Trigger).ToArray(); if (Nodes.Length > 0) { FilteredGroupToNodes[Group] = Nodes; } } // Skip this trigger if there's nothing to display if (FilteredGroupToNodes.Count == 0) { continue; } // Print the trigger name CommandUtils.Log(" Trigger: {0}", (Trigger == null)? "None" : Trigger.QualifiedName); if (Trigger != null && Options.HasFlag(GraphPrintOptions.ShowNotifications)) { foreach (string User in Trigger.NotifyUsers) { CommandUtils.Log(" notify> {0}", User); } } // Output all the groups for this trigger foreach (AgentGroup Group in Groups) { Node[] Nodes; if (FilteredGroupToNodes.TryGetValue(Group, out Nodes)) { CommandUtils.Log(" Group: {0} ({1})", Group.Name, String.Join(";", Group.PossibleTypes)); foreach (Node Node in Nodes) { CommandUtils.Log(" Node: {0}{1}", Node.Name, CompletedNodes.Contains(Node)? " (completed)" : ""); if (Options.HasFlag(GraphPrintOptions.ShowDependencies)) { HashSet <Node> InputDependencies = new HashSet <Node>(Node.GetDirectInputDependencies()); foreach (Node InputDependency in InputDependencies) { CommandUtils.Log(" input> {0}", InputDependency.Name); } HashSet <Node> OrderDependencies = new HashSet <Node>(Node.GetDirectOrderDependencies()); foreach (Node OrderDependency in OrderDependencies.Except(InputDependencies)) { CommandUtils.Log(" after> {0}", OrderDependency.Name); } } if (Options.HasFlag(GraphPrintOptions.ShowNotifications)) { string Label = Node.bNotifyOnWarnings? "warnings" : "errors"; foreach (string User in Node.NotifyUsers) { CommandUtils.Log(" {0}> {1}", Label, User); } foreach (string Submitter in Node.NotifySubmitters) { CommandUtils.Log(" {0}> submitters to {1}", Label, Submitter); } } } } } } CommandUtils.Log(""); // Print out all the aggregates string[] AggregateNames = AggregateNameToNodes.Keys.OrderBy(x => x).ToArray(); if (AggregateNames.Length > 0) { CommandUtils.Log("Aggregates:"); foreach (string AggregateName in AggregateNames) { CommandUtils.Log(" {0}", AggregateName); } CommandUtils.Log(""); } }
/// <summary> /// Export the build graph to a Json file, for parallel execution by the build system /// </summary> /// <param name="File">Output file to write</param> /// <param name="ActivatedTriggers">Set of triggers which have been activated</param> /// <param name="CompletedNodes">Set of nodes which have been completed</param> public void Export(FileReference File, HashSet <ManualTrigger> ActivatedTriggers, HashSet <Node> CompletedNodes) { // Find all the nodes which we're actually going to execute. We'll use this to filter the graph. HashSet <Node> NodesToExecute = new HashSet <Node>(); foreach (Node Node in Groups.SelectMany(x => x.Nodes)) { if (!CompletedNodes.Contains(Node)) { if (Node.ControllingTrigger == null || ActivatedTriggers.Contains(Node.ControllingTrigger)) { NodesToExecute.Add(Node); } } } // Open the output file using (JsonWriter JsonWriter = new JsonWriter(File.FullName)) { JsonWriter.WriteObjectStart(); // Write all the agent groups JsonWriter.WriteArrayStart("Groups"); foreach (AgentGroup Group in Groups) { Node[] Nodes = Group.Nodes.Where(x => NodesToExecute.Contains(x)).ToArray(); if (Nodes.Length > 0) { JsonWriter.WriteObjectStart(); JsonWriter.WriteValue("Name", Group.Name); JsonWriter.WriteArrayStart("Agent Types"); foreach (string AgentType in Group.PossibleTypes) { JsonWriter.WriteValue(AgentType); } JsonWriter.WriteArrayEnd(); JsonWriter.WriteArrayStart("Nodes"); foreach (Node Node in Nodes) { JsonWriter.WriteObjectStart(); JsonWriter.WriteValue("Name", Node.Name); JsonWriter.WriteValue("DependsOn", String.Join(";", Node.GetDirectOrderDependencies().Where(x => !CompletedNodes.Contains(x)))); JsonWriter.WriteObjectStart("Notify"); JsonWriter.WriteValue("Default", String.Join(";", Node.NotifyUsers)); JsonWriter.WriteValue("Submitters", String.Join(";", Node.NotifySubmitters)); JsonWriter.WriteValue("Warnings", Node.bNotifyOnWarnings); JsonWriter.WriteObjectEnd(); JsonWriter.WriteObjectEnd(); } JsonWriter.WriteArrayEnd(); JsonWriter.WriteObjectEnd(); } } JsonWriter.WriteArrayEnd(); // Write all the triggers JsonWriter.WriteArrayStart("Triggers"); foreach (ManualTrigger Trigger in NameToTrigger.Values) { if (!ActivatedTriggers.Contains(Trigger) && NodesToExecute.Any(x => x.ControllingTrigger == Trigger.Parent)) { // Find all the nodes that this trigger is dependent on HashSet <Node> Dependencies = new HashSet <Node>(); foreach (Node Node in Groups.SelectMany(x => x.Nodes)) { for (ManualTrigger ControllingTrigger = Node.ControllingTrigger; ControllingTrigger != null; ControllingTrigger = ControllingTrigger.Parent) { if (ControllingTrigger == Trigger) { Dependencies.UnionWith(Node.OrderDependencies.Where(x => x.ControllingTrigger != Trigger && NodesToExecute.Contains(x))); break; } } } // Reduce that list to the smallest subset of direct dependencies HashSet <Node> DirectDependencies = new HashSet <Node>(Dependencies); foreach (Node Dependency in Dependencies) { DirectDependencies.ExceptWith(Dependency.OrderDependencies); } // Write out the object JsonWriter.WriteObjectStart(); JsonWriter.WriteValue("Name", Trigger.Name); JsonWriter.WriteValue("AllDependencies", String.Join(";", Groups.SelectMany(x => x.Nodes).Where(x => Dependencies.Contains(x)).Select(x => x.Name))); JsonWriter.WriteValue("DirectDependencies", String.Join(";", Dependencies.Where(x => DirectDependencies.Contains(x)).Select(x => x.Name))); JsonWriter.WriteValue("Notify", String.Join(";", Trigger.NotifyUsers)); JsonWriter.WriteObjectEnd(); } } JsonWriter.WriteArrayEnd(); JsonWriter.WriteObjectEnd(); } }
/// <summary> /// Export the build graph to a Json file for parsing by Horde /// </summary> /// <param name="File">Output file to write</param> public void ExportForHorde(FileReference File) { DirectoryReference.CreateDirectory(File.Directory); using (JsonWriter JsonWriter = new JsonWriter(File.FullName)) { JsonWriter.WriteObjectStart(); JsonWriter.WriteArrayStart("Groups"); foreach (Agent Agent in Agents) { JsonWriter.WriteObjectStart(); JsonWriter.WriteArrayStart("Types"); foreach (string PossibleType in Agent.PossibleTypes) { JsonWriter.WriteValue(PossibleType); } JsonWriter.WriteArrayEnd(); JsonWriter.WriteArrayStart("Nodes"); foreach (Node Node in Agent.Nodes) { JsonWriter.WriteObjectStart(); JsonWriter.WriteValue("Name", Node.Name); JsonWriter.WriteValue("RunEarly", Node.bRunEarly); JsonWriter.WriteValue("Warnings", Node.bNotifyOnWarnings); JsonWriter.WriteArrayStart("InputDependencies"); foreach (string InputDependency in Node.GetDirectInputDependencies().Select(x => x.Name)) { JsonWriter.WriteValue(InputDependency); } JsonWriter.WriteArrayEnd(); JsonWriter.WriteArrayStart("OrderDependencies"); foreach (string OrderDependency in Node.GetDirectOrderDependencies().Select(x => x.Name)) { JsonWriter.WriteValue(OrderDependency); } JsonWriter.WriteArrayEnd(); JsonWriter.WriteObjectEnd(); } JsonWriter.WriteArrayEnd(); JsonWriter.WriteObjectEnd(); } JsonWriter.WriteArrayEnd(); JsonWriter.WriteArrayStart("Aggregates"); foreach (Aggregate Aggregate in NameToAggregate.Values) { JsonWriter.WriteObjectStart(); JsonWriter.WriteValue("Name", Aggregate.Name); JsonWriter.WriteArrayStart("Nodes"); foreach (Node RequiredNode in Aggregate.RequiredNodes.OrderBy(x => x.Name)) { JsonWriter.WriteValue(RequiredNode.Name); } JsonWriter.WriteArrayEnd(); JsonWriter.WriteObjectEnd(); } JsonWriter.WriteArrayEnd(); JsonWriter.WriteArrayStart("Labels"); foreach (Label Label in Labels) { JsonWriter.WriteObjectStart(); if (!String.IsNullOrEmpty(Label.DashboardName)) { JsonWriter.WriteValue("Name", Label.DashboardName); } if (!String.IsNullOrEmpty(Label.DashboardCategory)) { JsonWriter.WriteValue("Category", Label.DashboardCategory); } if (!String.IsNullOrEmpty(Label.UgsBadge)) { JsonWriter.WriteValue("UgsBadge", Label.UgsBadge); } if (!String.IsNullOrEmpty(Label.UgsProject)) { JsonWriter.WriteValue("UgsProject", Label.UgsProject); } if (Label.Change != LabelChange.Current) { JsonWriter.WriteValue("Change", Label.Change.ToString()); } JsonWriter.WriteArrayStart("RequiredNodes"); foreach (Node RequiredNode in Label.RequiredNodes.OrderBy(x => x.Name)) { JsonWriter.WriteValue(RequiredNode.Name); } JsonWriter.WriteArrayEnd(); JsonWriter.WriteArrayStart("IncludedNodes"); foreach (Node IncludedNode in Label.IncludedNodes.OrderBy(x => x.Name)) { JsonWriter.WriteValue(IncludedNode.Name); } JsonWriter.WriteArrayEnd(); JsonWriter.WriteObjectEnd(); } JsonWriter.WriteArrayEnd(); JsonWriter.WriteArrayStart("Badges"); foreach (Badge Badge in Badges) { HashSet <Node> Dependencies = Badge.Nodes; if (Dependencies.Count > 0) { // Reduce that list to the smallest subset of direct dependencies HashSet <Node> DirectDependencies = new HashSet <Node>(Dependencies); foreach (Node Dependency in Dependencies) { DirectDependencies.ExceptWith(Dependency.OrderDependencies); } JsonWriter.WriteObjectStart(); JsonWriter.WriteValue("Name", Badge.Name); if (!String.IsNullOrEmpty(Badge.Project)) { JsonWriter.WriteValue("Project", Badge.Project); } if (Badge.Change != 0) { JsonWriter.WriteValue("Change", Badge.Change); } JsonWriter.WriteValue("Dependencies", String.Join(";", DirectDependencies.Select(x => x.Name))); JsonWriter.WriteObjectEnd(); } } JsonWriter.WriteArrayEnd(); JsonWriter.WriteObjectEnd(); } }