reviewlette 0.0.9 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 163d81e853831b82b114bf4705a4b89621e308dc
4
- data.tar.gz: 75186e2b3813ee25c38b8ebdf60df1c9a5205171
3
+ metadata.gz: fc2e0db8f1f84d6d27f7057eecdb21a24aab3f7e
4
+ data.tar.gz: b7e681c5a4954a09144b509b5434a649b9c378a4
5
5
  SHA512:
6
- metadata.gz: 4daa9c0f5d7e62f4dc08604b66a6b8888b3ae5d6ca4486ac29d67cff05bec0ea9d5e7659e682b3107562e7021ac665e0d25e4955d067d4729e64c3d8a1d572ed
7
- data.tar.gz: 56f797d47df14a587b4b3bbfe99ad5290e345565c47548adb33f5d11641cc6fefdcd62f413798ad974d07bea0a3340f44a293a5684e44cea224b8c5d21e5e7f4
6
+ metadata.gz: 21647bb1f08a246343b1c3cb8920a668f87cbe2c461affaeceec60bb57f3d2c0f1c39357c4bcf77ae0419ff150a46ff8f6db9f21842c175cd5a3731f04af12ed
7
+ data.tar.gz: f4e2ac2ca8900f6a195d284d32e6e001751ee79528f8d0bbfdf899334f8e54e5bde6d96388892cc741cd2e928cfc8af743c512e1d1091eeb139cc59530a38791
@@ -0,0 +1 @@
1
+ /config/
@@ -1,5 +1,5 @@
1
1
  language: ruby
2
2
  rvm:
3
- - "2.0.0"
3
+ - "2.3.1"
4
4
  # uncomment this line if your project needs to run something other than `rake`:
5
- # script: bundle exec rspec spec
5
+ # script: bundle exec rspec spec
data/Gemfile CHANGED
@@ -1,24 +1,21 @@
1
1
  source 'http://rubygems.org'
2
2
 
3
- gem 'json'
4
- gem 'haml'
5
- gem 'octokit', '~> 3.8.0'
6
- gem 'ruby-trello'
7
- gem 'rdoc'
8
- gem 'rspec'
9
- gem 'webmock'
10
- gem 'rake'
11
- gem 'ap'
12
- gem 'byebug'
13
- gem 'simplecov'
14
- gem 'prophet'
15
- gem 'coveralls'
16
- gem 'sequel'
17
- gem 'sqlite3'
3
+ gemspec
18
4
 
5
+ group :development, :test do
6
+ gem 'ap'
7
+ gem 'rake'
8
+ gem 'debugger-linecache'
9
+ gem 'byebug'
10
+ end
19
11
 
20
- group :development do
12
+ group :test do
13
+ gem 'rspec'
14
+ gem 'webmock'
21
15
  gem 'guard'
22
16
  gem 'guard-rspec'
23
17
  gem 'libnotify'
18
+ gem 'simplecov'
19
+ gem 'coveralls'
20
+ gem 'rdoc'
24
21
  end
@@ -1,42 +1,47 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ reviewlette (1.0.0)
5
+ octokit
6
+ ruby-trello
7
+
1
8
  GEM
2
9
  remote: http://rubygems.org/
3
10
  specs:
4
- activemodel (4.1.1)
5
- activesupport (= 4.1.1)
6
- builder (~> 3.1)
7
- activesupport (4.1.1)
8
- i18n (~> 0.6, >= 0.6.9)
9
- json (~> 1.7, >= 1.7.7)
11
+ activemodel (5.0.0.1)
12
+ activesupport (= 5.0.0.1)
13
+ activesupport (5.0.0.1)
14
+ concurrent-ruby (~> 1.0, >= 1.0.2)
15
+ i18n (~> 0.7)
10
16
  minitest (~> 5.1)
11
- thread_safe (~> 0.1)
12
17
  tzinfo (~> 1.1)
13
- addressable (2.3.8)
18
+ addressable (2.5.0)
19
+ public_suffix (~> 2.0, >= 2.0.2)
14
20
  ap (0.1.1)
15
21
  httparty (>= 0.7.7)
16
- builder (3.2.2)
17
- byebug (3.1.2)
18
- columnize (~> 0.8)
19
- celluloid (0.16.0)
20
- timers (~> 4.0.0)
21
- coderay (1.1.0)
22
- columnize (0.8.9)
23
- coveralls (0.7.0)
24
- multi_json (~> 1.3)
25
- rest-client
26
- simplecov (>= 0.7)
27
- term-ansicolor
28
- thor
29
- crack (0.4.2)
22
+ byebug (9.0.6)
23
+ coderay (1.1.1)
24
+ concurrent-ruby (1.0.2)
25
+ coveralls (0.8.17)
26
+ json (>= 1.8, < 3)
27
+ simplecov (~> 0.12.0)
28
+ term-ansicolor (~> 1.3)
29
+ thor (~> 0.19.1)
30
+ tins (~> 1.6)
31
+ crack (0.4.3)
30
32
  safe_yaml (~> 1.0.0)
33
+ debugger-linecache (1.2.0)
31
34
  diff-lcs (1.2.5)
32
- docile (1.1.3)
33
- faraday (0.9.1)
35
+ docile (1.1.5)
36
+ domain_name (0.5.20161129)
37
+ unf (>= 0.0.5, < 1.0.0)
38
+ faraday (0.10.0)
34
39
  multipart-post (>= 1.2, < 3)
35
- ffi (1.9.8)
40
+ ffi (1.9.14)
36
41
  formatador (0.2.5)
37
- guard (2.12.6)
42
+ guard (2.14.0)
38
43
  formatador (>= 0.2.4)
39
- listen (~> 2.7)
44
+ listen (>= 2.7, < 4.0)
40
45
  lumberjack (~> 1.0)
41
46
  nenv (~> 0.1)
42
47
  notiffany (~> 0.0)
@@ -44,97 +49,96 @@ GEM
44
49
  shellany (~> 0.0)
45
50
  thor (>= 0.18.1)
46
51
  guard-compat (1.2.1)
47
- guard-rspec (4.5.2)
52
+ guard-rspec (4.7.3)
48
53
  guard (~> 2.1)
49
54
  guard-compat (~> 1.1)
50
55
  rspec (>= 2.99.0, < 4.0)
51
- haml (4.0.5)
52
- tilt
53
- hitimes (1.2.2)
54
- httparty (0.13.1)
55
- json (~> 1.8)
56
+ hashdiff (0.3.1)
57
+ http-cookie (1.0.3)
58
+ domain_name (~> 0.5)
59
+ httparty (0.14.0)
56
60
  multi_xml (>= 0.5.2)
57
- i18n (0.6.9)
58
- json (1.8.1)
61
+ i18n (0.7.0)
62
+ json (2.0.2)
59
63
  libnotify (0.9.1)
60
64
  ffi (>= 1.0.11)
61
- listen (2.10.1)
62
- celluloid (~> 0.16.0)
63
- rb-fsevent (>= 0.9.3)
64
- rb-inotify (>= 0.9)
65
- lumberjack (1.0.9)
65
+ listen (3.1.5)
66
+ rb-fsevent (~> 0.9, >= 0.9.4)
67
+ rb-inotify (~> 0.9, >= 0.9.7)
68
+ ruby_dep (~> 1.2)
69
+ lumberjack (1.0.10)
66
70
  method_source (0.8.2)
67
- mime-types (2.3)
68
- minitest (5.3.4)
69
- multi_json (1.10.0)
70
- multi_xml (0.5.5)
71
+ mime-types (2.99.3)
72
+ minitest (5.10.1)
73
+ multi_xml (0.6.0)
71
74
  multipart-post (2.0.0)
72
- nenv (0.2.0)
73
- notiffany (0.0.6)
75
+ nenv (0.3.0)
76
+ netrc (0.11.0)
77
+ notiffany (0.1.1)
74
78
  nenv (~> 0.1)
75
79
  shellany (~> 0.0)
76
- oauth (0.4.7)
77
- octokit (3.8.0)
78
- sawyer (~> 0.6.0, >= 0.5.3)
79
- prophet (1.5.5)
80
- octokit
81
- rspec
82
- pry (0.10.1)
80
+ oauth (0.5.1)
81
+ octokit (4.6.2)
82
+ sawyer (~> 0.8.0, >= 0.5.3)
83
+ pry (0.10.4)
83
84
  coderay (~> 1.1.0)
84
85
  method_source (~> 0.8.1)
85
86
  slop (~> 3.4)
86
- rake (10.3.2)
87
- rb-fsevent (0.9.5)
88
- rb-inotify (0.9.5)
87
+ public_suffix (2.0.4)
88
+ rake (12.0.0)
89
+ rb-fsevent (0.9.8)
90
+ rb-inotify (0.9.7)
89
91
  ffi (>= 0.5.0)
90
- rdoc (4.1.1)
91
- json (~> 1.4)
92
- rest-client (1.6.7)
93
- mime-types (>= 1.16)
94
- rspec (3.0.0)
95
- rspec-core (~> 3.0.0)
96
- rspec-expectations (~> 3.0.0)
97
- rspec-mocks (~> 3.0.0)
98
- rspec-core (3.0.0)
99
- rspec-support (~> 3.0.0)
100
- rspec-expectations (3.0.0)
92
+ rdoc (5.0.0)
93
+ rest-client (1.8.0)
94
+ http-cookie (>= 1.0.2, < 2.0)
95
+ mime-types (>= 1.16, < 3.0)
96
+ netrc (~> 0.7)
97
+ rspec (3.5.0)
98
+ rspec-core (~> 3.5.0)
99
+ rspec-expectations (~> 3.5.0)
100
+ rspec-mocks (~> 3.5.0)
101
+ rspec-core (3.5.4)
102
+ rspec-support (~> 3.5.0)
103
+ rspec-expectations (3.5.0)
104
+ diff-lcs (>= 1.2.0, < 2.0)
105
+ rspec-support (~> 3.5.0)
106
+ rspec-mocks (3.5.0)
101
107
  diff-lcs (>= 1.2.0, < 2.0)
102
- rspec-support (~> 3.0.0)
103
- rspec-mocks (3.0.0)
104
- rspec-support (~> 3.0.0)
105
- rspec-support (3.0.0)
106
- ruby-trello (1.1.1)
108
+ rspec-support (~> 3.5.0)
109
+ rspec-support (3.5.0)
110
+ ruby-trello (1.5.1)
107
111
  activemodel (>= 3.2.0)
108
112
  addressable (~> 2.3)
109
113
  json
110
- oauth (~> 0.4.5)
111
- rest-client (~> 1.6.7)
112
- safe_yaml (1.0.3)
113
- sawyer (0.6.0)
114
- addressable (~> 2.3.5)
115
- faraday (~> 0.8, < 0.10)
116
- sequel (4.13.0)
114
+ oauth (>= 0.4.5)
115
+ rest-client (~> 1.8.0)
116
+ ruby_dep (1.5.0)
117
+ safe_yaml (1.0.4)
118
+ sawyer (0.8.1)
119
+ addressable (>= 2.3.5, < 2.6)
120
+ faraday (~> 0.8, < 1.0)
117
121
  shellany (0.0.1)
118
- simplecov (0.8.2)
122
+ simplecov (0.12.0)
119
123
  docile (~> 1.1.0)
120
- multi_json
121
- simplecov-html (~> 0.8.0)
122
- simplecov-html (0.8.0)
124
+ json (>= 1.8, < 3)
125
+ simplecov-html (~> 0.10.0)
126
+ simplecov-html (0.10.0)
123
127
  slop (3.6.0)
124
- sqlite3 (1.3.9)
125
- term-ansicolor (1.3.0)
128
+ term-ansicolor (1.4.0)
126
129
  tins (~> 1.0)
127
- thor (0.19.1)
128
- thread_safe (0.3.4)
129
- tilt (2.0.1)
130
- timers (4.0.1)
131
- hitimes
132
- tins (1.1.0)
133
- tzinfo (1.2.1)
130
+ thor (0.19.4)
131
+ thread_safe (0.3.5)
132
+ tins (1.13.0)
133
+ tzinfo (1.2.2)
134
134
  thread_safe (~> 0.1)
135
- webmock (1.18.0)
135
+ unf (0.1.4)
136
+ unf_ext
137
+ unf_ext (0.0.7.2)
138
+ webmock (2.3.1)
136
139
  addressable (>= 2.3.6)
137
140
  crack (>= 0.3.2)
141
+ hashdiff
138
142
 
139
143
  PLATFORMS
140
144
  ruby
@@ -143,21 +147,16 @@ DEPENDENCIES
143
147
  ap
144
148
  byebug
145
149
  coveralls
150
+ debugger-linecache
146
151
  guard
147
152
  guard-rspec
148
- haml
149
- json
150
153
  libnotify
151
- octokit (~> 3.8.0)
152
- prophet
153
154
  rake
154
155
  rdoc
156
+ reviewlette!
155
157
  rspec
156
- ruby-trello
157
- sequel
158
158
  simplecov
159
- sqlite3
160
159
  webmock
161
160
 
162
161
  BUNDLED WITH
163
- 1.10.6
162
+ 1.13.6
data/README.md CHANGED
@@ -1,43 +1,43 @@
1
- Reviewlette
2
- ===========
3
-
4
- [![Coverage Status](https://img.shields.io/coveralls/jschmid1/reviewlette.svg)](https://coveralls.io/r/jschmid1/reviewlette)
5
- [![Code Climate](https://codeclimate.com/github/jschmid1/reviewlette.png)](https://codeclimate.com/github/jschmid1/reviewlette)
6
-
7
- Tool to automatically assign a "Reviewer" to a GitHub Issue and to the attached Trello Card.
1
+ [![Code Climate](https://codeclimate.com/github/SUSE/reviewlette.png)](https://codeclimate.com/github/SUSE/reviewlette)
2
+ [![Build Status](https://secure.travis-ci.org/SUSE/reviewlette.png?branch=master)](https://travis-ci.org/SUSE/reviewlette)
8
3
 
4
+ # Reviewlette
5
+ Tool to automatically assign reviewers to GitHub pull requests and to move and comment on their Trello cards.
9
6
 
10
7
  What it does:
11
8
 
12
- - Finds unassigned issues on GitHub.
13
- - Assigns a member of your team.
14
- - Locates the right Card on Trello.
15
- - Checks if the assignee is on vacation(using tel).
16
- - Adds the assigned member to the Card.
17
- - Move the card to 'In review'
18
-
9
+ - Finds pull requests with missing reviewers in your GitHub repos.
10
+ - Assigns random members of your team.
11
+ - Locates the right card in your Trello board.
12
+ - Mentions the assigned reviewer in a comment on the card.
13
+ - Moves the card to the 'In review' column.
19
14
 
20
15
  ## Installation
16
+ For the latest and greatest version you should `git clone https://github.com/SUSE/reviewlette`
21
17
 
18
+ ## Usage
19
+ ```ruby
20
+ Reviewlette.new(members: User.all, github_config: {}, trello_config: {}).run
22
21
  ```
23
- gem install reviewlette
24
- reviewlette
25
- ```
26
-
27
22
 
28
- ## Setup
23
+ Users must respond to `trello_handle` and `github_handle` methods.
29
24
 
30
- #### Name your pullrequest like so:
31
- #### Review_#23_name_of_review_42 <= trello card number
25
+ Examples for `github_config` and `trello_config` can be found in `config/`.
32
26
 
33
- Fill `config/.trello.yml` (instructions in the file)
34
- Fill `config/.github.yml` (instructions in the file
27
+ ### Matching Trello cards
28
+ To match a Trello card to a pull request, its title has to end with the card number (not the id)
35
29
 
30
+ #### Example:
36
31
 
37
- ---
32
+ URL of the Trello card: _https://trello.com/c/cardid/4242-fix-everything_
38
33
 
39
- [Using Octokit as a GitHub api wrapper](https://github.com/octokit/octokit.rb)
40
- [Using ruby-trello as a Trello api wrapper](https://github.com/jeremytregunna/ruby-trello)
34
+ Pull request title should be: `Fix almost everything 4242`
41
35
 
36
+ __Note:__ Pull requests without a matching Trello card get skipped and won't be assigned to a reviewer.
42
37
 
38
+ ### Labels
39
+ You can tweak Reviewlette's behavior by adding special labels to your pull request:
43
40
 
41
+ | Label | Description |
42
+ |-------------|----------------------|
43
+ | 2 reviewers | Assign two reviewers |
@@ -1,5 +1,4 @@
1
- # generate the token here: https://github.com/settings/tokens/new
2
-
3
- token:
4
- repos: ["SUSE/connect", "SUSE/happy-customer", "SUSE/reviewlette", "SUSE/scc-docker-images",
5
- "SUSE/scc-provisioning", "SUSE/scc-token", "SUSE/TeamDashboard" ]
1
+ token: # generate the token here: https://github.com/settings/tokens/new
2
+ repos:
3
+ - user/repo1
4
+ - org/repo2
@@ -1,15 +1,12 @@
1
1
  require 'reviewlette/trello_connection'
2
2
  require 'reviewlette/github_connection'
3
- require 'reviewlette/vacations'
4
3
  require 'yaml'
5
4
 
6
- VERSION = '0.0.9'
7
-
8
5
  class Reviewlette
9
- def initialize
10
- @trello = TrelloConnection.new
11
- @members = YAML.load_file("#{File.dirname(__FILE__)}/../config/members.yml")
12
- @github = YAML.load_file("#{File.dirname(__FILE__)}/../config/github.yml")
6
+ def initialize(members:, github_config: nil, trello_config: nil)
7
+ @trello = TrelloConnection.new(trello_config)
8
+ @github = github_config || YAML.load_file("#{File.dirname(__FILE__)}/../config/github.yml")
9
+ @members = members
13
10
  end
14
11
 
15
12
  def run
@@ -27,12 +24,20 @@ class Reviewlette
27
24
  return
28
25
  end
29
26
 
30
- repo.unassigned_pull_requests.each do |issue|
31
- issue_id = issue[:number]
27
+ repo.pull_requests.each do |issue|
28
+ issue_id = issue[:number]
32
29
  issue_title = issue[:title]
30
+ issue_labels = repo.labels(issue_id)
31
+
32
+ puts "*** Checking GitHub pull request: #{issue_title}"
33
+ matched = issue_title.match(/\d+[_'"]?$/)
34
+
35
+ unless matched
36
+ puts 'Pull request not assigned to a trello card'
37
+ next
38
+ end
33
39
 
34
- puts "*** Checking unassigned github pull request: #{issue_title}"
35
- card_id = issue_title.split(/[_ -#\.]/).last.to_i
40
+ card_id = matched[0].to_i
36
41
  card = @trello.find_card_by_id(card_id)
37
42
 
38
43
  unless card
@@ -41,35 +46,38 @@ class Reviewlette
41
46
  end
42
47
 
43
48
  puts "Found matching trello card: #{card.name}"
44
- reviewer = select_reviewer(issue, card)
45
49
 
46
- unless reviewer
47
- puts "Could not find a reviewer for card: #{card.name}"
48
- next
50
+ assignees = issue[:assignees].map(&:login)
51
+ already_assigned_members = @members.select { |m| assignees.include? m.github_handle }
52
+ wanted_number = how_many_should_review(issue_labels)
53
+
54
+ if assignees.size < wanted_number
55
+ reviewers = select_reviewers(card, wanted_number, already_assigned_members)
56
+ if reviewers.empty?
57
+ puts "Could not find a reviewer for card: #{card.name}"
58
+ next
59
+ end
60
+ repo.add_assignees(issue_id, reviewers.map { |r| r.github_handle } )
61
+ repo.comment_reviewers(issue_id, reviewers, card)
62
+ @trello.comment_reviewers(card, repo_name, issue_id, reviewers)
63
+ @trello.move_card_to_list(card, 'In review')
64
+ already_assigned_members
49
65
  end
50
66
 
51
- repo.add_assignee(issue_id, reviewer['github_username'])
52
- repo.reviewer_comment(issue_id, reviewer['github_username'], card)
53
- comment = "@#{reviewer['trello_username']} will review https://github.com/#{repo_name}/issues/#{issue_id}"
54
67
 
55
- @trello.comment_on_card(comment, card)
56
- @trello.move_card_to_list(card, 'In review')
57
68
  end
58
69
  end
59
70
 
60
- def select_reviewer(issue, card)
61
- reviewers = @members['members']
62
-
63
- # remove people on vacation
64
- members_on_vacation = Vacations.members_on_vacation(reviewers)
71
+ def select_reviewers(card, number = 1, already_assigned = [])
72
+ reviewers = @members
73
+ reviewers.reject! { |r| card.members.map(&:username).include? r.trello_handle }
74
+ reviewers -= already_assigned
65
75
 
66
- reviewers = reviewers.reject {|r| members_on_vacation.include? r['suse_username'] }
67
-
68
- # remove trello card owner
69
- reviewers = reviewers.reject {|r| card.members.map(&:username).include? r['trello_username'] }
70
- reviewer = reviewers.sample
71
- puts "Selected reviewer: #{reviewer['name']} from pool #{reviewers.map {|r| r['name'] }}" if reviewer
72
- reviewer
76
+ reviewers.sample(number - already_assigned.size) + already_assigned
73
77
  end
74
78
 
79
+ def how_many_should_review(labels)
80
+ return 2 if labels.include? '2 reviewers'
81
+ 1
82
+ end
75
83
  end