geet 0.1.8 → 0.1.9
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/.rspec +2 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +31 -0
- data/README.md +0 -2
- data/bin/geet +50 -39
- data/geet.gemspec +1 -1
- data/lib/geet/commandline/commands.rb +14 -0
- data/lib/geet/{helpers/configuration_helper.rb → commandline/configuration.rb} +4 -12
- data/lib/geet/git/repository.rb +93 -44
- data/lib/geet/{git_hub → github}/abstract_issue.rb +13 -13
- data/lib/geet/github/account.rb +19 -0
- data/lib/geet/{git_hub/api_helper.rb → github/api_interface.rb} +21 -19
- data/lib/geet/github/collaborator.rb +17 -0
- data/lib/geet/{git_hub → github}/gist.rb +4 -4
- data/lib/geet/{git_hub → github}/issue.rb +10 -10
- data/lib/geet/github/label.rb +17 -0
- data/lib/geet/{git_hub → github}/milestone.rb +11 -11
- data/lib/geet/github/pr.rb +61 -0
- data/lib/geet/services/create_gist.rb +4 -4
- data/lib/geet/services/create_issue.rb +30 -25
- data/lib/geet/services/create_pr.rb +28 -27
- data/lib/geet/services/list_issues.rb +2 -2
- data/lib/geet/services/list_labels.rb +2 -2
- data/lib/geet/services/list_milestones.rb +10 -10
- data/lib/geet/services/list_prs.rb +2 -2
- data/lib/geet/services/merge_pr.rb +8 -7
- data/lib/geet/version.rb +1 -1
- data/spec/integration/create_gist_spec.rb +46 -0
- data/spec/integration/create_issue_spec.rb +66 -0
- data/spec/integration/create_pr_spec.rb +68 -0
- data/spec/integration/list_issues_spec.rb +52 -0
- data/spec/integration/list_labels_spec.rb +28 -0
- data/spec/integration/list_milestones_spec.rb +43 -0
- data/spec/integration/list_prs_spec.rb +52 -0
- data/spec/integration/merge_pr_spec.rb +30 -0
- data/spec/spec_helper.rb +121 -0
- data/spec/vcr_cassettes/create_gist_private.yml +80 -0
- data/spec/vcr_cassettes/create_gist_public.yml +80 -0
- data/spec/vcr_cassettes/create_issue.yml +534 -0
- data/spec/vcr_cassettes/create_issue_upstream.yml +235 -0
- data/spec/vcr_cassettes/create_pr.yml +693 -0
- data/spec/vcr_cassettes/create_pr_upstream.yml +313 -0
- data/spec/vcr_cassettes/list_issues.yml +82 -0
- data/spec/vcr_cassettes/list_issues_upstream.yml +84 -0
- data/spec/vcr_cassettes/list_labels.yml +78 -0
- data/spec/vcr_cassettes/list_milestones.yml +468 -0
- data/spec/vcr_cassettes/list_prs.yml +84 -0
- data/spec/vcr_cassettes/list_prs_upstream.yml +80 -0
- data/spec/vcr_cassettes/merge_pr.yml +156 -0
- metadata +36 -11
- data/lib/geet/git_hub/account.rb +0 -19
- data/lib/geet/git_hub/pr.rb +0 -57
- data/lib/geet/git_hub/remote_repository.rb +0 -65
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative '../helpers/os_helper.rb'
|
4
|
-
require_relative '../git/repository.rb'
|
5
4
|
|
6
5
|
module Geet
|
7
6
|
module Services
|
@@ -13,21 +12,21 @@ module Geet
|
|
13
12
|
# :reviewer_patterns
|
14
13
|
# :no_open_pr
|
15
14
|
#
|
16
|
-
def execute(repository, title, description, label_patterns: nil, milestone_pattern: nil, reviewer_patterns: nil, no_open_pr: nil, **)
|
17
|
-
labels_thread = select_labels(repository, label_patterns) if label_patterns
|
18
|
-
milestone_thread = find_milestone(repository, milestone_pattern) if milestone_pattern
|
19
|
-
reviewers_thread = select_reviewers(repository, reviewer_patterns) if reviewer_patterns
|
15
|
+
def execute(repository, title, description, label_patterns: nil, milestone_pattern: nil, reviewer_patterns: nil, no_open_pr: nil, output: $stdout, **)
|
16
|
+
labels_thread = select_labels(repository, label_patterns, output) if label_patterns
|
17
|
+
milestone_thread = find_milestone(repository, milestone_pattern, output) if milestone_pattern
|
18
|
+
reviewers_thread = select_reviewers(repository, reviewer_patterns, output) if reviewer_patterns
|
20
19
|
|
21
20
|
selected_labels = labels_thread&.join&.value
|
22
21
|
reviewers = reviewers_thread&.join&.value
|
23
22
|
milestone = milestone_thread&.join&.value
|
24
23
|
|
25
|
-
pr = create_pr(repository, title, description)
|
24
|
+
pr = create_pr(repository, title, description, output)
|
26
25
|
|
27
|
-
assign_user_thread = assign_authenticated_user(pr, repository)
|
28
|
-
add_labels_thread = add_labels(pr, selected_labels) if selected_labels
|
29
|
-
set_milestone_thread = set_milestone(pr, milestone) if milestone
|
30
|
-
request_review_thread = request_review(pr, reviewers) if reviewers
|
26
|
+
assign_user_thread = assign_authenticated_user(pr, repository, output)
|
27
|
+
add_labels_thread = add_labels(pr, selected_labels, output) if selected_labels
|
28
|
+
set_milestone_thread = set_milestone(pr, milestone, output) if milestone
|
29
|
+
request_review_thread = request_review(pr, reviewers, output) if reviewers
|
31
30
|
|
32
31
|
assign_user_thread.join
|
33
32
|
add_labels_thread&.join
|
@@ -35,18 +34,20 @@ module Geet
|
|
35
34
|
request_review_thread&.join
|
36
35
|
|
37
36
|
if no_open_pr
|
38
|
-
puts "PR address: #{pr.link}"
|
37
|
+
output.puts "PR address: #{pr.link}"
|
39
38
|
else
|
40
39
|
os_open(pr.link)
|
41
40
|
end
|
41
|
+
|
42
|
+
pr
|
42
43
|
end
|
43
44
|
|
44
45
|
private
|
45
46
|
|
46
47
|
# Internal actions
|
47
48
|
|
48
|
-
def select_labels(repository, label_patterns)
|
49
|
-
puts 'Finding labels...'
|
49
|
+
def select_labels(repository, label_patterns, output)
|
50
|
+
output.puts 'Finding labels...'
|
50
51
|
|
51
52
|
Thread.new do
|
52
53
|
all_labels = repository.labels
|
@@ -55,8 +56,8 @@ module Geet
|
|
55
56
|
end
|
56
57
|
end
|
57
58
|
|
58
|
-
def find_milestone(repository, milestone_pattern)
|
59
|
-
puts 'Finding milestone...'
|
59
|
+
def find_milestone(repository, milestone_pattern, output)
|
60
|
+
output.puts 'Finding milestone...'
|
60
61
|
|
61
62
|
Thread.new do
|
62
63
|
if milestone_pattern =~ /\A\d+\Z/
|
@@ -69,8 +70,8 @@ module Geet
|
|
69
70
|
end
|
70
71
|
end
|
71
72
|
|
72
|
-
def select_reviewers(repository, reviewer_patterns)
|
73
|
-
puts 'Finding collaborators...'
|
73
|
+
def select_reviewers(repository, reviewer_patterns, output)
|
74
|
+
output.puts 'Finding collaborators...'
|
74
75
|
|
75
76
|
Thread.new do
|
76
77
|
all_collaborators = repository.collaborators
|
@@ -79,38 +80,38 @@ module Geet
|
|
79
80
|
end
|
80
81
|
end
|
81
82
|
|
82
|
-
def create_pr(repository, title, description)
|
83
|
-
puts 'Creating PR...'
|
83
|
+
def create_pr(repository, title, description, output)
|
84
|
+
output.puts 'Creating PR...'
|
84
85
|
|
85
86
|
repository.create_pr(title, description, repository.current_branch)
|
86
87
|
end
|
87
88
|
|
88
|
-
def assign_authenticated_user(pr, repository)
|
89
|
-
puts 'Assigning authenticated user...'
|
89
|
+
def assign_authenticated_user(pr, repository, output)
|
90
|
+
output.puts 'Assigning authenticated user...'
|
90
91
|
|
91
92
|
Thread.new do
|
92
93
|
pr.assign_users(repository.authenticated_user)
|
93
94
|
end
|
94
95
|
end
|
95
96
|
|
96
|
-
def add_labels(pr, selected_labels)
|
97
|
-
puts "Adding labels #{selected_labels.join(', ')}..."
|
97
|
+
def add_labels(pr, selected_labels, output)
|
98
|
+
output.puts "Adding labels #{selected_labels.join(', ')}..."
|
98
99
|
|
99
100
|
Thread.new do
|
100
101
|
pr.add_labels(selected_labels)
|
101
102
|
end
|
102
103
|
end
|
103
104
|
|
104
|
-
def set_milestone(pr, milestone)
|
105
|
-
puts "Setting milestone #{milestone.title}..."
|
105
|
+
def set_milestone(pr, milestone, output)
|
106
|
+
output.puts "Setting milestone #{milestone.title}..."
|
106
107
|
|
107
108
|
Thread.new do
|
108
109
|
pr.edit(milestone: milestone.number)
|
109
110
|
end
|
110
111
|
end
|
111
112
|
|
112
|
-
def request_review(pr, reviewers)
|
113
|
-
puts "Requesting review from #{reviewers.join(', ')}..."
|
113
|
+
def request_review(pr, reviewers, output)
|
114
|
+
output.puts "Requesting review from #{reviewers.join(', ')}..."
|
114
115
|
|
115
116
|
Thread.new do
|
116
117
|
pr.request_review(reviewers)
|
@@ -3,11 +3,11 @@
|
|
3
3
|
module Geet
|
4
4
|
module Services
|
5
5
|
class ListIssues
|
6
|
-
def execute(repository)
|
6
|
+
def execute(repository, output: $stdout)
|
7
7
|
issues = repository.issues
|
8
8
|
|
9
9
|
issues.each do |issue|
|
10
|
-
puts "#{issue.number}. #{issue.title} (#{issue.link})"
|
10
|
+
output.puts "#{issue.number}. #{issue.title} (#{issue.link})"
|
11
11
|
end
|
12
12
|
end
|
13
13
|
end
|
@@ -3,19 +3,19 @@
|
|
3
3
|
module Geet
|
4
4
|
module Services
|
5
5
|
class ListMilestones
|
6
|
-
def execute(repository)
|
7
|
-
milestones = find_milestones(repository)
|
8
|
-
issues_by_milestone_number = find_milestone_issues(repository, milestones)
|
6
|
+
def execute(repository, output: $stdout)
|
7
|
+
milestones = find_milestones(repository, output)
|
8
|
+
issues_by_milestone_number = find_milestone_issues(repository, milestones, output)
|
9
9
|
|
10
|
-
puts
|
10
|
+
output.puts
|
11
11
|
|
12
12
|
milestones.each do |milestone|
|
13
|
-
puts milestone_description(milestone)
|
13
|
+
output.puts milestone_description(milestone)
|
14
14
|
|
15
15
|
milestone_issues = issues_by_milestone_number[milestone.number]
|
16
16
|
|
17
17
|
milestone_issues.each do |issue|
|
18
|
-
puts " #{issue.number}. #{issue.title} (#{issue.link})"
|
18
|
+
output.puts " #{issue.number}. #{issue.title} (#{issue.link})"
|
19
19
|
end
|
20
20
|
end
|
21
21
|
end
|
@@ -30,14 +30,14 @@ module Geet
|
|
30
30
|
description
|
31
31
|
end
|
32
32
|
|
33
|
-
def find_milestones(repository)
|
34
|
-
puts 'Finding milestones...'
|
33
|
+
def find_milestones(repository, output)
|
34
|
+
output.puts 'Finding milestones...'
|
35
35
|
|
36
36
|
repository.milestones
|
37
37
|
end
|
38
38
|
|
39
|
-
def find_milestone_issues(repository, milestones)
|
40
|
-
puts 'Finding issues...'
|
39
|
+
def find_milestone_issues(repository, milestones, output)
|
40
|
+
output.puts 'Finding issues...'
|
41
41
|
|
42
42
|
# Interestingly, on MRI, concurrent hash access is not a problem without mutex,
|
43
43
|
# since due to the GIL, only one thread at a time will actually access it.
|
@@ -3,11 +3,11 @@
|
|
3
3
|
module Geet
|
4
4
|
module Services
|
5
5
|
class ListPrs
|
6
|
-
def execute(repository)
|
6
|
+
def execute(repository, output: $stdout)
|
7
7
|
prs = repository.prs
|
8
8
|
|
9
9
|
prs.each do |pr|
|
10
|
-
puts "#{pr.number}. #{pr.title} (#{pr.link})"
|
10
|
+
output.puts "#{pr.number}. #{pr.title} (#{pr.link})"
|
11
11
|
end
|
12
12
|
end
|
13
13
|
end
|
@@ -3,10 +3,11 @@
|
|
3
3
|
module Geet
|
4
4
|
module Services
|
5
5
|
class MergePr
|
6
|
-
def execute(repository)
|
6
|
+
def execute(repository, output: $stdout)
|
7
7
|
merge_head = find_merge_head(repository)
|
8
|
-
pr = checked_find_branch_pr(repository, merge_head)
|
9
|
-
merge_pr(pr)
|
8
|
+
pr = checked_find_branch_pr(repository, merge_head, output)
|
9
|
+
merge_pr(pr, output)
|
10
|
+
pr
|
10
11
|
end
|
11
12
|
|
12
13
|
private
|
@@ -16,8 +17,8 @@ module Geet
|
|
16
17
|
end
|
17
18
|
|
18
19
|
# Expect to find only one.
|
19
|
-
def checked_find_branch_pr(repository, head)
|
20
|
-
puts "Finding PR with head (#{head})..."
|
20
|
+
def checked_find_branch_pr(repository, head, output)
|
21
|
+
output.puts "Finding PR with head (#{head})..."
|
21
22
|
|
22
23
|
prs = repository.prs(head: head)
|
23
24
|
|
@@ -26,8 +27,8 @@ module Geet
|
|
26
27
|
prs[0]
|
27
28
|
end
|
28
29
|
|
29
|
-
def merge_pr(pr)
|
30
|
-
puts "Merging PR ##{pr.number}..."
|
30
|
+
def merge_pr(pr, output)
|
31
|
+
output.puts "Merging PR ##{pr.number}..."
|
31
32
|
|
32
33
|
pr.merge
|
33
34
|
end
|
data/lib/geet/version.rb
CHANGED
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'tempfile'
|
3
|
+
|
4
|
+
require_relative '../../lib/geet/git/repository'
|
5
|
+
require_relative '../../lib/geet/services/create_gist'
|
6
|
+
|
7
|
+
describe Geet::Services::CreateGist do
|
8
|
+
let(:repository) { Geet::Git::Repository.new(ENV.fetch('GITHUB_API_TOKEN')) }
|
9
|
+
let(:tempfile) { Tempfile.open('geet_gist') { |file| file << "testcontent" } }
|
10
|
+
|
11
|
+
it 'should create a public gist' do
|
12
|
+
expected_output = <<~STR
|
13
|
+
Creating a public gist...
|
14
|
+
Gist address: https://gist.github.com/b01dface
|
15
|
+
STR
|
16
|
+
|
17
|
+
actual_output = StringIO.new
|
18
|
+
|
19
|
+
VCR.use_cassette("create_gist_public") do
|
20
|
+
described_class.new.execute(
|
21
|
+
repository, tempfile.path,
|
22
|
+
description: 'testdescription', publik: true, no_browse: true, output: actual_output
|
23
|
+
)
|
24
|
+
end
|
25
|
+
|
26
|
+
expect(actual_output.string).to eql(expected_output)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should create a private gist' do
|
30
|
+
expected_output = <<~STR
|
31
|
+
Creating a private gist...
|
32
|
+
Gist address: https://gist.github.com/deadbeef
|
33
|
+
STR
|
34
|
+
|
35
|
+
actual_output = StringIO.new
|
36
|
+
|
37
|
+
VCR.use_cassette("create_gist_private") do
|
38
|
+
described_class.new.execute(
|
39
|
+
repository, tempfile.path,
|
40
|
+
description: 'testdescription', no_browse: true, output: actual_output
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
expect(actual_output.string).to eql(expected_output)
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require_relative '../../lib/geet/git/repository'
|
4
|
+
require_relative '../../lib/geet/services/create_issue'
|
5
|
+
|
6
|
+
describe Geet::Services::CreateIssue do
|
7
|
+
let(:repository) { Geet::Git::Repository.new(ENV.fetch('GITHUB_API_TOKEN')) }
|
8
|
+
let(:upstream_repository) { Geet::Git::Repository.new(ENV.fetch('GITHUB_API_TOKEN'), upstream: true) }
|
9
|
+
|
10
|
+
context 'with labels, assignees and milestones' do
|
11
|
+
it 'should create an issue' do
|
12
|
+
allow(repository).to receive(:remote).with('origin').and_return('git@github.com:donaldduck/testrepo')
|
13
|
+
|
14
|
+
expected_output = <<~STR
|
15
|
+
Finding labels...
|
16
|
+
Finding milestone...
|
17
|
+
Finding collaborators...
|
18
|
+
Creating the issue...
|
19
|
+
Adding labels bug, invalid...
|
20
|
+
Setting milestone 0.0.1...
|
21
|
+
Assigning users donald-ts, donald-fr...
|
22
|
+
Issue address: https://github.com/donaldduck/testrepo/issues/1
|
23
|
+
STR
|
24
|
+
|
25
|
+
actual_output = StringIO.new
|
26
|
+
|
27
|
+
actual_created_issue = VCR.use_cassette("create_issue") do
|
28
|
+
described_class.new.execute(
|
29
|
+
repository, 'Title', 'Description',
|
30
|
+
label_patterns: 'bug,invalid', milestone_pattern: '0.0.1', assignee_patterns: 'nald-ts,nald-fr',
|
31
|
+
no_open_issue: true, output: actual_output
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
expect(actual_output.string).to eql(expected_output)
|
36
|
+
|
37
|
+
expect(actual_created_issue.number).to eql(1)
|
38
|
+
expect(actual_created_issue.title).to eql('Title')
|
39
|
+
expect(actual_created_issue.link).to eql('https://github.com/donaldduck/testrepo/issues/1')
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should create an upstream issue' do
|
44
|
+
allow(upstream_repository).to receive(:current_branch).and_return('mybranch')
|
45
|
+
allow(upstream_repository).to receive(:remote).with('origin').and_return('git@github.com:donaldduck/testrepo')
|
46
|
+
allow(upstream_repository).to receive(:remote).with('upstream').and_return('git@github.com:donald-fr/testrepo_u')
|
47
|
+
|
48
|
+
expected_output = <<~STR
|
49
|
+
Creating the issue...
|
50
|
+
Assigning authenticated user...
|
51
|
+
Issue address: https://github.com/donald-fr/testrepo_u/issues/7
|
52
|
+
STR
|
53
|
+
|
54
|
+
actual_output = StringIO.new
|
55
|
+
|
56
|
+
actual_created_issue = VCR.use_cassette("create_issue_upstream") do
|
57
|
+
described_class.new.execute(upstream_repository, 'Title', 'Description', no_open_issue: true, output: actual_output)
|
58
|
+
end
|
59
|
+
|
60
|
+
expect(actual_output.string).to eql(expected_output)
|
61
|
+
|
62
|
+
expect(actual_created_issue.number).to eql(7)
|
63
|
+
expect(actual_created_issue.title).to eql('Title')
|
64
|
+
expect(actual_created_issue.link).to eql('https://github.com/donald-fr/testrepo_u/issues/7')
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require_relative '../../lib/geet/git/repository'
|
4
|
+
require_relative '../../lib/geet/services/create_pr'
|
5
|
+
|
6
|
+
describe Geet::Services::CreatePr do
|
7
|
+
let(:repository) { Geet::Git::Repository.new(ENV.fetch('GITHUB_API_TOKEN')) }
|
8
|
+
let(:upstream_repository) { Geet::Git::Repository.new(ENV.fetch('GITHUB_API_TOKEN'), upstream: true) }
|
9
|
+
|
10
|
+
context 'with labels, reviewers and milestones' do
|
11
|
+
it 'should create a PR' do
|
12
|
+
allow(repository).to receive(:current_branch).and_return('mybranch1')
|
13
|
+
allow(repository).to receive(:remote).with('origin').and_return('git@github.com:donaldduck/testrepo')
|
14
|
+
|
15
|
+
expected_output = <<~STR
|
16
|
+
Finding labels...
|
17
|
+
Finding milestone...
|
18
|
+
Finding collaborators...
|
19
|
+
Creating PR...
|
20
|
+
Assigning authenticated user...
|
21
|
+
Adding labels other_bug, invalid...
|
22
|
+
Setting milestone 0.0.1...
|
23
|
+
Requesting review from donald-ts, donald-fr...
|
24
|
+
PR address: https://github.com/donaldduck/testrepo/pull/3
|
25
|
+
STR
|
26
|
+
|
27
|
+
actual_output = StringIO.new
|
28
|
+
|
29
|
+
actual_created_pr = VCR.use_cassette("create_pr") do
|
30
|
+
described_class.new.execute(
|
31
|
+
repository, 'Title', 'Description',
|
32
|
+
label_patterns: '_bug,invalid', milestone_pattern: '0.0.1', reviewer_patterns: 'nald-ts,nald-fr',
|
33
|
+
no_open_pr: true, output: actual_output
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
expect(actual_output.string).to eql(expected_output)
|
38
|
+
|
39
|
+
expect(actual_created_pr.number).to eql(3)
|
40
|
+
expect(actual_created_pr.title).to eql('Title')
|
41
|
+
expect(actual_created_pr.link).to eql('https://github.com/donaldduck/testrepo/pull/3')
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should create an upstream PR' do
|
46
|
+
allow(upstream_repository).to receive(:current_branch).and_return('mybranch')
|
47
|
+
allow(upstream_repository).to receive(:remote).with('origin').and_return('git@github.com:donaldduck/testrepo_2f')
|
48
|
+
allow(upstream_repository).to receive(:remote).with('upstream').and_return('git@github.com:donald-fr/testrepo_u')
|
49
|
+
|
50
|
+
expected_output = <<~STR
|
51
|
+
Creating PR...
|
52
|
+
Assigning authenticated user...
|
53
|
+
PR address: https://github.com/donald-fr/testrepo_u/pull/4
|
54
|
+
STR
|
55
|
+
|
56
|
+
actual_output = StringIO.new
|
57
|
+
|
58
|
+
actual_created_pr = VCR.use_cassette("create_pr_upstream") do
|
59
|
+
described_class.new.execute(upstream_repository, 'Title', 'Description', no_open_pr: true, output: actual_output)
|
60
|
+
end
|
61
|
+
|
62
|
+
expect(actual_output.string).to eql(expected_output)
|
63
|
+
|
64
|
+
expect(actual_created_pr.number).to eql(4)
|
65
|
+
expect(actual_created_pr.title).to eql('Title')
|
66
|
+
expect(actual_created_pr.link).to eql('https://github.com/donald-fr/testrepo_u/pull/4')
|
67
|
+
end
|
68
|
+
end
|