geet 0.1.8 → 0.1.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +2 -0
  3. data/Gemfile +10 -0
  4. data/Gemfile.lock +31 -0
  5. data/README.md +0 -2
  6. data/bin/geet +50 -39
  7. data/geet.gemspec +1 -1
  8. data/lib/geet/commandline/commands.rb +14 -0
  9. data/lib/geet/{helpers/configuration_helper.rb → commandline/configuration.rb} +4 -12
  10. data/lib/geet/git/repository.rb +93 -44
  11. data/lib/geet/{git_hub → github}/abstract_issue.rb +13 -13
  12. data/lib/geet/github/account.rb +19 -0
  13. data/lib/geet/{git_hub/api_helper.rb → github/api_interface.rb} +21 -19
  14. data/lib/geet/github/collaborator.rb +17 -0
  15. data/lib/geet/{git_hub → github}/gist.rb +4 -4
  16. data/lib/geet/{git_hub → github}/issue.rb +10 -10
  17. data/lib/geet/github/label.rb +17 -0
  18. data/lib/geet/{git_hub → github}/milestone.rb +11 -11
  19. data/lib/geet/github/pr.rb +61 -0
  20. data/lib/geet/services/create_gist.rb +4 -4
  21. data/lib/geet/services/create_issue.rb +30 -25
  22. data/lib/geet/services/create_pr.rb +28 -27
  23. data/lib/geet/services/list_issues.rb +2 -2
  24. data/lib/geet/services/list_labels.rb +2 -2
  25. data/lib/geet/services/list_milestones.rb +10 -10
  26. data/lib/geet/services/list_prs.rb +2 -2
  27. data/lib/geet/services/merge_pr.rb +8 -7
  28. data/lib/geet/version.rb +1 -1
  29. data/spec/integration/create_gist_spec.rb +46 -0
  30. data/spec/integration/create_issue_spec.rb +66 -0
  31. data/spec/integration/create_pr_spec.rb +68 -0
  32. data/spec/integration/list_issues_spec.rb +52 -0
  33. data/spec/integration/list_labels_spec.rb +28 -0
  34. data/spec/integration/list_milestones_spec.rb +43 -0
  35. data/spec/integration/list_prs_spec.rb +52 -0
  36. data/spec/integration/merge_pr_spec.rb +30 -0
  37. data/spec/spec_helper.rb +121 -0
  38. data/spec/vcr_cassettes/create_gist_private.yml +80 -0
  39. data/spec/vcr_cassettes/create_gist_public.yml +80 -0
  40. data/spec/vcr_cassettes/create_issue.yml +534 -0
  41. data/spec/vcr_cassettes/create_issue_upstream.yml +235 -0
  42. data/spec/vcr_cassettes/create_pr.yml +693 -0
  43. data/spec/vcr_cassettes/create_pr_upstream.yml +313 -0
  44. data/spec/vcr_cassettes/list_issues.yml +82 -0
  45. data/spec/vcr_cassettes/list_issues_upstream.yml +84 -0
  46. data/spec/vcr_cassettes/list_labels.yml +78 -0
  47. data/spec/vcr_cassettes/list_milestones.yml +468 -0
  48. data/spec/vcr_cassettes/list_prs.yml +84 -0
  49. data/spec/vcr_cassettes/list_prs_upstream.yml +80 -0
  50. data/spec/vcr_cassettes/merge_pr.yml +156 -0
  51. metadata +36 -11
  52. data/lib/geet/git_hub/account.rb +0 -19
  53. data/lib/geet/git_hub/pr.rb +0 -57
  54. 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,11 +3,11 @@
3
3
  module Geet
4
4
  module Services
5
5
  class ListLabels
6
- def execute(repository)
6
+ def execute(repository, output: $stdout)
7
7
  labels = repository.labels
8
8
 
9
9
  labels.each do |label|
10
- puts "- #{label}"
10
+ output.puts "- #{label}"
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Geet
4
- VERSION = '0.1.8'
4
+ VERSION = '0.1.9'
5
5
  end
@@ -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