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 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
- (writing in cron is recommended)
22
+ See `pendaxes --help` for more.
21
23
 
22
24
  ### Configuration
23
25
 
24
- #### Minimal
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 = Config.new(YAML.load_file(args.first))
14
+ @config = nil
12
15
  end
13
16
 
14
- def run
15
- puts "=> Update repository"
16
- update
17
+ def config
18
+ return @config if @config
19
+ return nil if @args.empty? && !File.exist?(DEFAULT_CONFIG_FILE)
17
20
 
18
- puts "=> Detect pendings"
19
- detect
21
+ @config = Config.new(YAML.load_file(@args.first || DEFAULT_CONFIG_FILE))
22
+ end
20
23
 
21
- puts "=> Writing report"
22
- report
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
- puts "=> Send notifications"
25
- notify
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
- 0
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
- @workspace = Workspace.new(@config.workspace)
32
- @workspace.update
143
+ workspace.update if config.workspace
33
144
  end
34
145
 
35
146
  def detect
36
- @detector = Detector.find(@config.detection.use.to_sym).new(@workspace, {out: $stdout}.merge(@config.detection))
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
- @config.notifications.map{|x| Hashr.new(x) }.each do |notification|
49
- puts " * #{notification.use}"
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
@@ -3,7 +3,7 @@ require 'hashr'
3
3
  module Pendaxes
4
4
  class Config < Hashr
5
5
  define detection: {use: :rspec},
6
- workspace: {},
6
+ workspace: nil,
7
7
  report: {use: :text, to: "report.txt"},
8
8
  notifications: [{use: :terminal}]
9
9
  end
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Pendaxes
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -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 || "FETCH_HEAD"
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
@@ -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", "FETCH_HEAD").ordered
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", "FETCH_HEAD").ordered
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.1
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-25 00:00:00.000000000 Z
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: 314574877471589493
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: 314574877471589493
181
+ hash: -3174069537055922012
181
182
  requirements: []
182
183
  rubyforge_project:
183
184
  rubygems_version: 1.8.23