cobra_commander 0.14.0 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +4 -6
  3. data/.github/workflows/release.yml +1 -1
  4. data/.rubocop.yml +9 -16
  5. data/.rubocop_todo.yml +15 -0
  6. data/Rakefile +3 -2
  7. data/cobra_commander.gemspec +5 -4
  8. data/{CHANGELOG.md → docs/CHANGELOG.md} +8 -0
  9. data/{CODE_OF_CONDUCT.md → docs/CODE_OF_CONDUCT.md} +0 -0
  10. data/{README.md → docs/README.md} +31 -18
  11. data/gemfiles/bundler2.gemfile +1 -1
  12. data/lib/cobra_commander/affected.rb +8 -8
  13. data/lib/cobra_commander/change.rb +23 -32
  14. data/lib/cobra_commander/cli/filters.rb +25 -6
  15. data/lib/cobra_commander/cli.rb +12 -11
  16. data/lib/cobra_commander/component.rb +10 -8
  17. data/lib/cobra_commander/dependencies/bundler/package.rb +17 -0
  18. data/lib/cobra_commander/dependencies/bundler.rb +8 -6
  19. data/lib/cobra_commander/dependencies/yarn/package.rb +10 -27
  20. data/lib/cobra_commander/dependencies/yarn.rb +40 -0
  21. data/lib/cobra_commander/dependencies.rb +1 -1
  22. data/lib/cobra_commander/executor/concurrent.rb +2 -2
  23. data/lib/cobra_commander/executor/context.rb +1 -1
  24. data/lib/cobra_commander/executor.rb +1 -1
  25. data/lib/cobra_commander/git_changed.rb +41 -0
  26. data/lib/cobra_commander/output/ascii_tree.rb +4 -4
  27. data/lib/cobra_commander/output/graph_viz.rb +1 -1
  28. data/lib/cobra_commander/output/interactive_printer.rb +4 -4
  29. data/lib/cobra_commander/umbrella.rb +4 -14
  30. data/lib/cobra_commander/version.rb +1 -1
  31. data/lib/cobra_commander.rb +2 -2
  32. data/mkdocs.yml +8 -0
  33. data/portal.yml +12 -0
  34. metadata +36 -18
  35. data/lib/cobra_commander/dependencies/yarn/package_repo.rb +0 -32
  36. data/lib/cobra_commander/dependencies/yarn_workspace.rb +0 -55
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d3e2348a3ed7ceecd361b13fe0632bb5daa54a59652d4dd9eac5646c2ccc5878
4
- data.tar.gz: 49dc4f2937e87a8146c685d82d7d45fea82dd16e3e0b880ef9944c8ac0710b0c
3
+ metadata.gz: 4fe38b5cf9d55a71b6a24111018d90cbd624c4d6bd3a95a7313f9c7afbeb6e92
4
+ data.tar.gz: 4fe0c927cbc3b985c0153849ff48889511dd726e35ddf534dd723cf9c8d18501
5
5
  SHA512:
6
- metadata.gz: 2ca9041bfb43cbec99252e00f52e117d8e2f09778afc686f1b204c4ff2e5733841f10b727adc3e3c9f28b121d61dff6ef4c79745a9e7574eb9bc36c3dd6ee5a9
7
- data.tar.gz: befffb97f5743fce5066db00f5c434053bdebc275c12b74d95c3d33a375b8c9e6bf5e10fa186188a163f1f9c8fd91f01055d56c8880ee40815915878077aebc9
6
+ metadata.gz: e1d80dac7d927f2f6cf754d09f6aa731f95ac7279f49784f3c4d03f1d4373d17cd44edc67c30218af28cdf3957c3042ed683cbd899903fe4cdd568c4b061c116
7
+ data.tar.gz: f87bf50a8747adfc75617b3c55dabd11d1148bfe90587ed07c362d4fe0cfe9d30299889aab1b5fda6b3af4a8993cc26ce0381816d8585bc368fdf4876dee6013
@@ -10,8 +10,6 @@ jobs:
10
10
  fail-fast: false
11
11
  matrix:
12
12
  ruby:
13
- - "2.5"
14
- - "2.6"
15
13
  - "2.7"
16
14
  - "3.0"
17
15
  bundler:
@@ -20,7 +18,7 @@ jobs:
20
18
  env:
21
19
  BUNDLE_GEMFILE: gemfiles/bundler${{ matrix.bundler }}.gemfile
22
20
  steps:
23
- - uses: actions/checkout@v2
21
+ - uses: actions/checkout@v3
24
22
  - uses: ruby/setup-ruby@v1
25
23
  with:
26
24
  ruby-version: ${{ matrix.ruby }}
@@ -36,11 +34,11 @@ jobs:
36
34
  name: Lint Ruby
37
35
  runs-on: ubuntu-latest
38
36
  steps:
39
- - uses: actions/checkout@v2
37
+ - uses: actions/checkout@v3
40
38
  - uses: ruby/setup-ruby@v1
41
39
  with:
42
40
  ruby-version: 3.0
43
41
  - name: Bundle
44
42
  run: bundle
45
- - name: Run standard
46
- run: bundle exec rake standard
43
+ - name: Run Rubocop
44
+ run: bundle exec rubocop
@@ -10,7 +10,7 @@ jobs:
10
10
  build:
11
11
  runs-on: ubuntu-latest
12
12
  steps:
13
- - uses: actions/checkout@v2
13
+ - uses: actions/checkout@v3
14
14
  - name: Release Gem
15
15
  uses: cadwallion/publish-rubygems-action@master
16
16
  if: contains(github.ref, 'refs/tags/v')
data/.rubocop.yml CHANGED
@@ -1,20 +1,13 @@
1
- AllCops:
2
- TargetRubyVersion: 2.5
3
- NewCops: enable
1
+ inherit_from: .rubocop_todo.yml
4
2
 
5
- Metrics/BlockLength:
6
- Exclude:
7
- - spec/**/*.rb
8
- - cobra_commander.gemspec
3
+ require:
4
+ - rubocop-powerhome
9
5
 
10
- Layout/AccessModifierIndentation:
11
- EnforcedStyle: outdent
6
+ Rails:
7
+ Enabled: false
12
8
 
13
- Style/StringLiterals:
14
- EnforcedStyle: double_quotes
9
+ Gemspec/RequireMFA:
10
+ Enabled: false
15
11
 
16
- Style/TrailingCommaInArrayLiteral:
17
- EnforcedStyleForMultiline: consistent_comma
18
-
19
- Style/TrailingCommaInHashLiteral:
20
- EnforcedStyleForMultiline: consistent_comma
12
+ Style/ClassAndModuleChildren:
13
+ Enabled: false
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,15 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2022-08-09 19:10:45 UTC using RuboCop version 1.30.1.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 8
10
+ Performance/MethodObjectAsBlock:
11
+ Exclude:
12
+ - 'lib/cobra_commander/affected.rb'
13
+ - 'lib/cobra_commander/component.rb'
14
+ - 'lib/cobra_commander/dependencies/yarn_workspace.rb'
15
+ - 'lib/cobra_commander/output/interactive_printer.rb'
data/Rakefile CHANGED
@@ -1,9 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "bundler/gem_tasks"
4
- require "standard/rake"
4
+ require "rubocop/rake_task"
5
5
  require "rspec/core/rake_task"
6
6
 
7
7
  RSpec::Core::RakeTask.new(:spec)
8
+ RuboCop::RakeTask.new(:rubocop)
8
9
 
9
- task default: %i[spec standard]
10
+ task default: %i[spec rubocop]
@@ -10,16 +10,16 @@ Gem::Specification.new do |spec|
10
10
  spec.authors = [
11
11
  "Ben Langfeld",
12
12
  "Garett Arrowood",
13
- "Carlos Palhares"
13
+ "Carlos Palhares",
14
14
  ]
15
15
  spec.email = [
16
16
  "blangfeld@powerhrg.com",
17
17
  "garett.arrowood@powerhrg.com",
18
- "carlos.palhares@powerhrg.com"
18
+ "carlos.palhares@powerhrg.com",
19
19
  ]
20
20
  spec.summary = "Tools for working with Component Based Rails Apps"
21
21
  spec.description = <<~DESCRIPTION
22
- Tools for working with Component Based Rails Apps (see http://shageman.github.io/cbra.info/).
22
+ Tools for working with Component Based Rails Apps (see https://cbra.info).
23
23
  Includes tools for graphing the components of an app and their relationships, as well as selectively
24
24
  testing components based on changes made.
25
25
  DESCRIPTION
@@ -47,5 +47,6 @@ Gem::Specification.new do |spec|
47
47
  spec.add_development_dependency "pry"
48
48
  spec.add_development_dependency "rake", ">= 12.3.3"
49
49
  spec.add_development_dependency "rspec", "~> 3.5"
50
- spec.add_development_dependency "standard", ">= 1.3.0"
50
+ spec.add_development_dependency "rubocop", "1.30.1"
51
+ spec.add_development_dependency "rubocop-powerhome", ">= 0.5.0"
51
52
  end
@@ -2,6 +2,14 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## Version 0.15.0 - 2022-08-16
6
+
7
+ * Add `--affected` filter to `cobra ls` and `cobra exec`, to target all components affected by changes since given branch [#80](https://github.com/powerhome/cobra_commander/pull/80)
8
+ * Allows a comma separated list of components on `cobra ls` and `cobra exec` instead of a single component [#79](https://github.com/powerhome/cobra_commander/pull/79)
9
+ * Resolve YARN dependencies based on yarn workspaces info workspaceDependencies [#81](https://github.com/powerhome/cobra_commander/pull/81)
10
+ * Fix cbra.info links [#70](https://github.com/powerhome/cobra_commander/pull/70)
11
+ * Replace standardrb by rubocop-powerhome [#78](https://github.com/powerhome/cobra_commander/pull/78)
12
+
5
13
  ## Version 0.14.0 - 2021-11-24
6
14
 
7
15
  * Retain selection on Interactive Printer [#69](https://github.com/powerhome/cobra_commander/pull/69)
File without changes
@@ -5,7 +5,7 @@
5
5
  [![CI](https://github.com/powerhome/cobra_commander/actions/workflows/ci.yml/badge.svg)](https://github.com/powerhome/cobra_commander/actions/workflows/ci.yml)
6
6
  [![Maintainability](https://api.codeclimate.com/v1/badges/7fe0781c18f6923ab753/maintainability)](https://codeclimate.com/github/powerhome/cobra_commander/maintainability)
7
7
 
8
- Tools for working with Component Based Rails Apps (see https://cbra.info/). Includes tools for graphing both Ruby and Javascript components in an application and their relationships, as well as selectively testing components based on changes made.
8
+ Tools for working with Component Based Rails Apps (see https://cbra.info). Includes tools for graphing both Ruby and Javascript components in an application and their relationships, as well as selectively testing components based on changes made.
9
9
 
10
10
  ## Installation
11
11
 
@@ -28,16 +28,16 @@ Or install it yourself as:
28
28
  ```bash
29
29
  Commands:
30
30
  cobra changes [--results=RESULTS] [--branch=BRANCH] # Prints list of changed files
31
- 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.
31
+ cobra exec [components] <command> # Executes the command in the context of a given component or set thereof. Defaults to all components.
32
32
  cobra graph [component] # Outputs a graph of a given component or umbrella
33
33
  cobra help [COMMAND] # Describe available commands or one specific command
34
- cobra ls [component] # Lists the components in the context of a given component or umbrella
34
+ cobra ls [components] # Lists the components in the context of a given component or umbrella
35
35
  cobra tree [component] # Prints the dependency tree of a given component or umbrella
36
36
  cobra version # Prints version
37
37
 
38
38
  Options:
39
39
  -a, [--app=APP]
40
- # Default: /Users/chjunior/workspace/power/cobra_commander
40
+ # Default: /Users/me/myapp
41
41
  [--js], [--no-js] # Consider only the JS dependency graph
42
42
  [--ruby], [--no-ruby] # Consider only the Ruby dependency graph
43
43
  ```
@@ -45,7 +45,6 @@ Options:
45
45
  ### cobra changes
46
46
 
47
47
  ```sh
48
- ➜ nitro git:(nova/remove-cobra-commander) be cobra help changes
49
48
  Usage:
50
49
  cobra changes [--results=RESULTS] [--branch=BRANCH]
51
50
 
@@ -55,7 +54,7 @@ Options:
55
54
  -b, [--branch=BRANCH] # Specified target to calculate against
56
55
  # Default: master
57
56
  -a, [--app=APP]
58
- # Default: /Users/chjunior/workspace/power/nitro
57
+ # Default: /Users/me/myapp
59
58
  [--js], [--no-js] # Consider only the JS dependency graph
60
59
  [--ruby], [--no-ruby] # Consider only the Ruby dependency graph
61
60
 
@@ -66,17 +65,26 @@ Prints list of changed files
66
65
 
67
66
  ```sh
68
67
  Usage:
69
- cobra exec [component] <command>
68
+ cobra exec [components] <command>
69
+
70
+ [components] is all components by default, or a comma separated list of component names (no spaces between)
70
71
 
71
72
  Options:
72
- [--dependencies], [--no-dependencies] # Run the command on each dependency of a given component
73
- [--dependents], [--no-dependents] # Run the command on each dependency of a given component
73
+ [--affected=AFFECTED] # Components affected since given branch [default: main]
74
+ -d, [--dependencies], [--no-dependencies] # Run the command on each dependency of a given component
75
+ -D, [--dependents], [--no-dependents] # Run the command on each dependent of a given component
76
+ [--self], [--no-self] # Include the own component
77
+ # Default: true
78
+ -c, [--concurrency=N] # Max number of jobs to run concurrently
79
+ # Default: 5
80
+ -i, [--interactive], [--no-interactive] # Runs in interactive mode to allow the user to inspect the output of each component
81
+ # Default: true
74
82
  -a, [--app=APP]
75
- # Default: /Users/chjunior/workspace/power/cobra_commander
83
+ # Default: /Users/me/myapp
76
84
  [--js], [--no-js] # Consider only the JS dependency graph
77
85
  [--ruby], [--no-ruby] # Consider only the Ruby dependency graph
78
86
 
79
- 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.
87
+ Executes the command in the context of a given component or set thereof. Defaults to all components.
80
88
  ```
81
89
 
82
90
  ### cobra graph
@@ -87,9 +95,9 @@ Usage:
87
95
 
88
96
  Options:
89
97
  -o, [--output=OUTPUT] # Output file, accepts .png or .dot
90
- # Default: /Users/chjunior/workspace/power/cobra_commander/output.png
98
+ # Default: /Users/me/myapp/output.png
91
99
  -a, [--app=APP]
92
- # Default: /Users/chjunior/workspace/power/cobra_commander
100
+ # Default: /Users/me/myapp
93
101
  [--js], [--no-js] # Consider only the JS dependency graph
94
102
  [--ruby], [--no-ruby] # Consider only the Ruby dependency graph
95
103
 
@@ -100,14 +108,19 @@ Outputs a graph of a given component or umbrella
100
108
 
101
109
  ```sh
102
110
  Usage:
103
- cobra ls [component]
111
+ cobra ls [components]
112
+
113
+ [components] is all components by default, or a comma separated list of component names (no spaces between)
104
114
 
105
115
  Options:
106
- -d, [--dependencies], [--no-dependencies] # Run the command on each dependency of a given component
107
- -D, [--dependents], [--no-dependents] # Run the command on each dependency of a given component
116
+ [--affected=AFFECTED] # Components affected since given branch [default: main]
117
+ -d, [--dependencies], [--no-dependencies] # Lists all dependencies of a given component
118
+ -D, [--dependents], [--no-dependents] # Lists all dependents of a given component
119
+ [--self], [--no-self] # Include the own component
120
+ # Default: true
108
121
  -t, [--total], [--no-total] # Prints the total count of components
109
122
  -a, [--app=APP]
110
- # Default: /Users/chjunior/workspace/power/cobra_commander
123
+ # Default: /Users/me/myapp
111
124
  [--js], [--no-js] # Consider only the JS dependency graph
112
125
  [--ruby], [--no-ruby] # Consider only the Ruby dependency graph
113
126
 
@@ -122,7 +135,7 @@ Usage:
122
135
 
123
136
  Options:
124
137
  -a, [--app=APP]
125
- # Default: /Users/chjunior/workspace/power/cobra_commander
138
+ # Default: /Users/me/myapp
126
139
  [--js], [--no-js] # Consider only the JS dependency graph
127
140
  [--ruby], [--no-ruby] # Consider only the Ruby dependency graph
128
141
 
@@ -4,4 +4,4 @@ source "https://rubygems.org"
4
4
 
5
5
  gemspec path: "../"
6
6
 
7
- gem "bundler", "~> 2.2.11"
7
+ gem "bundler", "~> 2.3.5"
@@ -32,11 +32,11 @@ module CobraCommander
32
32
  transitively_affected_components: transitively,
33
33
  test_scripts: scripts,
34
34
  component_names: names,
35
- languages: {ruby: contains_ruby?, javascript: contains_js?}
35
+ languages: { ruby: contains_ruby?, javascript: contains_js? },
36
36
  }.to_json
37
37
  end
38
38
 
39
- private
39
+ private
40
40
 
41
41
  def run!
42
42
  @transitively = Set.new
@@ -65,7 +65,7 @@ module CobraCommander
65
65
  {
66
66
  name: component.name,
67
67
  path: component.root_paths,
68
- type: component.sources.keys.map(&:to_s).map(&:capitalize).join(" & ")
68
+ type: component.packages.keys.map(&:to_s).map(&:capitalize).join(" & "),
69
69
  }
70
70
  end
71
71
 
@@ -74,23 +74,23 @@ module CobraCommander
74
74
  end
75
75
 
76
76
  def paths
77
- @paths ||= all_affected.map(&:root_paths).flatten.uniq
77
+ @paths ||= all_affected.map(&:root_paths).flatten
78
78
  end
79
79
 
80
- def all_affected_sources
80
+ def all_affected_packages
81
81
  all_affected
82
- .map(&:sources)
82
+ .map(&:packages)
83
83
  .map(&:keys)
84
84
  .flatten
85
85
  .uniq
86
86
  end
87
87
 
88
88
  def contains_ruby?
89
- all_affected_sources.include?(:bundler)
89
+ all_affected_packages.include?(:bundler)
90
90
  end
91
91
 
92
92
  def contains_js?
93
- all_affected_sources.include?(:yarn)
93
+ all_affected_packages.include?(:yarn)
94
94
  end
95
95
  end
96
96
  end
@@ -1,34 +1,37 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "cobra_commander/git_changed"
3
4
  require "cobra_commander/affected"
4
- require "open3"
5
5
 
6
6
  module CobraCommander
7
7
  # Calculates and prints affected components & files
8
8
  class Change
9
9
  InvalidSelectionError = Class.new(StandardError)
10
10
 
11
- def initialize(umbrella, results, branch)
12
- @root_dir = Dir.chdir(umbrella.path) { `git rev-parse --show-toplevel`.chomp }
13
- @results = results
11
+ def initialize(umbrella, oformat, branch, changes: nil)
12
+ @format = oformat
14
13
  @branch = branch
15
14
  @umbrella = umbrella
16
- @affected = Affected.new(@umbrella, changes)
15
+ @changes = changes || GitChanged.new(umbrella.path, branch)
17
16
  end
18
17
 
19
18
  def run!
20
19
  assert_valid_result_choice
21
- if selected_result?("json")
22
- puts @affected.json_representation
20
+ if selected_format?("json")
21
+ puts affected.json_representation
23
22
  else
24
- show_full if selected_result?("full")
23
+ show_full if selected_format?("full")
25
24
  tests_to_run
26
25
  end
27
- rescue InvalidSelectionError => e
26
+ rescue GitChanged::InvalidSelectionError => e
28
27
  puts e.message
29
28
  end
30
29
 
31
- private
30
+ private
31
+
32
+ def affected
33
+ @affected ||= Affected.new(@umbrella, @changes)
34
+ end
32
35
 
33
36
  def show_full
34
37
  changes_since_last_commit
@@ -36,52 +39,40 @@ module CobraCommander
36
39
  transitively_affected_components
37
40
  end
38
41
 
39
- def changes
40
- @changes ||= begin
41
- diff, _, result = Dir.chdir(@root_dir) do
42
- Open3.capture3("git", "diff", "--name-only", @branch)
43
- end
44
-
45
- raise InvalidSelectionError, "Specified --branch could not be found" if result.exitstatus == 128
46
-
47
- diff.split("\n").map { |f| File.join(@root_dir, f) }
48
- end
49
- end
50
-
51
42
  def assert_valid_result_choice
52
- return if %w[test full name json].include?(@results)
43
+ return if %w[test full name json].include?(@format)
53
44
 
54
45
  raise InvalidSelectionError, "--results must be 'test', 'full', 'name' or 'json'"
55
46
  end
56
47
 
57
- def selected_result?(result)
58
- @results == result
48
+ def selected_format?(result)
49
+ @format == result
59
50
  end
60
51
 
61
52
  def changes_since_last_commit
62
53
  puts "<<< Changes since last commit on #{@branch} >>>"
63
- changes.each { |path| puts path }
54
+ puts(*@changes) if @changes.any?
64
55
  puts blank_line
65
56
  end
66
57
 
67
58
  def directly_affected_components
68
59
  puts "<<< Directly affected components >>>"
69
- @affected.directly.each { |component| puts display(**component) }
60
+ affected.directly.each { |component| puts display(**component) }
70
61
  puts blank_line
71
62
  end
72
63
 
73
64
  def transitively_affected_components
74
65
  puts "<<< Transitively affected components >>>"
75
- @affected.transitively.each { |component| puts display(**component) }
66
+ affected.transitively.each { |component| puts display(**component) }
76
67
  puts blank_line
77
68
  end
78
69
 
79
70
  def tests_to_run
80
- puts "<<< Test scripts to run >>>" if selected_result?("full")
81
- if selected_result?("name")
82
- @affected.names.each { |component_name| puts component_name }
71
+ puts "<<< Test scripts to run >>>" if selected_format?("full")
72
+ if selected_format?("name")
73
+ affected.names.each { |component_name| puts component_name }
83
74
  else
84
- @affected.scripts.each { |component_script| puts component_script }
75
+ affected.scripts.each { |component_script| puts component_script }
85
76
  end
86
77
  end
87
78
 
@@ -4,12 +4,13 @@ module CobraCommander
4
4
  # @private
5
5
  class CLI
6
6
  private_class_method def self.filter_options(dependents:, dependencies:)
7
+ method_option :affected, type: :string, desc: "Components affected since given branch [default: main]"
7
8
  method_option :dependencies, type: :boolean, aliases: "-d", desc: dependencies
8
9
  method_option :dependents, type: :boolean, aliases: "-D", desc: dependents
9
10
  method_option :self, type: :boolean, default: true, desc: "Include the own component"
10
11
  end
11
12
 
12
- private
13
+ private
13
14
 
14
15
  def find_component(name)
15
16
  return umbrella.root unless name
@@ -28,13 +29,31 @@ module CobraCommander
28
29
  []
29
30
  end
30
31
 
31
- def components_filtered(component_name)
32
- return umbrella.components unless component_name
32
+ def affected_by_changes(origin_branch)
33
+ changes = GitChanged.new(umbrella.path, origin_branch)
34
+ Affected.new(umbrella, changes).all_affected
35
+ end
33
36
 
37
+ def filter_component(component_name)
34
38
  component = find_component(component_name)
35
- components = options.self ? [component] : []
36
- components.concat component.deep_dependencies if options.dependencies
37
- components.concat component.deep_dependents if options.dependents
39
+ components = []
40
+ components << component if options.self
41
+ components += component.deep_dependencies if options.dependencies
42
+ components += component.deep_dependents if options.dependents
43
+ components
44
+ end
45
+
46
+ def filter_components(component_names)
47
+ component_names.reduce(Set.new) do |set, name|
48
+ set | filter_component(name)
49
+ end
50
+ end
51
+
52
+ protected
53
+
54
+ def components_filtered(names)
55
+ components = names ? filter_components(names.split(",")) : umbrella.components
56
+ components &= affected_by_changes(options.affected) if options.affected
38
57
  components
39
58
  end
40
59
  end
@@ -7,6 +7,7 @@ require "concurrent-ruby"
7
7
  require "cobra_commander"
8
8
  require "cobra_commander/affected"
9
9
  require "cobra_commander/change"
10
+ require "cobra_commander/git_changed"
10
11
  require "cobra_commander/executor"
11
12
  require "cobra_commander/output"
12
13
 
@@ -26,28 +27,28 @@ module CobraCommander
26
27
  puts CobraCommander::VERSION
27
28
  end
28
29
 
29
- desc "ls [component]", "Lists the components in the context of a given component or umbrella"
30
+ desc "ls [components]", "Lists the components in the context of a given component or umbrella"
30
31
  filter_options dependents: "Lists all dependents of a given component",
31
- dependencies: "Lists all dependencies of a given component"
32
+ dependencies: "Lists all dependencies of a given component"
32
33
  method_option :total, type: :boolean, aliases: "-t", desc: "Prints the total count of components"
33
- def ls(component = nil)
34
- components = components_filtered(component)
34
+ def ls(components = nil)
35
+ components = components_filtered(components)
35
36
  puts options.total ? components.size : CobraCommander::Output::FlatList.new(components).to_s
36
37
  end
37
38
 
38
- desc "exec [component] <command>", "Executes the command in the context of a given component or set thereof. " \
39
- "Defaults to all components."
39
+ desc "exec [components] <command>", "Executes the command in the context of a given component or set thereof. " \
40
+ "Defaults to all components."
40
41
  filter_options dependents: "Run the command on each dependent of a given component",
41
- dependencies: "Run the command on each dependency of a given component"
42
+ dependencies: "Run the command on each dependency of a given component"
42
43
  method_option :concurrency, type: :numeric, default: DEFAULT_CONCURRENCY, aliases: "-c",
43
44
  desc: "Max number of jobs to run concurrently"
44
45
  method_option :interactive, type: :boolean, default: true, aliases: "-i",
45
46
  desc: "Runs in interactive mode to allow the user to inspect the output of each " \
46
47
  "component"
47
- def exec(command_or_component, command = nil)
48
+ def exec(command_or_components, command = nil)
48
49
  results = CobraCommander::Executor.exec(
49
- components: components_filtered(command && command_or_component),
50
- command: command || command_or_component,
50
+ components: components_filtered(command && command_or_components),
51
+ command: command || command_or_components,
51
52
  concurrency: options.concurrency, status_output: $stderr
52
53
  )
53
54
  if options.interactive && results.size > 1
@@ -83,7 +84,7 @@ module CobraCommander
83
84
  Change.new(umbrella, options.results, options.branch).run!
84
85
  end
85
86
 
86
- private
87
+ private
87
88
 
88
89
  def umbrella
89
90
  @umbrella ||= CobraCommander.umbrella(options.app, yarn: options.js, bundler: options.ruby)
@@ -3,22 +3,24 @@
3
3
  module CobraCommander
4
4
  # Represents a component withing an Umbrella
5
5
  class Component
6
- attr_reader :name, :sources
6
+ attr_reader :name, :packages
7
7
 
8
8
  def initialize(umbrella, name)
9
9
  @umbrella = umbrella
10
10
  @name = name
11
11
  @dependency_names = []
12
- @sources = {}
12
+ @packages = {}
13
13
  end
14
14
 
15
- def add_source(key, path, dependency_names)
16
- @sources[key] = path
17
- @dependency_names |= dependency_names
15
+ def add_package(key, package)
16
+ @packages[key] = package
17
+ @dependency_names |= package.dependencies
18
18
  end
19
19
 
20
20
  def root_paths
21
- @sources.values.map(&File.method(:dirname)).uniq
21
+ @packages.values.map do |package|
22
+ File.dirname(package.path)
23
+ end.uniq
22
24
  end
23
25
 
24
26
  def inspect
@@ -45,8 +47,8 @@ module CobraCommander
45
47
 
46
48
  def dependencies
47
49
  @dependencies ||= @dependency_names.sort
48
- .map(&@umbrella.method(:find))
49
- .compact
50
+ .map(&@umbrella.method(:find))
51
+ .compact
50
52
  end
51
53
  end
52
54
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CobraCommander
4
+ module Dependencies
5
+ # Calculates ruby bundler dependencies
6
+ class Bundler::Package
7
+ attr_reader :path, :name, :dependencies
8
+
9
+ def initialize(spec = nil, path: spec&.loaded_from, name: spec&.name, dependencies: spec&.dependencies)
10
+ @spec = spec
11
+ @path = path
12
+ @name = name
13
+ @dependencies = dependencies&.map(&:name)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -8,6 +8,8 @@ module CobraCommander
8
8
  module Dependencies
9
9
  # Calculates ruby bundler dependencies
10
10
  class Bundler
11
+ autoload :Package, "cobra_commander/dependencies/bundler/package"
12
+
11
13
  attr_reader :path
12
14
 
13
15
  def initialize(root)
@@ -15,17 +17,17 @@ module CobraCommander
15
17
  @path = @root.join("Gemfile.lock").realpath
16
18
  end
17
19
 
18
- def dependencies
19
- lockfile.dependencies.values.map(&:name)
20
+ def root
21
+ Package.new(path: path, dependencies: lockfile.dependencies.values)
20
22
  end
21
23
 
22
- def components
23
- components_source.specs.map do |spec|
24
- {path: spec.loaded_from, name: spec.name, dependencies: spec.dependencies.map(&:name)}
24
+ def packages
25
+ @packages ||= components_source.specs.map do |spec|
26
+ Package.new(spec)
25
27
  end
26
28
  end
27
29
 
28
- private
30
+ private
29
31
 
30
32
  def lockfile
31
33
  @lockfile ||= ::Bundler::LockfileParser.new(::Bundler.read_file(path))
@@ -1,37 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "json"
4
- require "pathname"
5
-
6
3
  module CobraCommander
7
4
  module Dependencies
8
- module Yarn
9
- # Represents an Yarn package.json file
10
- class Package
11
- attr_reader :path
12
-
13
- def initialize(path)
14
- @path = ::Pathname.new(File.join(path, "package.json")).realpath
15
- end
16
-
17
- def project_tag
18
- name.match(%r{^@[\w-]+/}).to_s
19
- end
5
+ class Yarn::Package
6
+ attr_reader :path, :name, :dependencies
20
7
 
21
- def name
22
- json["name"]
23
- end
24
-
25
- def dependencies
26
- json.fetch("dependencies", {})
27
- .merge(json.fetch("devDependencies", {}))
28
- end
8
+ def initialize(path:, dependencies:, name: nil)
9
+ @path = path
10
+ @name = untag(name)
11
+ @dependencies = dependencies.map { |dep| untag(dep) }
12
+ end
29
13
 
30
- private
14
+ private
31
15
 
32
- def json
33
- @json ||= JSON.parse(File.read(@path))
34
- end
16
+ def untag(name)
17
+ name&.gsub(%r{^@[\w-]+/}, "")
35
18
  end
36
19
  end
37
20
  end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+ require "open3"
5
+ require "pathname"
6
+
7
+ module CobraCommander
8
+ module Dependencies
9
+ # Yarn workspace components source for an umbrella
10
+ class Yarn
11
+ PACKAGE_FILE = "package.json"
12
+
13
+ autoload :Package, "cobra_commander/dependencies/yarn/package"
14
+
15
+ def initialize(root_path)
16
+ @root_path = Pathname.new(root_path)
17
+ end
18
+
19
+ def root
20
+ @root ||= Package.new(
21
+ path: @root_path.join(PACKAGE_FILE).realpath,
22
+ dependencies: packages.map(&:name)
23
+ )
24
+ end
25
+
26
+ def packages
27
+ @packages ||= begin
28
+ output, = Open3.capture2("yarn workspaces --json info", chdir: @root_path.to_s)
29
+ JSON.parse(JSON.parse(output)["data"]).map do |name, spec|
30
+ Package.new(
31
+ path: @root_path.join(spec["location"], PACKAGE_FILE).realpath,
32
+ dependencies: spec["workspaceDependencies"],
33
+ name: name
34
+ )
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "dependencies/yarn_workspace"
3
+ require_relative "dependencies/yarn"
4
4
  require_relative "dependencies/bundler"
@@ -23,7 +23,7 @@ module CobraCommander
23
23
  @results
24
24
  end
25
25
 
26
- private
26
+ private
27
27
 
28
28
  def pastel
29
29
  @pastel ||= Pastel.new
@@ -33,7 +33,7 @@ module CobraCommander
33
33
  @spinner_options ||= {
34
34
  format: :bouncing,
35
35
  success_mark: pastel.green("[DONE]"),
36
- error_mark: pastel.red("[ERROR]")
36
+ error_mark: pastel.red("[ERROR]"),
37
37
  }
38
38
  end
39
39
 
@@ -35,7 +35,7 @@ module CobraCommander
35
35
  results.join("\n")
36
36
  end
37
37
 
38
- private
38
+ private
39
39
 
40
40
  def isolate_bundle(&block)
41
41
  if Bundler.respond_to?(:with_unbundled_env)
@@ -8,7 +8,7 @@ module CobraCommander
8
8
  module Executor
9
9
  def self.exec(components:, command:, concurrency:, status_output:)
10
10
  Concurrent.new(components, concurrency: concurrency, spin_output: status_output)
11
- .exec(command)
11
+ .exec(command)
12
12
  end
13
13
  end
14
14
  end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "open3"
4
+
5
+ module CobraCommander
6
+ # List of files changed in a git repository in the current branch in relation
7
+ # to the give base branch
8
+ #
9
+ # @private
10
+ #
11
+ class GitChanged
12
+ include Enumerable
13
+
14
+ InvalidSelectionError = Class.new(StandardError)
15
+
16
+ def initialize(repo_root, base_branch)
17
+ @repo_root = repo_root
18
+ @base_branch = base_branch
19
+ end
20
+
21
+ def each(&block)
22
+ changes.each(&block)
23
+ end
24
+
25
+ private
26
+
27
+ def changes
28
+ @changes ||= begin
29
+ diff, _, result = Dir.chdir(@repo_root) do
30
+ Open3.capture3("git", "diff", "--name-only", @base_branch)
31
+ end
32
+
33
+ raise InvalidSelectionError, "Specified branch #{@base_branch} could not be found" if result.exitstatus == 128
34
+
35
+ diff.split("\n").map do |f|
36
+ File.join(@repo_root, f)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -22,7 +22,7 @@ module CobraCommander
22
22
  end.string
23
23
  end
24
24
 
25
- private
25
+ private
26
26
 
27
27
  def list_dependencies(io, component, outdents = [])
28
28
  component.dependencies.each do |dep|
@@ -32,10 +32,10 @@ module CobraCommander
32
32
  end
33
33
 
34
34
  def decide_on_line(io, parent, dep, outdents)
35
- if parent.dependencies.last != dep
36
- add_tee(io, outdents, dep)
37
- else
35
+ if parent.dependencies.last == dep
38
36
  add_corner(io, outdents, dep)
37
+ else
38
+ add_tee(io, outdents, dep)
39
39
  end
40
40
  end
41
41
 
@@ -17,7 +17,7 @@ module CobraCommander
17
17
  end
18
18
 
19
19
  private_class_method def self.extract_format(output)
20
- format = output[-3..-1] # standard:disable Style/SlicingWithRange
20
+ format = output[-3..]
21
21
  return format if %w[png dot].include?(format)
22
22
 
23
23
  raise ArgumentError, "output format must be 'png' or 'dot'"
@@ -8,8 +8,8 @@ module CobraCommander
8
8
  # Runs an interactive output printer
9
9
  class InteractivePrinter
10
10
  pastel = Pastel.new
11
- SUCCESS = "#{pastel.green("")} %s"
12
- ERROR = "#{pastel.red("")} %s"
11
+ SUCCESS = "#{pastel.green('')} %s"
12
+ ERROR = "#{pastel.red('')} %s"
13
13
  BYE = pastel.decorate("\n\n👋 Bye!", :white, :on_black, :bold).freeze
14
14
 
15
15
  def self.run(contexts, output)
@@ -31,11 +31,11 @@ module CobraCommander
31
31
  output.puts BYE
32
32
  end
33
33
 
34
- private
34
+ private
35
35
 
36
36
  def map_options(contexts)
37
37
  contexts.sort(&method(:sort_contexts))
38
- .reduce({}) do |options, context|
38
+ .reduce({}) do |options, context|
39
39
  template = context.success? ? SUCCESS : ERROR
40
40
  options.merge format(template, context.component_name) => context
41
41
  end
@@ -28,25 +28,15 @@ module CobraCommander
28
28
  end
29
29
 
30
30
  def add_source(key, source)
31
- @root_component.add_source key, source.path, source.dependencies
32
- source.components.each do |component|
33
- @components[component[:name]] ||= Component.new(self, component[:name])
34
- @components[component[:name]].add_source key, component[:path], component[:dependencies]
31
+ @root_component.add_package key, source.root
32
+ source.packages.each do |packages|
33
+ @components[packages.name] ||= Component.new(self, packages.name)
34
+ @components[packages.name].add_package key, packages
35
35
  end
36
36
  end
37
37
 
38
38
  def components
39
39
  @components.values
40
40
  end
41
-
42
- def dependents_of(component)
43
- find(component)&.deep_dependents
44
- &.sort_by(&:name)
45
- end
46
-
47
- def dependencies_of(name)
48
- find(name)&.deep_dependencies
49
- &.sort_by(&:name)
50
- end
51
41
  end
52
42
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CobraCommander
4
- VERSION = "0.14.0"
4
+ VERSION = "0.15.0"
5
5
  end
@@ -5,7 +5,7 @@ require "cobra_commander/component"
5
5
  require "cobra_commander/umbrella"
6
6
  require "cobra_commander/version"
7
7
 
8
- # Tools for working with Component Based Rails Apps (see http://shageman.github.io/cbra.info/).
8
+ # Tools for working with Component Based Rails Apps (see https://cbra.info).
9
9
  # Includes tools for graphing the components of an app and their relationships, as well as selectively
10
10
  # testing components based on changes made.
11
11
  module CobraCommander
@@ -13,7 +13,7 @@ module CobraCommander
13
13
 
14
14
  def self.umbrella(root_path, yarn: false, bundler: false, name: UMBRELLA_APP_NAME)
15
15
  umbrella = Umbrella.new(name, root_path)
16
- umbrella.add_source(:yarn, Dependencies::YarnWorkspace.new(root_path)) unless bundler
16
+ umbrella.add_source(:yarn, Dependencies::Yarn.new(root_path)) unless bundler
17
17
  umbrella.add_source(:bundler, Dependencies::Bundler.new(root_path)) unless yarn
18
18
  umbrella
19
19
  end
data/mkdocs.yml ADDED
@@ -0,0 +1,8 @@
1
+ site_name: Cobra Commander
2
+ site_description: Cobra Commander Documentation
3
+ nav:
4
+ - "Home": "README.md"
5
+ - "Changelog": "CHANGELOG.md"
6
+ - "Code of Conduct": "CODE_OF_CONDUCT.md"
7
+ plugins:
8
+ - techdocs-core
data/portal.yml ADDED
@@ -0,0 +1,12 @@
1
+ apiVersion: backstage.io/v1alpha1
2
+ kind: Component
3
+ metadata:
4
+ name: cobra-commander
5
+ title: Cobra Commander
6
+ description: Tools for working with Component Based Rails Apps
7
+ annotations:
8
+ backstage.io/techdocs-ref: dir:.
9
+ spec:
10
+ type: library
11
+ owner: heroes-for-hire
12
+ lifecycle: production
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cobra_commander
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.0
4
+ version: 0.15.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Langfeld
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2021-11-24 00:00:00.000000000 Z
13
+ date: 2022-08-17 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
@@ -58,22 +58,22 @@ dependencies:
58
58
  name: thor
59
59
  requirement: !ruby/object:Gem::Requirement
60
60
  requirements:
61
- - - ">="
62
- - !ruby/object:Gem::Version
63
- version: 0.18.1
64
61
  - - "<"
65
62
  - !ruby/object:Gem::Version
66
63
  version: '2.0'
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: 0.18.1
67
67
  type: :runtime
68
68
  prerelease: false
69
69
  version_requirements: !ruby/object:Gem::Requirement
70
70
  requirements:
71
- - - ">="
72
- - !ruby/object:Gem::Version
73
- version: 0.18.1
74
71
  - - "<"
75
72
  - !ruby/object:Gem::Version
76
73
  version: '2.0'
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: 0.18.1
77
77
  - !ruby/object:Gem::Dependency
78
78
  name: tty-command
79
79
  requirement: !ruby/object:Gem::Requirement
@@ -201,21 +201,35 @@ dependencies:
201
201
  - !ruby/object:Gem::Version
202
202
  version: '3.5'
203
203
  - !ruby/object:Gem::Dependency
204
- name: standard
204
+ name: rubocop
205
+ requirement: !ruby/object:Gem::Requirement
206
+ requirements:
207
+ - - '='
208
+ - !ruby/object:Gem::Version
209
+ version: 1.30.1
210
+ type: :development
211
+ prerelease: false
212
+ version_requirements: !ruby/object:Gem::Requirement
213
+ requirements:
214
+ - - '='
215
+ - !ruby/object:Gem::Version
216
+ version: 1.30.1
217
+ - !ruby/object:Gem::Dependency
218
+ name: rubocop-powerhome
205
219
  requirement: !ruby/object:Gem::Requirement
206
220
  requirements:
207
221
  - - ">="
208
222
  - !ruby/object:Gem::Version
209
- version: 1.3.0
223
+ version: 0.5.0
210
224
  type: :development
211
225
  prerelease: false
212
226
  version_requirements: !ruby/object:Gem::Requirement
213
227
  requirements:
214
228
  - - ">="
215
229
  - !ruby/object:Gem::Version
216
- version: 1.3.0
230
+ version: 0.5.0
217
231
  description: |
218
- Tools for working with Component Based Rails Apps (see http://shageman.github.io/cbra.info/).
232
+ Tools for working with Component Based Rails Apps (see https://cbra.info).
219
233
  Includes tools for graphing the components of an app and their relationships, as well as selectively
220
234
  testing components based on changes made.
221
235
  email:
@@ -233,17 +247,18 @@ files:
233
247
  - ".gitignore"
234
248
  - ".rspec"
235
249
  - ".rubocop.yml"
236
- - CHANGELOG.md
237
- - CODE_OF_CONDUCT.md
250
+ - ".rubocop_todo.yml"
238
251
  - Gemfile
239
252
  - Guardfile
240
253
  - LICENSE.txt
241
- - README.md
242
254
  - Rakefile
243
255
  - _config.yml
244
256
  - bin/console
245
257
  - bin/setup
246
258
  - cobra_commander.gemspec
259
+ - docs/CHANGELOG.md
260
+ - docs/CODE_OF_CONDUCT.md
261
+ - docs/README.md
247
262
  - exe/cobra
248
263
  - gemfiles/bundler1.gemfile
249
264
  - gemfiles/bundler2.gemfile
@@ -255,12 +270,13 @@ files:
255
270
  - lib/cobra_commander/component.rb
256
271
  - lib/cobra_commander/dependencies.rb
257
272
  - lib/cobra_commander/dependencies/bundler.rb
273
+ - lib/cobra_commander/dependencies/bundler/package.rb
274
+ - lib/cobra_commander/dependencies/yarn.rb
258
275
  - lib/cobra_commander/dependencies/yarn/package.rb
259
- - lib/cobra_commander/dependencies/yarn/package_repo.rb
260
- - lib/cobra_commander/dependencies/yarn_workspace.rb
261
276
  - lib/cobra_commander/executor.rb
262
277
  - lib/cobra_commander/executor/concurrent.rb
263
278
  - lib/cobra_commander/executor/context.rb
279
+ - lib/cobra_commander/git_changed.rb
264
280
  - lib/cobra_commander/output.rb
265
281
  - lib/cobra_commander/output/ascii_tree.rb
266
282
  - lib/cobra_commander/output/flat_list.rb
@@ -269,6 +285,8 @@ files:
269
285
  - lib/cobra_commander/output/markdown_printer.rb
270
286
  - lib/cobra_commander/umbrella.rb
271
287
  - lib/cobra_commander/version.rb
288
+ - mkdocs.yml
289
+ - portal.yml
272
290
  - renovate.json
273
291
  homepage: http://tech.powerhrg.com/cobra_commander/
274
292
  licenses:
@@ -289,7 +307,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
289
307
  - !ruby/object:Gem::Version
290
308
  version: '0'
291
309
  requirements: []
292
- rubygems_version: 3.0.3
310
+ rubygems_version: 3.3.7
293
311
  signing_key:
294
312
  specification_version: 4
295
313
  summary: Tools for working with Component Based Rails Apps
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module CobraCommander
4
- module Dependencies
5
- module Yarn
6
- # Yarn package repository to load and cache package.json files
7
- class PackageRepo
8
- def initialize
9
- @specs = {}
10
- end
11
-
12
- def specs
13
- @specs.values
14
- end
15
-
16
- def load_linked_specs(package)
17
- package.dependencies.each_value do |spec|
18
- next unless spec =~ /link:(.+)/
19
-
20
- load_spec(File.join(package.path, "..", Regexp.last_match(1)))
21
- end
22
- end
23
-
24
- def load_spec(path)
25
- @specs[path] ||= Package.new(path).tap do |package|
26
- load_linked_specs(package)
27
- end
28
- end
29
- end
30
- end
31
- end
32
- end
@@ -1,55 +0,0 @@
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