reviewlette 0.0.6 → 0.0.7

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: 53593949368f61246646984e517e18c7e478497c
4
- data.tar.gz: 2c1af0b6ac234d1a06ea28f1906323857a398073
3
+ metadata.gz: aa4d4a0eb15ee9feae3c0d1d10cea567af2f2ffe
4
+ data.tar.gz: 84e46cc35612094c580654a48c5cd03eec633bb0
5
5
  SHA512:
6
- metadata.gz: 1e3e7d9571d7869b2f49e34a7d1be93269e8f8c6f300f00f02bb757e3036aeab4248dfddb8a9479735aac970ebbad56765b6defbfd4bcfc234ac3a94476bf60f
7
- data.tar.gz: f4fbe33ad2be3922ae2e9de8d494209f2defbecb0cd19f49affed7d72b4c88cd7d2bbd3b7e942920644f33f2349f74ed83f1995884441f222c0fe3ff92d5f2dc
6
+ metadata.gz: 104f9629561f1e3f329eebc6823810dcc25174e24b412132e5f297538b51c7ce2ebc76378e1583964619fbd59f1ec8d661ed41711cabbb974209cfc3872d93d7
7
+ data.tar.gz: dd5b12654663ed8a7aca64d2998157365bb250f2f6582cbbe3c207a2f7d94546ae899fe1d3b44c0d8851d97d94e06c38f1a806a5178f4d6492128691edbace98
data/.gitignore CHANGED
@@ -2,14 +2,8 @@
2
2
  *.db
3
3
  *.log
4
4
  *.html
5
- database
6
- *.yml~
7
5
  .idea
8
- /.idea
9
- .idea*
10
- /.idea/*
11
6
  *.rbc
12
- *.yml
13
7
  .bundle
14
8
  coverage
15
9
  .swp
@@ -25,3 +19,7 @@ tmp
25
19
  _yardoc
26
20
  rdoc/
27
21
  doc/
22
+ config/github.yml
23
+ config/trello.yml
24
+ config/members.yml
25
+
data/Gemfile CHANGED
@@ -2,7 +2,7 @@ source 'http://rubygems.org'
2
2
 
3
3
  gem 'json'
4
4
  gem 'haml'
5
- gem 'octokit', '~> 3.0'
5
+ gem 'octokit', '~> 3.8.0'
6
6
  gem 'ruby-trello'
7
7
  gem 'rdoc'
8
8
  gem 'rspec'
data/Gemfile.lock CHANGED
@@ -10,7 +10,7 @@ GEM
10
10
  minitest (~> 5.1)
11
11
  thread_safe (~> 0.1)
12
12
  tzinfo (~> 1.1)
13
- addressable (2.3.6)
13
+ addressable (2.3.8)
14
14
  ap (0.1.1)
15
15
  httparty (>= 0.7.7)
16
16
  builder (3.2.2)
@@ -27,7 +27,7 @@ GEM
27
27
  safe_yaml (~> 1.0.0)
28
28
  diff-lcs (1.2.5)
29
29
  docile (1.1.3)
30
- faraday (0.9.0)
30
+ faraday (0.9.1)
31
31
  multipart-post (>= 1.2, < 3)
32
32
  haml (4.0.5)
33
33
  tilt
@@ -42,8 +42,8 @@ GEM
42
42
  multi_xml (0.5.5)
43
43
  multipart-post (2.0.0)
44
44
  oauth (0.4.7)
45
- octokit (3.1.0)
46
- sawyer (~> 0.5.3)
45
+ octokit (3.8.0)
46
+ sawyer (~> 0.6.0, >= 0.5.3)
47
47
  prophet (1.5.5)
48
48
  octokit
49
49
  rspec
@@ -71,7 +71,7 @@ GEM
71
71
  oauth (~> 0.4.5)
72
72
  rest-client (~> 1.6.7)
73
73
  safe_yaml (1.0.3)
74
- sawyer (0.5.4)
74
+ sawyer (0.6.0)
75
75
  addressable (~> 2.3.5)
76
76
  faraday (~> 0.8, < 0.10)
77
77
  sequel (4.13.0)
@@ -102,7 +102,7 @@ DEPENDENCIES
102
102
  coveralls
103
103
  haml
104
104
  json
105
- octokit (~> 3.0)
105
+ octokit (~> 3.8.0)
106
106
  prophet
107
107
  rake
108
108
  rdoc
data/README.md CHANGED
@@ -10,31 +10,18 @@ Tool to automatically assign a "Reviewer" to a GitHub Issue and to the attached
10
10
  What it does:
11
11
 
12
12
  - Finds unassigned issues on GitHub.
13
- - Assignes a member of your team.
13
+ - Assigns a member of your team.
14
14
  - Locates the right Card on Trello.
15
15
  - Checks if the assignee is on vacation(using tel).
16
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)
17
+ - Move the card to 'In review'
22
18
 
23
19
 
24
20
  ## Installation
25
21
 
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
22
  ```
37
23
  gem install reviewlette
24
+ reviewlette
38
25
  ```
39
26
 
40
27
 
@@ -43,52 +30,13 @@ gem install reviewlette
43
30
  #### Name your pullrequest like so:
44
31
  #### Review_#23_name_of_review_42 <= trello card number
45
32
 
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)
33
+ Fill `config/.trello.yml` (instructions in the file)
34
+ Fill `config/.github.yml` (instructions in the file
64
35
 
65
36
 
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
37
  ---
87
38
 
88
39
  [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
40
  [Using ruby-trello as a Trello api wrapper](https://github.com/jeremytregunna/ruby-trello)
93
41
 
94
42
 
data/Rakefile CHANGED
@@ -2,4 +2,16 @@ require 'rspec/core/rake_task'
2
2
 
3
3
  RSpec::Core::RakeTask.new(:spec)
4
4
 
5
- task :default => :spec
5
+ task :default => :spec
6
+
7
+ desc 'Run console loaded with gem'
8
+ task :console do
9
+ require 'irb'
10
+ require 'irb/completion'
11
+ require 'byebug'
12
+ require 'awesome_print'
13
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), 'lib')
14
+ require 'reviewlette'
15
+ ARGV.clear
16
+ IRB.start
17
+ end
data/bin/reviewlette CHANGED
@@ -3,5 +3,6 @@
3
3
  $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
4
4
  require 'reviewlette'
5
5
 
6
- Reviewlette.spin
6
+ reviewlette = Reviewlette.new
7
+ reviewlette.run
7
8
 
@@ -0,0 +1,3 @@
1
+ # generate the token here: https://github.com/settings/tokens/new
2
+ token:
3
+ repo: SUSE/connect
@@ -0,0 +1,25 @@
1
+ members:
2
+ - name: Tom
3
+ suse_username: tschmidt
4
+ trello_username: thomasschmidt
5
+ github_username: digitaltom
6
+ - name: Artem
7
+ suse_username: achernikov
8
+ trello_username: artemchernikov
9
+ github_username: kalabiyau
10
+ - name: Kirill
11
+ suse_username: kpimenov
12
+ trello_username: kirillpimenov
13
+ github_username: kirushik
14
+ - name: Vlad
15
+ suse_username: vlewin
16
+ trello_username: vlewin
17
+ github_username: vlewin
18
+ - name: Will
19
+ suse_username: wstephenson
20
+ trello_username: wstephenson
21
+ github_username: wstephenson
22
+ - name: Nadja
23
+ suse_username: nwalter
24
+ trello_username: nadjaw2
25
+ github_username: nadjaw
@@ -0,0 +1,9 @@
1
+ # Get your trello keys here: https://trello.com/app-key
2
+ consumerkey:
3
+
4
+ # request the token here:
5
+ # https://trello.com/1/authorize?key=<key from above>&name=reviewlette&expiration=never&response_type=token&scope=read,write
6
+ oauthtoken:
7
+
8
+ # The board_id can be read from the url of the board.
9
+ board_id:
@@ -1,45 +1,40 @@
1
1
  require 'yaml'
2
2
  require 'octokit'
3
3
 
4
- module Reviewlette
4
+ GITHUB_CONFIG = YAML.load_file("#{File.dirname(__FILE__)}/../../config/github.yml")
5
5
 
6
- class GithubConnection
6
+ class GithubConnection
7
7
 
8
- GITHUB_CONFIG = YAML.load_file("#{File.dirname(__FILE__)}/../../config/.github.yml")
8
+ attr_accessor :client, :repo
9
9
 
10
- attr_accessor :client, :repo
11
-
12
- def initialize
13
- gh_connection
14
- end
15
-
16
- def gh_connection
17
- @client = Octokit::Client.new(:access_token => GITHUB_CONFIG['token'])
18
- end
19
-
20
- def get_branch_name(pr_id, repo)
21
- @client.pull_requests(repo)[pr_id].head.ref
22
- end
23
-
24
- def list_pulls(repo)
25
- @client.pull_requests(repo)
26
- end
27
-
28
- def pull_merged?(repo, number)
29
- client.pull_merged?(repo, number)
30
- end
10
+ def initialize
11
+ @client = Octokit::Client.new(:access_token => GITHUB_CONFIG['token'])
12
+ @repo = GITHUB_CONFIG['repo']
13
+ end
31
14
 
32
- def add_assignee(repo, number, title, body, name)
33
- @client.update_issue(repo, number, title, body, :assignee => name)
34
- end
15
+ def list_pulls
16
+ @client.pull_requests(@repo)
17
+ end
35
18
 
36
- def comment_on_issue(repo, number, name, trello_card_url)
37
- @client.add_comment(repo, number, "@#{name} is your reviewer :thumbsup: check #{trello_card_url}")
38
- end
19
+ def add_assignee(number, assignee)
20
+ @client.update_issue(@repo, number, assignee: assignee)
21
+ end
39
22
 
40
- def list_issues(repo)
41
- @client.list_issues(repo)
42
- end
23
+ def reviewer_comment(number, assignee, trello_card)
24
+ comment = "@#{assignee} is your reviewer :dancers: check #{trello_card.url} \n" \
25
+ "@#{assignee}: Please review this pull request using our guidelines: \n" \
26
+ "* test for acceptance criteria / functionality \n" \
27
+ "* check if the new code is covered with tests \n" \
28
+ "* check for unintended consequences \n" \
29
+ "* encourage usage of the boyscout rule \n" \
30
+ "* make sure the code is architected in the best way \n" \
31
+ "* check that no unnecessary technical debt got introduced \n" \
32
+ "* make sure that no unnecessary FIXMEs or TODOs got added \n"
33
+ @client.add_comment(@repo, number, comment)
34
+ end
43
35
 
36
+ def unassigned_pull_requests
37
+ list_pulls.select { |issue| !issue[:assignee] }
44
38
  end
45
- end
39
+
40
+ end
@@ -1,79 +1,45 @@
1
1
  require 'yaml'
2
2
  require 'trello'
3
- require 'logger'
4
- require_relative 'database'
5
- require_relative 'exceptions'
6
3
 
7
- class Trello::Card
4
+ TRELLO_CONFIG = YAML.load_file("#{File.dirname(__FILE__)}/../../config/trello.yml")
8
5
 
9
- def assignees
10
- @trello_connection = ::Reviewlette::TrelloConnection.new
11
- member_ids.map{|id| @trello_connection.find_member_by_id(id)}
12
- end
13
- end
14
-
15
- module Reviewlette
16
-
17
- class TrelloConnection
18
-
19
- attr_accessor :board
20
-
21
- def initialize
22
- setup_trello
23
- end
24
-
25
- def determine_reviewer(card)
26
- raise AlreadyAssignedException, "Everyone on the team is assigned to the Card." if reviewer_exception_handler(card)
27
- find_member_by_username(sample_reviewer(card))
28
- end
29
-
30
- def sample_reviewer(card)
31
- (team - card.assignees.map(&:username)).sample
32
- end
33
-
34
- def reviewer_exception_handler(card)
35
- (team - card.assignees.map(&:username)).count <= 0
36
- end
37
-
38
- def add_reviewer_to_card(reviewer, card)
39
- card.add_member(reviewer) if reviewer
40
- end
6
+ class TrelloConnection
41
7
 
42
- def comment_on_card(reviewer, card)
43
- card.add_comment(reviewer) if reviewer
44
- end
8
+ attr_accessor :board
45
9
 
46
- def move_card_to_list(card, column)
47
- card.move_to_list(column)
10
+ def initialize
11
+ Trello.configure do |config|
12
+ config.developer_public_key = TRELLO_CONFIG['consumerkey']
13
+ config.member_token = TRELLO_CONFIG['oauthtoken']
48
14
  end
15
+ @board = Trello::Board.find(TRELLO_CONFIG['board_id'])
16
+ end
49
17
 
50
- def team
51
- #where vacation is not false
52
- @team ||= Reviewlette::Database.new.get_users_trello_entries
53
- end
18
+ def add_reviewer_to_card(reviewer, card)
19
+ reviewer = find_member_by_username(reviewer)
20
+ card.add_member(reviewer)
21
+ end
54
22
 
55
- def find_column(column_name)
56
- @board.lists.find {|x| x.name == column_name}
57
- end
23
+ def comment_on_card(comment, card)
24
+ card.add_comment(comment)
25
+ end
58
26
 
59
- def find_member_by_username(username)
60
- @board.members.find{|m| m.username == username}
61
- end
27
+ def move_card_to_list(card, column_name)
28
+ column = find_column(column_name)
29
+ card.move_to_list(column)
30
+ end
62
31
 
63
- def find_member_by_id(id)
64
- @board.members.find{|m| m.id == id}
65
- end
32
+ def find_column(column_name)
33
+ @board.lists.find { |x| x.name == column_name }
34
+ end
66
35
 
67
- def find_card_by_id(id)
68
- @board.cards.find{|c| c.short_id == id.to_i}
69
- end
36
+ def find_member_by_username(username)
37
+ @board.members.find { |m| m.username == username }
38
+ end
70
39
 
71
- def setup_trello
72
- Trello.configure do |config|
73
- config.developer_public_key = ::Reviewlette::TRELLO_CONFIG1['consumerkey']
74
- config.member_token = ::Reviewlette::TRELLO_CONFIG1['oauthtoken']
75
- end
76
- @board = Trello::Board.find(::Reviewlette::TRELLO_CONFIG1['board_id'])
77
- end
40
+ def find_card_by_id(id)
41
+ @board.cards.find { |c| c.short_id == id.to_i }
78
42
  end
43
+
79
44
  end
45
+
@@ -1,38 +1,30 @@
1
1
  require 'net/telnet'
2
- module Reviewlette
3
2
 
4
- class Vacations
3
+ class Vacations
5
4
 
6
- def self.find_vacations(username)
7
- vacations = []
8
- tn = Net::Telnet.new('Host' => 'present.suse.de', 'Port' => 9874, 'Binmode' => false)
9
- collect = false
10
- tn.cmd(username) do |data|
11
- data.split("\n").each do |l|
12
- collect = true if l =~ /^Absence/
13
- next unless collect
14
- if l[0,1] == "-"
15
- collect = false
16
- next
17
- end
18
- dates = []
19
- l.split(" ").each do |date|
20
- unless date =~ /#{Time.now.year}/
21
- next
22
- end
23
- dates.push(date)
24
- end
25
- case dates.size
26
- when 1
27
- vacations.push("#{dates[0]}")
28
- when 2
29
- vacations.push("#{dates[0]} - #{dates[1]}")
30
- else
31
- end
5
+ def self.find_vacations(username)
6
+ vacations = []
7
+ tn = Net::Telnet.new('Host' => 'present.suse.de', 'Port' => 9874, 'Binmode' => false)
8
+ tn.cmd("#{username}").split("\n").each do |line|
9
+ if line =~ /\S{3} #{Time.now.year}-\d\d-\d\d/
10
+ dates = []
11
+ line.split(" ").each do |date|
12
+ dates.push(date) if date =~ /#{Time.now.year}-\d\d-\d\d/
32
13
  end
14
+ dates[1] = dates[0] unless dates[1]
15
+ vacations.push(Date.parse(dates[0])..Date.parse(dates[1]))
33
16
  end
34
- tn.close
35
- vacations
36
17
  end
18
+ tn.close
19
+ vacations
37
20
  end
38
- end
21
+
22
+ def self.members_on_vacation
23
+ members_on_vacation = MEMBERS_CONFIG['members'].collect do |member|
24
+ username = member['suse_username']
25
+ username if (username && Vacations.find_vacations(username).any? { |v| v === Date.today })
26
+ end
27
+ members_on_vacation.compact
28
+ end
29
+
30
+ end