lib/gush/graph.rb in gush-2.0.2 vs lib/gush/graph.rb in gush-2.1.0

- old
+ new

@@ -1,72 +1,83 @@ +# frozen_string_literal: true + +require 'tmpdir' + module Gush class Graph - attr_reader :workflow, :filename, :path, :start, :end_node + attr_reader :workflow, :filename, :path, :start_node, :end_node def initialize(workflow, options = {}) @workflow = workflow @filename = options.fetch(:filename, "graph.png") @path = options.fetch(:path, Pathname.new(Dir.tmpdir).join(filename)) end def viz - GraphViz.new(:G, graph_options) do |graph| - set_node_options!(graph) - set_edge_options!(graph) + @graph = Graphviz::Graph.new(**graph_options) + @start_node = add_node('start', shape: 'diamond', fillcolor: '#CFF09E') + @end_node = add_node('end', shape: 'diamond', fillcolor: '#F56991') - @start = graph.start(shape: 'diamond', fillcolor: '#CFF09E') - @end_node = graph.end(shape: 'diamond', fillcolor: '#F56991') + # First, create nodes for all jobs + @job_name_to_node_map = {} + workflow.jobs.each do |job| + add_job_node(job) + end - workflow.jobs.each do |job| - add_job(graph, job) - end - - graph.output(png: path) + # Next, link up the jobs with edges + workflow.jobs.each do |job| + link_job_edges(job) end + + format = 'png' + file_format = path.split('.')[-1] + format = file_format if file_format.length == 3 + + Graphviz::output(@graph, path: path, format: format) end def path @path.to_s end private - def add_job(graph, job) - name = job.class.to_s - graph.add_nodes(job.name, label: name) + def add_node(name, **specific_options) + @graph.add_node(name, **node_options.merge(specific_options)) + end + + def add_job_node(job) + @job_name_to_node_map[job.name] = add_node(job.name, label: node_label_for_job(job)) + end + + def link_job_edges(job) + job_node = @job_name_to_node_map[job.name] + if job.incoming.empty? - graph.add_edges(start, job.name) + @start_node.connect(job_node, **edge_options) end if job.outgoing.empty? - graph.add_edges(job.name, end_node) + job_node.connect(@end_node, **edge_options) else job.outgoing.each do |id| outgoing_job = workflow.find_job(id) - graph.add_edges(job.name, outgoing_job.name) + job_node.connect(@job_name_to_node_map[outgoing_job.name], **edge_options) end end end - def set_node_options!(graph) - node_options.each do |key, value| - graph.node[key] = value - end + def node_label_for_job(job) + job.class.to_s end - def set_edge_options!(graph) - edge_options.each do |key, value| - graph.edge[key] = value - end - end - def graph_options { - type: :digraph, - dpi: 200, - compound: true, - rankdir: "LR", - center: true + dpi: 200, + compound: true, + rankdir: "LR", + center: true, + format: 'png' } end def node_options {