reviewlette 0.0.6

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 53593949368f61246646984e517e18c7e478497c
4
+ data.tar.gz: 2c1af0b6ac234d1a06ea28f1906323857a398073
5
+ SHA512:
6
+ metadata.gz: 1e3e7d9571d7869b2f49e34a7d1be93269e8f8c6f300f00f02bb757e3036aeab4248dfddb8a9479735aac970ebbad56765b6defbfd4bcfc234ac3a94476bf60f
7
+ data.tar.gz: f4fbe33ad2be3922ae2e9de8d494209f2defbecb0cd19f49affed7d72b4c88cd7d2bbd3b7e942920644f33f2349f74ed83f1995884441f222c0fe3ff92d5f2dc
@@ -0,0 +1,27 @@
1
+ *.gem
2
+ *.db
3
+ *.log
4
+ *.html
5
+ database
6
+ *.yml~
7
+ .idea
8
+ /.idea
9
+ .idea*
10
+ /.idea/*
11
+ *.rbc
12
+ *.yml
13
+ .bundle
14
+ coverage
15
+ .swp
16
+ InstalledFiles
17
+ lib/bundler/man
18
+ pkg
19
+ rdoc
20
+ spec/reports
21
+ test/tmp
22
+ test/version_tmp
23
+ tmp
24
+ .yardoc
25
+ _yardoc
26
+ rdoc/
27
+ doc/
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour --format documentation
data/Gemfile ADDED
@@ -0,0 +1,17 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'json'
4
+ gem 'haml'
5
+ gem 'octokit', '~> 3.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'
@@ -0,0 +1,114 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ 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)
10
+ minitest (~> 5.1)
11
+ thread_safe (~> 0.1)
12
+ tzinfo (~> 1.1)
13
+ addressable (2.3.6)
14
+ ap (0.1.1)
15
+ httparty (>= 0.7.7)
16
+ builder (3.2.2)
17
+ byebug (3.1.2)
18
+ columnize (~> 0.8)
19
+ columnize (0.8.9)
20
+ coveralls (0.7.0)
21
+ multi_json (~> 1.3)
22
+ rest-client
23
+ simplecov (>= 0.7)
24
+ term-ansicolor
25
+ thor
26
+ crack (0.4.2)
27
+ safe_yaml (~> 1.0.0)
28
+ diff-lcs (1.2.5)
29
+ docile (1.1.3)
30
+ faraday (0.9.0)
31
+ multipart-post (>= 1.2, < 3)
32
+ haml (4.0.5)
33
+ tilt
34
+ httparty (0.13.1)
35
+ json (~> 1.8)
36
+ multi_xml (>= 0.5.2)
37
+ i18n (0.6.9)
38
+ json (1.8.1)
39
+ mime-types (2.3)
40
+ minitest (5.3.4)
41
+ multi_json (1.10.0)
42
+ multi_xml (0.5.5)
43
+ multipart-post (2.0.0)
44
+ oauth (0.4.7)
45
+ octokit (3.1.0)
46
+ sawyer (~> 0.5.3)
47
+ prophet (1.5.5)
48
+ octokit
49
+ rspec
50
+ rake (10.3.2)
51
+ rdoc (4.1.1)
52
+ json (~> 1.4)
53
+ rest-client (1.6.7)
54
+ mime-types (>= 1.16)
55
+ rspec (3.0.0)
56
+ rspec-core (~> 3.0.0)
57
+ rspec-expectations (~> 3.0.0)
58
+ rspec-mocks (~> 3.0.0)
59
+ rspec-core (3.0.0)
60
+ rspec-support (~> 3.0.0)
61
+ rspec-expectations (3.0.0)
62
+ diff-lcs (>= 1.2.0, < 2.0)
63
+ rspec-support (~> 3.0.0)
64
+ rspec-mocks (3.0.0)
65
+ rspec-support (~> 3.0.0)
66
+ rspec-support (3.0.0)
67
+ ruby-trello (1.1.1)
68
+ activemodel (>= 3.2.0)
69
+ addressable (~> 2.3)
70
+ json
71
+ oauth (~> 0.4.5)
72
+ rest-client (~> 1.6.7)
73
+ safe_yaml (1.0.3)
74
+ sawyer (0.5.4)
75
+ addressable (~> 2.3.5)
76
+ faraday (~> 0.8, < 0.10)
77
+ sequel (4.13.0)
78
+ simplecov (0.8.2)
79
+ docile (~> 1.1.0)
80
+ multi_json
81
+ simplecov-html (~> 0.8.0)
82
+ simplecov-html (0.8.0)
83
+ sqlite3 (1.3.9)
84
+ term-ansicolor (1.3.0)
85
+ tins (~> 1.0)
86
+ thor (0.19.1)
87
+ thread_safe (0.3.4)
88
+ tilt (2.0.1)
89
+ tins (1.1.0)
90
+ tzinfo (1.2.1)
91
+ thread_safe (~> 0.1)
92
+ webmock (1.18.0)
93
+ addressable (>= 2.3.6)
94
+ crack (>= 0.3.2)
95
+
96
+ PLATFORMS
97
+ ruby
98
+
99
+ DEPENDENCIES
100
+ ap
101
+ byebug
102
+ coveralls
103
+ haml
104
+ json
105
+ octokit (~> 3.0)
106
+ prophet
107
+ rake
108
+ rdoc
109
+ rspec
110
+ ruby-trello
111
+ sequel
112
+ simplecov
113
+ sqlite3
114
+ webmock
@@ -0,0 +1,24 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard :rspec do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+
9
+ # Rails example
10
+ watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
11
+ watch(%r{^app/(.*)(\.erb|\.haml|\.slim)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
12
+ watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
13
+ watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
14
+ watch('config/routes.rb') { "spec/routing" }
15
+ watch('app/controllers/application_controller.rb') { "spec/controllers" }
16
+
17
+ # Capybara features specs
18
+ watch(%r{^app/views/(.+)/.*\.(erb|haml|slim)$}) { |m| "spec/features/#{m[1]}_spec.rb" }
19
+
20
+ # Turnip features and steps
21
+ watch(%r{^spec/acceptance/(.+)\.feature$})
22
+ watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
23
+ end
24
+
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 jschmid1
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,95 @@
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.
8
+
9
+
10
+ What it does:
11
+
12
+ - Finds unassigned issues on GitHub.
13
+ - Assignes 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
+ - If the Issue/PullRequest is closed or merged move it in the right column.
18
+ - Prints graphs using Morris.js to display statistics(autorefresh every 5 seconds).
19
+
20
+
21
+ ![alt tag](http://h.dropcanvas.com/72fj0/graph.jpg)
22
+
23
+
24
+ ## Installation
25
+
26
+ ```
27
+ git clone git@github.com:jschmid1/reviewlette.git
28
+ cd reviewlette
29
+ bundle
30
+ cd bin
31
+ ./reviewlette
32
+ ```
33
+
34
+ or
35
+
36
+ ```
37
+ gem install reviewlette
38
+ ```
39
+
40
+
41
+ ## Setup
42
+
43
+ #### Name your pullrequest like so:
44
+ #### Review_#23_name_of_review_42 <= trello card number
45
+
46
+ Fill `config/.trello.yml` with your **consumerkey**, **consumersecret**, **oauthtoken** and **board_id**
47
+
48
+ ```yml
49
+ -comsumerkey: theconsumerkey11
50
+ -consumersecret: theconsumersecret11
51
+ -oauthtoken: theoauthtoken11
52
+ ```
53
+
54
+ [Which can be generated here](https://trello.com/1/appKey/generate)
55
+
56
+ Fill `config/.github.yml` with your **token** and **repo**
57
+
58
+ ```yml
59
+ -token: thetokenfromgithub
60
+ -repo: ['my/repo', 'my/otherrepo']
61
+ ```
62
+
63
+ [Which can be generated here](https://github.com/settings/applications/new)
64
+
65
+
66
+ Edit the `reviewlette.db` scaffold in the main directory to your needs.
67
+
68
+ Structure:
69
+
70
+ | primary_key | first_name | last_name | Reviews_count | created_at | github_name | trello_name | vacation_status | tel_name |
71
+ |:-------------:|:-------------: |:-------------:|:-------------: |:-------------:|:-------------:|:-------------:|:-------------: |:-------------:|
72
+ | Integer(PK) | Text | Text | Integer | Text | Text |Text | Numeric| Text|
73
+ | 1 | Joshua | Schmid | 30 | 2014-01-01 | jschmid1 |jschmid1 | false | jschmid|
74
+
75
+
76
+
77
+
78
+ You can either use a GUI like [Sqlite database browser](http://sqlitebrowser.org/) or the sqlite commandline interface
79
+
80
+ e.g.
81
+
82
+ ```ruby
83
+ insert into reviewer values('John','Smith', '0', '', 'github_name', 'trello_name', 'false', 'tel_name');
84
+ ```
85
+
86
+ ---
87
+
88
+ [Using Octokit as a GitHub api wrapper](https://github.com/octokit/octokit.rb)
89
+
90
+ [Using Sequel as Database Module](https://github.com/jeremyevans/sequel)
91
+
92
+ [Using ruby-trello as a Trello api wrapper](https://github.com/jeremytregunna/ruby-trello)
93
+
94
+
95
+
@@ -0,0 +1,5 @@
1
+ require 'rspec/core/rake_task'
2
+
3
+ RSpec::Core::RakeTask.new(:spec)
4
+
5
+ task :default => :spec
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/ruby
2
+
3
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
4
+ require 'reviewlette'
5
+
6
+ Reviewlette.spin
7
+
File without changes
@@ -0,0 +1,202 @@
1
+ require 'reviewlette/trello_connection'
2
+ require 'reviewlette/github_connection'
3
+ require 'reviewlette/database'
4
+ require 'reviewlette/graph_gen'
5
+ require 'reviewlette/vacations'
6
+ require 'yaml'
7
+ require 'octokit'
8
+ require 'trello'
9
+
10
+ class Trello::Card
11
+
12
+ def assignees
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
77
+
78
+ def update_vacations
79
+ @db.get_users_tel_entries.each do |name|
80
+ @vacations = Reviewlette::Vacations.find_vacations(name) #tel_name
81
+ evaluate_vacations(name)
82
+ end
83
+ end
84
+
85
+ def evaluate_vacations(reviewer)
86
+ parse_vacations.each do |check|
87
+ check[1] = check[0] unless check[1] # Rewrite if statement with catch to prevent this error?
88
+ if (check[0]..check[1]).cover?(Date.today)
89
+ @db.set_vacation_flag(reviewer, 'true')
90
+ break
91
+ else
92
+ @db.set_vacation_flag(reviewer, 'false') # hopefully not to_bool?
93
+ 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
+ else
145
+ @logger.warn("Id not found, skipping Issue #{@title} with number #{@number}")
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
163
+ end
164
+ end
165
+
166
+ # Get Trelloname from configfile.
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
190
+
191
+ # TODO: More generic 'Done' and 'in Review' are not present everywhere
192
+ def move_to_list
193
+ if @github_connection.pull_merged?(@repo, @id)
194
+ @column = @trello_connection.find_column('Done')
195
+ @trello_connection.move_card_to_list(@card, @column)
196
+ else
197
+ @column = @trello_connection.find_column('In review')
198
+ @trello_connection.move_card_to_list(@card, @column)
199
+ end
200
+ end
201
+ end
202
+ end