geet 0.2.1 → 0.3.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
  SHA1:
3
- metadata.gz: 810fe20ea861a01c88e0cad7fc14bfbb92ee7bf1
4
- data.tar.gz: 6aebe64e41a3fc69e6e6e8628d1d3d4bf74a2723
3
+ metadata.gz: 37b511c318e9f2cb1c18ecf1a1f247236c841040
4
+ data.tar.gz: 61aeabbdbd6e3616e49247acf47ffbbbf18d8085
5
5
  SHA512:
6
- metadata.gz: 37d3ef70153f9ff4fa010c3e28883e4e3f5d1ba896e737c6f6597cdfceb9d8e986ab5f1c5cdf2d5c4f1dd179bd1a871e0edf6cf89f98b655b3ab83ca890f5329
7
- data.tar.gz: c76276bb1bf6d9147e17fa92eb49baca3cd7f96a90a3c1786b4b6c60964ab24c6daca1df5e1a7164f69f3bebe09cb3683de26c1498b538b1c8f243a8575680d9
6
+ metadata.gz: 6692e7597431f0d0ef9d194030086112985f7f1f2e4e0b6b8caf3c6dbeea565fd3d22b7b0033cf3290bf156e6f331e4e70ea6b3cf3be962e45110aa32ffdf05c
7
+ data.tar.gz: e57f240a2c9a3b0ecb65a874efa7f3c4c61e0102cd365c7a53ac6b2579367c37c95dae072014f33ac5d6077ca75df649aff0dd4e7912a92502503e5a6a0e554e
data/Gemfile CHANGED
@@ -5,6 +5,7 @@ source 'https://rubygems.org'
5
5
  git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
6
6
 
7
7
  gem 'simple_scripting', '~> 0.9.3'
8
+ gem 'temp-fork-tp-filter', '= 0.0.3'
8
9
 
9
10
  group :development, :test do
10
11
  gem 'byebug', '~> 9.1.0'
@@ -8,11 +8,17 @@ GEM
8
8
  crack (0.4.3)
9
9
  safe_yaml (~> 1.0.0)
10
10
  diff-lcs (1.3)
11
+ equatable (0.5.0)
11
12
  hashdiff (0.3.7)
13
+ hitimes (1.2.6)
14
+ necromancer (0.4.0)
12
15
  parallel (1.12.1)
13
16
  parseconfig (1.0.8)
14
17
  parser (2.4.0.2)
15
18
  ast (~> 2.3)
19
+ pastel (0.7.2)
20
+ equatable (~> 0.5.0)
21
+ tty-color (~> 0.4.0)
16
22
  powerpack (0.1.1)
17
23
  public_suffix (3.0.1)
18
24
  rainbow (3.0.0)
@@ -41,12 +47,28 @@ GEM
41
47
  safe_yaml (1.0.4)
42
48
  simple_scripting (0.9.3)
43
49
  parseconfig (~> 1.0)
50
+ temp-fork-tp-filter (0.0.3)
51
+ necromancer (~> 0.4.0)
52
+ pastel (~> 0.7.0)
53
+ timers (~> 4.1.2)
54
+ tty-cursor (~> 0.5.0)
55
+ tty-reader (~> 0.2.0)
56
+ timers (4.1.2)
57
+ hitimes
58
+ tty-color (0.4.2)
59
+ tty-cursor (0.5.0)
60
+ tty-reader (0.2.0)
61
+ tty-cursor (~> 0.5.0)
62
+ tty-screen (~> 0.6.4)
63
+ wisper (~> 2.0.0)
64
+ tty-screen (0.6.4)
44
65
  unicode-display_width (1.3.0)
45
66
  vcr (3.0.3)
46
67
  webmock (3.1.1)
47
68
  addressable (>= 2.3.6)
48
69
  crack (>= 0.3.2)
49
70
  hashdiff
71
+ wisper (2.0.0)
50
72
 
51
73
  PLATFORMS
52
74
  ruby
@@ -57,8 +79,9 @@ DEPENDENCIES
57
79
  rspec (~> 3.7.0)
58
80
  rubocop (~> 0.52.0)
59
81
  simple_scripting (~> 0.9.3)
82
+ temp-fork-tp-filter (= 0.0.3)
60
83
  vcr (~> 3.0.3)
61
84
  webmock (~> 3.1.1)
62
85
 
63
86
  BUNDLED WITH
64
- 1.16.0.pre.3
87
+ 1.16.1
@@ -10,7 +10,7 @@ Gem::Specification.new do |s|
10
10
  s.platform = Gem::Platform::RUBY
11
11
  s.required_ruby_version = '>= 2.3.0'
12
12
  s.authors = ['Saverio Miroddi']
13
- s.date = '2018-01-14'
13
+ s.date = '2018-01-19'
14
14
  s.email = ['saverio.pub2@gmail.com']
15
15
  s.homepage = 'https://github.com/saveriomiroddi/geet'
16
16
  s.summary = 'Commandline interface for performing SCM (eg. GitHub) operations (eg. PR creation).'
@@ -18,6 +18,7 @@ Gem::Specification.new do |s|
18
18
  s.license = 'GPL-3.0'
19
19
 
20
20
  s.add_runtime_dependency 'simple_scripting', '~> 0.9.3'
21
+ s.add_runtime_dependency 'temp-fork-tp-filter', '= 0.0.3'
21
22
 
22
23
  s.files = `git ls-files`.split("\n")
23
24
  s.executables << 'geet'
@@ -23,7 +23,7 @@ module Geet
23
23
  ISSUE_CREATE_OPTIONS = [
24
24
  ['-n', '--no-open-issue', "Don't open the issue link in the browser after creation"],
25
25
  ['-l', '--label-patterns "bug,help wanted"', 'Label patterns'],
26
- ['-m', '--milestone number_or_pattern', 'Milestone number or description pattern'],
26
+ ['-m', '--milestone 1.5.0', 'Milestone title pattern'],
27
27
  ['-a', '--assignee-patterns john,tom,adrian,kevin', 'Assignee login patterns. Defaults to authenticated user'],
28
28
  ['-u', '--upstream', 'Create on the upstream repository'],
29
29
  long_help: 'The default editor will be opened for editing title and description.'
@@ -46,7 +46,7 @@ module Geet
46
46
  PR_CREATE_OPTIONS = [
47
47
  ['-n', '--no-open-pr', "Don't open the PR link in the browser after creation"],
48
48
  ['-l', '--label-patterns "legacy,code review"', 'Label patterns'],
49
- ['-m', '--milestone number_or_pattern', 'Milestone number or description pattern'],
49
+ ['-m', '--milestone 1.5.0', 'Milestone title pattern'],
50
50
  ['-r', '--reviewer-patterns john,tom,adrian,kevin', 'Reviewer login patterns'],
51
51
  ['-u', '--upstream', 'Create on the upstream repository'],
52
52
  long_help: 'The default editor will be opened for editing title and description; if the PR adds one commit only, '\
@@ -1,12 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative '../helpers/os_helper.rb'
4
+ require_relative '../utils/manual_list_selection.rb'
5
+ require_relative '../utils/pattern_matching_selection.rb'
4
6
 
5
7
  module Geet
6
8
  module Services
7
9
  class CreateIssue
8
10
  include Geet::Helpers::OsHelper
9
11
 
12
+ MANUAL_LIST_SELECTION_FLAG = '-'.freeze
13
+
10
14
  # options:
11
15
  # :label_patterns
12
16
  # :milestone_pattern: number or description pattern.
@@ -18,30 +22,17 @@ module Geet
18
22
  label_patterns: nil, milestone_pattern: nil, assignee_patterns: nil, no_open_issue: nil,
19
23
  output: $stdout, **
20
24
  )
21
- labels_thread = select_labels(repository, label_patterns, output) if label_patterns
22
- milestone_thread = find_milestone(repository, milestone_pattern, output) if milestone_pattern
23
- assignees_thread = select_assignees(repository, assignee_patterns, output) if assignee_patterns
25
+ all_labels, all_milestones, all_collaborators = find_all_attribute_entries(
26
+ repository, label_patterns, milestone_pattern, assignee_patterns, output
27
+ )
24
28
 
25
- selected_labels = labels_thread&.join&.value
26
- assignees = assignees_thread&.join&.value
27
- milestone = milestone_thread&.join&.value
29
+ labels = select_entries('label', all_labels, label_patterns, :multiple, :name) if label_patterns
30
+ milestone, _ = select_entries('milestone', all_milestones, milestone_pattern, :single, :title) if milestone_pattern
31
+ assignees = select_entries('collaborator', all_collaborators, assignee_patterns, :multiple, nil) if assignee_patterns
28
32
 
29
- output.puts 'Creating the issue...'
33
+ issue = create_issue(repository, title, description, output)
30
34
 
31
- issue = repository.create_issue(title, description)
32
-
33
- add_labels_thread = add_labels(issue, selected_labels, output) if selected_labels
34
- set_milestone_thread = set_milestone(issue, milestone, output) if milestone
35
-
36
- if assignees
37
- assign_users_thread = assign_users(issue, assignees, output)
38
- else
39
- assign_users_thread = assign_authenticated_user(repository, issue, output)
40
- end
41
-
42
- add_labels_thread&.join
43
- set_milestone_thread&.join
44
- assign_users_thread.join
35
+ edit_issue(repository, issue, labels, milestone, assignees, output)
45
36
 
46
37
  if no_open_issue
47
38
  output.puts "Issue address: #{issue.link}"
@@ -56,38 +47,48 @@ module Geet
56
47
 
57
48
  # Internal actions
58
49
 
59
- def select_labels(repository, label_patterns, output)
60
- output.puts 'Finding labels...'
61
-
62
- Thread.new do
63
- all_labels = repository.labels
50
+ def find_all_attribute_entries(repository, label_patterns, milestone_pattern, assignee_patterns, output)
51
+ if label_patterns
52
+ output.puts 'Finding labels...'
53
+ labels_thread = Thread.new { repository.labels }
54
+ end
64
55
 
65
- select_entries(all_labels, label_patterns, type: 'labels', instance_method: :name)
56
+ if milestone_pattern
57
+ output.puts 'Finding milestone...'
58
+ milestone_thread = Thread.new { repository.milestones }
66
59
  end
67
- end
68
60
 
69
- def find_milestone(repository, milestone_pattern, output)
70
- output.puts 'Finding milestone...'
61
+ if assignee_patterns
62
+ output.puts 'Finding collaborators...'
63
+ reviewers_thread = Thread.new { repository.collaborators }
64
+ end
71
65
 
72
- Thread.new do
73
- if milestone_pattern =~ /\A\d+\Z/
74
- repository.milestone(milestone_pattern)
75
- else
76
- all_milestones = repository.milestones
66
+ labels = labels_thread&.value
67
+ milestones = milestone_thread&.value
68
+ reviewers = reviewers_thread&.value
77
69
 
78
- select_entries(all_milestones, milestone_pattern, type: 'milestones', instance_method: :title).first
79
- end
80
- end
70
+ [labels, milestones, reviewers]
81
71
  end
82
72
 
83
- def select_assignees(repository, assignee_patterns, output)
84
- output.puts 'Finding collaborators...'
73
+ def create_issue(repository, title, description, output)
74
+ output.puts 'Creating the issue...'
85
75
 
86
- Thread.new do
87
- all_collaborators = repository.collaborators
76
+ issue = repository.create_issue(title, description)
77
+ end
78
+
79
+ def edit_issue(repository, issue, labels, milestone, assignees, output)
80
+ add_labels_thread = add_labels(issue, labels, output) if labels
81
+ set_milestone_thread = set_milestone(issue, milestone, output) if milestone
88
82
 
89
- select_entries(all_collaborators, assignee_patterns, type: 'collaborators')
83
+ if assignees
84
+ assign_users_thread = assign_users(issue, assignees, output)
85
+ else
86
+ assign_users_thread = assign_authenticated_user(repository, issue, output)
90
87
  end
88
+
89
+ add_labels_thread&.join
90
+ set_milestone_thread&.join
91
+ assign_users_thread.join
91
92
  end
92
93
 
93
94
  def add_labels(issue, selected_labels, output)
@@ -126,23 +127,11 @@ module Geet
126
127
 
127
128
  # Generic helpers
128
129
 
129
- def select_entries(entries, raw_patterns, type: 'entries', instance_method: nil)
130
- patterns = raw_patterns.split(',')
131
-
132
- patterns.map do |pattern|
133
- entries_found = entries.select do |entry|
134
- entry = entry.send(instance_method) if instance_method
135
- entry =~ /#{pattern}/i
136
- end
137
-
138
- case entries_found.size
139
- when 1
140
- entries_found.first
141
- when 0
142
- raise "No #{type} found for pattern: #{pattern.inspect}"
143
- else
144
- raise "Multiple #{type} found for pattern #{pattern.inspect}: #{entries_found}"
145
- end
130
+ def select_entries(entry_type, entries, raw_patterns, selection_type, instance_method)
131
+ if raw_patterns == MANUAL_LIST_SELECTION_FLAG
132
+ Geet::Utils::ManualListSelection.new.select(entry_type, entries, selection_type, instance_method: instance_method)
133
+ else
134
+ Geet::Utils::PatternMatchingSelection.new.select(entry_type, entries, raw_patterns, instance_method: instance_method)
146
135
  end
147
136
  end
148
137
  end
@@ -1,12 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative '../helpers/os_helper.rb'
4
+ require_relative '../utils/manual_list_selection.rb'
5
+ require_relative '../utils/pattern_matching_selection.rb'
4
6
 
5
7
  module Geet
6
8
  module Services
7
9
  class CreatePr
8
10
  include Geet::Helpers::OsHelper
9
11
 
12
+ MANUAL_LIST_SELECTION_FLAG = '-'.freeze
13
+
10
14
  # options:
11
15
  # :label_patterns
12
16
  # :reviewer_patterns
@@ -16,25 +20,17 @@ module Geet
16
20
  repository, title, description, label_patterns: nil, milestone_pattern: nil, reviewer_patterns: nil,
17
21
  no_open_pr: nil, output: $stdout, **
18
22
  )
19
- labels_thread = select_labels(repository, label_patterns, output) if label_patterns
20
- milestone_thread = find_milestone(repository, milestone_pattern, output) if milestone_pattern
21
- reviewers_thread = select_reviewers(repository, reviewer_patterns, output) if reviewer_patterns
23
+ all_labels, all_milestones, all_collaborators = find_all_attribute_entries(
24
+ repository, label_patterns, milestone_pattern, reviewer_patterns, output
25
+ )
22
26
 
23
- selected_labels = labels_thread&.join&.value
24
- reviewers = reviewers_thread&.join&.value
25
- milestone = milestone_thread&.join&.value
27
+ labels = select_entries('label', all_labels, label_patterns, :multiple, :name) if label_patterns
28
+ milestone, _ = select_entries('milestone', all_milestones, milestone_pattern, :single, :title) if milestone_pattern
29
+ reviewers = select_entries('collaborator', all_collaborators, reviewer_patterns, :multiple, nil) if reviewer_patterns
26
30
 
27
31
  pr = create_pr(repository, title, description, output)
28
32
 
29
- assign_user_thread = assign_authenticated_user(pr, repository, output)
30
- add_labels_thread = add_labels(pr, selected_labels, output) if selected_labels
31
- set_milestone_thread = set_milestone(pr, milestone, output) if milestone
32
- request_review_thread = request_review(pr, reviewers, output) if reviewers
33
-
34
- assign_user_thread.join
35
- add_labels_thread&.join
36
- set_milestone_thread&.join
37
- request_review_thread&.join
33
+ edit_pr(repository, pr, labels, milestone, reviewers, output)
38
34
 
39
35
  if no_open_pr
40
36
  output.puts "PR address: #{pr.link}"
@@ -49,38 +45,27 @@ module Geet
49
45
 
50
46
  # Internal actions
51
47
 
52
- def select_labels(repository, label_patterns, output)
53
- output.puts 'Finding labels...'
54
-
55
- Thread.new do
56
- all_labels = repository.labels
57
-
58
- select_entries(all_labels, label_patterns, type: 'labels', instance_method: :name)
48
+ def find_all_attribute_entries(repository,label_patterns, milestone_pattern, reviewer_patterns, output)
49
+ if label_patterns
50
+ output.puts 'Finding labels...'
51
+ labels_thread = Thread.new { repository.labels }
59
52
  end
60
- end
61
-
62
- def find_milestone(repository, milestone_pattern, output)
63
- output.puts 'Finding milestone...'
64
-
65
- Thread.new do
66
- if milestone_pattern =~ /\A\d+\Z/
67
- repository.milestone(milestone_pattern)
68
- else
69
- all_milestones = repository.milestones
70
53
 
71
- select_entries(all_milestones, milestone_pattern, type: 'milestones', instance_method: :title).first
72
- end
54
+ if milestone_pattern
55
+ output.puts 'Finding milestone...'
56
+ milestone_thread = Thread.new { repository.milestones }
73
57
  end
74
- end
75
58
 
76
- def select_reviewers(repository, reviewer_patterns, output)
77
- output.puts 'Finding collaborators...'
59
+ if reviewer_patterns
60
+ output.puts 'Finding collaborators...'
61
+ reviewers_thread = Thread.new { repository.collaborators }
62
+ end
78
63
 
79
- Thread.new do
80
- all_collaborators = repository.collaborators
64
+ labels = labels_thread&.value
65
+ milestones = milestone_thread&.value
66
+ reviewers = reviewers_thread&.value
81
67
 
82
- select_entries(all_collaborators, reviewer_patterns, type: 'collaborators')
83
- end
68
+ [labels, milestones, reviewers]
84
69
  end
85
70
 
86
71
  def create_pr(repository, title, description, output)
@@ -89,6 +74,19 @@ module Geet
89
74
  repository.create_pr(title, description, repository.current_branch)
90
75
  end
91
76
 
77
+ def edit_pr(repository, pr, labels, milestone, reviewers, output)
78
+ assign_user_thread = assign_authenticated_user(pr, repository, output)
79
+
80
+ add_labels_thread = add_labels(pr, labels, output) if labels
81
+ set_milestone_thread = set_milestone(pr, milestone, output) if milestone
82
+ request_review_thread = request_review(pr, reviewers, output) if reviewers
83
+
84
+ assign_user_thread.join
85
+ add_labels_thread&.join
86
+ set_milestone_thread&.join
87
+ request_review_thread&.join
88
+ end
89
+
92
90
  def assign_authenticated_user(pr, repository, output)
93
91
  output.puts 'Assigning authenticated user...'
94
92
 
@@ -125,23 +123,11 @@ module Geet
125
123
 
126
124
  # Generic helpers
127
125
 
128
- def select_entries(entries, raw_patterns, type: 'entries', instance_method: nil)
129
- patterns = raw_patterns.split(',')
130
-
131
- patterns.map do |pattern|
132
- entries_found = entries.select do |entry|
133
- entry = entry.send(instance_method) if instance_method
134
- entry =~ /#{pattern}/i
135
- end
136
-
137
- case entries_found.size
138
- when 1
139
- entries_found.first
140
- when 0
141
- raise "No #{type} found for pattern: #{pattern.inspect}"
142
- else
143
- raise "Multiple #{type} found for pattern #{pattern.inspect}: #{entries_found}"
144
- end
126
+ def select_entries(entry_type, entries, raw_patterns, selection_type, instance_method)
127
+ if raw_patterns == MANUAL_LIST_SELECTION_FLAG
128
+ Geet::Utils::ManualListSelection.new.select(entry_type, entries, selection_type, instance_method: instance_method)
129
+ else
130
+ Geet::Utils::PatternMatchingSelection.new.select(entry_type, entries, raw_patterns, instance_method: instance_method)
145
131
  end
146
132
  end
147
133
  end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'temp-fork-tp-filter'
4
+
5
+ module Geet
6
+ module Utils
7
+ class ManualListSelection
8
+ PAGER_SIZE = 16
9
+
10
+ PROMPT_METHODS = {
11
+ single: :select,
12
+ multiple: :multi_select,
13
+ }
14
+
15
+ # selection_type: :single or :multiple
16
+ def select(entry_type, entries, selection_type, instance_method: nil)
17
+ raise "No #{entry_type} provided!" if entries.empty?
18
+
19
+ prompt_method = find_prompt_method(selection_type)
20
+ prompt_title = "Please select the #{entry_type}(s):"
21
+
22
+ if instance_method
23
+ entries = entries.each_with_object({}) do |entry, current_map|
24
+ current_map[entry.send(instance_method)] = entry
25
+ end
26
+ end
27
+
28
+ selected_entries = TTY::Prompt.new.send(prompt_method, prompt_title, entries, filter: true, per_page: PAGER_SIZE)
29
+
30
+ if selected_entries.is_a?(Array)
31
+ raise "No #{entry_type} selected!" if selected_entries.empty?
32
+ else
33
+ raise "No #{entry_type} selected!" if selected_entries.nil?
34
+ end
35
+
36
+ selected_entries
37
+ end
38
+
39
+ private
40
+
41
+ def find_prompt_method(selection_type)
42
+ PROMPT_METHODS[selection_type] || raise("Unrecognized selection_type: #{selection_type}")
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Geet
4
+ module Utils
5
+ class PatternMatchingSelection
6
+ def select(entry_type, entries, raw_patterns, instance_method: nil)
7
+ patterns = raw_patterns.split(',')
8
+
9
+ patterns.map do |pattern|
10
+ entries_found = entries.select do |entry|
11
+ entry = entry.send(instance_method) if instance_method
12
+ entry =~ /#{pattern}/i
13
+ end
14
+
15
+ case entries_found.size
16
+ when 1
17
+ entries_found.first
18
+ when 0
19
+ raise "No entry found for #{entry_type} pattern: #{pattern.inspect}"
20
+ else
21
+ raise "Multiple entries found for #{entry_type} pattern #{pattern.inspect}: #{entries_found}"
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Geet
4
- VERSION = '0.2.1'
4
+ VERSION = '0.3.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: geet
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Saverio Miroddi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-01-14 00:00:00.000000000 Z
11
+ date: 2018-01-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: simple_scripting
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.9.3
27
+ - !ruby/object:Gem::Dependency
28
+ name: temp-fork-tp-filter
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 0.0.3
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 0.0.3
27
41
  description: Commandline interface for performing SCM (eg. GitHub) operations (eg.
28
42
  PR creation).
29
43
  email:
@@ -76,6 +90,8 @@ files:
76
90
  - lib/geet/services/list_prs.rb
77
91
  - lib/geet/services/merge_pr.rb
78
92
  - lib/geet/utils/git.rb
93
+ - lib/geet/utils/manual_list_selection.rb
94
+ - lib/geet/utils/pattern_matching_selection.rb
79
95
  - lib/geet/version.rb
80
96
  - spec/integration/create_gist_spec.rb
81
97
  - spec/integration/create_issue_spec.rb
@@ -126,7 +142,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
126
142
  version: '0'
127
143
  requirements: []
128
144
  rubyforge_project:
129
- rubygems_version: 2.6.13
145
+ rubygems_version: 2.6.14
130
146
  signing_key:
131
147
  specification_version: 4
132
148
  summary: Commandline interface for performing SCM (eg. GitHub) operations (eg. PR