visualize_packs 0.5.18 → 0.5.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/visualize_packs +7 -0
- data/lib/graph.dot.erb +32 -16
- data/lib/visualize_packs.rb +93 -42
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b8efefa896a6d002c7333dad53f2a8fa0be10d8c0004895682239c7a7f6a1105
|
4
|
+
data.tar.gz: 0046a3a518c25de488b4b2e0d89c04ced6e45c1ff5d90e9e85d71d46b5256e89
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5282d8a1af4103a3d6c38675c378adee512029eb4320a29874b91463c2fc4aa7380a76165306f8dc2d8163b67e60875b2496aeacca209b40ebdb09217744888c
|
7
|
+
data.tar.gz: 99f84713ec95080f82668184bd69ce4e67dc30fbc739803f67efe8ebbe51728dbd4717d22eec946a2e24ce1128cd646d3cca47413a09a481718b76c029c47ae7
|
data/bin/visualize_packs
CHANGED
@@ -34,6 +34,13 @@ OptionParser.new do |opt|
|
|
34
34
|
|
35
35
|
opt.on('--title=STRING', "Set a custom diagram title") { |o| options.title = o }
|
36
36
|
|
37
|
+
opt.on('-V', '--version', "Show version") do
|
38
|
+
spec_path = File.expand_path("../visualize_packs.gemspec", __dir__)
|
39
|
+
spec = Gem::Specification::load(spec_path)
|
40
|
+
puts "Version #{spec.version}"
|
41
|
+
exit
|
42
|
+
end
|
43
|
+
|
37
44
|
opt.on_tail("-h", "--help", "Show this message") do
|
38
45
|
puts opt
|
39
46
|
exit
|
data/lib/graph.dot.erb
CHANGED
@@ -87,19 +87,19 @@ digraph package_diagram {
|
|
87
87
|
<%- todo_types = todos_by_package[todos_to_package].group_by(&:type) -%>
|
88
88
|
<%- todo_types.keys.each do |todo_type| -%>
|
89
89
|
<%- if show_edge.call(package.name, todos_to_package) -%>
|
90
|
-
"<%= package.name -%>" -> "<%= todos_to_package -%>"<%= todo_type == 'privacy' ? ':private' : '' -%> [
|
90
|
+
"<%= package.name -%>" -> "<%= todos_to_package -%>"<%= todo_type == 'privacy' ? ':private' : '' -%> [
|
91
91
|
<%- if !options.use_todos_for_layout -%>
|
92
92
|
constraint=false
|
93
93
|
<%- end -%>
|
94
94
|
# headlabel="<%= todo_type -%>"
|
95
95
|
<%- if todo_type == 'privacy' -%>
|
96
|
-
|
96
|
+
<%= VisualizePacks::ArrowHead::PrivacyTodo.serialize %>
|
97
97
|
<%- elsif todo_type == 'architecture' -%>
|
98
|
-
|
98
|
+
<%= VisualizePacks::ArrowHead::ArchitectureTodo.serialize %>
|
99
99
|
<%- elsif todo_type == 'visibility' -%>
|
100
|
-
|
100
|
+
<%= VisualizePacks::ArrowHead::VisibilityTodo.serialize %>
|
101
101
|
<%- elsif todo_type == 'dependency' -%>
|
102
|
-
|
102
|
+
<%= VisualizePacks::ArrowHead::DependencyTodo.serialize %>
|
103
103
|
<%- end -%>
|
104
104
|
penwidth=<%= todo_edge_width(todo_types[todo_type].count, max_todo_count) -%>
|
105
105
|
]
|
@@ -128,30 +128,46 @@ digraph package_diagram {
|
|
128
128
|
subgraph cluster_legend {
|
129
129
|
fontsize=16
|
130
130
|
label="Edges Styles and Arrow Heads"
|
131
|
+
<%- if options.show_dependencies -%>
|
131
132
|
A [ fontsize=12 shape=box label="package"]
|
132
133
|
B [ fontsize=12 shape=box label="package"]
|
134
|
+
A -> B [label="accepted dependency" <%= VisualizePacks::ArrowHead::ConfiguredDependency.serialize %>]
|
135
|
+
<%- end -%>
|
136
|
+
<%- if options.show_nested_relationships -%>
|
133
137
|
K [ fontsize=12 shape=box label="package"]
|
134
138
|
L [ fontsize=12 shape=box label="package"]
|
139
|
+
K -> L [label="nested package" <%= VisualizePacks::ArrowHead::ConfiguredNested.serialize %>]
|
140
|
+
<%- end -%>
|
141
|
+
<%- if options.show_visibility -%>
|
135
142
|
M [ fontsize=12 shape=box label="package"]
|
136
143
|
N [ fontsize=12 shape=box label="package"]
|
137
|
-
|
144
|
+
M -> N [label="visibile to" <%= VisualizePacks::ArrowHead::ConfiguredVisibileTo.serialize %>]
|
145
|
+
<%- end -%>
|
146
|
+
<%- if options.show_todos -%>
|
147
|
+
<%- if options.only_todo_types.include?(EdgeTodoTypes::Privacy) -%>
|
138
148
|
C [ fontsize=12 shape=box label="package"]
|
139
149
|
D [ fontsize=12 shape=box label="package"]
|
150
|
+
C -> D [label="privacy todo" <%= VisualizePacks::ArrowHead::PrivacyTodo.serialize %>]
|
151
|
+
<%- end -%>
|
152
|
+
<%- if options.only_todo_types.include?(EdgeTodoTypes::Architecture) -%>
|
140
153
|
E [ fontsize=12 shape=box label="package"]
|
141
154
|
F [ fontsize=12 shape=box label="package"]
|
155
|
+
E -> F [label="architecture todo" <%= VisualizePacks::ArrowHead::ArchitectureTodo.serialize %>]
|
156
|
+
<%- end -%>
|
157
|
+
<%- if options.only_todo_types.include?(EdgeTodoTypes::Visibility) -%>
|
142
158
|
G [ fontsize=12 shape=box label="package"]
|
143
159
|
H [ fontsize=12 shape=box label="package"]
|
160
|
+
G -> H [label="visibility todo" <%= VisualizePacks::ArrowHead::VisibilityTodo.serialize %>]
|
161
|
+
<%- end -%>
|
162
|
+
<%- if options.only_todo_types.include?(EdgeTodoTypes::Dependency) -%>
|
144
163
|
I [ fontsize=12 shape=box label="package"]
|
145
164
|
J [ fontsize=12 shape=box label="package"]
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
E -> F [label="architecture todo" color=darkred style=dashed arrowhead=invodot]
|
153
|
-
G -> H [label="visibility todo" color=darkred style=dashed arrowhead=obox]
|
154
|
-
I -> J [label="dependency todo" color=darkred style=dashed arrowhead=odot]
|
165
|
+
I -> J [label="dependency todo" <%= VisualizePacks::ArrowHead::DependencyTodo.serialize %>]
|
166
|
+
<%- end -%>
|
167
|
+
<%- end -%>
|
168
|
+
LEGEND_NODE_1 [ label="" peripheries=0 height=0 width=0 style=invis ]
|
169
|
+
LEGEND_NODE_2 [ label="" peripheries=0 height=0 width=0 style=invis ]
|
170
|
+
LEGEND_NODE_1 -> LEGEND_NODE_2 [ style=invis ]
|
155
171
|
}
|
156
172
|
<%- end -%>
|
157
173
|
<%- if options.show_teams && all_team_names != [] -%>
|
@@ -172,7 +188,7 @@ digraph package_diagram {
|
|
172
188
|
<%- end -%>
|
173
189
|
}
|
174
190
|
<%- if options.show_legend -%>
|
175
|
-
|
191
|
+
LEGEND_NODE_2 -> "<%= all_team_names.last %><%= all_team_names.last %>" [style=invis]
|
176
192
|
<%- end -%>
|
177
193
|
<%- end -%>
|
178
194
|
}
|
data/lib/visualize_packs.rb
CHANGED
@@ -11,6 +11,18 @@ require 'visualize_packs/options'
|
|
11
11
|
module VisualizePacks
|
12
12
|
extend T::Sig
|
13
13
|
|
14
|
+
class ArrowHead < T::Enum
|
15
|
+
enums do
|
16
|
+
DependencyTodo = new('color=darkred style=dashed arrowhead=odiamond')
|
17
|
+
PrivacyTodo = new('color=darkred style=dashed arrowhead=crow')
|
18
|
+
ArchitectureTodo = new('color=darkred style=dashed arrowhead=obox')
|
19
|
+
VisibilityTodo = new('color=darkred style=dashed arrowhead=tee')
|
20
|
+
ConfiguredDependency = new('color=darkgreen')
|
21
|
+
ConfiguredVisibileTo = new('color=blue')
|
22
|
+
ConfiguredNested = new('color=purple')
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
14
26
|
sig { params(options: Options, raw_config: T::Hash[String, T.untyped], packages: T::Array[ParsePackwerk::Package]).returns(String) }
|
15
27
|
def self.package_graph!(options, raw_config, packages)
|
16
28
|
all_packages = filtered(packages, options).compact.sort_by {|x| x.name }
|
@@ -58,25 +70,31 @@ module VisualizePacks
|
|
58
70
|
def self.diagram_title(options, max_todo_count)
|
59
71
|
return "<<b>#{options.title}</b>>" if options.title
|
60
72
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
options.
|
69
|
-
options.
|
70
|
-
|
71
|
-
options.
|
72
|
-
options.
|
73
|
-
options.
|
74
|
-
options.
|
75
|
-
options.
|
76
|
-
options.
|
73
|
+
focus_info = if options.focus_pack
|
74
|
+
"Focus on #{limited_sentence(options.focus_pack)} (Edge mode: #{options.show_only_edges_to_focus_pack.serialize})"
|
75
|
+
else
|
76
|
+
"All packs"
|
77
|
+
end
|
78
|
+
|
79
|
+
hidden_aspects = [
|
80
|
+
options.show_legend ? nil : "legend",
|
81
|
+
options.show_layers ? nil : "layers",
|
82
|
+
options.show_dependencies ? nil : "dependencies",
|
83
|
+
options.show_todos ? nil : "todos",
|
84
|
+
options.show_privacy ? nil : "privacy",
|
85
|
+
options.show_teams ? nil : "teams",
|
86
|
+
options.show_visibility ? nil : "visibility",
|
87
|
+
options.roll_nested_into_parent_packs ? "nested packs" : nil,
|
88
|
+
options.show_nested_relationships ? nil : "nested relationships",
|
77
89
|
].compact.join(', ').strip
|
78
|
-
|
79
|
-
|
90
|
+
hidden_aspects_title = hidden_aspects != '' ? "Hiding #{hidden_aspects}" : nil
|
91
|
+
|
92
|
+
todo_types = EdgeTodoTypes.values.size == options.only_todo_types.size ? nil : "Only #{options.only_todo_types.map &:serialize} todos",
|
93
|
+
|
94
|
+
exclusions = options.exclude_packs.empty? ? nil : "Excluding pack#{options.exclude_packs.size > 1 ? 's' : ''}: #{limited_sentence(options.exclude_packs)}",
|
95
|
+
|
96
|
+
main_title = [focus_info, hidden_aspects_title, todo_types, exclusions].compact.join('. ')
|
97
|
+
|
80
98
|
if options.show_todos && max_todo_count
|
81
99
|
sub_title = "<br/><font point-size='12'>Widest todo edge is #{max_todo_count} todo#{max_todo_count > 1 ? 's' : ''}</font>"
|
82
100
|
end
|
@@ -103,6 +121,8 @@ module VisualizePacks
|
|
103
121
|
case options.show_only_edges_to_focus_pack
|
104
122
|
when FocusPackEdgeDirection::All then
|
105
123
|
true
|
124
|
+
when FocusPackEdgeDirection::None then
|
125
|
+
match_packs?(start_node, options.focus_pack) && match_packs?(end_node, options.focus_pack)
|
106
126
|
when FocusPackEdgeDirection::InOut then
|
107
127
|
match_packs?(start_node, options.focus_pack) || match_packs?(end_node, options.focus_pack)
|
108
128
|
when FocusPackEdgeDirection::In then
|
@@ -188,36 +208,32 @@ module VisualizePacks
|
|
188
208
|
result = T.let([], T::Array[T.nilable(String)])
|
189
209
|
result = packages.map { |pack| pack.name }
|
190
210
|
|
191
|
-
if focus_pack
|
211
|
+
if focus_pack
|
192
212
|
result = []
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
213
|
+
focus_pack_name = packages.map { |pack| pack.name }.select { |p| match_packs?(p, focus_pack) }
|
214
|
+
result += focus_pack_name
|
215
|
+
|
216
|
+
dependents = options.show_dependencies ? dependents_on(packages, focus_pack_name) : []
|
217
|
+
dependencies = options.show_dependencies ? dependencies_of(packages, focus_pack_name) : []
|
218
|
+
todos_out = options.show_todos ? todos_out(packages, focus_pack_name, options) : []
|
219
|
+
todos_in = options.show_todos ? todos_in(packages, focus_pack_name, options) : []
|
220
|
+
|
221
|
+
case options.show_only_edges_to_focus_pack
|
222
|
+
when FocusPackEdgeDirection::All, FocusPackEdgeDirection::InOut then
|
223
|
+
result += dependents + dependencies + todos_out + todos_in
|
224
|
+
when FocusPackEdgeDirection::In then
|
225
|
+
result += dependents + todos_in
|
226
|
+
when FocusPackEdgeDirection::Out then
|
227
|
+
result += dependencies + todos_out
|
228
|
+
when FocusPackEdgeDirection::None then
|
229
|
+
# nothing to do
|
204
230
|
end
|
205
|
-
|
206
|
-
if options.show_dependencies
|
207
|
-
result += packages_by_name[p].dependencies
|
208
|
-
end
|
209
|
-
if options.show_todos && [FocusPackEdgeDirection::All, FocusPackEdgeDirection::Out, FocusPackEdgeDirection::InOut].include?(options.show_only_edges_to_focus_pack)
|
210
|
-
result += (packages_by_name[p].violations || []).inject([]) do |res, todo|
|
211
|
-
res << todo.to_package_name if options.only_todo_types.include?(EdgeTodoTypes.deserialize(todo.type))
|
212
|
-
res
|
213
|
-
end
|
214
|
-
end
|
215
|
-
end
|
216
|
-
result = result.uniq
|
231
|
+
|
217
232
|
parent_packs = result.inject([]) do |res, package_name|
|
218
233
|
res << nested_packages[package_name]
|
219
234
|
res
|
220
235
|
end
|
236
|
+
|
221
237
|
result = (result + parent_packs).uniq.compact
|
222
238
|
end
|
223
239
|
|
@@ -306,4 +322,39 @@ module VisualizePacks
|
|
306
322
|
def self.match_packs?(pack, packs_name_with_wildcards)
|
307
323
|
!packs_name_with_wildcards || packs_name_with_wildcards.any? {|p| File.fnmatch(p, pack)}
|
308
324
|
end
|
325
|
+
|
326
|
+
sig { params(all_packages: T::Array[ParsePackwerk::Package], focus_packs_names: T::Array[String]).returns(T::Array[String]) }
|
327
|
+
def self.dependencies_of(all_packages, focus_packs_names)
|
328
|
+
focus_packs = all_packages.select { focus_packs_names.include?(_1.name)}
|
329
|
+
|
330
|
+
focus_packs.inject([]) do |result, pack|
|
331
|
+
result += pack.dependencies
|
332
|
+
result
|
333
|
+
end.uniq
|
334
|
+
end
|
335
|
+
|
336
|
+
sig { params(all_packages: T::Array[ParsePackwerk::Package], focus_packs_names: T::Array[String]).returns(T::Array[String]) }
|
337
|
+
def self.dependents_on(all_packages, focus_packs_names)
|
338
|
+
all_packages.select { |pack| pack.dependencies.any? { focus_packs_names.include?(_1) }}.map &:name
|
339
|
+
end
|
340
|
+
|
341
|
+
sig { params(all_packages: T::Array[ParsePackwerk::Package], focus_packs_names: T::Array[String], options: Options).returns(T::Array[String]) }
|
342
|
+
def self.todos_in(all_packages, focus_packs_names, options)
|
343
|
+
all_packages.select do |p|
|
344
|
+
(p.violations || []).inject([]) do |res, todo|
|
345
|
+
res << todo.to_package_name if options.only_todo_types.include?(EdgeTodoTypes.deserialize(todo.type))
|
346
|
+
res
|
347
|
+
end.any? { |v| focus_packs_names.include?(v) }
|
348
|
+
end.map { |pack| pack.name }
|
349
|
+
end
|
350
|
+
|
351
|
+
sig { params(all_packages: T::Array[ParsePackwerk::Package], focus_packs_names: T::Array[String], options: Options).returns(T::Array[String]) }
|
352
|
+
def self.todos_out(all_packages, focus_packs_names, options)
|
353
|
+
all_packages.inject([]) do |result, p|
|
354
|
+
focus_packs_names.include?(p.name) && (p.violations || []).each do |todo|
|
355
|
+
result << todo.to_package_name if options.only_todo_types.include?(EdgeTodoTypes.deserialize(todo.type))
|
356
|
+
end
|
357
|
+
result
|
358
|
+
end
|
359
|
+
end
|
309
360
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: visualize_packs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.20
|
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-09-
|
11
|
+
date: 2023-09-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|