visualize_packs 0.5.5 → 0.5.7

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: b4ade528fc794c71afb2470d457f31d72b2456b85a484f2b328ca1c73e7fc2cf
4
- data.tar.gz: 239feaba7ced4136ac77625e6ed1632a031492e86ca6d1c0d025976b23e31300
3
+ metadata.gz: 698ac9ebae377a99e2b9b5fe62c3646bcaa8b4ce81439feee7354d81d80682c1
4
+ data.tar.gz: 15335a5ce4cc6eb90926af902da548c268bc6c86caa8ae6fd9df5127cfb7e071
5
5
  SHA512:
6
- metadata.gz: 18a67a3b983c99f4d273a8e32e390a63bb0fa0398c7da51d4552fee73eedda0e77debfe45a3e196cae5b8d0e370124f7eeb82d202f4daba7b68bb90fb5b15708
7
- data.tar.gz: 60e06eaacba3c796ee9045223d47203f63b19e83664c58b9db69696c591f68169f217bc8172287fcb9cc61befaa2008c4a337e486febd0477b6a0b8d14100520
6
+ metadata.gz: 79f8106bfafe0a7cd9c17ff6f886871b4a24990e562a389b5dab45ff5838a3a0a22fc225d44ea7afcdeb8d8a20ff98e2037b74ed95cd170964027b8b53d40176
7
+ data.tar.gz: 5e5d466148f46ee4876baa8ae184187115bc5d77f66d36d8396867c4fb61066f47ac6b32e22781fcbd4d98c7b387f60f271a8b0cc1a89f91ba383462ca48fcec
data/README.md CHANGED
@@ -16,7 +16,7 @@ This will generate a local dependency diagram for every pack in your app
16
16
  find . -iname 'package.yml' | sed 's/\/package.yml//g' | sed 's/\.\///' | xargs -I % sh -c "bundle exec visualize_packs --only=% > %/packs.dot && dot %/packs.dot -Tpng -o %/packs.png"
17
17
  ```
18
18
 
19
- If your app is large and has many packages and violations, the above graphs will likely be too big. Try this version to get only the edges to and from the focus package for each diagram:
19
+ If your app is large and has many packages and todos, the above graphs will likely be too big. Try this version to get only the edges to and from the focus package for each diagram:
20
20
 
21
21
  ```
22
22
  find . -iname 'package.yml' | sed 's/\/package.yml//g' | sed 's/\.\///' | xargs -I % sh -c "bundle exec visualize_packs --only=% --only-edges-to-focus > %/packs.dot && dot %/packs.dot -Tpng -o %/packs.png"
data/bin/visualize_packs CHANGED
@@ -35,9 +35,9 @@ OptionParser.new do |opt|
35
35
  opt.on('--focus-on=PACKAGE', "Focus on a specific package") { |o| options.focus_package = o }
36
36
  opt.on('--only-edges-to-focus', "If focus is set, this shows only the edges to/from the focus node instead of all edges in the focussed graph. This only has effect when --focus-on is set.") { |o| options.show_only_edges_to_focus_package = true }
37
37
 
38
- opt.on('--roll_nested_todos_into_top_level', "Don't show nested packages (not counting root). Connect edges to top-level package instead") { |o| options.roll_nested_todos_into_top_level = true }
38
+ opt.on('--roll-nested-into-parent-packs', "Don't show nested packages (not counting root). Connect edges to top-level package instead") { |o| options.roll_nested_into_parent_packs = true }
39
39
  opt.on('--focus_folder=FOLDER', "Draw package diagram only for packages in FOLDER") { |o| options.focus_folder = o }
40
- opt.on('--no_nested_relationships', "Don't draw nested package relationships") { |o| options.show_nested_relationships = false }
40
+ opt.on('--no_nested_relationships', "Don't draw relationships between parents and nested packs") { |o| options.show_nested_relationships = false }
41
41
 
42
42
  opt.on('--exclude-packs=pack1,pack2,etc', "Exclude these packs from diagram") { |o| options.exclude_packs = o.to_s.split(",") }
43
43
 
data/lib/graph.dot.erb CHANGED
@@ -81,32 +81,28 @@ digraph package_diagram {
81
81
  <%- end -%>
82
82
  <%- if options.show_todos -%>
83
83
  <%- all_packages.each do |package| -%>
84
- <%- filtered_violations = package.violations -%>
84
+ <%- filtered_todos = package.violations -%>
85
85
  <%- if options.only_todo_types.any? -%>
86
- <%- filtered_violations = filtered_violations.select { options.only_todo_types.include?(_1.type) } -%>
86
+ <%- filtered_todos = filtered_todos.select { options.only_todo_types.include?(_1.type) } -%>
87
87
  <%- end -%>
88
- <%- violations_by_package = filtered_violations.group_by(&:to_package_name) -%>
89
- <%- violations_by_package.keys.each do |violations_to_package| -%>
90
- <%- todo_types = violations_by_package[violations_to_package].group_by(&:type) -%>
91
- <%- todo_types.keys.each do |violation_type| -%>
92
- <%- if show_edge.call(package.name, violations_to_package) -%>
93
- "<%= package.name -%>" -> "<%= violations_to_package -%>"<%= violation_type == 'privacy' ? ':private' : '' -%> [ color=darkred style=dashed
88
+ <%- todos_by_package = filtered_todos.group_by(&:to_package_name) -%>
89
+ <%- todos_by_package.keys.each do |todos_to_package| -%>
90
+ <%- todo_types = todos_by_package[todos_to_package].group_by(&:type) -%>
91
+ <%- todo_types.keys.each do |todo_type| -%>
92
+ <%- if show_edge.call(package.name, todos_to_package) -%>
93
+ "<%= package.name -%>" -> "<%= todos_to_package -%>"<%= todo_type == 'privacy' ? ':private' : '' -%> [ color=darkred style=dashed
94
94
  constraint=false
95
- # headlabel="<%= violation_type -%>"
96
- <%- if violation_type == 'privacy' -%>
95
+ # headlabel="<%= todo_type -%>"
96
+ <%- if todo_type == 'privacy' -%>
97
97
  arrowhead=crow
98
- <%- elsif violation_type == 'architecture' -%>
98
+ <%- elsif todo_type == 'architecture' -%>
99
99
  arrowhead=invodot
100
- <%- elsif violation_type == 'visibility' -%>
100
+ <%- elsif todo_type == 'visibility' -%>
101
101
  arrowhead=obox
102
- <%- elsif violation_type == 'dependency' -%>
102
+ <%- elsif todo_type == 'dependency' -%>
103
103
  arrowhead=odot
104
104
  <%- end -%>
105
- <%-
106
- max_edge_width = 10
107
- edge_width = (todo_types[violation_type].count / max_violation_count.to_f * max_edge_width).to_i
108
- -%>
109
- penwidth=<%= edge_width -%>
105
+ penwidth=<%= todo_edge_width(todo_types[todo_type].count, max_todo_count) -%>
110
106
  ]
111
107
  <%- end -%>
112
108
  <%- end -%>
@@ -139,7 +135,7 @@ digraph package_diagram {
139
135
  K [ fontsize=12 shape=box label="package"]
140
136
  L [ fontsize=12 shape=box label="package"]
141
137
  A -> B [label="accepted dependency" color=darkgreen]
142
- C -> D [label="privac todo" color=darkred style=dashed arrowhead=crow]
138
+ C -> D [label="privacy todo" color=darkred style=dashed arrowhead=crow]
143
139
  E -> F [label="architecture todo" color=darkred style=dashed arrowhead=invodot]
144
140
  G -> H [label="visibility todo" color=darkred style=dashed arrowhead=obox]
145
141
  I -> J [label="dependency todo" color=darkred style=dashed arrowhead=odot]
data/lib/options.rb CHANGED
@@ -15,7 +15,7 @@ class Options < T::Struct
15
15
  prop :focus_package, T.nilable(String)
16
16
  prop :show_only_edges_to_focus_package, T::Boolean, default: false
17
17
 
18
- prop :roll_nested_todos_into_top_level, T::Boolean, default: false
18
+ prop :roll_nested_into_parent_packs, T::Boolean, default: false
19
19
  prop :focus_folder, T.nilable(String)
20
20
  prop :show_nested_relationships, T::Boolean, default: true
21
21
 
@@ -14,13 +14,13 @@ module VisualizePacks
14
14
  all_packages = filtered(packages, options.focus_package, options.focus_folder, options.exclude_packs).sort_by {|x| x.name }
15
15
  all_package_names = all_packages.map &:name
16
16
 
17
- all_packages = remove_nested_packs(all_packages) if options.roll_nested_todos_into_top_level
17
+ all_packages = remove_nested_packs(all_packages) if options.roll_nested_into_parent_packs
18
18
 
19
19
  show_edge = show_edge_builder(options, all_package_names)
20
20
  node_color = node_color_builder()
21
- max_violation_count = max_violation_count(all_packages, show_edge)
21
+ max_todo_count = max_todo_count(all_packages, show_edge)
22
22
 
23
- title = diagram_title(options, max_violation_count)
23
+ title = diagram_title(options, max_todo_count)
24
24
 
25
25
  architecture_layers = (raw_config['architecture_layers'] || []) + ["NotInLayer"]
26
26
  grouped_packages = architecture_layers.inject({}) do |result, key|
@@ -52,7 +52,7 @@ module VisualizePacks
52
52
  package.config.dig("metadata", "owner") || package.config["owner"]
53
53
  end
54
54
 
55
- def self.diagram_title(options, max_violation_count)
55
+ def self.diagram_title(options, max_todo_count)
56
56
  app_name = File.basename(Dir.pwd)
57
57
  focus_edge_info = options.focus_package && options.show_only_edges_to_focus_package ? "showing only edges to/from focus pack" : "showing all edges between visible packs"
58
58
  focus_info = options.focus_package || options.focus_folder ? "Focus on #{[options.focus_package, options.focus_folder].compact.join(' and ')} (#{focus_edge_info})" : "All packs"
@@ -65,14 +65,14 @@ module VisualizePacks
65
65
  options.only_todo_types.empty? ? nil : "only #{limited_sentence(options.only_todo_types)} todos",
66
66
  options.show_privacy ? nil : "hiding privacy",
67
67
  options.show_teams ? nil : "hiding teams",
68
- options.roll_nested_todos_into_top_level ? "hiding nested packs" : nil,
68
+ options.roll_nested_into_parent_packs ? "hiding nested packs" : nil,
69
69
  options.show_nested_relationships ? nil : "hiding nested relationships",
70
70
  options.exclude_packs.empty? ? nil : "excluding pack#{options.exclude_packs.size > 1 ? 's' : ''}: #{limited_sentence(options.exclude_packs)}",
71
71
  ].compact.join(', ').strip
72
72
  main_title = "#{app_name}: #{focus_info}#{skipped_info != '' ? ' - ' + skipped_info : ''}"
73
73
  sub_title = ""
74
- if options.show_todos && max_violation_count
75
- sub_title = "<br/><font point-size='12'>Widest todo edge is #{max_violation_count} violation#{max_violation_count > 1 ? 's' : ''}</font>"
74
+ if options.show_todos && max_todo_count
75
+ sub_title = "<br/><font point-size='12'>Widest todo edge is #{max_todo_count} todo#{max_todo_count > 1 ? 's' : ''}</font>"
76
76
  end
77
77
  "<<b>#{main_title}</b>#{sub_title}>"
78
78
  end
@@ -113,24 +113,43 @@ module VisualizePacks
113
113
  end
114
114
  end
115
115
 
116
- def self.max_violation_count(all_packages, show_edge)
117
- violation_counts = {}
116
+ def self.max_todo_count(all_packages, show_edge)
117
+ todo_counts = {}
118
118
  all_packages.each do |package|
119
- violations_by_package = package.violations.group_by(&:to_package_name)
120
- violations_by_package.keys.each do |violations_to_package|
121
- todo_types = violations_by_package[violations_to_package].group_by(&:type)
122
- todo_types.keys.each do |violation_type|
123
- if show_edge.call(package.name, violations_to_package)
124
- key = "#{package.name}->#{violations_to_package}:#{violation_type}"
125
- violation_counts[key] = todo_types[violation_type].count
126
- # violation_counts[key] += 1
119
+ todos_by_package = package.violations.group_by(&:to_package_name)
120
+ todos_by_package.keys.each do |todos_to_package|
121
+ todo_types = todos_by_package[todos_to_package].group_by(&:type)
122
+ todo_types.keys.each do |todo_type|
123
+ if show_edge.call(package.name, todos_to_package)
124
+ key = "#{package.name}->#{todos_to_package}:#{todo_type}"
125
+ todo_counts[key] = todo_types[todo_type].count
126
+ # todo_counts[key] += 1
127
127
  end
128
128
  end
129
129
  end
130
130
  end
131
- violation_counts.values.max
131
+ todo_counts.values.max
132
132
  end
133
133
 
134
+ def self.todo_edge_width(todo_count, max_count)
135
+ # Limits
136
+ min_width = 1
137
+ max_width = 10
138
+ min_count = 1 # Number of todos equivalent to min_width
139
+
140
+ # Ensure safe values
141
+ return 0 if todo_count < min_count
142
+ return max_width if todo_count > max_count
143
+
144
+ todo_range = max_count - min_count
145
+ width_range = max_width - min_width
146
+ count_delta = todo_count - min_count
147
+
148
+ width_delta = count_delta / todo_range.to_f * width_range
149
+ edge_width = min_width + width_delta
150
+ edge_width.round(2)
151
+ end
152
+
134
153
  def self.filtered(packages, filter_package, filter_folder, exclude_packs)
135
154
  return packages unless filter_package || filter_folder || exclude_packs.any?
136
155
 
@@ -159,13 +178,12 @@ module VisualizePacks
159
178
  def self.all_nested_packages(all_package_names)
160
179
  all_package_names.reject { |p| p == '.' }.inject({}) do |result, package|
161
180
  package_map_tally = all_package_names.map { |other_package| Pathname.new(package).parent.to_s.include?(other_package) }
162
- if package_map_tally.tally[true].nil?
163
- #nothing to do
164
- elsif package_map_tally.tally[true] > 1
165
- raise "Can't handle multiple levels of nesting atm"
166
- elsif package_map_tally.tally[true] == 1
167
- result[package] = all_package_names[package_map_tally.find_index(true)]
168
- end
181
+
182
+ acc = []
183
+ all_package_names.each_with_index { |pack, idx| acc << pack if package_map_tally[idx] }
184
+ acc.sort_by(&:length)
185
+ result[package] = acc.first unless acc.empty?
186
+
169
187
  result
170
188
  end
171
189
  end
@@ -201,7 +219,7 @@ module VisualizePacks
201
219
  nested_packages[d] || d
202
220
  end.uniq.reject { |p| p == package.name }
203
221
 
204
- morphed_violations = package.violations.map do |v|
222
+ morphed_todos = package.violations.map do |v|
205
223
  ParsePackwerk::Violation.new(
206
224
  type: v.type,
207
225
  to_package_name: nested_packages[v.to_package_name] || v.to_package_name,
@@ -219,10 +237,10 @@ module VisualizePacks
219
237
  metadata: package.metadata,
220
238
  dependencies: morphed_dependencies,
221
239
  config: package.config,
222
- violations: morphed_violations
240
+ violations: morphed_todos
223
241
  )
224
242
  # add dependencies TO nested packages to top-level package
225
- # add violations TO nested packages to top-level package
243
+ # add todos TO nested packages to top-level package
226
244
  end
227
245
  end
228
246
 
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.5
4
+ version: 0.5.7
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-08-25 00:00:00.000000000 Z
11
+ date: 2023-08-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler