reviewlette 0.0.6 → 0.0.7
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/.gitignore +4 -6
- data/Gemfile +1 -1
- data/Gemfile.lock +6 -6
- data/README.md +5 -57
- data/Rakefile +13 -1
- data/bin/reviewlette +2 -1
- data/config/github_example.yml +3 -0
- data/config/members_example.yml +25 -0
- data/config/trello_example.yml +9 -0
- data/lib/reviewlette/github_connection.rb +29 -34
- data/lib/reviewlette/trello_connection.rb +30 -64
- data/lib/reviewlette/vacations.rb +23 -31
- data/lib/reviewlette.rb +36 -185
- data/reviewlette.gemspec +2 -2
- data/spec/github_connection_spec.rb +18 -73
- data/spec/reviewlette_spec.rb +40 -336
- data/spec/spec_helper.rb +1 -8
- data/spec/trello_connection_spec.rb +29 -164
- data/spec/vacation_spec.rb +26 -4
- metadata +12 -27
- data/Guardfile +0 -24
- data/config/.github.yml +0 -2
- data/config/.members.yml +0 -1
- data/config/.trello.yml +0 -4
- data/lib/matching.rb +0 -0
- data/lib/reviewlette/database.rb +0 -77
- data/lib/reviewlette/exceptions.rb +0 -7
- data/lib/reviewlette/graph.html +0 -17
- data/lib/reviewlette/graph_gen.rb +0 -62
- data/lib/reviewlette/mail.rb +0 -27
- data/lib/reviewlette/reviewlette.db +0 -0
- data/lib/reviewlette/version.rb +0 -3
- data/prophet.rb +0 -4
- data/reviewlette.db +0 -0
- data/spec/database_spec.rb +0 -34
- data/spec/support/request_stubbing.rb +0 -305
- data/task +0 -1
data/lib/reviewlette.rb
CHANGED
@@ -1,202 +1,53 @@
|
|
1
1
|
require 'reviewlette/trello_connection'
|
2
2
|
require 'reviewlette/github_connection'
|
3
|
-
require 'reviewlette/database'
|
4
|
-
require 'reviewlette/graph_gen'
|
5
3
|
require 'reviewlette/vacations'
|
6
4
|
require 'yaml'
|
7
|
-
require 'octokit'
|
8
|
-
require 'trello'
|
9
5
|
|
10
|
-
|
6
|
+
VERSION = '0.0.7'
|
7
|
+
MEMBERS_CONFIG = YAML.load_file("#{File.dirname(__FILE__)}/../config/members.yml")
|
11
8
|
|
12
|
-
|
13
|
-
@trello_connection = Reviewlette::TrelloConnection.new
|
14
|
-
member_ids.map{|id| @trello_connection.find_member_by_id(id)}
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
module Reviewlette
|
19
|
-
|
20
|
-
attr_accessor :trello_connection, :github_connection, :repo, :board, :db
|
21
|
-
|
22
|
-
TRELLO_CONFIG1 = YAML.load_file("#{File.dirname(__FILE__)}/../config/.trello.yml")
|
23
|
-
|
24
|
-
class << self
|
25
|
-
|
26
|
-
# Execute logic.
|
27
|
-
def spin
|
28
|
-
setup
|
29
|
-
get_available_repos.each do |repo|
|
30
|
-
@repo = repo
|
31
|
-
get_unassigned_github_issues.each do |issue|
|
32
|
-
@number = issue[:number]
|
33
|
-
@title = issue[:title]
|
34
|
-
@body = issue[:body]
|
35
|
-
update_vacations
|
36
|
-
|
37
|
-
if find_card(@title.to_s) and find_id
|
38
|
-
if set_reviewer
|
39
|
-
transform_name
|
40
|
-
add_reviewer_on_github
|
41
|
-
comment_on_github
|
42
|
-
# add_to_trello_card
|
43
|
-
comment_on_trello
|
44
|
-
move_to_list
|
45
|
-
@db.add_pr_to_db(@title, @reviewer.username)
|
46
|
-
@reviewer = nil
|
47
|
-
Reviewlette::Graphgenerator.new.write_to_graphs('graph.html',Reviewlette::Graphgenerator.new.model_graphs(Reviewlette::Database.new.conscruct_line_data.to_json, Reviewlette::Database.new.conscruct_graph_struct.to_json, 'Donut'))
|
48
|
-
else
|
49
|
-
comment_on_error
|
50
|
-
end
|
51
|
-
end
|
52
|
-
puts 'No new issues.' unless @issues.present?
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
def get_available_repos
|
58
|
-
@repos = Reviewlette::GithubConnection::GITHUB_CONFIG['repo']
|
59
|
-
end
|
60
|
-
|
61
|
-
# Finds card based on title of Github Issue.
|
62
|
-
# Or by branch name if title does not include the trello number.
|
63
|
-
# Happens if the pullrequest consists of only one commit.
|
64
|
-
def find_card(title)
|
65
|
-
begin
|
66
|
-
match_pr_id_with_issue_id
|
67
|
-
@id = title.split('_').last.to_i
|
68
|
-
@id = fetch_branch if @id == 0 && !(@pullreq_ids.values.index(@number)).nil?
|
69
|
-
raise NoTrelloCardException, "Could not find a Trello card. Found #{title.split('_').last} instead, maybe the naming of your pullrequest is wrong? And/or you dont have a branch?" if @id == 0
|
70
|
-
true
|
71
|
-
rescue NoTrelloCardException => e
|
72
|
-
@logger.error e.message
|
73
|
-
puts (e.message)
|
74
|
-
false
|
75
|
-
end
|
76
|
-
end
|
9
|
+
class Reviewlette
|
77
10
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
end
|
83
|
-
end
|
11
|
+
def initialize
|
12
|
+
@github = GithubConnection.new
|
13
|
+
@trello = TrelloConnection.new
|
14
|
+
end
|
84
15
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
16
|
+
def run
|
17
|
+
@github.unassigned_pull_requests.each do |issue|
|
18
|
+
issue_id = issue[:number]
|
19
|
+
issue_title = issue[:title]
|
20
|
+
puts "*** Checking unassigned github pull request: #{issue_title}"
|
21
|
+
card_id = issue_title.split(/[_ -#\.]/).last.to_i
|
22
|
+
if card = @trello.find_card_by_id(card_id)
|
23
|
+
puts "Found matching trello card: #{card.name}"
|
24
|
+
reviewer = select_reviewer(issue, card)
|
25
|
+
if reviewer
|
26
|
+
@github.add_assignee(issue_id, reviewer['github_username'])
|
27
|
+
@github.reviewer_comment(issue_id, reviewer['github_username'], card)
|
28
|
+
comment = "@#{reviewer['trello_username']} will review https://github.com/#{@github.repo}/issues/#{issue_id}"
|
29
|
+
@trello.comment_on_card(comment, card)
|
30
|
+
@trello.move_card_to_list(card, 'In review')
|
91
31
|
else
|
92
|
-
|
32
|
+
puts "Could not find a reviewer for card: #{card.name}"
|
93
33
|
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
def parse_vacations
|
98
|
-
split = @vacations.map { |x| x.split(' - ') }
|
99
|
-
split.map { |x| x.map { |b| Date.parse(b) } }
|
100
|
-
end
|
101
|
-
|
102
|
-
# gets the branchname from github pullrequest
|
103
|
-
def fetch_branch
|
104
|
-
pr_id = @pullreq_ids.values.index(@number)
|
105
|
-
branch_name = @github_connection.get_branch_name(pr_id, @repo)
|
106
|
-
branch_name.split('_').last.to_i
|
107
|
-
end
|
108
|
-
|
109
|
-
# Matches Pull Request IDs with the respective Order of PullRequests
|
110
|
-
# to call them and get the branch name.
|
111
|
-
def match_pr_id_with_issue_id
|
112
|
-
@pullreq_ids = {}
|
113
|
-
@counter = 0
|
114
|
-
@github_connection.list_pulls(@repo).each do |x|
|
115
|
-
@pullreq_ids[@counter] = x.number
|
116
|
-
@counter +=1
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
# TODO: Generic Error message.
|
121
|
-
def comment_on_error
|
122
|
-
@trello_connection.comment_on_card("Skipped Issue #{@number} because everyone on the team is assigned to the card", @card)
|
123
|
-
end
|
124
|
-
|
125
|
-
# Gets [Array(String, String)] all GitHub Issues that are not assigned to someone.
|
126
|
-
def get_unassigned_github_issues
|
127
|
-
@issues = @github_connection.list_issues(@repo).select{|issue| !issue[:assignee]}
|
128
|
-
end
|
129
|
-
|
130
|
-
# Sets instance variables.
|
131
|
-
def setup
|
132
|
-
@logger = Logger.new('review.log')
|
133
|
-
@db = Reviewlette::Database.new
|
134
|
-
@github_connection = Reviewlette::GithubConnection.new
|
135
|
-
@trello_connection = Reviewlette::TrelloConnection.new
|
136
|
-
@board = Trello::Board.find(TRELLO_CONFIG1['board_id'])
|
137
|
-
end
|
138
|
-
|
139
|
-
# Finds a sets card.
|
140
|
-
def find_id
|
141
|
-
if @id != 0
|
142
|
-
@card = @trello_connection.find_card_by_id(@id)
|
143
|
-
true
|
144
34
|
else
|
145
|
-
|
146
|
-
false
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
# Selects and sets reviewer.
|
151
|
-
def set_reviewer
|
152
|
-
begin
|
153
|
-
while !(@reviewer)
|
154
|
-
@reviewer = @trello_connection.determine_reviewer(@card) if @card
|
155
|
-
end
|
156
|
-
@trelloname = @reviewer.username
|
157
|
-
puts "Selected #{@reviewer.username}"
|
158
|
-
return true
|
159
|
-
rescue AlreadyAssignedException => e
|
160
|
-
@logger.warn("Skipped Issue #{@card.short_id} because #{e.message}")
|
161
|
-
puts ("Skipped Issue #{@card.short_id} because #{e.message}")
|
162
|
-
return false
|
35
|
+
puts "No matching card found (id #{card_id})"
|
163
36
|
end
|
164
37
|
end
|
165
38
|
|
166
|
-
|
167
|
-
def transform_name
|
168
|
-
@githubname = @db.find_gh_name_by_trello_name(@trelloname)
|
169
|
-
end
|
170
|
-
|
171
|
-
# Adds Assignee on GitHub.
|
172
|
-
def add_reviewer_on_github
|
173
|
-
@github_connection.add_assignee(@repo, @number, @title, @body, @githubname) if @number && @githubname
|
174
|
-
end
|
175
|
-
|
176
|
-
# Comments on GitHub.
|
177
|
-
def comment_on_github
|
178
|
-
@github_connection.comment_on_issue(@repo, @number, @githubname, @card.url) if @number && @githubname
|
179
|
-
end
|
180
|
-
# Adds Reviewer on Trello Card.
|
181
|
-
def add_to_trello_card
|
182
|
-
@trello_connection.add_reviewer_to_card(@reviewer, @card)
|
183
|
-
end
|
184
|
-
|
185
|
-
# Comments on Trello Card.
|
186
|
-
def comment_on_trello
|
187
|
-
@full_comment = '@' + @trelloname + ' will review ' + 'https://github.com/'+ @repo+'/issues/'+@number.to_s
|
188
|
-
@trello_connection.comment_on_card(@full_comment, @card) if @full_comment
|
189
|
-
end
|
39
|
+
end
|
190
40
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
41
|
+
def select_reviewer(issue, card)
|
42
|
+
reviewers = MEMBERS_CONFIG['members']
|
43
|
+
# remove people on vacation
|
44
|
+
members_on_vacation = Vacations.members_on_vacation
|
45
|
+
reviewers = reviewers.reject{|r| members_on_vacation.include? r['suse_username'] }
|
46
|
+
# remove trello card owner
|
47
|
+
reviewers = reviewers.reject{|r| card.members.map(&:username).include? r['trello_username'] }
|
48
|
+
reviewer = reviewers.sample
|
49
|
+
puts "Selected reviewer: #{reviewer['name']} from pool #{reviewers.map{|r| r['name']}}" if reviewer
|
50
|
+
reviewer
|
201
51
|
end
|
52
|
+
|
202
53
|
end
|
data/reviewlette.gemspec
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
lib = File.expand_path('../lib', __FILE__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'reviewlette
|
4
|
+
require 'reviewlette'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "reviewlette"
|
8
|
-
spec.version =
|
8
|
+
spec.version = VERSION
|
9
9
|
spec.authors = ["jschmid1"]
|
10
10
|
spec.email = ["jschmid@suse.de"]
|
11
11
|
spec.summary = %q{Randomly assignes a reviewer to your Pullrequest and corresponding Trello Card.}
|
@@ -1,96 +1,41 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
3
|
+
describe GithubConnection do
|
4
4
|
|
5
|
-
|
5
|
+
GITHUB_CONFIG = { token: '661', repo: 'SUSE/reviewlette' }
|
6
|
+
subject { GithubConnection }
|
7
|
+
let( :connection ) { subject.new }
|
6
8
|
|
7
9
|
describe '.new' do
|
8
10
|
|
9
|
-
it '
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
describe '#pull_merged?' do
|
17
|
-
let( :connection ) { subject.new }
|
18
|
-
|
19
|
-
it 'checks if the pull is merged' do
|
20
|
-
allow(connection.client).to receive(:pull_merged?).with('true', 6).and_return true
|
21
|
-
expect(connection.pull_merged?('true', 6)).to be true
|
22
|
-
end
|
23
|
-
|
24
|
-
it 'checks if the pull is not merged' do
|
25
|
-
allow(connection.client).to receive(:pull_merged?).with('false', 5).and_return false
|
26
|
-
expect(connection.pull_merged?('false', 5)).to be false
|
11
|
+
it 'initializes octokit client and repo' do
|
12
|
+
expect(Octokit::Client).to receive(:new).with(:access_token => GITHUB_CONFIG['token'])
|
13
|
+
connection = subject.new
|
14
|
+
expect(connection.repo).to eq(GITHUB_CONFIG['repo'])
|
27
15
|
end
|
28
16
|
end
|
29
17
|
|
30
18
|
describe '#add_assignee' do
|
31
|
-
let( :connection ) { subject.new }
|
32
|
-
|
33
19
|
it 'adds an assignee to the gh issue' do
|
34
|
-
|
35
|
-
|
36
|
-
allow(connection.client).to receive(:update_issue).with(*params2).and_return true
|
37
|
-
expect(connection.add_assignee(*params)).to eq true
|
38
|
-
end
|
39
|
-
|
40
|
-
it 'fails to add an assignee to the gh issue' do
|
41
|
-
params = [connection.repo, 4, 'title', 'body', 'name']
|
42
|
-
params2 = [connection.repo, 4, 'title', 'body', :assignee => 'name']
|
43
|
-
allow(connection.client).to receive(:update_issue).with(*params2).and_return false
|
44
|
-
expect(connection.add_assignee(*params)).to eq false
|
20
|
+
expect(connection.client).to receive(:update_issue).with(connection.repo, 11, :assignee => 'test')
|
21
|
+
connection.add_assignee(11, 'test')
|
45
22
|
end
|
46
23
|
end
|
47
24
|
|
48
|
-
describe '#
|
49
|
-
let( :connection ) { subject.new }
|
50
|
-
|
25
|
+
describe '#reviewer_comment' do
|
51
26
|
it 'comments on a given issue' do
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
end
|
57
|
-
|
58
|
-
it 'fails to comment on a given issue and fails' do
|
59
|
-
params = [connection.repo, 4, '@name is your reviewer :thumbsup: check url']
|
60
|
-
params2 = [connection.repo, 4, 'name', 'url']
|
61
|
-
allow(connection.client).to receive(:add_comment).with(*params).and_return false
|
62
|
-
expect(connection.comment_on_issue(*params2)).to eq false
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
describe '#list_issues' do
|
67
|
-
let( :connection ) { subject.new }
|
68
|
-
|
69
|
-
it 'fails to determine if an assignee is set' do
|
70
|
-
allow(connection.client).to receive_message_chain(:list_issues)
|
71
|
-
connection.list_issues(connection.repo)
|
27
|
+
card = Trello::Card.new
|
28
|
+
allow(card).to receive(:url).and_return('url')
|
29
|
+
expect(connection.client).to receive(:add_comment).with(connection.repo, 11, anything)
|
30
|
+
connection.reviewer_comment(11, 'test', card)
|
72
31
|
end
|
73
32
|
end
|
74
33
|
|
75
34
|
describe '#list_pulls' do
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
expect(connection.client).to receive(:pull_requests)
|
80
|
-
connection.list_pulls(connection.repo)
|
35
|
+
it 'lists all pullrequests for a given repository' do
|
36
|
+
expect(connection.client).to receive(:pull_requests).with(connection.repo)
|
37
|
+
connection.list_pulls
|
81
38
|
end
|
82
39
|
end
|
83
40
|
|
84
|
-
describe '#get_branch_name' do
|
85
|
-
let( :connection ) { subject.new }
|
86
|
-
|
87
|
-
it 'get branch name based on a repo and a pullrequest id' do
|
88
|
-
pulls = [double({ 'head' => double({ 'ref' => 'number'})})]
|
89
|
-
pr = pulls.first
|
90
|
-
expect(connection.client).to receive(:pull_requests).with(connection.repo).and_return pulls
|
91
|
-
expect(pulls).to receive(:[]).with(3).and_return pr
|
92
|
-
expect(pr).to receive(:head).and_return pr.head
|
93
|
-
connection.get_branch_name(3, connection.repo)
|
94
|
-
end
|
95
|
-
end
|
96
41
|
end
|