geet 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +6 -10
- data/Gemfile.lock +8 -2
- data/README.md +27 -2
- data/Rakefile +3 -1
- data/bin/geet +37 -17
- data/geet.gemspec +3 -1
- data/lib/geet/commandline/configuration.rb +18 -5
- data/lib/geet/commandline/editor.rb +14 -24
- data/lib/geet/git/repository.rb +30 -84
- data/lib/geet/github/api_interface.rb +11 -3
- data/lib/geet/github/gist.rb +1 -0
- data/lib/geet/gitlab/api_interface.rb +5 -2
- data/lib/geet/helpers/os_helper.rb +36 -3
- data/lib/geet/helpers/summary_helper.rb +20 -0
- data/lib/geet/resources/{edit_summary_template.md → templates/edit_summary.md} +0 -3
- data/lib/geet/services/create_gist.rb +18 -2
- data/lib/geet/services/create_issue.rb +46 -21
- data/lib/geet/services/create_label.rb +8 -4
- data/lib/geet/services/create_pr.rb +67 -18
- data/lib/geet/services/list_issues.rb +9 -5
- data/lib/geet/services/list_labels.rb +6 -2
- data/lib/geet/services/list_milestones.rb +11 -7
- data/lib/geet/services/list_prs.rb +6 -2
- data/lib/geet/services/merge_pr.rb +18 -11
- data/lib/geet/utils/git_client.rb +160 -0
- data/lib/geet/utils/manual_list_selection.rb +41 -23
- data/lib/geet/version.rb +1 -1
- data/spec/integration/create_gist_spec.rb +2 -5
- data/spec/integration/create_issue_spec.rb +10 -10
- data/spec/integration/create_label_spec.rb +30 -5
- data/spec/integration/create_pr_spec.rb +85 -10
- data/spec/integration/list_issues_spec.rb +12 -11
- data/spec/integration/list_labels_spec.rb +28 -5
- data/spec/integration/list_milestones_spec.rb +30 -3
- data/spec/integration/list_prs_spec.rb +8 -7
- data/spec/integration/merge_pr_spec.rb +8 -7
- data/spec/vcr_cassettes/create_gist_private.yml +1 -1
- data/spec/vcr_cassettes/create_gist_public.yml +1 -1
- data/spec/vcr_cassettes/create_issue.yml +9 -9
- data/spec/vcr_cassettes/create_issue_upstream.yml +3 -3
- data/spec/vcr_cassettes/create_label.yml +1 -1
- data/spec/vcr_cassettes/create_label_upstream.yml +80 -0
- data/spec/vcr_cassettes/create_label_with_random_color.yml +1 -1
- data/spec/vcr_cassettes/create_pr.yml +13 -13
- data/spec/vcr_cassettes/create_pr_in_auto_mode_create_upstream.yml +235 -0
- data/spec/vcr_cassettes/create_pr_in_auto_mode_with_push.yml +235 -0
- data/spec/vcr_cassettes/create_pr_upstream.yml +4 -4
- data/spec/vcr_cassettes/github_com/list_issues.yml +5 -5
- data/spec/vcr_cassettes/github_com/list_issues_upstream.yml +6 -6
- data/spec/vcr_cassettes/github_com/list_issues_with_assignee.yml +4 -4
- data/spec/vcr_cassettes/github_com/list_labels.yml +1 -1
- data/spec/vcr_cassettes/github_com/list_labels_upstream.yml +78 -0
- data/spec/vcr_cassettes/gitlab_com/list_issues.yml +5 -5
- data/spec/vcr_cassettes/gitlab_com/list_labels.yml +1 -1
- data/spec/vcr_cassettes/list_milestones.yml +15 -15
- data/spec/vcr_cassettes/list_milestones_upstream.yml +155 -0
- data/spec/vcr_cassettes/list_prs.yml +6 -6
- data/spec/vcr_cassettes/list_prs_upstream.yml +3 -3
- data/spec/vcr_cassettes/merge_pr.yml +2 -2
- data/spec/vcr_cassettes/merge_pr_with_branch_deletion.yml +2 -2
- metadata +24 -4
- data/lib/geet/utils/git.rb +0 -30
@@ -3,12 +3,16 @@
|
|
3
3
|
module Geet
|
4
4
|
module Services
|
5
5
|
class ListIssues
|
6
|
-
def
|
7
|
-
|
6
|
+
def initialize(repository)
|
7
|
+
@repository = repository
|
8
|
+
end
|
9
|
+
|
10
|
+
def execute(assignee_pattern: nil, output: $stdout, **)
|
11
|
+
assignee_thread = find_assignee(assignee_pattern, output) if assignee_pattern
|
8
12
|
|
9
13
|
assignee = assignee_thread&.join&.value
|
10
14
|
|
11
|
-
issues = repository.issues(assignee: assignee)
|
15
|
+
issues = @repository.issues(assignee: assignee)
|
12
16
|
|
13
17
|
issues.each do |issue|
|
14
18
|
output.puts "#{issue.number}. #{issue.title} (#{issue.link})"
|
@@ -17,11 +21,11 @@ module Geet
|
|
17
21
|
|
18
22
|
private
|
19
23
|
|
20
|
-
def find_assignee(
|
24
|
+
def find_assignee(assignee_pattern, output)
|
21
25
|
output.puts 'Finding assignee...'
|
22
26
|
|
23
27
|
Thread.new do
|
24
|
-
collaborators = repository.collaborators
|
28
|
+
collaborators = @repository.collaborators
|
25
29
|
collaborator = collaborators.find { |collaborator| collaborator =~ /#{assignee_pattern}/i }
|
26
30
|
collaborator || raise("No collaborator found for pattern: #{assignee_pattern.inspect}")
|
27
31
|
end
|
@@ -3,8 +3,12 @@
|
|
3
3
|
module Geet
|
4
4
|
module Services
|
5
5
|
class ListLabels
|
6
|
-
def
|
7
|
-
|
6
|
+
def initialize(repository)
|
7
|
+
@repository = repository
|
8
|
+
end
|
9
|
+
|
10
|
+
def execute(output: $stdout)
|
11
|
+
labels = @repository.labels
|
8
12
|
|
9
13
|
labels.each do |label|
|
10
14
|
output.puts "- #{label.name} (##{label.color})"
|
@@ -3,9 +3,13 @@
|
|
3
3
|
module Geet
|
4
4
|
module Services
|
5
5
|
class ListMilestones
|
6
|
-
def
|
7
|
-
|
8
|
-
|
6
|
+
def initialize(repository)
|
7
|
+
@repository = repository
|
8
|
+
end
|
9
|
+
|
10
|
+
def execute(output: $stdout)
|
11
|
+
milestones = find_milestones(output)
|
12
|
+
issues_by_milestone_number = find_milestone_issues(milestones, output)
|
9
13
|
|
10
14
|
output.puts
|
11
15
|
|
@@ -30,13 +34,13 @@ module Geet
|
|
30
34
|
description
|
31
35
|
end
|
32
36
|
|
33
|
-
def find_milestones(
|
37
|
+
def find_milestones(output)
|
34
38
|
output.puts 'Finding milestones...'
|
35
39
|
|
36
|
-
repository.milestones
|
40
|
+
@repository.milestones
|
37
41
|
end
|
38
42
|
|
39
|
-
def find_milestone_issues(
|
43
|
+
def find_milestone_issues(milestones, output)
|
40
44
|
output.puts 'Finding issues...'
|
41
45
|
|
42
46
|
# Interestingly, on MRI, concurrent hash access is not a problem without mutex,
|
@@ -46,7 +50,7 @@ module Geet
|
|
46
50
|
|
47
51
|
issue_threads = milestones.map do |milestone|
|
48
52
|
Thread.new do
|
49
|
-
issues = repository.abstract_issues(milestone: milestone.number)
|
53
|
+
issues = @repository.abstract_issues(milestone: milestone.number)
|
50
54
|
|
51
55
|
mutex.synchronize do
|
52
56
|
issues_by_milestone_number[milestone.number] = issues
|
@@ -3,8 +3,12 @@
|
|
3
3
|
module Geet
|
4
4
|
module Services
|
5
5
|
class ListPrs
|
6
|
-
def
|
7
|
-
|
6
|
+
def initialize(repository)
|
7
|
+
@repository = repository
|
8
|
+
end
|
9
|
+
|
10
|
+
def execute(output: $stdout)
|
11
|
+
prs = @repository.prs
|
8
12
|
|
9
13
|
prs.each do |pr|
|
10
14
|
output.puts "#{pr.number}. #{pr.title} (#{pr.link})"
|
@@ -3,25 +3,32 @@
|
|
3
3
|
module Geet
|
4
4
|
module Services
|
5
5
|
class MergePr
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
DEFAULT_GIT_CLIENT = Geet::Utils::GitClient.new
|
7
|
+
|
8
|
+
def initialize(repository, git_client: DEFAULT_GIT_CLIENT)
|
9
|
+
@repository = repository
|
10
|
+
@git_client = git_client
|
11
|
+
end
|
12
|
+
|
13
|
+
def execute(delete_branch: false, output: $stdout)
|
14
|
+
merge_head = find_merge_head
|
15
|
+
pr = checked_find_branch_pr(merge_head, output)
|
9
16
|
merge_pr(pr, output)
|
10
|
-
do_delete_branch(
|
17
|
+
do_delete_branch(output) if delete_branch
|
11
18
|
pr
|
12
19
|
end
|
13
20
|
|
14
21
|
private
|
15
22
|
|
16
|
-
def find_merge_head
|
17
|
-
|
23
|
+
def find_merge_head
|
24
|
+
@git_client.current_branch
|
18
25
|
end
|
19
26
|
|
20
27
|
# Expect to find only one.
|
21
|
-
def checked_find_branch_pr(
|
28
|
+
def checked_find_branch_pr(head, output)
|
22
29
|
output.puts "Finding PR with head (#{head})..."
|
23
30
|
|
24
|
-
prs = repository.prs(head: head)
|
31
|
+
prs = @repository.prs(head: head)
|
25
32
|
|
26
33
|
raise "Expected to find only one PR for the current branch; found: #{prs.size}" if prs.size != 1
|
27
34
|
|
@@ -34,10 +41,10 @@ module Geet
|
|
34
41
|
pr.merge
|
35
42
|
end
|
36
43
|
|
37
|
-
def do_delete_branch(
|
38
|
-
output.puts "Deleting branch #{
|
44
|
+
def do_delete_branch(output)
|
45
|
+
output.puts "Deleting branch #{@git_client.current_branch}..."
|
39
46
|
|
40
|
-
repository.delete_branch(
|
47
|
+
@repository.delete_branch(@git_client.current_branch)
|
41
48
|
end
|
42
49
|
end
|
43
50
|
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'shellwords'
|
4
|
+
require_relative '../helpers/os_helper.rb'
|
5
|
+
|
6
|
+
module Geet
|
7
|
+
module Utils
|
8
|
+
# Represents the git program interface; used for performing git operations.
|
9
|
+
#
|
10
|
+
class GitClient
|
11
|
+
include Geet::Helpers::OsHelper
|
12
|
+
|
13
|
+
ORIGIN_NAME = 'origin'
|
14
|
+
UPSTREAM_NAME = 'upstream'
|
15
|
+
|
16
|
+
# For simplicity, we match any character except the ones the separators.
|
17
|
+
REMOTE_ORIGIN_REGEX = %r{
|
18
|
+
\A
|
19
|
+
(?:https://(.+?)/|git@(.+?):)
|
20
|
+
([^/]+/.*?)
|
21
|
+
(?:\.git)?
|
22
|
+
\Z
|
23
|
+
}x
|
24
|
+
|
25
|
+
UPSTREAM_BRANCH_REGEX = %r{\A[^/]+/([^/]+)\Z}
|
26
|
+
|
27
|
+
CLEAN_TREE_MESSAGE_REGEX = /^nothing to commit, working tree clean$/
|
28
|
+
|
29
|
+
def initialize(location: nil)
|
30
|
+
@location = location
|
31
|
+
end
|
32
|
+
|
33
|
+
##########################################################################
|
34
|
+
# BRANCH/TREE APIS
|
35
|
+
##########################################################################
|
36
|
+
|
37
|
+
# Return the commit shas between HEAD and `limit`, excluding the already applied commits
|
38
|
+
# (which start with `-`)
|
39
|
+
#
|
40
|
+
def cherry(limit)
|
41
|
+
raw_commits = execute_command("git #{gitdir_option} cherry #{limit.shellescape}")
|
42
|
+
|
43
|
+
raw_commits.split("\n").grep(/^\+/).map { |line| line[3..-1] }
|
44
|
+
end
|
45
|
+
|
46
|
+
def current_branch
|
47
|
+
branch = execute_command("git #{gitdir_option} rev-parse --abbrev-ref HEAD")
|
48
|
+
|
49
|
+
raise "Couldn't find current branch" if branch == 'HEAD'
|
50
|
+
|
51
|
+
branch
|
52
|
+
end
|
53
|
+
|
54
|
+
# Not to be confused with `upstream` repository!
|
55
|
+
#
|
56
|
+
# return: nil, if the upstream branch is not configured.
|
57
|
+
#
|
58
|
+
def upstream_branch
|
59
|
+
head_symbolic_ref = execute_command("git #{gitdir_option} symbolic-ref -q HEAD")
|
60
|
+
|
61
|
+
raw_upstream_branch = execute_command("git #{gitdir_option} for-each-ref --format='%(upstream:short)' #{head_symbolic_ref.shellescape}").strip
|
62
|
+
|
63
|
+
if raw_upstream_branch != ''
|
64
|
+
raw_upstream_branch[UPSTREAM_BRANCH_REGEX, 1] || raise("Unexpected upstream format: #{raw_upstream_branch}")
|
65
|
+
else
|
66
|
+
nil
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def working_tree_clean?
|
71
|
+
git_message = execute_command("git #{gitdir_option} status")
|
72
|
+
|
73
|
+
!!(git_message =~ CLEAN_TREE_MESSAGE_REGEX)
|
74
|
+
end
|
75
|
+
|
76
|
+
##########################################################################
|
77
|
+
# COMMIT/OBJECT APIS
|
78
|
+
##########################################################################
|
79
|
+
|
80
|
+
# Show the description ("<subject>\n\n<body>") for the given git object.
|
81
|
+
#
|
82
|
+
def show_description(object)
|
83
|
+
execute_command("git #{gitdir_option} show --quiet --format='%s\n\n%b' #{object.shellescape}")
|
84
|
+
end
|
85
|
+
|
86
|
+
##########################################################################
|
87
|
+
# REPOSITORY/REMOTE APIS
|
88
|
+
##########################################################################
|
89
|
+
|
90
|
+
# Example: `donaldduck/geet`
|
91
|
+
#
|
92
|
+
def path(upstream: false)
|
93
|
+
remote_name = upstream ? UPSTREAM_NAME : ORIGIN_NAME
|
94
|
+
|
95
|
+
remote(remote_name)[REMOTE_ORIGIN_REGEX, 3]
|
96
|
+
end
|
97
|
+
|
98
|
+
def provider_domain
|
99
|
+
# We assume that it's not possible to have origin and upstream on different providers.
|
100
|
+
#
|
101
|
+
remote_url = remote(ORIGIN_NAME)
|
102
|
+
|
103
|
+
domain = remote_url[REMOTE_ORIGIN_REGEX, 1] || remote_url[REMOTE_ORIGIN_REGEX, 2]
|
104
|
+
|
105
|
+
raise "Can't identify domain in the provider domain string: #{domain}" if domain !~ /(.*)\.\w+/
|
106
|
+
|
107
|
+
domain
|
108
|
+
end
|
109
|
+
|
110
|
+
# Returns the URL of the remote with the given name.
|
111
|
+
# Sanity checks are performed.
|
112
|
+
#
|
113
|
+
# The result is in the format `git@github.com:donaldduck/geet.git`
|
114
|
+
#
|
115
|
+
def remote(name)
|
116
|
+
remote_url = execute_command("git #{gitdir_option} ls-remote --get-url #{name}")
|
117
|
+
|
118
|
+
if remote_url == name
|
119
|
+
raise "Remote #{name.inspect} not found!"
|
120
|
+
elsif remote_url !~ REMOTE_ORIGIN_REGEX
|
121
|
+
raise "Unexpected remote reference format: #{remote_url.inspect}"
|
122
|
+
end
|
123
|
+
|
124
|
+
remote_url
|
125
|
+
end
|
126
|
+
|
127
|
+
# Doesn't sanity check for the remote url format; this action is for querying
|
128
|
+
# purposes, any any action that needs to work with the remote, uses #remote.
|
129
|
+
#
|
130
|
+
def remote_defined?(name)
|
131
|
+
remote_url = execute_command("git #{gitdir_option} ls-remote --get-url #{name}")
|
132
|
+
|
133
|
+
# If the remote is not define, `git ls-remote` will return the passed value.
|
134
|
+
remote_url != name
|
135
|
+
end
|
136
|
+
|
137
|
+
##########################################################################
|
138
|
+
# OPERATION APIS
|
139
|
+
##########################################################################
|
140
|
+
|
141
|
+
# upstream_branch: create an upstream branch.
|
142
|
+
#
|
143
|
+
def push(upstream_branch: nil)
|
144
|
+
upstream_branch_option = "-u origin #{upstream_branch.shellescape}" if upstream_branch
|
145
|
+
|
146
|
+
execute_command("git #{gitdir_option} push #{upstream_branch_option}")
|
147
|
+
end
|
148
|
+
|
149
|
+
##########################################################################
|
150
|
+
# INTERNAL HELPERS
|
151
|
+
##########################################################################
|
152
|
+
|
153
|
+
private
|
154
|
+
|
155
|
+
def gitdir_option
|
156
|
+
"--git-dir #{@location.shellescape}/.git" if @location
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
@@ -5,41 +5,59 @@ require 'temp-fork-tp-filter'
|
|
5
5
|
module Geet
|
6
6
|
module Utils
|
7
7
|
class ManualListSelection
|
8
|
-
|
8
|
+
NO_SELECTION_KEY = '(none)'
|
9
9
|
|
10
|
-
|
11
|
-
single: :select,
|
12
|
-
multiple: :multi_select,
|
13
|
-
}
|
10
|
+
PAGER_SIZE = 16
|
14
11
|
|
15
|
-
#
|
12
|
+
# entry_type: description of the entries type.
|
13
|
+
# entries: array of objects; if they're not strings, must also pass :instance_method.
|
14
|
+
# this value must not be empty.
|
15
|
+
# selection_type: :single or :multiple
|
16
|
+
# instance_method: required when non-string objects are passed as entries; its invocation on
|
17
|
+
# each object must return a string, which is used as key.
|
18
|
+
#
|
19
|
+
# returns: the selected entry or array of entries. for single selection, if no entries are
|
20
|
+
# chosen, nil is returned.
|
21
|
+
#
|
16
22
|
def select(entry_type, entries, selection_type, instance_method: nil)
|
17
|
-
|
23
|
+
check_entries(entries)
|
18
24
|
|
19
|
-
|
20
|
-
|
25
|
+
entries = create_entries_map(entries, instance_method)
|
26
|
+
|
27
|
+
result = show_prompt(entry_type, selection_type, entries)
|
28
|
+
|
29
|
+
result
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
21
33
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
34
|
+
def check_entries(entries)
|
35
|
+
raise "No #{entry_type} provided!" if entries.empty?
|
36
|
+
end
|
37
|
+
|
38
|
+
def create_entries_map(entries, instance_method)
|
39
|
+
entries.each_with_object({}) do |entry, current_map|
|
40
|
+
key = instance_method ? entry.send(instance_method) : entry
|
41
|
+
current_map[key] = entry
|
26
42
|
end
|
43
|
+
end
|
27
44
|
|
28
|
-
|
45
|
+
def show_prompt(entry_type, selection_type, entries)
|
46
|
+
prompt_title = "Please select the #{entry_type}(s):"
|
29
47
|
|
30
|
-
|
31
|
-
|
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)
|
32
54
|
else
|
33
|
-
raise "
|
55
|
+
raise "Unexpected selection type: #{selection_type.inspect}"
|
34
56
|
end
|
35
|
-
|
36
|
-
selected_entries
|
37
57
|
end
|
38
58
|
|
39
|
-
|
40
|
-
|
41
|
-
def find_prompt_method(selection_type)
|
42
|
-
PROMPT_METHODS[selection_type] || raise("Unrecognized selection_type: #{selection_type}")
|
59
|
+
def add_no_selection_entry(entries)
|
60
|
+
{NO_SELECTION_KEY => nil}.merge(entries)
|
43
61
|
end
|
44
62
|
end
|
45
63
|
end
|
data/lib/geet/version.rb
CHANGED
@@ -7,7 +7,6 @@ require_relative '../../lib/geet/git/repository'
|
|
7
7
|
require_relative '../../lib/geet/services/create_gist'
|
8
8
|
|
9
9
|
describe Geet::Services::CreateGist do
|
10
|
-
let(:repository) { Geet::Git::Repository.new }
|
11
10
|
let(:tempfile) { Tempfile.open('geet_gist') { |file| file << 'testcontent' } }
|
12
11
|
|
13
12
|
it 'should create a public gist' do
|
@@ -20,8 +19,7 @@ describe Geet::Services::CreateGist do
|
|
20
19
|
|
21
20
|
VCR.use_cassette('create_gist_public') do
|
22
21
|
described_class.new.execute(
|
23
|
-
|
24
|
-
description: 'testdescription', publik: true, no_browse: true, output: actual_output
|
22
|
+
tempfile.path, description: 'testdescription', publik: true, no_browse: true, output: actual_output
|
25
23
|
)
|
26
24
|
end
|
27
25
|
|
@@ -38,8 +36,7 @@ describe Geet::Services::CreateGist do
|
|
38
36
|
|
39
37
|
VCR.use_cassette('create_gist_private') do
|
40
38
|
described_class.new.execute(
|
41
|
-
|
42
|
-
description: 'testdescription', no_browse: true, output: actual_output
|
39
|
+
tempfile.path, description: 'testdescription', no_browse: true, output: actual_output
|
43
40
|
)
|
44
41
|
end
|
45
42
|
|
@@ -6,12 +6,13 @@ require_relative '../../lib/geet/git/repository'
|
|
6
6
|
require_relative '../../lib/geet/services/create_issue'
|
7
7
|
|
8
8
|
describe Geet::Services::CreateIssue do
|
9
|
-
let(:
|
10
|
-
let(:
|
9
|
+
let(:git_client) { Geet::Utils::GitClient.new }
|
10
|
+
let(:repository) { Geet::Git::Repository.new(git_client: git_client) }
|
11
|
+
let(:upstream_repository) { Geet::Git::Repository.new(upstream: true, git_client: git_client) }
|
11
12
|
|
12
13
|
context 'with labels, assignees and milestones' do
|
13
14
|
it 'should create an issue' do
|
14
|
-
allow(
|
15
|
+
allow(git_client).to receive(:remote).with('origin').and_return('git@github.com:donaldduck/testrepo')
|
15
16
|
|
16
17
|
expected_output = <<~STR
|
17
18
|
Finding labels...
|
@@ -27,8 +28,8 @@ describe Geet::Services::CreateIssue do
|
|
27
28
|
actual_output = StringIO.new
|
28
29
|
|
29
30
|
actual_created_issue = VCR.use_cassette('create_issue') do
|
30
|
-
described_class.new.execute(
|
31
|
-
|
31
|
+
described_class.new(repository).execute(
|
32
|
+
'Title', 'Description',
|
32
33
|
label_patterns: 'bug,invalid', milestone_pattern: '0.0.1', assignee_patterns: 'nald-ts,nald-fr',
|
33
34
|
no_open_issue: true, output: actual_output
|
34
35
|
)
|
@@ -43,13 +44,12 @@ describe Geet::Services::CreateIssue do
|
|
43
44
|
end
|
44
45
|
|
45
46
|
it 'should create an upstream issue' do
|
46
|
-
allow(
|
47
|
-
allow(
|
48
|
-
allow(
|
47
|
+
allow(git_client).to receive(:current_branch).and_return('mybranch')
|
48
|
+
allow(git_client).to receive(:remote).with('origin').and_return('git@github.com:donaldduck/testrepo')
|
49
|
+
allow(git_client).to receive(:remote).with('upstream').and_return('git@github.com:donald-fr/testrepo_u')
|
49
50
|
|
50
51
|
expected_output = <<~STR
|
51
52
|
Creating the issue...
|
52
|
-
Assigning authenticated user...
|
53
53
|
Issue address: https://github.com/donald-fr/testrepo_u/issues/7
|
54
54
|
STR
|
55
55
|
|
@@ -57,7 +57,7 @@ describe Geet::Services::CreateIssue do
|
|
57
57
|
|
58
58
|
actual_created_issue = VCR.use_cassette('create_issue_upstream') do
|
59
59
|
create_options = { no_open_issue: true, output: actual_output }
|
60
|
-
described_class.new.execute(
|
60
|
+
described_class.new(upstream_repository).execute('Title', 'Description', create_options)
|
61
61
|
end
|
62
62
|
|
63
63
|
expect(actual_output.string).to eql(expected_output)
|