cobra_commander 0.5.0 → 0.8.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: 0a05f3e1ab4ccff9ca040dcf4d694aebc28df0f50160067cf73eaea89f4bad59
4
- data.tar.gz: d0132e226b7527e72ebb84e3844116dd3a0c2ed8ecc1394d9df5f7fad5f777d8
3
+ metadata.gz: 6f1de2b5ceb4fbde7dcd12fd71606c55cdd733e6928e4c6a866dfc1f3ec65af3
4
+ data.tar.gz: 5a9537dabd13b974df919be911755debf92761b6bdf99b370c59cec2c8fc09af
5
5
  SHA512:
6
- metadata.gz: 1cb90f61448f1bc69088418fc86dafbc25fce09d069507e22fc22f0a2d9a63eccf95ce3edeb13b6ee2657e19303489c2b59087944ddc07597c7d0e201c36a307
7
- data.tar.gz: '023961e1f0abe297e0d0cacc169b3da23fac68f833627d01d480f06d0822019877cd1ac78bb20bf7f951b2bbdce04a0c0ddbb7b3b444a90669f18c967a43775c'
6
+ metadata.gz: 58f066894063d46d3b1c25baf2b085f3212db9ac716eee5c8ef6c2465c82233f06fae79e30c04205d95b75551799cd3f1c67901a60a516bf079e2cb154baa2b2
7
+ data.tar.gz: 99babd4c1ae0b5e218ed913bf175cbd38d4efe4bc19d11ea108d8f914c9f3381a7f43bb6c8a4d64171bec648e5c5e8441c39c30f5c3a83f11e0c9f1aa4e0948b
@@ -0,0 +1,11 @@
1
+ # EditorConfig is awesome: https://EditorConfig.org
2
+ # top-most EditorConfig file
3
+ root = true
4
+
5
+ # Unix-style newlines with a newline ending every file
6
+ [*]
7
+ end_of_line = lf
8
+ insert_final_newline = true
9
+ trim_trailing_whitespace = true
10
+ indent_style = space
11
+ indent_size = 2
@@ -4,8 +4,9 @@ before_install:
4
4
  - "find /home/travis/.rvm/rubies -wholename '*default/bundler-*.gemspec' -delete"
5
5
  - gem install bundler:"$BUNDLER_VERSION"
6
6
  - sudo apt-get -qq install graphviz
7
+ - curl -o- -L https://yarnpkg.com/install.sh | bash -s -- --version 1.13.0
8
+ - export PATH="$HOME/.yarn/bin:$PATH"
7
9
  rvm:
8
10
  - 2.5.1
9
11
  env:
10
- - BUNDLER_VERSION=1.15.4
11
- - BUNDLER_VERSION=1.16.3
12
+ - BUNDLER_VERSION=1.17.3
@@ -2,6 +2,32 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## Version 0.8 - 2020-07-21
6
+
7
+ * Standardize Cobra CLI options
8
+ * More powerful filters to all cobra commands (--js, --ruby)
9
+ * More powerful filters to cobra ls and exec (--dependencies, --dependents)
10
+ * Graphs for components, not just umbrella
11
+
12
+ ## Version 0.7 - 2020-07-08
13
+
14
+ * Introduces CobraCommander::Umbrella with optimizations for dependency resolution
15
+ * Deprecates cobra cache and cache usages
16
+
17
+ ## Version 0.6.1 - 2019-07-05
18
+
19
+ * Better supports yarn workspaces globbing by delegating to yarn to calculate the list of components rather than re-implementing in Ruby. PR [#34](https://github.com/powerhome/cobra_commander/pull/34)
20
+
21
+ ## Version 0.6.0 - 2019-07-03
22
+
23
+ * Tracks package.json `workspaces` in addition to `dependencies` and `devDependencies`. PR [#31](https://github.com/powerhome/cobra_commander/pull/31)
24
+ * Permits caching the component tree of a project on disk to avoid calculating it repeatedly on subsequent cobra invocations.
25
+
26
+ ## Version 0.5.1 - 2018-10-15
27
+
28
+ * Fix a bug with dependencies_of where it wouldn't match components further down the list of umbrella's dependencies
29
+ * Bumps Thor version from 0.19.4 to a range (< 2.0, >= 0.18.1) compatible with railties
30
+
5
31
  ## Version 0.5.0 - 2018-09-20
6
32
 
7
33
  * Renames `dependencies_of` to `dependents_of`. PR [#25](https://github.com/powerhome/cobra_commander/pull/25)
data/README.md CHANGED
@@ -24,24 +24,115 @@ Or install it yourself as:
24
24
 
25
25
  $ gem install cobra_commander
26
26
 
27
- ## Usage
27
+ ## Usage (cobra help)
28
28
 
29
29
  ```bash
30
30
  Commands:
31
- cobra changes APP_PATH [--results=RESULTS] [--branch=BRANCH] # Prints list of changed files
32
- cobra graph APP_PATH [--format=FORMAT] # Outputs graph
33
- cobra help [COMMAND] # Describe available commands or one specific command
34
- cobra ls APP_PATH [--format=list|tree] # Prints tree of components for an app
35
- cobra version # Prints version
36
- cobra do [command] # Executes the command in the context of each component
37
- cobra dependencies_of [component] [--app=/path/to/app] [--format=list|tree] # Lists the dependencies of the component in the app context
38
- cobra dependents_of [component] [--app=/path/to/app] [--format=list|count] # Lists or counts the components that depend directly or indirectly on the given component
39
- cobra version # Prints version
31
+ cobra changes [--results=RESULTS] [--branch=BRANCH] # Prints list of changed files
32
+ cobra exec [component] <command> # Executes the command in the context of a given component or set of components. If no component is given executes the command in all components.
33
+ cobra graph [component] # Outputs a graph of a given component or umbrella
34
+ cobra help [COMMAND] # Describe available commands or one specific command
35
+ cobra ls [component] # Lists the components in the context of a given component or umbrella
36
+ cobra tree [component] # Prints the dependency tree of a given component or umbrella
37
+ cobra version # Prints version
38
+
39
+ Options:
40
+ -a, [--app=APP]
41
+ # Default: /Users/chjunior/workspace/power/cobra_commander
42
+ [--js], [--no-js] # Consider only the JS dependency graph
43
+ [--ruby], [--no-ruby] # Consider only the Ruby dependency graph
44
+ ```
45
+
46
+ ### cobra changes
47
+
48
+ ```sh
49
+ ➜ nitro git:(nova/remove-cobra-commander) be cobra help changes
50
+ Usage:
51
+ cobra changes [--results=RESULTS] [--branch=BRANCH]
52
+
53
+ Options:
54
+ -r, [--results=RESULTS] # Accepts test, full, name or json
55
+ # Default: test
56
+ -b, [--branch=BRANCH] # Specified target to calculate against
57
+ # Default: master
58
+ -a, [--app=APP]
59
+ # Default: /Users/chjunior/workspace/power/nitro
60
+ [--js], [--no-js] # Consider only the JS dependency graph
61
+ [--ruby], [--no-ruby] # Consider only the Ruby dependency graph
62
+
63
+ Prints list of changed files
64
+ ```
65
+
66
+ ### cobra exec
67
+
68
+ ```sh
69
+ Usage:
70
+ cobra exec [component] <command>
71
+
72
+ Options:
73
+ [--dependencies], [--no-dependencies] # Run the command on each dependency of a given component
74
+ [--dependents], [--no-dependents] # Run the command on each dependency of a given component
75
+ -a, [--app=APP]
76
+ # Default: /Users/chjunior/workspace/power/cobra_commander
77
+ [--js], [--no-js] # Consider only the JS dependency graph
78
+ [--ruby], [--no-ruby] # Consider only the Ruby dependency graph
79
+
80
+ Executes the command in the context of a given component or set of components. If no component is given executes the command in all components.
81
+ ```
82
+
83
+ ### cobra graph
84
+
85
+ ```sh
86
+ Usage:
87
+ cobra graph [component]
88
+
89
+ Options:
90
+ -o, [--output=OUTPUT] # Output file, accepts .png or .dot
91
+ # Default: /Users/chjunior/workspace/power/cobra_commander/output.png
92
+ -a, [--app=APP]
93
+ # Default: /Users/chjunior/workspace/power/cobra_commander
94
+ [--js], [--no-js] # Consider only the JS dependency graph
95
+ [--ruby], [--no-ruby] # Consider only the Ruby dependency graph
96
+
97
+ Outputs a graph of a given component or umbrella
98
+ ```
99
+
100
+ ### cobra ls
101
+
102
+ ```sh
103
+ Usage:
104
+ cobra ls [component]
105
+
106
+ Options:
107
+ -d, [--dependencies], [--no-dependencies] # Run the command on each dependency of a given component
108
+ -D, [--dependents], [--no-dependents] # Run the command on each dependency of a given component
109
+ -t, [--total], [--no-total] # Prints the total count of components
110
+ -a, [--app=APP]
111
+ # Default: /Users/chjunior/workspace/power/cobra_commander
112
+ [--js], [--no-js] # Consider only the JS dependency graph
113
+ [--ruby], [--no-ruby] # Consider only the Ruby dependency graph
114
+
115
+ Lists the components in the context of a given component or umbrella
116
+ ```
117
+
118
+ ### cobra tree
119
+
120
+ ```sh
121
+ Usage:
122
+ cobra tree [component]
123
+
124
+ Options:
125
+ -a, [--app=APP]
126
+ # Default: /Users/chjunior/workspace/power/cobra_commander
127
+ [--js], [--no-js] # Consider only the JS dependency graph
128
+ [--ruby], [--no-ruby] # Consider only the Ruby dependency graph
129
+
130
+ Prints the dependency tree of a given component or umbrella
40
131
  ```
41
132
 
42
133
  ## Development
43
134
 
44
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
135
+ After checking out the repo, run `bin/setup` to install dependencies. You will also need to install `graphviz` by running `brew install graphviz`. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
45
136
 
46
137
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
47
138
 
@@ -11,10 +11,12 @@ Gem::Specification.new do |spec|
11
11
  spec.authors = [
12
12
  "Ben Langfeld",
13
13
  "Garett Arrowood",
14
+ "Carlos Palhares",
14
15
  ]
15
16
  spec.email = [
16
17
  "blangfeld@powerhrg.com",
17
18
  "garett.arrowood@powerhrg.com",
19
+ "carlos.palhares@powerhrg.com",
18
20
  ]
19
21
  spec.summary = "Tools for working with Component Based Rails Apps"
20
22
  spec.description = <<~DESCRIPTION
@@ -32,10 +34,11 @@ DESCRIPTION
32
34
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
33
35
  spec.require_paths = ["lib"]
34
36
 
35
- spec.add_dependency "thor", "~> 0.19.4"
37
+ spec.add_dependency "bundler", "~> 1.17"
38
+ spec.add_dependency "thor", ["< 2.0", ">= 0.18.1"]
36
39
  spec.add_dependency "ruby-graphviz", "~> 1.2.3"
37
40
 
38
- spec.add_development_dependency "bundler", "~> 1.13"
41
+ spec.add_development_dependency "bundler", "~> 1.17"
39
42
  spec.add_development_dependency "rake", "~> 10.0"
40
43
  spec.add_development_dependency "rspec", "~> 3.5"
41
44
  spec.add_development_dependency "guard-rspec"
data/exe/cobra CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require "cobra_commander"
4
+ require "cobra_commander/cli"
5
5
 
6
6
  CobraCommander::CLI.start
@@ -1,13 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "cobra_commander/cli"
4
- require "cobra_commander/component_tree"
3
+ require "cobra_commander/dependencies"
4
+ require "cobra_commander/component"
5
+ require "cobra_commander/umbrella"
5
6
  require "cobra_commander/version"
6
- require "cobra_commander/graph"
7
- require "cobra_commander/change"
8
- require "cobra_commander/affected"
9
- require "cobra_commander/output"
10
- require "cobra_commander/executor"
11
7
 
12
8
  # Tools for working with Component Based Rails Apps (see http://shageman.github.io/cbra.info/).
13
9
  # Includes tools for graphing the components of an app and their relationships, as well as selectively
@@ -15,7 +11,18 @@ require "cobra_commander/executor"
15
11
  module CobraCommander
16
12
  UMBRELLA_APP_NAME = "App"
17
13
 
14
+ def self.umbrella(root_path, yarn: false, bundler: false, name: UMBRELLA_APP_NAME)
15
+ umbrella = Umbrella.new(name, root_path)
16
+ umbrella.add_source(:yarn, Dependencies::YarnWorkspace.new(root_path)) unless bundler
17
+ umbrella.add_source(:bundler, Dependencies::Bundler.new(root_path)) unless yarn
18
+ umbrella
19
+ end
20
+
18
21
  def self.umbrella_tree(path)
19
- ComponentTree.new(UMBRELLA_APP_NAME, path)
22
+ CalculatedComponentTree.new(UMBRELLA_APP_NAME, path)
23
+ end
24
+
25
+ def self.tree_from_cache(cache_file)
26
+ CachedComponentTree.from_cache_file(cache_file)
20
27
  end
21
28
  end
@@ -3,28 +3,33 @@
3
3
  module CobraCommander
4
4
  # Calculates directly & transitively affected components
5
5
  class Affected
6
- attr_reader :directly, :transitively
7
-
8
- def initialize(tree, changes, path)
9
- @tree = tree
6
+ def initialize(umbrella, changes)
7
+ @umbrella = umbrella
10
8
  @changes = changes
11
- @path = path
12
9
  run!
13
10
  end
14
11
 
15
12
  def names
16
- @names ||= paths.map { |path| File.basename(path) }
13
+ @names ||= all_affected.map(&:name)
17
14
  end
18
15
 
19
16
  def scripts
20
17
  @scripts ||= paths.map { |path| File.join(path, "test.sh") }
21
18
  end
22
19
 
20
+ def directly
21
+ @directly.map(&method(:affected_component))
22
+ end
23
+
24
+ def transitively
25
+ @transitively.map(&method(:affected_component))
26
+ end
27
+
23
28
  def json_representation # rubocop:disable Metrics/MethodLength
24
29
  {
25
30
  changed_files: @changes,
26
- directly_affected_components: @directly,
27
- transitively_affected_components: @transitively,
31
+ directly_affected_components: directly,
32
+ transitively_affected_components: transitively,
28
33
  test_scripts: scripts,
29
34
  component_names: names,
30
35
  languages: {
@@ -39,46 +44,48 @@ module CobraCommander
39
44
  def run!
40
45
  @transitively = Set.new
41
46
  @directly = Set.new
42
- find_dependencies(@tree)
43
- @transitively.delete(name: UMBRELLA_APP_NAME, path: @path, type: @tree[:type])
44
- @transitively = @transitively.to_a.sort_by { |h| h[:name] }
45
- @directly = @directly.to_a.sort_by { |h| h[:name] }
47
+ @umbrella.components.each(&method(:add_if_changed))
48
+ @transitively = @transitively.sort_by(&:name)
49
+ @directly = @directly.sort_by(&:name)
46
50
  end
47
51
 
48
- def find_dependencies(parent_component)
49
- parent_component[:dependencies].each do |component|
50
- add_if_changed(component)
51
- find_dependencies(component)
52
- end
52
+ def add_if_changed(component)
53
+ return if component.root_paths.uniq.none? { |path| @changes.any?(Regexp.new(path)) }
54
+
55
+ @directly << component
56
+ @transitively.merge(component.deep_dependents)
53
57
  end
54
58
 
55
- def add_if_changed(component)
56
- @changes.each do |change|
57
- if change.start_with?(component[:path])
58
- @directly << component.reject { |k| k == :dependencies || k == :ancestry }
59
- @transitively.merge component[:ancestry]
60
- end
61
- end
59
+ def affected_component(component)
60
+ {
61
+ name: component.name,
62
+ path: component.root_paths,
63
+ type: component.sources.keys.map(&:to_s).map(&:capitalize).join(" & "),
64
+ }
62
65
  end
63
66
 
64
67
  def all_affected
65
- @all_affected ||= (@directly + @transitively).uniq.sort_by { |h| h[:path] }
68
+ @all_affected ||= (@directly | @transitively).sort_by(&:name)
66
69
  end
67
70
 
68
71
  def paths
69
- @paths ||= all_affected.map { |component| component[:path] }
72
+ @paths ||= all_affected.map(&:root_paths).flatten.uniq
70
73
  end
71
74
 
72
- def types
73
- @types ||= all_affected.map { |component| component[:type] }
75
+ def all_affected_sources
76
+ all_affected
77
+ .map(&:sources)
78
+ .map(&:keys)
79
+ .flatten
80
+ .uniq
74
81
  end
75
82
 
76
83
  def contains_ruby?
77
- types.uniq.join.include?("Ruby")
84
+ all_affected_sources.include?(:bundler)
78
85
  end
79
86
 
80
87
  def contains_js?
81
- types.uniq.join.include?("JS")
88
+ all_affected_sources.include?(:yarn)
82
89
  end
83
90
  end
84
91
  end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "cobra_commander/component_tree"
4
3
  require "cobra_commander/affected"
5
4
  require "open3"
6
5
 
@@ -9,12 +8,12 @@ module CobraCommander
9
8
  class Change
10
9
  InvalidSelectionError = Class.new(StandardError)
11
10
 
12
- def initialize(path, results, branch)
13
- @root_dir = Dir.chdir(path) { `git rev-parse --show-toplevel`.chomp }
11
+ def initialize(umbrella, results, branch)
12
+ @root_dir = Dir.chdir(umbrella.path) { `git rev-parse --show-toplevel`.chomp }
14
13
  @results = results
15
14
  @branch = branch
16
- @tree = CobraCommander.umbrella_tree(path).to_h
17
- @affected = Affected.new(@tree, changes, path)
15
+ @umbrella = umbrella
16
+ @affected = Affected.new(@umbrella, changes)
18
17
  end
19
18
 
20
19
  def run!
@@ -86,8 +85,8 @@ module CobraCommander
86
85
  end
87
86
  end
88
87
 
89
- def display(component)
90
- "#{component[:name]} - #{component[:type]}"
88
+ def display(name:, type:, **)
89
+ "#{name} - #{type}"
91
90
  end
92
91
 
93
92
  def blank_line
@@ -1,62 +1,93 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "thor"
4
+ require "fileutils"
5
+
6
+ require "cobra_commander"
7
+ require "cobra_commander/affected"
8
+ require "cobra_commander/change"
9
+ require "cobra_commander/executor"
10
+ require "cobra_commander/output"
4
11
 
5
12
  module CobraCommander
6
13
  # Implements the tool's CLI
7
14
  class CLI < Thor
8
- desc "do [command]", "Executes the command in the context of each component in [app]"
9
- method_option :app, default: Dir.pwd, aliases: "-a", desc: "App path (default: CWD)"
10
- def do(command)
11
- tree = CobraCommander.umbrella_tree(options.app)
12
- executor = Executor.new(tree)
13
- executor.exec(command)
14
- end
15
-
16
- desc "ls [app_path]", "Prints tree of components for an app"
17
- method_option :app, default: Dir.pwd, aliases: "-a", desc: "App path (default: CWD)"
18
- method_option :format, default: "tree", aliases: "-f", desc: "Format (list or tree, default: list)"
19
- def ls(app_path = nil)
20
- Output.print(
21
- CobraCommander.umbrella_tree(app_path || options.app),
22
- options.format
23
- )
15
+ class_option :app, default: Dir.pwd, aliases: "-a", type: :string
16
+ class_option :js, default: false, type: :boolean, desc: "Consider only the JS dependency graph"
17
+ class_option :ruby, default: false, type: :boolean, desc: "Consider only the Ruby dependency graph"
18
+
19
+ desc "version", "Prints version"
20
+ def version
21
+ puts CobraCommander::VERSION
24
22
  end
25
23
 
26
- desc "dependents_of [component]", "Outputs count of components in [app] dependent on [component]"
27
- method_option :app, default: Dir.pwd, aliases: "-a", desc: "Path to the root app where the component is mounted"
28
- method_option :format, default: "count", aliases: "-f", desc: "count or list"
29
- def dependents_of(component)
30
- dependents = CobraCommander.umbrella_tree(options.app).dependents_of(component)
31
- puts "list" == options.format ? dependents.map(&:name) : dependents.size
24
+ desc "ls [component]", "Lists the components in the context of a given component or umbrella"
25
+ method_option :dependencies, type: :boolean, aliases: "-d",
26
+ desc: "Run the command on each dependency of a given component"
27
+ method_option :dependents, type: :boolean, aliases: "-D",
28
+ desc: "Run the command on each dependency of a given component"
29
+ method_option :total, type: :boolean, aliases: "-t", desc: "Prints the total count of components"
30
+ def ls(component = nil)
31
+ components = components_filtered(component)
32
+ puts options.total ? components.size : CobraCommander::Output::FlatList.new(components).to_s
32
33
  end
33
34
 
34
- desc "dependencies_of [component]", "Outputs a list of components that [component] depends on within [app] context"
35
- method_option :app, default: Dir.pwd, aliases: "-a", desc: "App path (default: CWD)"
36
- method_option :format, default: "list", aliases: "-f", desc: "Format (list or tree, default: list)"
37
- def dependencies_of(component)
38
- Output.print(
39
- CobraCommander.umbrella_tree(options.app).subtree(component),
40
- options.format
35
+ desc "exec [component] <command>", "Executes the command in the context of a given component or set of components. " \
36
+ "If no component is given executes the command in all components."
37
+ method_option :dependencies, type: :boolean, desc: "Run the command on each dependency of a given component"
38
+ method_option :dependents, type: :boolean, desc: "Run the command on each dependency of a given component"
39
+ def exec(command_or_component, command = nil)
40
+ CobraCommander::Executor.exec(
41
+ components_filtered(command && command_or_component),
42
+ command ? command : command_or_component
41
43
  )
42
44
  end
43
45
 
44
- desc "version", "Prints version"
45
- def version
46
- puts CobraCommander::VERSION
46
+ desc "tree [component]", "Prints the dependency tree of a given component or umbrella"
47
+ def tree(component = nil)
48
+ component = find_component(component)
49
+ puts CobraCommander::Output::AsciiTree.new(component).to_s
47
50
  end
48
51
 
49
- desc "graph APP_PATH [--format=FORMAT]", "Outputs graph"
50
- method_option :format, default: "png", aliases: "-f", desc: "Accepts png or dot"
51
- def graph(app_path)
52
- Graph.new(app_path, options.format).generate!
52
+ desc "graph [component]", "Outputs a graph of a given component or umbrella"
53
+ method_option :output, default: File.join(Dir.pwd, "output.png"), aliases: "-o",
54
+ desc: "Output file, accepts .png or .dot"
55
+ def graph(component = nil)
56
+ CobraCommander::Output::GraphViz.generate(
57
+ find_component(component),
58
+ options.output
59
+ )
60
+ puts "Graph generated at #{options.output}"
61
+ rescue ArgumentError => error
62
+ error error.message
53
63
  end
54
64
 
55
- desc "changes APP_PATH [--results=RESULTS] [--branch=BRANCH]", "Prints list of changed files"
65
+ desc "changes [--results=RESULTS] [--branch=BRANCH]", "Prints list of changed files"
56
66
  method_option :results, default: "test", aliases: "-r", desc: "Accepts test, full, name or json"
57
67
  method_option :branch, default: "master", aliases: "-b", desc: "Specified target to calculate against"
58
- def changes(app_path)
59
- Change.new(app_path, options.results, options.branch).run!
68
+ def changes
69
+ Change.new(umbrella, options.results, options.branch).run!
70
+ end
71
+
72
+ private
73
+
74
+ def umbrella
75
+ @umbrella ||= CobraCommander.umbrella(options.app, yarn: options.js, bundler: options.ruby)
76
+ end
77
+
78
+ def find_component(name)
79
+ return umbrella.root unless name
80
+
81
+ umbrella.find(name) || error("Component #{name} not found, try one of `cobra ls`") || exit(1)
82
+ end
83
+
84
+ def components_filtered(component_name)
85
+ return umbrella.components unless component_name
86
+ component = find_component(component_name)
87
+
88
+ return component.deep_dependencies if options.dependencies
89
+ return component.deep_dependents if options.dependents
90
+ [component]
60
91
  end
61
92
  end
62
93
  end