cobra_commander 0.4.0 → 0.7.0
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/.editorconfig +11 -0
- data/.travis.yml +3 -2
- data/CHANGELOG.md +25 -0
- data/README.md +10 -6
- data/cobra_commander.gemspec +4 -2
- data/lib/cobra_commander.rb +23 -2
- data/lib/cobra_commander/affected.rb +37 -30
- data/lib/cobra_commander/cached_component_tree.rb +24 -0
- data/lib/cobra_commander/calculated_component_tree.rb +141 -0
- data/lib/cobra_commander/change.rb +6 -7
- data/lib/cobra_commander/cli.rb +61 -11
- data/lib/cobra_commander/component.rb +52 -0
- data/lib/cobra_commander/component_tree.rb +46 -117
- data/lib/cobra_commander/dependencies.rb +4 -0
- data/lib/cobra_commander/dependencies/bundler.rb +38 -0
- data/lib/cobra_commander/dependencies/yarn/package.rb +37 -0
- data/lib/cobra_commander/dependencies/yarn/package_repo.rb +31 -0
- data/lib/cobra_commander/dependencies/yarn_workspace.rb +55 -0
- data/lib/cobra_commander/executor.rb +20 -0
- data/lib/cobra_commander/graph.rb +6 -15
- data/lib/cobra_commander/output.rb +74 -0
- data/lib/cobra_commander/umbrella.rb +51 -0
- data/lib/cobra_commander/version.rb +1 -1
- data/renovate.json +8 -0
- metadata +29 -9
- data/lib/cobra_commander/formatted_output.rb +0 -76
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "open3"
|
4
|
+
|
5
|
+
require_relative "yarn/package"
|
6
|
+
require_relative "yarn/package_repo"
|
7
|
+
|
8
|
+
module CobraCommander
|
9
|
+
module Dependencies
|
10
|
+
# Yarn workspace components source for an umbrella
|
11
|
+
class YarnWorkspace
|
12
|
+
attr_reader :packages
|
13
|
+
|
14
|
+
def initialize(root_path)
|
15
|
+
@repo = Yarn::PackageRepo.new
|
16
|
+
@root_package = Yarn::Package.new(root_path)
|
17
|
+
@repo.load_linked_specs(@root_package)
|
18
|
+
load_workspace_packages
|
19
|
+
end
|
20
|
+
|
21
|
+
def path
|
22
|
+
@root_package.path
|
23
|
+
end
|
24
|
+
|
25
|
+
def dependencies
|
26
|
+
(workspace_spec.keys | @root_package.dependencies.keys).map(&method(:untag))
|
27
|
+
end
|
28
|
+
|
29
|
+
def components
|
30
|
+
@repo.specs.map do |spec|
|
31
|
+
{ path: spec.path, name: untag(spec.name), dependencies: spec.dependencies.keys.map(&method(:untag)) }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def load_workspace_packages
|
38
|
+
workspace_spec.map do |_name, spec|
|
39
|
+
@repo.load_spec File.expand_path(File.join(@root_package.path, "..", spec["location"]))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def workspace_spec
|
44
|
+
@workspace_spec ||= begin
|
45
|
+
output, = Open3.capture2("yarn workspaces --json info", chdir: File.dirname(@root_package.path))
|
46
|
+
JSON.parse(JSON.parse(output)["data"])
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def untag(name)
|
51
|
+
name.gsub(@root_package.project_tag, "")
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CobraCommander
|
4
|
+
# Execute commands on all components of a ComponentTree
|
5
|
+
class Executor
|
6
|
+
def initialize(components)
|
7
|
+
@components = components
|
8
|
+
end
|
9
|
+
|
10
|
+
def exec(command, printer = $stdout)
|
11
|
+
@components.each do |component|
|
12
|
+
component.root_paths.each do |path|
|
13
|
+
printer.puts "===> #{component.name} (#{path})"
|
14
|
+
output, = Open3.capture2e(command, chdir: path, unsetenv_others: true)
|
15
|
+
printer.puts output
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -1,36 +1,27 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "graphviz"
|
4
|
-
require "cobra_commander/component_tree"
|
5
4
|
|
6
5
|
module CobraCommander
|
7
6
|
# Generates graphs of components
|
8
7
|
class Graph
|
9
|
-
def initialize(
|
8
|
+
def initialize(node, format)
|
10
9
|
@format = format
|
11
|
-
@
|
10
|
+
@node = node
|
12
11
|
end
|
13
12
|
|
14
13
|
def generate!
|
15
14
|
return unless valid_format?
|
16
15
|
|
17
16
|
g = GraphViz.new(:G, type: :digraph, concentrate: true)
|
17
|
+
([@node] + @node.deep_dependencies).each do |component|
|
18
|
+
g.add_nodes component.name
|
19
|
+
g.add_edges component.name, component.dependencies.map(&:name)
|
20
|
+
end
|
18
21
|
|
19
|
-
app_node = g.add_nodes(@tree[:name])
|
20
|
-
map_nodes(g, app_node, @tree)
|
21
22
|
output(g)
|
22
23
|
end
|
23
24
|
|
24
|
-
private
|
25
|
-
|
26
|
-
def map_nodes(g, parent_node, tree)
|
27
|
-
tree[:dependencies].each do |dep|
|
28
|
-
node = g.find_node(dep[:name]) || g.add_nodes(dep[:name])
|
29
|
-
g.add_edges(parent_node, node)
|
30
|
-
map_nodes(g, node, dep)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
25
|
def output(g)
|
35
26
|
graph = "graph.#{@format}"
|
36
27
|
g.output(@format => graph)
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CobraCommander
|
4
|
+
# Module for pretty printing dependency trees
|
5
|
+
module Output
|
6
|
+
def self.print(node, format)
|
7
|
+
output = format == "list" ? Output::FlatList.new(node) : Output::Tree.new(node)
|
8
|
+
puts output.to_s
|
9
|
+
end
|
10
|
+
|
11
|
+
# Flattens a tree and prints unique items
|
12
|
+
class FlatList
|
13
|
+
def initialize(tree)
|
14
|
+
@tree = tree
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_s
|
18
|
+
@tree.deep_dependencies.map(&:name).sort
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Prints the tree in a nice tree form
|
23
|
+
class Tree
|
24
|
+
attr_accessor :tree
|
25
|
+
|
26
|
+
SPACE = " "
|
27
|
+
BAR = "│ "
|
28
|
+
TEE = "├── "
|
29
|
+
CORNER = "└── "
|
30
|
+
|
31
|
+
def initialize(node)
|
32
|
+
@node = node
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_s
|
36
|
+
StringIO.new.tap do |io|
|
37
|
+
io.puts @node.name
|
38
|
+
list_dependencies(io, @node)
|
39
|
+
end.string
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def list_dependencies(io, node, outdents = [])
|
45
|
+
node.dependencies.each do |dep|
|
46
|
+
decide_on_line(io, node, dep, outdents)
|
47
|
+
end
|
48
|
+
nil
|
49
|
+
end
|
50
|
+
|
51
|
+
def decide_on_line(io, parent, dep, outdents)
|
52
|
+
if parent.dependencies.last != dep
|
53
|
+
add_tee(io, outdents, dep)
|
54
|
+
else
|
55
|
+
add_corner(io, outdents, dep)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def add_tee(io, outdents, dep)
|
60
|
+
io.puts line(outdents, TEE, dep.name)
|
61
|
+
list_dependencies(io, dep, (outdents + [BAR]))
|
62
|
+
end
|
63
|
+
|
64
|
+
def add_corner(io, outdents, dep)
|
65
|
+
io.puts line(outdents, CORNER, dep.name)
|
66
|
+
list_dependencies(io, dep, (outdents + [SPACE]))
|
67
|
+
end
|
68
|
+
|
69
|
+
def line(outdents, sym, name)
|
70
|
+
(outdents + [sym] + [name]).join
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CobraCommander
|
4
|
+
# An umbrella application
|
5
|
+
class Umbrella
|
6
|
+
attr_reader :name, :path
|
7
|
+
|
8
|
+
def initialize(name, path)
|
9
|
+
@root_component = Component.new(self, name)
|
10
|
+
@path = path
|
11
|
+
@components = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def find(name)
|
15
|
+
@components[name]
|
16
|
+
end
|
17
|
+
|
18
|
+
def root
|
19
|
+
@root_component
|
20
|
+
end
|
21
|
+
|
22
|
+
def resolve(component_root_path)
|
23
|
+
return root if root.root_paths.include?(component_root_path)
|
24
|
+
components.find do |component|
|
25
|
+
component.root_paths.include?(component_root_path)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def add_source(key, source)
|
30
|
+
@root_component.add_source key, source.path, source.dependencies
|
31
|
+
source.components.each do |path:, name:, dependencies:|
|
32
|
+
@components[name] ||= Component.new(self, name)
|
33
|
+
@components[name].add_source key, path, dependencies
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def components
|
38
|
+
@components.values
|
39
|
+
end
|
40
|
+
|
41
|
+
def dependents_of(component)
|
42
|
+
find(component)&.deep_dependents
|
43
|
+
&.sort_by(&:name)
|
44
|
+
end
|
45
|
+
|
46
|
+
def dependencies_of(name)
|
47
|
+
find(name)&.deep_dependencies
|
48
|
+
&.sort_by(&:name)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/renovate.json
ADDED
metadata
CHANGED
@@ -1,30 +1,37 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cobra_commander
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Langfeld
|
8
8
|
- Garett Arrowood
|
9
|
+
- Carlos Palhares
|
9
10
|
autorequire:
|
10
11
|
bindir: exe
|
11
12
|
cert_chain: []
|
12
|
-
date:
|
13
|
+
date: 2020-07-08 00:00:00.000000000 Z
|
13
14
|
dependencies:
|
14
15
|
- !ruby/object:Gem::Dependency
|
15
16
|
name: thor
|
16
17
|
requirement: !ruby/object:Gem::Requirement
|
17
18
|
requirements:
|
18
|
-
- - "
|
19
|
+
- - "<"
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '2.0'
|
22
|
+
- - ">="
|
19
23
|
- !ruby/object:Gem::Version
|
20
|
-
version: 0.
|
24
|
+
version: 0.18.1
|
21
25
|
type: :runtime
|
22
26
|
prerelease: false
|
23
27
|
version_requirements: !ruby/object:Gem::Requirement
|
24
28
|
requirements:
|
25
|
-
- - "
|
29
|
+
- - "<"
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
version: '2.0'
|
32
|
+
- - ">="
|
26
33
|
- !ruby/object:Gem::Version
|
27
|
-
version: 0.
|
34
|
+
version: 0.18.1
|
28
35
|
- !ruby/object:Gem::Dependency
|
29
36
|
name: ruby-graphviz
|
30
37
|
requirement: !ruby/object:Gem::Requirement
|
@@ -45,14 +52,14 @@ dependencies:
|
|
45
52
|
requirements:
|
46
53
|
- - "~>"
|
47
54
|
- !ruby/object:Gem::Version
|
48
|
-
version: '1.
|
55
|
+
version: '1.17'
|
49
56
|
type: :development
|
50
57
|
prerelease: false
|
51
58
|
version_requirements: !ruby/object:Gem::Requirement
|
52
59
|
requirements:
|
53
60
|
- - "~>"
|
54
61
|
- !ruby/object:Gem::Version
|
55
|
-
version: '1.
|
62
|
+
version: '1.17'
|
56
63
|
- !ruby/object:Gem::Dependency
|
57
64
|
name: rake
|
58
65
|
requirement: !ruby/object:Gem::Requirement
|
@@ -144,11 +151,13 @@ description: |
|
|
144
151
|
email:
|
145
152
|
- blangfeld@powerhrg.com
|
146
153
|
- garett.arrowood@powerhrg.com
|
154
|
+
- carlos.palhares@powerhrg.com
|
147
155
|
executables:
|
148
156
|
- cobra
|
149
157
|
extensions: []
|
150
158
|
extra_rdoc_files: []
|
151
159
|
files:
|
160
|
+
- ".editorconfig"
|
152
161
|
- ".gitignore"
|
153
162
|
- ".rspec"
|
154
163
|
- ".rubocop.yml"
|
@@ -167,12 +176,23 @@ files:
|
|
167
176
|
- exe/cobra
|
168
177
|
- lib/cobra_commander.rb
|
169
178
|
- lib/cobra_commander/affected.rb
|
179
|
+
- lib/cobra_commander/cached_component_tree.rb
|
180
|
+
- lib/cobra_commander/calculated_component_tree.rb
|
170
181
|
- lib/cobra_commander/change.rb
|
171
182
|
- lib/cobra_commander/cli.rb
|
183
|
+
- lib/cobra_commander/component.rb
|
172
184
|
- lib/cobra_commander/component_tree.rb
|
173
|
-
- lib/cobra_commander/
|
185
|
+
- lib/cobra_commander/dependencies.rb
|
186
|
+
- lib/cobra_commander/dependencies/bundler.rb
|
187
|
+
- lib/cobra_commander/dependencies/yarn/package.rb
|
188
|
+
- lib/cobra_commander/dependencies/yarn/package_repo.rb
|
189
|
+
- lib/cobra_commander/dependencies/yarn_workspace.rb
|
190
|
+
- lib/cobra_commander/executor.rb
|
174
191
|
- lib/cobra_commander/graph.rb
|
192
|
+
- lib/cobra_commander/output.rb
|
193
|
+
- lib/cobra_commander/umbrella.rb
|
175
194
|
- lib/cobra_commander/version.rb
|
195
|
+
- renovate.json
|
176
196
|
homepage: http://tech.powerhrg.com/cobra_commander/
|
177
197
|
licenses:
|
178
198
|
- MIT
|
@@ -1,76 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "cobra_commander/component_tree"
|
4
|
-
|
5
|
-
module CobraCommander
|
6
|
-
# Formats CLI ls output
|
7
|
-
class FormattedOutput
|
8
|
-
attr_accessor :tree
|
9
|
-
|
10
|
-
SPACE = " "
|
11
|
-
BAR = "│ "
|
12
|
-
TEE = "├── "
|
13
|
-
CORNER = "└── "
|
14
|
-
|
15
|
-
def initialize(app_path)
|
16
|
-
@tree = ComponentTree.new(app_path).to_h
|
17
|
-
end
|
18
|
-
|
19
|
-
def run!
|
20
|
-
puts @tree[:name]
|
21
|
-
list_dependencies(@tree)
|
22
|
-
nil
|
23
|
-
end
|
24
|
-
|
25
|
-
def dependencies_of!(component_name, format)
|
26
|
-
@component_name = component_name
|
27
|
-
|
28
|
-
results = @tree[:dependencies].map do |component|
|
29
|
-
if @component_name == component[:name]
|
30
|
-
@tree[:name]
|
31
|
-
elsif dependency?(component)
|
32
|
-
component[:name]
|
33
|
-
end
|
34
|
-
end.compact
|
35
|
-
|
36
|
-
"list" == format ? results : results.size
|
37
|
-
end
|
38
|
-
|
39
|
-
private
|
40
|
-
|
41
|
-
def dependency?(deps)
|
42
|
-
deps[:dependencies].each do |dep|
|
43
|
-
return true if @component_name == dep[:name] || dependency?(dep)
|
44
|
-
end
|
45
|
-
false
|
46
|
-
end
|
47
|
-
|
48
|
-
def list_dependencies(deps, outdents = [])
|
49
|
-
deps[:dependencies].each do |dep|
|
50
|
-
decide_on_line(deps, dep, outdents)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def decide_on_line(parent, dep, outdents)
|
55
|
-
if parent[:dependencies].last != dep
|
56
|
-
add_tee(outdents, dep)
|
57
|
-
else
|
58
|
-
add_corner(outdents, dep)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def add_tee(outdents, dep)
|
63
|
-
puts line(outdents, TEE, dep[:name])
|
64
|
-
list_dependencies(dep, (outdents + [BAR]))
|
65
|
-
end
|
66
|
-
|
67
|
-
def add_corner(outdents, dep)
|
68
|
-
puts line(outdents, CORNER, dep[:name])
|
69
|
-
list_dependencies(dep, (outdents + [SPACE]))
|
70
|
-
end
|
71
|
-
|
72
|
-
def line(outdents, sym, name)
|
73
|
-
(outdents + [sym] + [name]).join
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|