visualize_packwerk 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 358f7f6ce6490e9a49b9a898af9d877181c1ecffd99068dea9cbaa5267f1a552
4
- data.tar.gz: 4ff54f1b92868804ce3a49bba54f54668ccc1510b446873fc7dbb3da7d9d4cfe
3
+ metadata.gz: c15049155fd43dca095255941ff8f996409fd2712f28008874fe3a772ba9b28b
4
+ data.tar.gz: 406b008fa89777838b588080aa3ee25afd417f16663124b668937ea91c3b9c17
5
5
  SHA512:
6
- metadata.gz: 4933f49f8868128aaecd6b6696d79cc677d8185bea9b18e3f2f7bdbafec85dfd9d055ebe8c196aad7008b52a92f5fcad53d69af5535ffad152b6c8188ebbb8bb
7
- data.tar.gz: 5f72a6c8a97623326a94e4fca096b5a836c9208e801a5f70f720d515115f074a41d35f7b4ccc801f02bb44d01e95e338826d3ce2ee39f50808ce3d8006a6709a
6
+ metadata.gz: b6ee92e733adf0da1062cf262849685a5adb053baef2adb34793aadedbb68c072193a19df4ff9d8eed280e491cfb0afac4bb9a1211962f6cd1d8a9b20c4bf6d8
7
+ data.tar.gz: 6ca30bbcadd94b1b8241456001c6d8144f6b395718cb1d765605cb0c2f1fb7b0bffe4d36c312cbb7510ed9930385013eafe598788f63d6c675abbcd8b6034539
data/README.md CHANGED
@@ -1,8 +1,19 @@
1
1
  # visualize_packwerk
2
2
 
3
- This gem contains rake tasks to help visualize relationships between packwerk packs.
3
+ This gem helps visualize relationships between packwerk packs.
4
4
 
5
- # Usage
5
+ ![Example of visualization](docs/example.png)
6
+
7
+ # CLI Usage
8
+ ## bin/packs
9
+ For simpler use, add `bin/packs` via `use_packs` (https://github.com/rubyatscale/use_packs)
10
+ ```
11
+ bin/packs visualize # all packs
12
+ bin/packs visualize packs/a packs/b # subset of packs
13
+ bin/packs # enter interactive mode to select what packs to visualize
14
+ ```
15
+
16
+ # Ruby API Usage
6
17
  ## Building a package graph for a selection of packages
7
18
  ```ruby
8
19
  # Select the packs you want to include
@@ -12,7 +23,7 @@ selected_packs = Packs.all.select{ |p| ['Team 1', 'Team 2'].include?(CodeOwnersh
12
23
  VisualizePackwerk.package_graph!(selected_packs)
13
24
  ```
14
25
 
15
- # Building a team graph for specific teams
26
+ ## Building a team graph for specific teams
16
27
  ```ruby
17
28
  # Select the teams you want to include
18
29
  selected_teams = CodeTeams.all
@@ -20,8 +31,5 @@ selected_teams = CodeTeams.all.select{ |t| ['Team 1', 'Team 2'].include?(t.name)
20
31
  VisualizePackwerk.team_graph!(selected_teams)
21
32
  ```
22
33
 
23
- ## bin/packs
24
- For simpler use, use `bin/packs` in `use_packwerk` (https://github.com/rubyatscale/use_packwerk)
25
-
26
34
  # Want to change something or add a feature?
27
35
  Submit a PR or post an issue!
Binary file
@@ -45,7 +45,15 @@ module VisualizePackwerk
45
45
  # https://graphviz.org/docs/layouts/
46
46
  default_layout = :dot
47
47
  # other_layout = :sfdp
48
- graphviz_graph = GraphViz.new(:G, type: :digraph, dpi: 100, layout: default_layout)
48
+ graphviz_graph = GraphViz.new(
49
+ :G,
50
+ type: :digraph,
51
+ dpi: 100,
52
+ layout: default_layout,
53
+ label: "Visualization of #{node_names.count} packs, generated using `bin/packs`",
54
+ fontsize: 24,
55
+ labelloc: "t",
56
+ )
49
57
 
50
58
  # Create graph nodes
51
59
  graphviz_nodes = T.let({}, T::Hash[String, GraphViz::Node])
@@ -56,36 +64,32 @@ module VisualizePackwerk
56
64
  graphviz_nodes[node.name] = add_node(node, graphviz_graph)
57
65
  end
58
66
 
59
- max_edge_width = 10
60
-
61
67
  # Draw all edges
62
68
  nodes_to_draw.each do |node|
63
69
  node.dependencies.each do |to_node|
64
70
  next unless node_names.include?(to_node)
65
71
 
66
- graphviz_graph.add_edges(
67
- graphviz_nodes[node.name],
68
- graphviz_nodes[to_node],
69
- { color: 'darkgreen' }
72
+ add_dependency(
73
+ graph: graphviz_graph,
74
+ node1: T.must(graphviz_nodes[node.name]),
75
+ node2: T.must(graphviz_nodes[to_node]),
70
76
  )
71
77
  end
72
78
 
73
79
  node.violations_by_node_name.each do |to_node_name, violation_count|
74
80
  next unless node_names.include?(to_node_name)
75
81
 
76
- edge_width = [
77
- [(violation_count / 5).to_i, 1].max, # rubocop:disable Lint/NumberConversion
78
- max_edge_width,
79
- ].min
80
-
81
- graphviz_graph.add_edges(
82
- graphviz_nodes[node.name],
83
- graphviz_nodes[to_node_name],
84
- { color: 'red', penwidth: edge_width }
82
+ add_violation(
83
+ graph: graphviz_graph,
84
+ node1: T.must(graphviz_nodes[node.name]),
85
+ node2: T.must(graphviz_nodes[to_node_name]),
86
+ violation_count: violation_count
85
87
  )
86
88
  end
87
89
  end
88
90
 
91
+ add_legend(graphviz_graph)
92
+
89
93
  # Save graph to filesystem
90
94
  puts "Outputting to: #{OUTPUT_FILENAME}"
91
95
  graphviz_graph.output(png: OUTPUT_FILENAME)
@@ -106,6 +110,60 @@ module VisualizePackwerk
106
110
 
107
111
  graph.add_nodes(node.name, **node_options)
108
112
  end
113
+
114
+ sig { params(graph: GraphViz).void }
115
+ def add_legend(graph)
116
+ legend = graph.add_graph("legend")
117
+
118
+ # This commented out code was used to generate an image that I edited by hand.
119
+ # I was unable to figure out how to:
120
+ # - put a box around the legend
121
+ # - layout the node pairs in vertical order
122
+ # - give it a title
123
+ # So I just generated this using graphviz and then pulled the image in.
124
+ # a_node = legend.add_nodes("packs/a")
125
+ # b_node = legend.add_nodes("packs/b")
126
+ # c_node = legend.add_nodes("packs/c")
127
+ # d_node = legend.add_nodes("packs/d")
128
+ # e_node = legend.add_nodes("packs/e")
129
+ # f_node = legend.add_nodes("packs/f")
130
+
131
+ # add_dependency(graph: legend, node1: a_node, node2: b_node, label: 'Dependency in package.yml')
132
+ # add_violation(graph: legend, node1: c_node, node2: d_node, violation_count: 1, label: 'Violations (few)')
133
+ # add_violation(graph: legend, node1: e_node, node2: f_node, violation_count: 30, label: 'Violations (many)')
134
+
135
+ image = legend.add_node("",
136
+ shape: "image",
137
+ image: Pathname.new(__dir__).join("./legend.png").to_s,
138
+ )
139
+ end
140
+
141
+ sig { params(graph: GraphViz, node1: GraphViz::Node, node2: GraphViz::Node, violation_count: Integer, label: T.nilable(String)).void }
142
+ def add_violation(graph:, node1:, node2:, violation_count:, label: nil)
143
+ max_edge_width = 10
144
+
145
+ edge_width = [
146
+ [(violation_count / 5).to_i, 1].max, # rubocop:disable Lint/NumberConversion
147
+ max_edge_width,
148
+ ].min
149
+
150
+ opts = { color: 'red', style: 'dashed', penwidth: edge_width }
151
+ if label
152
+ opts.merge!(label: label)
153
+ end
154
+
155
+ graph.add_edges(node1, node2, opts)
156
+ end
157
+
158
+ sig { params(graph: GraphViz, node1: GraphViz::Node, node2: GraphViz::Node, label: T.nilable(String)).void }
159
+ def add_dependency(graph:, node1:, node2:, label: nil)
160
+ opts = { color: 'darkgreen' }
161
+ if label
162
+ opts.merge!(label: label)
163
+ end
164
+
165
+ graph.add_edges(node1, node2, opts)
166
+ end
109
167
  end
110
168
 
111
169
  private_constant :PackageRelationships
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: visualize_packwerk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gusto Engineers
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-04-09 00:00:00.000000000 Z
11
+ date: 2023-05-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sorbet-runtime
@@ -160,6 +160,7 @@ files:
160
160
  - README.md
161
161
  - lib/visualize_packwerk.rb
162
162
  - lib/visualize_packwerk/graph_interface.rb
163
+ - lib/visualize_packwerk/legend.png
163
164
  - lib/visualize_packwerk/node_interface.rb
164
165
  - lib/visualize_packwerk/package_graph.rb
165
166
  - lib/visualize_packwerk/package_node.rb