geet 0.3.1 → 0.3.2
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/Gemfile.lock +3 -3
- data/README.md +25 -24
- data/bin/geet +21 -3
- data/geet.gemspec +2 -2
- data/lib/geet/commandline/configuration.rb +5 -5
- data/lib/geet/git/repository.rb +34 -15
- data/lib/geet/services/abstract_create_issue.rb +33 -0
- data/lib/geet/services/create_gist.rb +6 -4
- data/lib/geet/services/create_issue.rb +33 -87
- data/lib/geet/services/create_label.rb +7 -6
- data/lib/geet/services/create_pr.rb +42 -86
- data/lib/geet/services/list_issues.rb +13 -14
- data/lib/geet/services/list_labels.rb +4 -3
- data/lib/geet/services/list_milestones.rb +12 -11
- data/lib/geet/services/list_prs.rb +4 -3
- data/lib/geet/services/merge_pr.rb +12 -11
- data/lib/geet/shared/constants.rb +9 -0
- data/lib/geet/utils/attributes_selection_manager.rb +87 -0
- data/lib/geet/utils/manual_list_selection.rb +41 -27
- data/lib/geet/utils/string_matching_selection.rb +32 -0
- data/lib/geet/version.rb +1 -1
- data/spec/integration/create_gist_spec.rb +4 -4
- data/spec/integration/create_issue_spec.rb +6 -6
- data/spec/integration/create_label_spec.rb +3 -3
- data/spec/integration/create_pr_spec.rb +13 -13
- data/spec/integration/list_issues_spec.rb +5 -5
- data/spec/integration/list_labels_spec.rb +3 -3
- data/spec/integration/list_milestones_spec.rb +2 -2
- data/spec/integration/list_prs_spec.rb +2 -2
- data/spec/integration/merge_pr_spec.rb +2 -2
- data/spec/vcr_cassettes/create_issue_upstream.yml +1 -1
- data/spec/vcr_cassettes/create_pr.yml +181 -102
- data/spec/vcr_cassettes/create_pr_in_auto_mode_create_upstream.yml +1 -1
- data/spec/vcr_cassettes/create_pr_in_auto_mode_with_push.yml +1 -1
- data/spec/vcr_cassettes/create_pr_upstream.yml +2 -2
- metadata +8 -5
- data/lib/geet/utils/pattern_matching_selection.rb +0 -27
@@ -0,0 +1,87 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'manual_list_selection'
|
4
|
+
require_relative 'string_matching_selection'
|
5
|
+
require_relative '../shared/constants'
|
6
|
+
|
7
|
+
module Geet
|
8
|
+
module Utils
|
9
|
+
# Manages the retrieval and selection of attributes.
|
10
|
+
#
|
11
|
+
# Selecting an attribute happens in two steps: retrieval and selection.
|
12
|
+
#
|
13
|
+
# With this structure, the retrieval happens in parallel, cutting the time considerably when
|
14
|
+
# multiple attributes are required (typically, three).
|
15
|
+
#
|
16
|
+
class AttributesSelectionManager
|
17
|
+
include Geet::Shared::Constants
|
18
|
+
|
19
|
+
# Initialize the instance, and starts the background threads.
|
20
|
+
#
|
21
|
+
def initialize(repository, out: output)
|
22
|
+
@repository = repository
|
23
|
+
@out = out
|
24
|
+
@selections_data = []
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_attribute(repository_call, description, pattern, selection_type, name_method: nil, &pre_selection_hook)
|
28
|
+
raise "Unrecognized selection type #{selection_type.inspect}" if ![:single, :multiple].include?(selection_type)
|
29
|
+
|
30
|
+
finder_thread = find_attribute_entries(repository_call)
|
31
|
+
|
32
|
+
@selections_data << [finder_thread, description, pattern, selection_type, name_method, pre_selection_hook]
|
33
|
+
end
|
34
|
+
|
35
|
+
# Select and return the attributes, in the same order they've been added.
|
36
|
+
#
|
37
|
+
def select_attributes
|
38
|
+
@selections_data.map do |finder_thread, description, pattern, selection_type, name_method, pre_selection_hook|
|
39
|
+
entries = finder_thread.value
|
40
|
+
|
41
|
+
entries = pre_selection_hook.(entries) if pre_selection_hook
|
42
|
+
|
43
|
+
case selection_type
|
44
|
+
when :single
|
45
|
+
select_entry(description, entries, pattern, name_method)
|
46
|
+
when :multiple
|
47
|
+
select_entries(description, entries, pattern, name_method)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def find_attribute_entries(repository_call)
|
55
|
+
@out.puts "Finding #{repository_call}..."
|
56
|
+
|
57
|
+
Thread.new do
|
58
|
+
@repository.send(repository_call)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Sample call:
|
63
|
+
#
|
64
|
+
# select_entry('milestone', all_milestones, '0.1.0', :title)
|
65
|
+
#
|
66
|
+
def select_entry(entry_type, entries, pattern, name_method)
|
67
|
+
if pattern == MANUAL_LIST_SELECTION_FLAG
|
68
|
+
Geet::Utils::ManualListSelection.new.select_entry(entry_type, entries, name_method: name_method)
|
69
|
+
else
|
70
|
+
Geet::Utils::StringMatchingSelection.new.select_entry(entry_type, entries, pattern, name_method: name_method)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Sample call:
|
75
|
+
#
|
76
|
+
# select_entries('reviewer', all_collaborators, 'donaldduck', nil)
|
77
|
+
#
|
78
|
+
def select_entries(entry_type, entries, pattern, name_method)
|
79
|
+
if pattern == MANUAL_LIST_SELECTION_FLAG
|
80
|
+
Geet::Utils::ManualListSelection.new.select_entries(entry_type, entries, name_method: name_method)
|
81
|
+
else
|
82
|
+
Geet::Utils::StringMatchingSelection.new.select_entries(entry_type, entries, pattern, name_method: name_method)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -9,56 +9,70 @@ module Geet
|
|
9
9
|
|
10
10
|
PAGER_SIZE = 16
|
11
11
|
|
12
|
+
# Shows a prompt for selecting an entry from a list.
|
13
|
+
#
|
14
|
+
# Returns nil, without showing the prompt, if there are no entries.
|
15
|
+
#
|
12
16
|
# entry_type: description of the entries type.
|
13
|
-
# entries: array of objects; if they're not strings, must also pass :
|
17
|
+
# entries: array of objects; if they're not strings, must also pass :name_method.
|
14
18
|
# this value must not be empty.
|
15
|
-
#
|
16
|
-
# instance_method: required when non-string objects are passed as entries; its invocation on
|
19
|
+
# name_method: required when non-string objects are passed as entries; its invocation on
|
17
20
|
# each object must return a string, which is used as key.
|
18
21
|
#
|
19
|
-
# returns: the selected entry
|
20
|
-
#
|
22
|
+
# returns: the selected entry. if no entries are nil is returned.
|
23
|
+
#
|
24
|
+
def select_entry(entry_type, entries, name_method: nil)
|
25
|
+
return nil if entries.empty?
|
26
|
+
|
27
|
+
check_entries(entries, entry_type)
|
28
|
+
|
29
|
+
entries = create_entries_map(entries, name_method)
|
30
|
+
entries = add_no_selection_entry(entries)
|
31
|
+
|
32
|
+
show_prompt(:select, entry_type, entries)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Shows a prompt for selecting an entry from a list.
|
36
|
+
#
|
37
|
+
# Returns an empty array, without showing the prompt, if there are no entries.
|
38
|
+
#
|
39
|
+
# See #select_entry for the parameters.
|
21
40
|
#
|
22
|
-
|
23
|
-
|
41
|
+
# returns: array of entries.
|
42
|
+
#
|
43
|
+
def select_entries(entry_type, entries, name_method: nil)
|
44
|
+
return [] if entries.empty?
|
24
45
|
|
25
|
-
|
46
|
+
check_entries(entries, entry_type)
|
26
47
|
|
27
|
-
|
48
|
+
entries = create_entries_map(entries, name_method)
|
28
49
|
|
29
|
-
|
50
|
+
show_prompt(:multi_select, entry_type, entries)
|
30
51
|
end
|
31
52
|
|
32
53
|
private
|
33
54
|
|
34
|
-
def check_entries(entries)
|
55
|
+
def check_entries(entries, entry_type)
|
35
56
|
raise "No #{entry_type} provided!" if entries.empty?
|
36
57
|
end
|
37
58
|
|
38
|
-
def create_entries_map(entries,
|
59
|
+
def create_entries_map(entries, name_method)
|
39
60
|
entries.each_with_object({}) do |entry, current_map|
|
40
|
-
key =
|
61
|
+
key = name_method ? entry.send(name_method) : entry
|
41
62
|
current_map[key] = entry
|
42
63
|
end
|
43
64
|
end
|
44
65
|
|
45
|
-
def show_prompt(entry_type, selection_type, entries)
|
46
|
-
prompt_title = "Please select the #{entry_type}(s):"
|
47
|
-
|
48
|
-
case selection_type
|
49
|
-
when :single
|
50
|
-
entries = add_no_selection_entry(entries)
|
51
|
-
TTY::Prompt.new.select(prompt_title, entries, filter: true, per_page: PAGER_SIZE)
|
52
|
-
when :multiple
|
53
|
-
TTY::Prompt.new.multi_select(prompt_title, entries, filter: true, per_page: PAGER_SIZE)
|
54
|
-
else
|
55
|
-
raise "Unexpected selection type: #{selection_type.inspect}"
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
66
|
def add_no_selection_entry(entries)
|
60
67
|
{NO_SELECTION_KEY => nil}.merge(entries)
|
61
68
|
end
|
69
|
+
|
70
|
+
def show_prompt(invocation_method, entry_type, entries)
|
71
|
+
# Arguably inexact phrasing for avoiding language complexities.
|
72
|
+
prompt_title = "Please select the #{entry_type}(s):"
|
73
|
+
|
74
|
+
TTY::Prompt.new.send(invocation_method, prompt_title, entries, filter: true, per_page: PAGER_SIZE)
|
75
|
+
end
|
62
76
|
end
|
63
77
|
end
|
64
78
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Geet
|
4
|
+
module Utils
|
5
|
+
class StringMatchingSelection
|
6
|
+
def select_entry(entry_type, entries, pattern, name_method: nil)
|
7
|
+
entries_found = entries.select do |entry|
|
8
|
+
entry = entry.send(name_method) if name_method
|
9
|
+
entry.downcase == pattern.downcase
|
10
|
+
end
|
11
|
+
|
12
|
+
case entries_found.size
|
13
|
+
when 1
|
14
|
+
entries_found.first
|
15
|
+
when 0
|
16
|
+
raise "No entry found for #{entry_type} pattern: #{pattern.inspect}"
|
17
|
+
else
|
18
|
+
raise "Multiple entries found for #{entry_type} pattern #{pattern.inspect}: #{entries_found}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def select_entries(entry_type, entries, raw_patterns, name_method: nil)
|
23
|
+
patterns = raw_patterns.split(',')
|
24
|
+
|
25
|
+
patterns.map do |pattern|
|
26
|
+
# Haha.
|
27
|
+
select_entry(entry_type, entries, pattern, name_method: name_method)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/geet/version.rb
CHANGED
@@ -18,8 +18,8 @@ describe Geet::Services::CreateGist do
|
|
18
18
|
actual_output = StringIO.new
|
19
19
|
|
20
20
|
VCR.use_cassette('create_gist_public') do
|
21
|
-
described_class.new.execute(
|
22
|
-
tempfile.path, description: 'testdescription', publik: true, no_browse: true
|
21
|
+
described_class.new(out: actual_output).execute(
|
22
|
+
tempfile.path, description: 'testdescription', publik: true, no_browse: true
|
23
23
|
)
|
24
24
|
end
|
25
25
|
|
@@ -35,8 +35,8 @@ describe Geet::Services::CreateGist do
|
|
35
35
|
actual_output = StringIO.new
|
36
36
|
|
37
37
|
VCR.use_cassette('create_gist_private') do
|
38
|
-
described_class.new.execute(
|
39
|
-
tempfile.path, description: 'testdescription', no_browse: true
|
38
|
+
described_class.new(out: actual_output).execute(
|
39
|
+
tempfile.path, description: 'testdescription', no_browse: true
|
40
40
|
)
|
41
41
|
end
|
42
42
|
|
@@ -16,7 +16,7 @@ describe Geet::Services::CreateIssue do
|
|
16
16
|
|
17
17
|
expected_output = <<~STR
|
18
18
|
Finding labels...
|
19
|
-
Finding
|
19
|
+
Finding milestones...
|
20
20
|
Finding collaborators...
|
21
21
|
Creating the issue...
|
22
22
|
Adding labels bug, invalid...
|
@@ -28,10 +28,10 @@ describe Geet::Services::CreateIssue do
|
|
28
28
|
actual_output = StringIO.new
|
29
29
|
|
30
30
|
actual_created_issue = VCR.use_cassette('create_issue') do
|
31
|
-
described_class.new(repository).execute(
|
31
|
+
described_class.new(repository, out: actual_output).execute(
|
32
32
|
'Title', 'Description',
|
33
|
-
|
34
|
-
no_open_issue: true
|
33
|
+
labels: 'bug,invalid', milestone: '0.0.1', assignees: 'donald-ts,donald-fr',
|
34
|
+
no_open_issue: true
|
35
35
|
)
|
36
36
|
end
|
37
37
|
|
@@ -56,8 +56,8 @@ describe Geet::Services::CreateIssue do
|
|
56
56
|
actual_output = StringIO.new
|
57
57
|
|
58
58
|
actual_created_issue = VCR.use_cassette('create_issue_upstream') do
|
59
|
-
create_options = { no_open_issue: true,
|
60
|
-
described_class.new(upstream_repository).execute('Title', 'Description', create_options)
|
59
|
+
create_options = { no_open_issue: true, out: actual_output }
|
60
|
+
described_class.new(upstream_repository, out: actual_output).execute('Title', 'Description', create_options)
|
61
61
|
end
|
62
62
|
|
63
63
|
expect(actual_output.string).to eql(expected_output)
|
@@ -22,7 +22,7 @@ describe Geet::Services::CreateLabel do
|
|
22
22
|
actual_output = StringIO.new
|
23
23
|
|
24
24
|
actual_created_label = VCR.use_cassette('create_label') do
|
25
|
-
described_class.new(repository).execute('my_label', color: 'c64c64'
|
25
|
+
described_class.new(repository, out: actual_output).execute('my_label', color: 'c64c64')
|
26
26
|
end
|
27
27
|
|
28
28
|
expect(actual_output.string).to eql(expected_output)
|
@@ -44,7 +44,7 @@ describe Geet::Services::CreateLabel do
|
|
44
44
|
actual_output = StringIO.new
|
45
45
|
|
46
46
|
actual_created_label = VCR.use_cassette('create_label_upstream') do
|
47
|
-
described_class.new(upstream_repository).execute('my_label', color: 'c64c64'
|
47
|
+
described_class.new(upstream_repository, out: actual_output).execute('my_label', color: 'c64c64')
|
48
48
|
end
|
49
49
|
|
50
50
|
expect(actual_output.string).to eql(expected_output)
|
@@ -67,7 +67,7 @@ describe Geet::Services::CreateLabel do
|
|
67
67
|
actual_output = StringIO.new
|
68
68
|
|
69
69
|
actual_created_label = VCR.use_cassette('create_label_with_random_color') do
|
70
|
-
described_class.new(repository).execute('my_label'
|
70
|
+
described_class.new(repository, out: actual_output).execute('my_label')
|
71
71
|
end
|
72
72
|
|
73
73
|
expected_output = format(expected_output_template, color: actual_created_label.color)
|
@@ -17,32 +17,32 @@ describe Geet::Services::CreatePr do
|
|
17
17
|
|
18
18
|
expected_output = <<~STR
|
19
19
|
Finding labels...
|
20
|
-
Finding
|
20
|
+
Finding milestones...
|
21
21
|
Finding collaborators...
|
22
22
|
Creating PR...
|
23
23
|
Assigning authenticated user...
|
24
|
-
Adding labels
|
25
|
-
Setting milestone
|
26
|
-
Requesting review from donald-
|
27
|
-
PR address: https://github.com/donaldduck/testrepo/pull/
|
24
|
+
Adding labels bug, invalid...
|
25
|
+
Setting milestone milestone 1...
|
26
|
+
Requesting review from donald-fr...
|
27
|
+
PR address: https://github.com/donaldduck/testrepo/pull/39
|
28
28
|
STR
|
29
29
|
|
30
30
|
actual_output = StringIO.new
|
31
31
|
|
32
32
|
actual_created_pr = VCR.use_cassette('create_pr') do
|
33
|
-
service_instance = described_class.new(repository, git_client: git_client)
|
33
|
+
service_instance = described_class.new(repository, out: actual_output, git_client: git_client)
|
34
34
|
service_instance.execute(
|
35
35
|
'Title', 'Description',
|
36
|
-
|
36
|
+
labels: 'bug,invalid', milestone: 'milestone 1', reviewers: 'donald-fr',
|
37
37
|
no_open_pr: true, output: actual_output
|
38
38
|
)
|
39
39
|
end
|
40
40
|
|
41
41
|
expect(actual_output.string).to eql(expected_output)
|
42
42
|
|
43
|
-
expect(actual_created_pr.number).to eql(
|
43
|
+
expect(actual_created_pr.number).to eql(39)
|
44
44
|
expect(actual_created_pr.title).to eql('Title')
|
45
|
-
expect(actual_created_pr.link).to eql('https://github.com/donaldduck/testrepo/pull/
|
45
|
+
expect(actual_created_pr.link).to eql('https://github.com/donaldduck/testrepo/pull/39')
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
@@ -60,7 +60,7 @@ describe Geet::Services::CreatePr do
|
|
60
60
|
actual_output = StringIO.new
|
61
61
|
|
62
62
|
actual_created_pr = VCR.use_cassette('create_pr_upstream') do
|
63
|
-
service_instance = described_class.new(upstream_repository, git_client: git_client)
|
63
|
+
service_instance = described_class.new(upstream_repository, out: actual_output, git_client: git_client)
|
64
64
|
service_instance.execute('Title', 'Description', no_open_pr: true, output: actual_output)
|
65
65
|
end
|
66
66
|
|
@@ -83,7 +83,7 @@ describe Geet::Services::CreatePr do
|
|
83
83
|
actual_output = StringIO.new
|
84
84
|
|
85
85
|
operation = -> do
|
86
|
-
service_instance = described_class.new(repository, git_client: git_client)
|
86
|
+
service_instance = described_class.new(repository, out: actual_output, git_client: git_client)
|
87
87
|
service_instance.execute('Title', 'Description', output: actual_output, automated_mode: true, no_open_pr: true)
|
88
88
|
end
|
89
89
|
|
@@ -110,7 +110,7 @@ describe Geet::Services::CreatePr do
|
|
110
110
|
actual_output = StringIO.new
|
111
111
|
|
112
112
|
actual_created_pr = VCR.use_cassette('create_pr_in_auto_mode_with_push') do
|
113
|
-
service_instance = described_class.new(repository, git_client: git_client)
|
113
|
+
service_instance = described_class.new(repository, out: actual_output, git_client: git_client)
|
114
114
|
service_instance.execute('Title', 'Description', output: actual_output, automated_mode: true, no_open_pr: true)
|
115
115
|
end
|
116
116
|
|
@@ -135,7 +135,7 @@ describe Geet::Services::CreatePr do
|
|
135
135
|
actual_output = StringIO.new
|
136
136
|
|
137
137
|
actual_created_pr = VCR.use_cassette('create_pr_in_auto_mode_create_upstream') do
|
138
|
-
service_instance = described_class.new(repository, git_client: git_client)
|
138
|
+
service_instance = described_class.new(repository, out: actual_output, git_client: git_client)
|
139
139
|
service_instance.execute('Title', 'Description', output: actual_output, automated_mode: true, no_open_pr: true)
|
140
140
|
end
|
141
141
|
|
@@ -23,7 +23,7 @@ describe Geet::Services::ListIssues do
|
|
23
23
|
actual_output = StringIO.new
|
24
24
|
|
25
25
|
service_result = VCR.use_cassette('github_com/list_issues') do
|
26
|
-
described_class.new(repository
|
26
|
+
described_class.new(repository, out: actual_output).execute
|
27
27
|
end
|
28
28
|
|
29
29
|
actual_issue_numbers = service_result.map(&:number)
|
@@ -37,7 +37,7 @@ describe Geet::Services::ListIssues do
|
|
37
37
|
allow(git_client).to receive(:remote).with('origin').and_return('git@github.com:donaldduck/testrepo_gh')
|
38
38
|
|
39
39
|
expected_output = <<~STR
|
40
|
-
Finding
|
40
|
+
Finding collaborators...
|
41
41
|
12. test issue 3 (https://github.com/donaldduck/testrepo_gh/issues/12)
|
42
42
|
10. test issue 1 (https://github.com/donaldduck/testrepo_gh/issues/10)
|
43
43
|
STR
|
@@ -46,7 +46,7 @@ describe Geet::Services::ListIssues do
|
|
46
46
|
actual_output = StringIO.new
|
47
47
|
|
48
48
|
service_result = VCR.use_cassette('github_com/list_issues_with_assignee') do
|
49
|
-
described_class.new(repository).execute(
|
49
|
+
described_class.new(repository, out: actual_output).execute(assignee: 'donald-fr', )
|
50
50
|
end
|
51
51
|
|
52
52
|
actual_issue_numbers = service_result.map(&:number)
|
@@ -69,7 +69,7 @@ describe Geet::Services::ListIssues do
|
|
69
69
|
actual_output = StringIO.new
|
70
70
|
|
71
71
|
service_result = VCR.use_cassette('github_com/list_issues_upstream') do
|
72
|
-
described_class.new(upstream_repository
|
72
|
+
described_class.new(upstream_repository, out: actual_output).execute
|
73
73
|
end
|
74
74
|
|
75
75
|
actual_issue_numbers = service_result.map(&:number)
|
@@ -92,7 +92,7 @@ describe Geet::Services::ListIssues do
|
|
92
92
|
actual_output = StringIO.new
|
93
93
|
|
94
94
|
service_result = VCR.use_cassette('gitlab_com/list_issues') do
|
95
|
-
described_class.new(repository
|
95
|
+
described_class.new(repository, out: actual_output).execute
|
96
96
|
end
|
97
97
|
|
98
98
|
actual_issue_numbers = service_result.map(&:number)
|
@@ -24,7 +24,7 @@ describe Geet::Services::ListLabels do
|
|
24
24
|
|
25
25
|
actual_output = StringIO.new
|
26
26
|
actual_labels = VCR.use_cassette('github.com/list_labels') do
|
27
|
-
described_class.new(repository
|
27
|
+
described_class.new(repository, out: actual_output).execute
|
28
28
|
end
|
29
29
|
|
30
30
|
actual_label_names = actual_labels.map(&:name)
|
@@ -45,7 +45,7 @@ describe Geet::Services::ListLabels do
|
|
45
45
|
|
46
46
|
actual_output = StringIO.new
|
47
47
|
actual_labels = VCR.use_cassette('github.com/list_labels_upstream') do
|
48
|
-
described_class.new(upstream_repository
|
48
|
+
described_class.new(upstream_repository, out: actual_output).execute
|
49
49
|
end
|
50
50
|
|
51
51
|
actual_label_names = actual_labels.map(&:name)
|
@@ -73,7 +73,7 @@ describe Geet::Services::ListLabels do
|
|
73
73
|
|
74
74
|
actual_output = StringIO.new
|
75
75
|
actual_labels = VCR.use_cassette('gitlab.com/list_labels') do
|
76
|
-
described_class.new(repository
|
76
|
+
described_class.new(repository, out: actual_output).execute
|
77
77
|
end
|
78
78
|
|
79
79
|
actual_label_names = actual_labels.map(&:name)
|