visualize_packs 0.5.21 → 0.5.23

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: 72b6b3b6121cd9e3a2f30a4b927882be78fab2bbff55d2168100552cdf5b8276
4
- data.tar.gz: 2281e4d89e00c73e18ed025b8b636d2cbafef28addc4955ff4f82ea22ddc442d
3
+ metadata.gz: 0e0cfe73d505dcc80ec3792514b251aa3320c5e7c9703c071202bf1c384ca77a
4
+ data.tar.gz: 0bff429e62083b1a193ddaeb15c443568363ac5400d22b06e5d220e38aea2b90
5
5
  SHA512:
6
- metadata.gz: 3b9affb4f63a85e56125c00e412373d60c705f793c8da118d0e11899b1dcff0e143cade00d4d2562d23d075e3f2a58d9be594cc751e6ee67038a5d591e6c1c27
7
- data.tar.gz: e99623cfaaa59016939a675a500f12357da8401d2fb3ac6e87c37b1a1f861c5976665e59e830f2fc44fe38c33e7cc6926721e264a9516e2dd57df20e1bff95dc
6
+ metadata.gz: cd23c6aa9d40fc57d4b0272af1046c7a289062a27c809b78ef121c239b53347f7dee5e3ccd7afbebca49d25697ee01da6de9b92864c83d0524f1f3a394b8f0f3
7
+ data.tar.gz: d394fdfb12da6cb44fa0401aa33f17e9fcfcb801b201a485c92683260f5bb17be66054d7361bc01c95dea5bcb82e136d1da1c09040a43bf053ddc403521e1738
data/README.md CHANGED
@@ -1,9 +1,11 @@
1
1
  # visualize_packs
2
+
2
3
  Visualize_packs helps you visualize the structure, intended and actual, of your package-based Ruby application.
3
4
 
4
5
  This gem takes a minimal approach in that it only outputs a graph in the format of [graphviz](https://graphviz.org/)' [dot language](https://graphviz.org/doc/info/lang.html). Install graphviz and use one of the chains of commands from below to generate full or partial images of the graphs of your application.
5
6
 
6
7
  ## Visualize your entire application
8
+
7
9
  ```
8
10
  bundle exec visualize_packs > packs.dot && dot packs.dot -Tpng -o packs.png && open packs.png
9
11
  ```
@@ -13,16 +15,15 @@ bundle exec visualize_packs > packs.dot && dot packs.dot -Tpng -o packs.png && o
13
15
  This will generate a local dependency diagram for every pack in your app
14
16
 
15
17
  ```
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"
18
+ find . -iname 'package.yml' | sed 's/\/package.yml//g' | sed 's/\.\///' | xargs -I % sh -c "bundle exec visualize_packs --focus-pack=% > %/packs.dot && dot %/packs.dot -Tpng -o %/packs.png"
17
19
  ```
18
20
 
19
21
  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
22
 
21
23
  ```
22
- find . -iname 'package.yml' | sed 's/\/package.yml//g' | sed 's/\.\///' | xargs -I % sh -c "bundle exec visualize_packs --only=% --focus-pack-edge-mode=inout > %/packs.dot && dot %/packs.dot -Tpng -o %/packs.png"
24
+ find . -iname 'package.yml' | sed 's/\/package.yml//g' | sed 's/\.\///' | xargs -I % sh -c "bundle exec visualize_packs --focus-pack=% --focus-pack-edge-mode=inout > %/packs.dot && dot %/packs.dot -Tpng -o %/packs.png"
23
25
  ```
24
26
 
25
-
26
27
  ## Get help
27
28
 
28
29
  ```
@@ -49,4 +50,4 @@ Once you are ready, run the following and commit the new `diagram_examples.png`
49
50
  ./spec/update_cassettes.sh
50
51
  ```
51
52
 
52
- Please check in a new `diagram_examples.png` only if there are actual visual changes.
53
+ Please check in a new `diagram_examples.png` only if there are actual visual changes.
data/bin/visualize_packs CHANGED
@@ -1,55 +1,10 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require "pathname"
5
- require "optparse"
6
- require "ostruct"
7
-
8
4
  require_relative '../lib/visualize_packs'
9
5
 
10
- options = Options.new
11
-
12
- OptionParser.new do |opt|
13
- opt.on('--no-legend', "Don't show legend") { |o| options.show_legend = false }
14
-
15
- opt.on('--no-dependency-arrows', "Don't show accepted dependency arrows") { |o| options.show_dependencies = false }
16
- opt.on('--no-privacy-boxes', "Don't show privacy enforcement box on a pack") { |o| options.show_privacy = false }
17
- opt.on('--no-layers', "Don't show architectural layers") { |o| options.show_layers = false }
18
- opt.on('--no-visibility-arrows', "Don't show visibility arrows") { |o| options.show_visibility = false }
19
-
20
- opt.on('--no-todo-edges', "Don't show todos for package relationships") { |o| options.show_relationship_todos = false }
21
- opt.on("--edge-todo-types=STRING", "Show only the selected types of relationship todos. Comma-separated list of #{EdgeTodoTypes.values.map &:serialize}") { |o| options.relationship_todo_types = o.to_s.split(",").uniq.map { EdgeTodoTypes.deserialize(_1) } }
22
- opt.on("--use-edge-todos-for-layout", "Show only the selected types of relationship todos. Comma-separated list of #{EdgeTodoTypes.values.map &:serialize}") { |o| options.use_relationship_todos_for_layout = true }
23
-
24
- opt.on('--no-teams', "Don't show team colors") { |o| options.show_teams = false }
25
- opt.on('--no-node-todos', "Don't show package-based todos") { |o| options.show_node_todos = false }
26
-
27
- opt.on('--focus-pack=STRING', "Focus on a specific pack(s). Comma-separated list of packs. Wildcards supported: 'packs/*'") { |o| options.focus_pack = o.to_s.split(",") }
28
- opt.on('--focus-pack-edge-mode=STRING', "If focus-pack is set, this shows only between focussed packs (when set to none) or the edges into / out of / in and out of the focus packs to non-focus packs (which will be re-added to the graph). One of #{FocusPackEdgeDirection.values.map &:serialize}") { |o| options.show_only_edges_to_focus_pack = FocusPackEdgeDirection.deserialize(o) }
29
- opt.on('--exclude-packs=', "Exclude listed packs from diagram. If used with include you will get all included that are not excluded. Wildcards support: 'packs/ignores/*'") { |o| options.exclude_packs = o.to_s.split(",") }
30
-
31
- opt.on('--roll-nested-into-parent-packs', "Don't show nested packs (not counting root). Connect edges to top-level pack instead") { |o| options.roll_nested_into_parent_packs = true }
32
- opt.on('--no-nesting-arrows', "Don't draw relationships between parents and nested packs") { |o| options.show_nested_relationships = false }
33
-
34
- opt.on('--remote-base-url=STRING', "Link pack packs to a URL (affects graphviz SVG generation)") { |o| options.remote_base_url = o }
35
-
36
- opt.on('--title=STRING', "Set a custom diagram title") { |o| options.title = o }
37
-
38
- opt.on('-V', '--version', "Show version") do
39
- spec_path = File.expand_path("../visualize_packs.gemspec", __dir__)
40
- spec = Gem::Specification::load(spec_path)
41
- puts "Version #{spec.version}"
42
- exit
43
- end
44
-
45
- opt.on_tail("-h", "--help", "Show this message") do
46
- puts opt
47
- exit
48
- end
49
- end.parse!
50
-
51
6
  puts VisualizePacks.package_graph!(
52
- options,
7
+ ARGV,
53
8
  ParsePackwerk::Configuration.fetch.raw,
54
9
  Packs.all.map { ParsePackwerk.find(_1.name) }
55
10
  )
data/lib/graph.dot.erb CHANGED
@@ -105,6 +105,8 @@ digraph package_diagram {
105
105
  <%= VisualizePacks::ArrowHead::ArchitectureTodo.serialize %>
106
106
  <%- elsif todo_type == 'visibility' -%>
107
107
  <%= VisualizePacks::ArrowHead::VisibilityTodo.serialize %>
108
+ <%- elsif todo_type == 'folder_visibility' -%>
109
+ <%= VisualizePacks::ArrowHead::FolderVisibilityTodo.serialize %>
108
110
  <%- elsif todo_type == 'dependency' -%>
109
111
  <%= VisualizePacks::ArrowHead::DependencyTodo.serialize %>
110
112
  <%- end -%>
@@ -141,14 +143,14 @@ digraph package_diagram {
141
143
  A -> B [label="accepted dependency" <%= VisualizePacks::ArrowHead::ConfiguredDependency.serialize %>]
142
144
  <%- end -%>
143
145
  <%- if options.show_nested_relationships -%>
144
- K [ fontsize=12 shape=box label="package"]
145
- L [ fontsize=12 shape=box label="package"]
146
- K -> L [label="nested package" <%= VisualizePacks::ArrowHead::ConfiguredNested.serialize %>]
147
- <%- end -%>
148
- <%- if options.show_visibility -%>
149
146
  M [ fontsize=12 shape=box label="package"]
150
147
  N [ fontsize=12 shape=box label="package"]
151
- M -> N [label="visibile to" <%= VisualizePacks::ArrowHead::ConfiguredVisibileTo.serialize %>]
148
+ M -> N [label="nested package" <%= VisualizePacks::ArrowHead::ConfiguredNested.serialize %>]
149
+ <%- end -%>
150
+ <%- if options.show_visibility -%>
151
+ O [ fontsize=12 shape=box label="package"]
152
+ P [ fontsize=12 shape=box label="package"]
153
+ O -> P [label="visible to" <%= VisualizePacks::ArrowHead::ConfiguredVisibleTo.serialize %>]
152
154
  <%- end -%>
153
155
  <%- if options.show_relationship_todos -%>
154
156
  <%- if options.relationship_todo_types.include?(EdgeTodoTypes::Privacy) -%>
@@ -166,10 +168,15 @@ digraph package_diagram {
166
168
  H [ fontsize=12 shape=box label="package"]
167
169
  G -> H [label="visibility todo" <%= VisualizePacks::ArrowHead::VisibilityTodo.serialize %>]
168
170
  <%- end -%>
169
- <%- if options.relationship_todo_types.include?(EdgeTodoTypes::Dependency) -%>
171
+ <%- if options.relationship_todo_types.include?(EdgeTodoTypes::Folder_Visibility) -%>
170
172
  I [ fontsize=12 shape=box label="package"]
171
173
  J [ fontsize=12 shape=box label="package"]
172
- I -> J [label="dependency todo" <%= VisualizePacks::ArrowHead::DependencyTodo.serialize %>]
174
+ I -> J [label="folder visibility todo" <%= VisualizePacks::ArrowHead::FolderVisibilityTodo.serialize %>]
175
+ <%- end -%>
176
+ <%- if options.relationship_todo_types.include?(EdgeTodoTypes::Dependency) -%>
177
+ K [ fontsize=12 shape=box label="package"]
178
+ L [ fontsize=12 shape=box label="package"]
179
+ K -> L [label="dependency todo" <%= VisualizePacks::ArrowHead::DependencyTodo.serialize %>]
173
180
  <%- end -%>
174
181
  <%- end -%>
175
182
  LEGEND_NODE_1 [ label="" peripheries=0 height=0 width=0 style=invis ]
@@ -198,4 +205,4 @@ digraph package_diagram {
198
205
  LEGEND_NODE_2 -> "<%= all_team_names.last %><%= all_team_names.last %>" [style=invis]
199
206
  <%- end -%>
200
207
  <%- end -%>
201
- }
208
+ }
@@ -7,6 +7,7 @@ class EdgeTodoTypes < T::Enum
7
7
  Privacy = new
8
8
  Architecture = new
9
9
  Visibility = new
10
+ Folder_Visibility = new
10
11
  end
11
12
  end
12
13
 
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+ #typed: strict
3
+
4
+ require "optparse"
5
+
6
+ class OptionsParser
7
+ extend T::Sig
8
+
9
+ sig { params(args: T::Array[String]).returns(Options) }
10
+ def self.parse(args)
11
+ options = Options.new
12
+
13
+ OptionParser.new do |opt|
14
+ opt.on('--no-legend', "Don't show legend") { |o| options.show_legend = false }
15
+
16
+ opt.on('--no-dependency-arrows', "Don't show accepted dependency arrows") { |o| options.show_dependencies = false }
17
+ opt.on('--no-privacy-boxes', "Don't show privacy enforcement box on a pack") { |o| options.show_privacy = false }
18
+ opt.on('--no-layers', "Don't show architectural layers") { |o| options.show_layers = false }
19
+ opt.on('--no-visibility-arrows', "Don't show visibility arrows") { |o| options.show_visibility = false }
20
+
21
+ opt.on('--no-todo-edges', "Don't show todos for package relationships") { |o| options.show_relationship_todos = false }
22
+ opt.on("--edge-todo-types=STRING", "Show only the selected types of relationship todos. Comma-separated list of #{EdgeTodoTypes.values.map &:serialize}") { |o| options.relationship_todo_types = o.to_s.split(",").uniq.map { EdgeTodoTypes.deserialize(_1) } }
23
+ opt.on("--use-edge-todos-for-layout", "Show only the selected types of relationship todos. Comma-separated list of #{EdgeTodoTypes.values.map &:serialize}") { |o| options.use_relationship_todos_for_layout = true }
24
+
25
+ opt.on('--no-teams', "Don't show team colors") { |o| options.show_teams = false }
26
+ opt.on('--no-node-todos', "Don't show package-based todos") { |o| options.show_node_todos = false }
27
+
28
+ opt.on('--focus-pack=STRING', "Focus on a specific pack(s). Comma-separated list of packs. Wildcards supported: 'packs/*'") { |o| options.focus_pack = o.to_s.split(",") }
29
+ opt.on('--focus-pack-edge-mode=STRING', "If focus-pack is set, this shows only between focussed packs (when set to none) or the edges into / out of / in and out of the focus packs to non-focus packs (which will be re-added to the graph). One of #{FocusPackEdgeDirection.values.map &:serialize}") { |o| options.show_only_edges_to_focus_pack = FocusPackEdgeDirection.deserialize(o) }
30
+ opt.on('--exclude-packs=', "Exclude listed packs from diagram. If used with include you will get all included that are not excluded. Wildcards support: 'packs/ignores/*'") { |o| options.exclude_packs = o.to_s.split(",") }
31
+
32
+ opt.on('--roll-nested-into-parent-packs', "Don't show nested packs (not counting root). Connect edges to top-level pack instead") { |o| options.roll_nested_into_parent_packs = true }
33
+ opt.on('--no-nesting-arrows', "Don't draw relationships between parents and nested packs") { |o| options.show_nested_relationships = false }
34
+
35
+ opt.on('--remote-base-url=STRING', "Link pack packs to a URL (affects graphviz SVG generation)") { |o| options.remote_base_url = o }
36
+
37
+ opt.on('--title=STRING', "Set a custom diagram title") { |o| options.title = o }
38
+
39
+ opt.on('-V', '--version', "Show version") do
40
+ spec_path = File.expand_path("../visualize_packs.gemspec", __dir__)
41
+ spec = Gem::Specification::load(spec_path)
42
+ puts "Version #{spec.version}"
43
+ exit
44
+ end
45
+
46
+ opt.on_tail("-h", "--help", "Show this message") do
47
+ puts opt
48
+ exit
49
+ end
50
+ end.parse(args)
51
+
52
+ options
53
+ end
54
+ end
55
+
@@ -7,6 +7,7 @@ require 'parse_packwerk'
7
7
  require 'digest/md5'
8
8
 
9
9
  require 'visualize_packs/options'
10
+ require 'visualize_packs/options_parser'
10
11
 
11
12
  module VisualizePacks
12
13
  extend T::Sig
@@ -17,14 +18,17 @@ module VisualizePacks
17
18
  PrivacyTodo = new('color=darkred style=dashed arrowhead=crow')
18
19
  ArchitectureTodo = new('color=darkred style=dashed arrowhead=obox')
19
20
  VisibilityTodo = new('color=darkred style=dashed arrowhead=tee')
21
+ FolderVisibilityTodo = new('color=darkred style=dashed arrowhead=odot')
20
22
  ConfiguredDependency = new('color=darkgreen')
21
- ConfiguredVisibileTo = new('color=blue')
23
+ ConfiguredVisibleTo = new('color=blue')
22
24
  ConfiguredNested = new('color=purple')
23
25
  end
24
26
  end
25
27
 
26
- sig { params(options: Options, raw_config: T::Hash[String, T.untyped], packages: T::Array[ParsePackwerk::Package]).returns(String) }
27
- def self.package_graph!(options, raw_config, packages)
28
+ sig { params(args: T::Array[String], raw_config: T::Hash[String, T.untyped], packages: T::Array[ParsePackwerk::Package]).returns(String) }
29
+ def self.package_graph!(args, raw_config, packages)
30
+ options = OptionsParser.parse(args)
31
+
28
32
  all_packages = filtered(packages, options).compact.sort_by {|x| x.name }
29
33
  all_packages = remove_nested_packs(all_packages, options)
30
34
  all_package_names = all_packages.map &:name
@@ -34,7 +38,7 @@ module VisualizePacks
34
38
  node_protection = package_based_todos_text_maker()
35
39
  max_todo_count = max_todo_count(all_packages, show_edge, options)
36
40
 
37
- title = diagram_title(options, max_todo_count)
41
+ title = diagram_title(args, options, max_todo_count)
38
42
 
39
43
  architecture_layers = (raw_config['architecture_layers'] || []) + ["NotInLayer"]
40
44
  grouped_packages = architecture_layers.inject({}) do |result, key|
@@ -67,10 +71,24 @@ module VisualizePacks
67
71
  package.config.dig("metadata", "owner") || package.config["owner"]
68
72
  end
69
73
 
70
- sig { params(options: Options, max_todo_count: T.nilable(Integer)).returns(String) }
71
- def self.diagram_title(options, max_todo_count)
74
+ sig { params(args: T::Array[String], options: Options, max_todo_count: T.nilable(Integer)).returns(String) }
75
+ def self.diagram_title(args, options, max_todo_count)
72
76
  return "<<b>#{options.title}</b>>" if options.title
73
77
 
78
+ sub_title1_length = 0
79
+ options_to_display = args.inject('') do |result, item|
80
+ sub_title1_length += item.length
81
+ if sub_title1_length > 90
82
+ sub_title1_length = 0
83
+ result += "<br/>#{item}"
84
+ else
85
+ result += " #{item}"
86
+ end
87
+ result
88
+ end
89
+ sub_title1 = "<br/>#{options_to_display}"
90
+
91
+
74
92
  focus_info = if options.focus_pack
75
93
  "Focus on #{limited_sentence(options.focus_pack)} (Edge mode: #{options.show_only_edges_to_focus_pack.serialize})"
76
94
  else
@@ -98,9 +116,9 @@ module VisualizePacks
98
116
  main_title = [focus_info, hidden_aspects_title, todo_types, exclusions].compact.join('. ')
99
117
 
100
118
  if options.show_relationship_todos && max_todo_count
101
- sub_title = "<br/><font point-size='12'>Widest todo edge is #{max_todo_count} todo#{max_todo_count > 1 ? 's' : ''}</font>"
119
+ sub_title2 = "<br/><font point-size='12'>Widest todo edge is #{max_todo_count} todo#{max_todo_count > 1 ? 's' : ''}</font>"
102
120
  end
103
- "<<b>#{main_title}</b>#{sub_title}>"
121
+ "<<b>#{main_title}</b>#{sub_title1}#{sub_title2}>"
104
122
  end
105
123
 
106
124
  sig { params(list: T.nilable(T::Array[String])).returns(T.nilable(String)) }
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.21
4
+ version: 0.5.23
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-27 00:00:00.000000000 Z
11
+ date: 2023-12-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -122,6 +122,7 @@ files:
122
122
  - lib/graph.dot.erb
123
123
  - lib/visualize_packs.rb
124
124
  - lib/visualize_packs/options.rb
125
+ - lib/visualize_packs/options_parser.rb
125
126
  homepage: https://github.com/rubyatscale/visualize_packs
126
127
  licenses:
127
128
  - MIT