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 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