reviewr 0.0.1
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.
- data/History.txt +0 -0
- data/LICENSE +19 -0
- data/Manifest.txt +16 -0
- data/README.md +62 -0
- data/bin/reviewr +6 -0
- data/lib/reviewr/cli/help.rb +33 -0
- data/lib/reviewr/cli/main.rb +53 -0
- data/lib/reviewr/cli/request.rb +45 -0
- data/lib/reviewr/cli.rb +8 -0
- data/lib/reviewr/git.rb +48 -0
- data/lib/reviewr/mailer.rb +26 -0
- data/lib/reviewr/project.rb +48 -0
- data/lib/reviewr/templates/commit_msg.erb +4 -0
- data/lib/reviewr/templates/request_email.erb +12 -0
- data/lib/reviewr/version.rb +3 -0
- data/lib/reviewr.rb +10 -0
- metadata +126 -0
data/History.txt
ADDED
File without changes
|
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2010 Ryan Burrows
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/Manifest.txt
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
LICENSE
|
2
|
+
README.md
|
3
|
+
History.txt
|
4
|
+
Manifest.txt
|
5
|
+
bin/reviewr
|
6
|
+
lib/reviewr.rb
|
7
|
+
lib/reviewr/cli.rb
|
8
|
+
lib/reviewr/git.rb
|
9
|
+
lib/reviewr/mailer.rb
|
10
|
+
lib/reviewr/project.rb
|
11
|
+
lib/reviewr/version.rb
|
12
|
+
lib/reviewr/cli/help.rb
|
13
|
+
lib/reviewr/cli/main.rb
|
14
|
+
lib/reviewr/cli/request.rb
|
15
|
+
lib/reviewr/templates/commit_msg.erb
|
16
|
+
lib/reviewr/templates/request_email.erb
|
data/README.md
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# Reviewr: Simple code review
|
2
|
+
|
3
|
+
Reviewr is an application to simplify code review for projects using
|
4
|
+
git and github.com for version control.
|
5
|
+
|
6
|
+
# Installation
|
7
|
+
gem install reviewr
|
8
|
+
|
9
|
+
# Requesting a code review
|
10
|
+
reviewr request <email>
|
11
|
+
This will result in the following actions:
|
12
|
+
|
13
|
+
* Create a code review branch
|
14
|
+
* Create a commit with information about the code review request
|
15
|
+
* Push the code review branch to the origin repository
|
16
|
+
* Send an email to <email> requesting a code review of the branch
|
17
|
+
The email will include a link to Github's compare view for the
|
18
|
+
changes
|
19
|
+
|
20
|
+
## Limitations
|
21
|
+
|
22
|
+
* Right now reviewr considers the origin/master the branch that the
|
23
|
+
reviewed code will be merged into when approved
|
24
|
+
* Email can only be sent from a Gmail (or Google Apps for my domain)
|
25
|
+
address
|
26
|
+
|
27
|
+
# TODO
|
28
|
+
|
29
|
+
## Finish out the basic workflow
|
30
|
+
|
31
|
+
General workflow goes something like this:
|
32
|
+
|
33
|
+
Code, code, code. Decide changes are ready for review and run `reviewr
|
34
|
+
request email@site.com`. This causes reviewr to:
|
35
|
+
|
36
|
+
* create a new branch with the name `review_0f38ef31` where `0f38ef31`
|
37
|
+
is the SHA of the current commit
|
38
|
+
* Add a commit to the branch with metadata about the request
|
39
|
+
(requester name/email etc).
|
40
|
+
* push the branch to the origin repository
|
41
|
+
* generate a github review url from the current head to the pushed
|
42
|
+
review branch
|
43
|
+
* Send an email to `email@site.com` with a nice message and the url
|
44
|
+
|
45
|
+
The reviewer then looks over the code on github and comments as
|
46
|
+
necessary. If the code is acceptable the reviewer runs `reviewr accept
|
47
|
+
review_0f38ef31`. reviewr will then:
|
48
|
+
|
49
|
+
* fetch the review branch
|
50
|
+
* attempt to merge the reviewed branch into the master
|
51
|
+
* if it fails an error will be raised and execution will stop
|
52
|
+
* if is succeeds the merged master will be pushed
|
53
|
+
* the remote review branch will be deleted.
|
54
|
+
* an email will be sent to the review requester saying the code was accepted
|
55
|
+
|
56
|
+
If the code the reviewer is checking is not acceptable, upon finishing
|
57
|
+
comments on github the reviewer can run `reviewr reject
|
58
|
+
review_0f38ef31`. reviewr will:
|
59
|
+
|
60
|
+
* Re-generate the github url for comparing to the current master
|
61
|
+
* Send an email to the requester of the review saying the code has
|
62
|
+
been rejected and to please see the comments on the linked page
|
data/bin/reviewr
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
module Reviewr
|
2
|
+
module CLI
|
3
|
+
class Help
|
4
|
+
def call(command)
|
5
|
+
if command.nil?
|
6
|
+
usage
|
7
|
+
else
|
8
|
+
request_help
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def usage
|
13
|
+
puts <<-HELP
|
14
|
+
usage: reviewr COMMAND [ARGS]
|
15
|
+
|
16
|
+
reviewr commands
|
17
|
+
request Request a code review
|
18
|
+
help Find out more about a specific command
|
19
|
+
|
20
|
+
See 'reviewr help COMMAND' for more information on a specific command.
|
21
|
+
HELP
|
22
|
+
end
|
23
|
+
|
24
|
+
def request_help
|
25
|
+
puts <<-HELP
|
26
|
+
usage: reviewr request <email>
|
27
|
+
|
28
|
+
Request a code review from <email>.
|
29
|
+
HELP
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'termios'
|
2
|
+
require 'ruby-debug'
|
3
|
+
|
4
|
+
module Reviewr
|
5
|
+
module CLI
|
6
|
+
class Main
|
7
|
+
attr_reader :command
|
8
|
+
attr_accessor :project
|
9
|
+
|
10
|
+
def initialize(args, input = STDIN, output = STDOUT)
|
11
|
+
@command = args.shift
|
12
|
+
@project = Project.new(args.shift)
|
13
|
+
@input, @output = input, output
|
14
|
+
end
|
15
|
+
|
16
|
+
def run
|
17
|
+
case command
|
18
|
+
when "request"
|
19
|
+
prompt_for_user(@input, @output)
|
20
|
+
Request.new(project).call
|
21
|
+
else
|
22
|
+
#FIXME
|
23
|
+
Help.new.call(project.to)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def prompt_for_user(input = STDIN, output = STDOUT)
|
28
|
+
output.print("Email (default #{project.user_email}): ")
|
29
|
+
email = input.gets.chomp
|
30
|
+
project.user_email = email unless email.empty?
|
31
|
+
|
32
|
+
output.print("Email password: ")
|
33
|
+
no_echo(input) do
|
34
|
+
project.email_password = input.gets.chomp
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
#TODO, should this be somewhere better?
|
41
|
+
def no_echo(input)
|
42
|
+
oldt = Termios.tcgetattr(input)
|
43
|
+
newt = oldt.dup
|
44
|
+
newt.lflag &= ~Termios::ECHO
|
45
|
+
Termios.tcsetattr(input, Termios::TCSANOW, newt)
|
46
|
+
|
47
|
+
yield
|
48
|
+
|
49
|
+
Termios.tcsetattr(input, Termios::TCSANOW, oldt)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'forwardable'
|
3
|
+
|
4
|
+
module Reviewr
|
5
|
+
module CLI
|
6
|
+
class Request
|
7
|
+
attr_reader :project
|
8
|
+
|
9
|
+
def initialize(project)
|
10
|
+
@project = project
|
11
|
+
end
|
12
|
+
|
13
|
+
def call
|
14
|
+
project.create_review_branch
|
15
|
+
project.create_review_commit(commit_msg)
|
16
|
+
project.push_review_branch
|
17
|
+
Mailer.new(project).send(email_body)
|
18
|
+
end
|
19
|
+
|
20
|
+
def compare_url
|
21
|
+
repo = project.origin_location.split(':')[1].gsub(/.git$/, "/compare")
|
22
|
+
"http://github.com/#{repo}/#{project.master_sha}...#{project.review_sha}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def commit_msg
|
26
|
+
read_template('commit_msg.erb')
|
27
|
+
end
|
28
|
+
|
29
|
+
def email_body
|
30
|
+
read_template('request_email.erb')
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def read_template(name)
|
36
|
+
@templates ||= {}
|
37
|
+
@templates[name] ||= ERB.new(File.read(File.join(File.dirname(__FILE__),
|
38
|
+
'..',
|
39
|
+
'templates',
|
40
|
+
name)))
|
41
|
+
@templates[name].result(binding)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/reviewr/cli.rb
ADDED
data/lib/reviewr/git.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
module Reviewr
|
2
|
+
class Git
|
3
|
+
class << self
|
4
|
+
def instance
|
5
|
+
@instance ||= Git.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def instance=(instance)
|
9
|
+
@instance = instance
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def last_commit
|
14
|
+
execute('git show --pretty=format:"%H" HEAD').split("\n")[0]
|
15
|
+
end
|
16
|
+
|
17
|
+
def create_branch(branch_name)
|
18
|
+
execute("git checkout -b #{branch_name}")
|
19
|
+
end
|
20
|
+
|
21
|
+
def commit(msg)
|
22
|
+
execute("git commit --allow-empty -m \"#{msg}\"")
|
23
|
+
end
|
24
|
+
|
25
|
+
def user_email
|
26
|
+
email = execute('git config user.email')
|
27
|
+
email && email.chomp
|
28
|
+
end
|
29
|
+
|
30
|
+
def push_branch(branch_name)
|
31
|
+
execute("git push origin #{branch_name}")
|
32
|
+
end
|
33
|
+
|
34
|
+
def origin_location
|
35
|
+
r = execute("git remote show origin")
|
36
|
+
r && r.match(/URL: (.+)$/)[1]
|
37
|
+
end
|
38
|
+
|
39
|
+
def origin_master_commit
|
40
|
+
r = execute("git ls-remote origin refs/heads/master")
|
41
|
+
r && r.split(/\s+/)[0]
|
42
|
+
end
|
43
|
+
|
44
|
+
def execute(cmd)
|
45
|
+
`#{cmd}`
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'pony'
|
2
|
+
|
3
|
+
module Reviewr
|
4
|
+
class Mailer
|
5
|
+
def initialize(project)
|
6
|
+
@project = project
|
7
|
+
end
|
8
|
+
|
9
|
+
def send(body)
|
10
|
+
Pony.mail(:from => @project.user_email,
|
11
|
+
:to => @project.to,
|
12
|
+
:body => body,
|
13
|
+
:subject => "Code review request from #{@project.user_email}",
|
14
|
+
:via => :smtp,
|
15
|
+
:smtp => {
|
16
|
+
:host => 'smtp.gmail.com',
|
17
|
+
:port => '587',
|
18
|
+
:user => @project.user_email,
|
19
|
+
:tls => true,
|
20
|
+
:password => @project.email_password,
|
21
|
+
:auth => :plain,
|
22
|
+
:domain => @project.email_server
|
23
|
+
})
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module Reviewr
|
4
|
+
class Project
|
5
|
+
extend Forwardable
|
6
|
+
|
7
|
+
attr_reader :to, :git, :email_server
|
8
|
+
attr_accessor :user_email, :email_password
|
9
|
+
|
10
|
+
def_delegators :git, :push_branch, :origin_location
|
11
|
+
|
12
|
+
def initialize(to, git = Git.instance)
|
13
|
+
@to, @git = to, git
|
14
|
+
end
|
15
|
+
|
16
|
+
def create_review_branch
|
17
|
+
git.create_branch(review_branch)
|
18
|
+
end
|
19
|
+
|
20
|
+
def create_review_commit(msg)
|
21
|
+
git.commit(msg)
|
22
|
+
end
|
23
|
+
|
24
|
+
def push_review_branch
|
25
|
+
git.push_branch(review_branch)
|
26
|
+
end
|
27
|
+
|
28
|
+
def review_sha
|
29
|
+
@review_sha ||= git.last_commit.slice(0, 8)
|
30
|
+
end
|
31
|
+
|
32
|
+
def master_sha
|
33
|
+
@master_sha ||= git.origin_master_commit.slice(0, 8)
|
34
|
+
end
|
35
|
+
|
36
|
+
def review_branch
|
37
|
+
@review_branch ||= "review_#{review_sha}"
|
38
|
+
end
|
39
|
+
|
40
|
+
def user_email
|
41
|
+
@user_email ||= git.user_email
|
42
|
+
end
|
43
|
+
|
44
|
+
def email_server
|
45
|
+
@email_server ||= user_email.split('@')[1]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
Hi,
|
2
|
+
|
3
|
+
Could you please code review and comment on the following changes:
|
4
|
+
|
5
|
+
<%= compare_url %>
|
6
|
+
|
7
|
+
If you find the changes acceptable please run:
|
8
|
+
reviewr accept <%= project.review_branch %>
|
9
|
+
If you think more work needs to be done please run:
|
10
|
+
reviewr reject <%= project.review_branch %>
|
11
|
+
|
12
|
+
Thanks!
|
data/lib/reviewr.rb
ADDED
metadata
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: reviewr
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: 0.0.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Ryan Burrows
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-04-08 00:00:00 -07:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: termios
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
version: "0"
|
30
|
+
type: :runtime
|
31
|
+
version_requirements: *id001
|
32
|
+
- !ruby/object:Gem::Dependency
|
33
|
+
name: pony
|
34
|
+
prerelease: false
|
35
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
segments:
|
40
|
+
- 0
|
41
|
+
version: "0"
|
42
|
+
type: :runtime
|
43
|
+
version_requirements: *id002
|
44
|
+
- !ruby/object:Gem::Dependency
|
45
|
+
name: rspec
|
46
|
+
prerelease: false
|
47
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
segments:
|
52
|
+
- 0
|
53
|
+
version: "0"
|
54
|
+
type: :development
|
55
|
+
version_requirements: *id003
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: cucumber
|
58
|
+
prerelease: false
|
59
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
segments:
|
64
|
+
- 0
|
65
|
+
version: "0"
|
66
|
+
type: :development
|
67
|
+
version_requirements: *id004
|
68
|
+
description: " Reviewr makes git code reviews easy using Github to manage code and comments\n"
|
69
|
+
email: rhburrows@gmail.com
|
70
|
+
executables:
|
71
|
+
- reviewr
|
72
|
+
extensions: []
|
73
|
+
|
74
|
+
extra_rdoc_files: []
|
75
|
+
|
76
|
+
files:
|
77
|
+
- LICENSE
|
78
|
+
- README.md
|
79
|
+
- History.txt
|
80
|
+
- Manifest.txt
|
81
|
+
- bin/reviewr
|
82
|
+
- lib/reviewr.rb
|
83
|
+
- lib/reviewr/cli.rb
|
84
|
+
- lib/reviewr/git.rb
|
85
|
+
- lib/reviewr/mailer.rb
|
86
|
+
- lib/reviewr/project.rb
|
87
|
+
- lib/reviewr/version.rb
|
88
|
+
- lib/reviewr/cli/help.rb
|
89
|
+
- lib/reviewr/cli/main.rb
|
90
|
+
- lib/reviewr/cli/request.rb
|
91
|
+
- lib/reviewr/templates/commit_msg.erb
|
92
|
+
- lib/reviewr/templates/request_email.erb
|
93
|
+
has_rdoc: true
|
94
|
+
homepage: http://github.com/rhburrows/reviewr
|
95
|
+
licenses: []
|
96
|
+
|
97
|
+
post_install_message:
|
98
|
+
rdoc_options: []
|
99
|
+
|
100
|
+
require_paths:
|
101
|
+
- lib
|
102
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
segments:
|
107
|
+
- 0
|
108
|
+
version: "0"
|
109
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
110
|
+
requirements:
|
111
|
+
- - ">="
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
segments:
|
114
|
+
- 1
|
115
|
+
- 3
|
116
|
+
- 6
|
117
|
+
version: 1.3.6
|
118
|
+
requirements: []
|
119
|
+
|
120
|
+
rubyforge_project:
|
121
|
+
rubygems_version: 1.3.6
|
122
|
+
signing_key:
|
123
|
+
specification_version: 3
|
124
|
+
summary: Easy git code reviews
|
125
|
+
test_files: []
|
126
|
+
|