pendaxes 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +14 -57
- data/lib/pendaxes/command_line.rb +158 -23
- data/lib/pendaxes/config.rb +1 -1
- data/lib/pendaxes/detectors/rspec.rb +7 -0
- data/lib/pendaxes/notificators/file.rb +16 -0
- data/lib/pendaxes/version.rb +1 -1
- data/lib/pendaxes/workspace.rb +4 -1
- data/spec/workspace_spec.rb +2 -2
- metadata +5 -4
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# Pendaxes
|
2
2
|
|
3
|
+
![sample notification using mail](https://img.skitch.com/20120925-essq4fdifg79axb2ssi2cyb2ne.png)
|
4
|
+
|
3
5
|
Throw axes to pending makers!
|
4
6
|
|
5
7
|
Leaving a pending long time is really bad, shouldn't be happened. They'll make a trouble.
|
@@ -17,11 +19,16 @@ Avoid the trouble due to pending examples :D
|
|
17
19
|
|
18
20
|
$ pendaxes <config_file>
|
19
21
|
|
20
|
-
|
22
|
+
See `pendaxes --help` for more.
|
21
23
|
|
22
24
|
### Configuration
|
23
25
|
|
24
|
-
|
26
|
+
$ pendaxes --init # will write to .pendaxes.yml
|
27
|
+
$ pendaxes --init config.yml # will write to config.yml
|
28
|
+
|
29
|
+
see https://github.com/cookpad/pendaxes/wiki/Configuration for detail.
|
30
|
+
|
31
|
+
#### Example
|
25
32
|
|
26
33
|
Clone `https://github.com/foo/bar.git` to `/path/to/be/cloned/repository`, then detect pendings using rspec detector (default).
|
27
34
|
|
@@ -30,67 +37,17 @@ Finally send notification to committers via email (from `no-reply@example.com`).
|
|
30
37
|
workspace:
|
31
38
|
path: /path/to/be/cloned/repository # where to clone?
|
32
39
|
repository: https://github.com/foo/bar.git # where clone from?
|
33
|
-
report:
|
34
|
-
use: haml
|
35
|
-
to: "report.html"
|
36
40
|
notifications:
|
41
|
+
- use: file
|
42
|
+
to: "report.html"
|
43
|
+
reporter:
|
44
|
+
use: haml
|
37
45
|
- use: mail
|
38
46
|
from: no-reply@example.com
|
47
|
+
delivery_method: sendmail
|
39
48
|
reporter:
|
40
49
|
use: haml
|
41
50
|
|
42
|
-
|
43
|
-
#### Full
|
44
|
-
|
45
|
-
detection:
|
46
|
-
use: rspec # use rspec detector for pending detection. (default)
|
47
|
-
# pattern: '*_spec.rb' # this will be passed after `git grep ... --`. Default is "*_spec.rb".
|
48
|
-
# allowed_for: 604800 # (second) = 1 week. Pendings will be marked "not allowed" if it elapsed more than this value
|
49
|
-
|
50
|
-
workspace:
|
51
|
-
path: /path/to/be/cloned/repository # where to clone?
|
52
|
-
repository: "https://github.com/user/repo.git" # where clone from?
|
53
|
-
|
54
|
-
report: # report configuration to save
|
55
|
-
use: haml # what reporter to use (haml and text is bundled in the gem)
|
56
|
-
to: "report.html" # where to save?
|
57
|
-
include_allowed: true # include "allowed" pendings in report. (default: true)
|
58
|
-
# VVV haml reporter specific configuration VVV
|
59
|
-
commit_url: "https://github.com/user/repo/commit/%commit%" # Used for link to commit. %commit% will be replaced to sha1. If not specified, will not be a link.
|
60
|
-
file_url: "https://github.com/user/repo/blob/HEAD/%file%#L%line%" # Used for link to file. %file% and %line% will be replaced to filepath and line no. If not specified, will not be a link.
|
61
|
-
|
62
|
-
notifications: # notifications. multiple values are accepted.
|
63
|
-
- use: terminal # use terminal notificator.
|
64
|
-
- use: mail # use mail notificator.
|
65
|
-
reporter: # reporter setting for this (mail) notification
|
66
|
-
use: haml
|
67
|
-
commit_url: "https://github.com/user/repo/commit/%commit%"
|
68
|
-
file_url: "https://github.com/user/repo/blob/HEAD/%file%#L%line%"
|
69
|
-
|
70
|
-
# VVV mail notificator specific configuration VVV
|
71
|
-
from: no-reply@example.com
|
72
|
-
to: foo@example.com # (optional) mail will be sent once to this mail address.
|
73
|
-
# without this, mail will be sent separated for each committer.
|
74
|
-
# (mails will include pendings added by its recipient only.)
|
75
|
-
|
76
|
-
delivery_method: sendmail # specify delivery_method. https://github.com/mikel/mail for more detail.
|
77
|
-
delivery_options: # (optional) used as option for delivery_method.
|
78
|
-
:location: /usr/sbin/sendmail
|
79
|
-
|
80
|
-
whitelist: # (optional) if whitelist set, mail won't be sent if not matched.
|
81
|
-
- foo@bar # complete match.
|
82
|
-
- /example\.com$/ # used as regexp.
|
83
|
-
blacklist: # (optional) mail won't be sent if matched. preferred than whitelist.
|
84
|
-
- black@example.com
|
85
|
-
- /^black/
|
86
|
-
|
87
|
-
alias: # (optional) Aliasing emails. if mail will be sent to <value> if git commit author is <key>.
|
88
|
-
"foo@gmail.com": "foo@company.com"
|
89
|
-
|
90
|
-
|
91
|
-
* Reporter: generates text or html by given pendings
|
92
|
-
* Notificator: get text or html by reporter, and notify it (via mail, to terminal, etc...)
|
93
|
-
|
94
51
|
## Axes?
|
95
52
|
|
96
53
|
斧... Axe in Japanese. Recently, Japanese engineer says a review comment as axe (斧).
|
@@ -3,54 +3,189 @@ require_relative "./workspace"
|
|
3
3
|
require_relative "./detector"
|
4
4
|
require_relative "./reporter"
|
5
5
|
require_relative "./notificator"
|
6
|
+
require 'yaml'
|
6
7
|
|
7
8
|
module Pendaxes
|
8
9
|
class CommandLine
|
10
|
+
DEFAULT_CONFIG_FILE = ".pendaxes.yml"
|
11
|
+
|
9
12
|
def initialize(*args)
|
10
13
|
@args = args
|
11
|
-
@config =
|
14
|
+
@config = nil
|
12
15
|
end
|
13
16
|
|
14
|
-
def
|
15
|
-
|
16
|
-
|
17
|
+
def config
|
18
|
+
return @config if @config
|
19
|
+
return nil if @args.empty? && !File.exist?(DEFAULT_CONFIG_FILE)
|
17
20
|
|
18
|
-
|
19
|
-
|
21
|
+
@config = Config.new(YAML.load_file(@args.first || DEFAULT_CONFIG_FILE))
|
22
|
+
end
|
20
23
|
|
21
|
-
|
22
|
-
|
24
|
+
def write_default_config(options={})
|
25
|
+
options[:to] ||= DEFAULT_CONFIG_FILE
|
26
|
+
workspace = (options[:path] || options[:repository])
|
27
|
+
open(options[:to], 'w') do |io|
|
28
|
+
io.puts <<-EOC
|
29
|
+
# Pendaxes default configuration file.
|
30
|
+
# See https://github.com/cookpad/pendaxes/wiki/Configuration for detail.
|
23
31
|
|
24
|
-
|
25
|
-
|
32
|
+
##
|
33
|
+
# for automatic git-pulling. recommend to set if you run periodically.
|
34
|
+
#
|
35
|
+
# path: path to working copy to use.
|
36
|
+
# if not exist, pendaxes will clone automatically from `repository`.
|
37
|
+
# PENDAXES WILL DO "git reset --hard".
|
38
|
+
# MAKE SURE path TO BE NOT SAME WITH working copy you use.
|
39
|
+
#
|
40
|
+
# repository: remote url of repository.
|
41
|
+
# if `path` doesn't exist, will automatically cloned from specified url.
|
42
|
+
##
|
26
43
|
|
27
|
-
|
44
|
+
#{workspace ? '' : '# '}workspace:
|
45
|
+
#{options[:path] ? '' : '# '} path: #{options[:path] || '/tmp/repository'}
|
46
|
+
#{options[:repository] ? '' : '# '} repository: #{options[:repository] || "git@github.com:cookpad/pendaxes.git"}
|
47
|
+
|
48
|
+
##
|
49
|
+
# Settings of notification.
|
50
|
+
# See https://github.com/cookpad/pendaxes/wiki/Configuration for detail.
|
51
|
+
##
|
52
|
+
|
53
|
+
notifications:
|
54
|
+
- use: file # write report to file.
|
55
|
+
to: report.html # path to write.
|
56
|
+
reporter:
|
57
|
+
use: haml
|
58
|
+
# - use: mail # send mails to each committer of pending.
|
59
|
+
# reporter:
|
60
|
+
# use: haml
|
61
|
+
# from: no-reply@example.com
|
62
|
+
# delivery_method: sendmail
|
63
|
+
# - use: terminal # show pendings on STDOUT.
|
64
|
+
|
65
|
+
##
|
66
|
+
# Settings for pending detection
|
67
|
+
##
|
68
|
+
|
69
|
+
detector:
|
70
|
+
use: rspec # Use rspec detector. Currently only rspec is available.
|
71
|
+
pattern: # pattern of rspec file. this will be passed right after of "git grep --".
|
72
|
+
- '*_spec.rb'
|
73
|
+
# - 'spec/**/*.rb'
|
74
|
+
EOC
|
75
|
+
end
|
76
|
+
|
77
|
+
puts "Just written default config file to #{options[:to]} !"
|
78
|
+
if workspace
|
79
|
+
puts "\nWith automatic git-pulling enabled:"
|
80
|
+
|
81
|
+
if options[:repository] && options[:path]
|
82
|
+
puts " * using #{options[:repository]}"
|
83
|
+
puts " * will cloned at #{options[:path]}"
|
84
|
+
|
85
|
+
if File.exist?(options[:path])
|
86
|
+
puts "WARNING: #{options[:path]} already exists! Pendaxes does `git reset --hard`, be careful!"
|
87
|
+
end
|
88
|
+
elsif options[:path]
|
89
|
+
puts " * using working copy on #{options[:path]}"
|
90
|
+
puts "WARNING: #{options[:path]} doesn't exist, you have to clone." unless File.exist?(options[:path])
|
91
|
+
elsif options[:repository]
|
92
|
+
end
|
93
|
+
else
|
94
|
+
puts <<-EOM
|
95
|
+
|
96
|
+
In default configuration, this will do:
|
97
|
+
|
98
|
+
1. Detect pendings
|
99
|
+
2. Write report file to "./report.html"
|
100
|
+
|
101
|
+
For more about configuration, see https://github.com/cookpad/pendaxes/wiki/Configuration !
|
102
|
+
EOM
|
103
|
+
|
104
|
+
if File.exist?(".git")
|
105
|
+
puts "\nWARNING: this directory doesn't seem git working copy."
|
106
|
+
puts "(Pendaxes works with git working copy.)"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def init
|
112
|
+
write_default_config(to: @args[1], path: @args[2], repository: @args[3])
|
113
|
+
end
|
114
|
+
|
115
|
+
def usage
|
116
|
+
puts <<-USAGE
|
117
|
+
Usage:
|
118
|
+
pendaxes [config]
|
119
|
+
config: (default = ./.pendaxes.yml)
|
120
|
+
Path to config file to use.
|
121
|
+
|
122
|
+
pendaxes --init [config] [path] [remote]
|
123
|
+
|
124
|
+
config: (default = ./.pendaxes.yml)
|
125
|
+
Where to write config file.
|
126
|
+
path: (optional)
|
127
|
+
Path to working copy.
|
128
|
+
remote: (optional)
|
129
|
+
remote git url. if `path` doesn't exist,
|
130
|
+
will be cloned from this onto `path`.
|
131
|
+
|
132
|
+
pendaxes --help
|
133
|
+
|
134
|
+
Show this help.
|
135
|
+
USAGE
|
136
|
+
end
|
137
|
+
|
138
|
+
def workspace
|
139
|
+
@workspace ||= Workspace.new(config.workspace || {path: Dir.pwd})
|
28
140
|
end
|
29
141
|
|
30
142
|
def update
|
31
|
-
|
32
|
-
@workspace.update
|
143
|
+
workspace.update if config.workspace
|
33
144
|
end
|
34
145
|
|
35
146
|
def detect
|
36
|
-
@detector = Detector.find(
|
147
|
+
@detector = Detector.find(config.detection.use.to_sym).new(@workspace, {out: $stdout}.merge(config.detection))
|
37
148
|
@pendings = @detector.detect
|
38
149
|
end
|
39
150
|
|
40
|
-
def report
|
41
|
-
@reporter = Reporter.find(@config.report.use.to_sym).new(@config.report)
|
42
|
-
@reporter.add @pendings
|
43
|
-
report = @reporter.report
|
44
|
-
open(@config.report.to, 'w') {|io| io.puts report }
|
45
|
-
end
|
46
|
-
|
47
151
|
def notify
|
48
|
-
|
49
|
-
puts "
|
152
|
+
config.notifications.map{|x| Hashr.new(x) }.each do |notification|
|
153
|
+
puts " * #{notification.use}"
|
50
154
|
notificator = Notificator.find(notification.use.to_sym).new({out: $stdout}.merge(notification))
|
51
155
|
notificator.add @pendings
|
52
156
|
notificator.notify
|
53
157
|
end
|
54
158
|
end
|
159
|
+
|
160
|
+
def run
|
161
|
+
case @args.first
|
162
|
+
when "--help"
|
163
|
+
usage
|
164
|
+
when "--init"
|
165
|
+
init
|
166
|
+
else
|
167
|
+
unless config
|
168
|
+
warn "./.pendaxes.yml not exists. showing usage..."
|
169
|
+
usage
|
170
|
+
return 1
|
171
|
+
end
|
172
|
+
|
173
|
+
if config.workspace
|
174
|
+
puts "=> Update repository"
|
175
|
+
update
|
176
|
+
else
|
177
|
+
warn "=> Using this working copy. To use automatic fetching, please fill 'workspace' in your config file."
|
178
|
+
workspace # to initialize @workspace
|
179
|
+
end
|
180
|
+
|
181
|
+
puts "=> Detect pendings"
|
182
|
+
detect
|
183
|
+
|
184
|
+
puts "=> Send notifications"
|
185
|
+
notify
|
186
|
+
end
|
187
|
+
|
188
|
+
0
|
189
|
+
end
|
55
190
|
end
|
56
191
|
end
|
data/lib/pendaxes/config.rb
CHANGED
@@ -51,6 +51,7 @@ module Pendaxes
|
|
51
51
|
}
|
52
52
|
|
53
53
|
pending[:commit] = blame(file, line)
|
54
|
+
next unless pending[:commit]
|
54
55
|
pending[:allowed] = (Time.now - pending[:commit][:at]) <= @config.allowed_for
|
55
56
|
|
56
57
|
pendings << pending
|
@@ -70,6 +71,12 @@ module Pendaxes
|
|
70
71
|
sha: blame[0].first, name: blame[1][1..-1].join(' '),
|
71
72
|
email: blame[2][1..-1].join(' ').gsub(/^</,'').gsub(/>$/,'')
|
72
73
|
}
|
74
|
+
|
75
|
+
if commit[:sha] == "0000000000000000000000000000000000000000" && commit[:name] == "Not Committed Yet"
|
76
|
+
@config.out.puts " NOT COMMITTED YET, skipping." if @config.out
|
77
|
+
return nil
|
78
|
+
end
|
79
|
+
|
73
80
|
commit[:at] = Time.parse(@workspace.git(*%w(log --pretty=%aD -n1), commit[:sha]).chomp)
|
74
81
|
commit
|
75
82
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require_relative '../notificator'
|
2
|
+
|
3
|
+
module Pendaxes
|
4
|
+
class Notificator
|
5
|
+
class File < Notificator
|
6
|
+
defaults to: "report.txt", reporter: {use: :text}
|
7
|
+
|
8
|
+
def notify
|
9
|
+
@config.out.puts " * writing report to #{@config.to}" if @config.out
|
10
|
+
open(@config.to, 'w') do |io|
|
11
|
+
io.puts report_for(pendings)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/pendaxes/version.rb
CHANGED
data/lib/pendaxes/workspace.rb
CHANGED
@@ -10,6 +10,7 @@ module Pendaxes
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def clone
|
13
|
+
raise RemoteUrlMissing, "Set git remote url to workspace.repository, or clone to path yourself." unless @config.repository
|
13
14
|
FileUtils.remove_entry_secure(path) if File.exist?(path)
|
14
15
|
git "clone", @config.repository, path
|
15
16
|
end
|
@@ -19,7 +20,7 @@ module Pendaxes
|
|
19
20
|
|
20
21
|
dive do
|
21
22
|
git "fetch", "origin"
|
22
|
-
git "reset", "--hard", @config.branch || "
|
23
|
+
git "reset", "--hard", @config.branch || "origin/HEAD"
|
23
24
|
end
|
24
25
|
end
|
25
26
|
|
@@ -35,5 +36,7 @@ module Pendaxes
|
|
35
36
|
str = IO.popen([@config.git || "git", *args], 'r', &:read)
|
36
37
|
$?.success? ? str : nil
|
37
38
|
end
|
39
|
+
|
40
|
+
class RemoteUrlMissing < Exception; end
|
38
41
|
end
|
39
42
|
end
|
data/spec/workspace_spec.rb
CHANGED
@@ -37,7 +37,7 @@ describe Pendaxes::Workspace do
|
|
37
37
|
it "fetch and reset" do
|
38
38
|
subject.should_receive(:dive).and_yield.ordered
|
39
39
|
subject.should_receive(:git).with("fetch", "origin").ordered
|
40
|
-
subject.should_receive(:git).with("reset", "--hard", "
|
40
|
+
subject.should_receive(:git).with("reset", "--hard", "origin/HEAD").ordered
|
41
41
|
|
42
42
|
subject.update
|
43
43
|
end
|
@@ -51,7 +51,7 @@ describe Pendaxes::Workspace do
|
|
51
51
|
subject.should_receive(:clone).ordered
|
52
52
|
subject.should_receive(:dive).and_yield.ordered
|
53
53
|
subject.should_receive(:git).with("fetch", "origin").ordered
|
54
|
-
subject.should_receive(:git).with("reset", "--hard", "
|
54
|
+
subject.should_receive(:git).with("reset", "--hard", "origin/HEAD").ordered
|
55
55
|
|
56
56
|
subject.update
|
57
57
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pendaxes
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-09-
|
12
|
+
date: 2012-09-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: hashr
|
@@ -131,6 +131,7 @@ files:
|
|
131
131
|
- lib/pendaxes/detectors/rspec.rb
|
132
132
|
- lib/pendaxes/finder.rb
|
133
133
|
- lib/pendaxes/notificator.rb
|
134
|
+
- lib/pendaxes/notificators/file.rb
|
134
135
|
- lib/pendaxes/notificators/mail.rb
|
135
136
|
- lib/pendaxes/notificators/terminal.rb
|
136
137
|
- lib/pendaxes/pending_manager.rb
|
@@ -168,7 +169,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
168
169
|
version: '0'
|
169
170
|
segments:
|
170
171
|
- 0
|
171
|
-
hash:
|
172
|
+
hash: -3174069537055922012
|
172
173
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
173
174
|
none: false
|
174
175
|
requirements:
|
@@ -177,7 +178,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
177
178
|
version: '0'
|
178
179
|
segments:
|
179
180
|
- 0
|
180
|
-
hash:
|
181
|
+
hash: -3174069537055922012
|
181
182
|
requirements: []
|
182
183
|
rubyforge_project:
|
183
184
|
rubygems_version: 1.8.23
|