seisuke-whenever 0.6.3

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.
@@ -0,0 +1,58 @@
1
+ module Whenever
2
+ module Output
3
+ class Redirection
4
+
5
+ def initialize(output)
6
+ @output = output
7
+ end
8
+
9
+ def to_s
10
+ return '' unless defined?(@output)
11
+ case @output
12
+ when String then redirect_from_string
13
+ when Hash then redirect_from_hash
14
+ when NilClass then ">> /dev/null 2>&1"
15
+ else ''
16
+ end
17
+ end
18
+
19
+ protected
20
+
21
+ def stdout
22
+ return unless @output.has_key?(:standard)
23
+ @output[:standard].nil? ? '/dev/null' : @output[:standard]
24
+ end
25
+
26
+ def stderr
27
+ return unless @output.has_key?(:error)
28
+ @output[:error].nil? ? '/dev/null' : @output[:error]
29
+ end
30
+
31
+ def redirect_from_hash
32
+ case
33
+ when stdout == '/dev/null' && stderr == '/dev/null'
34
+ "> /dev/null 2>&1"
35
+ when stdout && stderr == '/dev/null'
36
+ ">> #{stdout} 2> /dev/null"
37
+ when stdout && stderr
38
+ ">> #{stdout} 2>> #{stderr}"
39
+ when stderr == '/dev/null'
40
+ "2> /dev/null"
41
+ when stderr
42
+ "2>> #{stderr}"
43
+ when stdout == '/dev/null'
44
+ "> /dev/null"
45
+ when stdout
46
+ ">> #{stdout}"
47
+ else
48
+ ''
49
+ end
50
+ end
51
+
52
+ def redirect_from_string
53
+ ">> #{@output} 2>&1"
54
+ end
55
+
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,18 @@
1
+ # Environemnt defaults to production
2
+ set :environment, "production"
3
+ # Path defaults to the directory `whenever` was run from
4
+ set :path, Whenever.path
5
+
6
+ # All jobs are wrapped in this template.
7
+ # http://blog.scoutapp.com/articles/2010/09/07/rvm-and-cron-in-production
8
+ set :job_template, "/bin/bash -l -c ':job'"
9
+
10
+ job_type :command, ":task :output"
11
+ job_type :rake, "cd :path && RAILS_ENV=:environment rake :task --silent :output"
12
+
13
+ # Create a runner job that's appropriate for the Rails version,
14
+ if File.exists?(File.join(path, 'script', 'rails'))
15
+ job_type :runner, "cd :path && script/rails runner -e :environment ':task' :output"
16
+ else
17
+ job_type :runner, "cd :path && script/runner -e :environment ':task' :output"
18
+ end
@@ -0,0 +1,3 @@
1
+ module Whenever
2
+ VERSION = '0.6.3'
3
+ end unless defined?(Whenever::VERSION)
@@ -0,0 +1,310 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../test_helper")
2
+
3
+ class CommandLineTest < Test::Unit::TestCase
4
+
5
+ context "A command line write" do
6
+ setup do
7
+ File.expects(:exists?).with('config/schedule.rb').returns(true)
8
+ @command = Whenever::CommandLine.new(:write => true, :identifier => 'My identifier')
9
+ @task = "#{two_hours} /my/command"
10
+ Whenever.expects(:cron).returns(@task)
11
+ end
12
+
13
+ should "output the cron job with identifier blocks" do
14
+ output = <<-EXPECTED
15
+ # Begin Whenever generated tasks for: My identifier
16
+ #{@task}
17
+ # End Whenever generated tasks for: My identifier
18
+ EXPECTED
19
+
20
+ assert_equal output, @command.send(:whenever_cron)
21
+ end
22
+
23
+ should "write the crontab when run" do
24
+ @command.expects(:write_crontab).returns(true)
25
+ assert @command.run
26
+ end
27
+ end
28
+
29
+ context "A command line update" do
30
+ setup do
31
+ File.expects(:exists?).with('config/schedule.rb').returns(true)
32
+ @command = Whenever::CommandLine.new(:update => true, :identifier => 'My identifier')
33
+ @task = "#{two_hours} /my/command"
34
+ Whenever.expects(:cron).returns(@task)
35
+ end
36
+
37
+ should "add the cron to the end of the file if there is no existing identifier block" do
38
+ existing = '# Existing crontab'
39
+ @command.expects(:read_crontab).at_least_once.returns(existing)
40
+
41
+ new_cron = <<-EXPECTED
42
+ #{existing}
43
+
44
+ # Begin Whenever generated tasks for: My identifier
45
+ #{@task}
46
+ # End Whenever generated tasks for: My identifier
47
+ EXPECTED
48
+
49
+ assert_equal new_cron, @command.send(:updated_crontab)
50
+
51
+ @command.expects(:write_crontab).with(new_cron).returns(true)
52
+ assert @command.run
53
+ end
54
+
55
+ should "replace an existing block if the identifier matches" do
56
+ existing = <<-EXISTING_CRON
57
+ # Something
58
+
59
+ # Begin Whenever generated tasks for: My identifier
60
+ My whenever job that was already here
61
+ # End Whenever generated tasks for: My identifier
62
+
63
+ # Begin Whenever generated tasks for: Other identifier
64
+ This shouldn't get replaced
65
+ # End Whenever generated tasks for: Other identifier
66
+ EXISTING_CRON
67
+
68
+ new_cron = <<-NEW_CRON
69
+ # Something
70
+
71
+ # Begin Whenever generated tasks for: My identifier
72
+ #{@task}
73
+ # End Whenever generated tasks for: My identifier
74
+
75
+ # Begin Whenever generated tasks for: Other identifier
76
+ This shouldn't get replaced
77
+ # End Whenever generated tasks for: Other identifier
78
+ NEW_CRON
79
+
80
+ @command.expects(:read_crontab).at_least_once.returns(existing)
81
+ assert_equal new_cron, @command.send(:updated_crontab)
82
+
83
+ @command.expects(:write_crontab).with(new_cron).returns(true)
84
+ assert @command.run
85
+ end
86
+ end
87
+
88
+ context "A command line update that contains backslashes" do
89
+ setup do
90
+ @existing = <<-EXISTING_CRON
91
+ # Begin Whenever generated tasks for: My identifier
92
+ script/runner -e production 'puts '\\''hello'\\'''
93
+ # End Whenever generated tasks for: My identifier
94
+ EXISTING_CRON
95
+ File.expects(:exists?).with('config/schedule.rb').returns(true)
96
+ @command = Whenever::CommandLine.new(:update => true, :identifier => 'My identifier')
97
+ @command.expects(:read_crontab).at_least_once.returns(@existing)
98
+ @command.expects(:whenever_cron).returns(@existing)
99
+ end
100
+
101
+ should "replace the existing block with the backslashes in tact" do
102
+ assert_equal @existing, @command.send(:updated_crontab)
103
+ end
104
+ end
105
+
106
+ context "A command line update with an identifier similar to an existing one in the crontab already" do
107
+ setup do
108
+ @existing = <<-EXISTING_CRON
109
+ # Begin Whenever generated tasks for: WheneverExisting
110
+ # End Whenever generated tasks for: WheneverExisting
111
+ EXISTING_CRON
112
+ @new = <<-NEW_CRON
113
+ # Begin Whenever generated tasks for: Whenever
114
+ # End Whenever generated tasks for: Whenever
115
+ NEW_CRON
116
+ File.expects(:exists?).with('config/schedule.rb').returns(true)
117
+ @command = Whenever::CommandLine.new(:update => true, :identifier => 'Whenever')
118
+ @command.expects(:read_crontab).at_least_once.returns(@existing)
119
+ @command.expects(:whenever_cron).returns(@new)
120
+ end
121
+
122
+ should "append the similarly named command" do
123
+ assert_equal @existing + "\n" + @new, @command.send(:updated_crontab)
124
+ end
125
+ end
126
+
127
+ context "A command line clear" do
128
+ setup do
129
+ File.expects(:exists?).with('config/schedule.rb').returns(true)
130
+ @command = Whenever::CommandLine.new(:clear => true, :identifier => 'My identifier')
131
+ @task = "#{two_hours} /my/command"
132
+ end
133
+
134
+ should "clear an existing block if the identifier matches" do
135
+ existing = <<-EXISTING_CRON
136
+ # Something
137
+
138
+ # Begin Whenever generated tasks for: My identifier
139
+ My whenever job that was already here
140
+ # End Whenever generated tasks for: My identifier
141
+
142
+ # Begin Whenever generated tasks for: Other identifier
143
+ This shouldn't get replaced
144
+ # End Whenever generated tasks for: Other identifier
145
+ EXISTING_CRON
146
+
147
+ @command.expects(:read_crontab).at_least_once.returns(existing)
148
+
149
+ new_cron = <<-NEW_CRON
150
+ # Something
151
+
152
+ # Begin Whenever generated tasks for: Other identifier
153
+ This shouldn't get replaced
154
+ # End Whenever generated tasks for: Other identifier
155
+ NEW_CRON
156
+
157
+ assert_equal new_cron, @command.send(:updated_crontab)
158
+
159
+ @command.expects(:write_crontab).with(new_cron).returns(true)
160
+ assert @command.run
161
+ end
162
+ end
163
+
164
+ context "A command line update with no identifier" do
165
+ setup do
166
+ File.expects(:exists?).with('config/schedule.rb').returns(true)
167
+ Whenever::CommandLine.any_instance.expects(:default_identifier).returns('DEFAULT')
168
+ @command = Whenever::CommandLine.new(:update => true, :file => @file)
169
+ end
170
+
171
+ should "use the default identifier" do
172
+ assert_equal "Whenever generated tasks for: DEFAULT", @command.send(:comment_base)
173
+ end
174
+ end
175
+
176
+ context "combined params" do
177
+ setup do
178
+ Whenever::CommandLine.any_instance.expects(:exit)
179
+ Whenever::CommandLine.any_instance.expects(:warn)
180
+ File.expects(:exists?).with('config/schedule.rb').returns(true)
181
+ end
182
+
183
+ should "exit with write and clear" do
184
+ @command = Whenever::CommandLine.new(:write => true, :clear => true)
185
+ end
186
+
187
+ should "exit with write and update" do
188
+ @command = Whenever::CommandLine.new(:write => true, :update => true)
189
+ end
190
+
191
+ should "exit with update and clear" do
192
+ @command = Whenever::CommandLine.new(:update => true, :clear => true)
193
+ end
194
+ end
195
+
196
+ context "A runner where the environment is overridden using the :set option" do
197
+ setup do
198
+ @output = Whenever.cron :set => 'environment=serious', :string => \
199
+ <<-file
200
+ set :job_template, nil
201
+ set :environment, :silly
202
+ set :path, '/my/path'
203
+ every 2.hours do
204
+ runner "blahblah"
205
+ end
206
+ file
207
+ end
208
+
209
+ should "output the runner using the override environment" do
210
+ assert_match two_hours + %( cd /my/path && script/runner -e serious 'blahblah'), @output
211
+ end
212
+ end
213
+
214
+ context "A runner where the environment and path are overridden using the :set option" do
215
+ setup do
216
+ @output = Whenever.cron :set => 'environment=serious&path=/serious/path', :string => \
217
+ <<-file
218
+ set :job_template, nil
219
+ set :environment, :silly
220
+ set :path, '/silly/path'
221
+ every 2.hours do
222
+ runner "blahblah"
223
+ end
224
+ file
225
+ end
226
+
227
+ should "output the runner using the overridden path and environment" do
228
+ assert_match two_hours + %( cd /serious/path && script/runner -e serious 'blahblah'), @output
229
+ end
230
+ end
231
+
232
+ context "A runner where the environment and path are overridden using the :set option with spaces in the string" do
233
+ setup do
234
+ @output = Whenever.cron :set => ' environment = serious& path =/serious/path', :string => \
235
+ <<-file
236
+ set :job_template, nil
237
+ set :environment, :silly
238
+ set :path, '/silly/path'
239
+ every 2.hours do
240
+ runner "blahblah"
241
+ end
242
+ file
243
+ end
244
+
245
+ should "output the runner using the overridden path and environment" do
246
+ assert_match two_hours + %( cd /serious/path && script/runner -e serious 'blahblah'), @output
247
+ end
248
+ end
249
+
250
+ context "A runner where the environment is overridden using the :set option but no value is given" do
251
+ setup do
252
+ @output = Whenever.cron :set => ' environment=', :string => \
253
+ <<-file
254
+ set :job_template, nil
255
+ set :environment, :silly
256
+ set :path, '/silly/path'
257
+ every 2.hours do
258
+ runner "blahblah"
259
+ end
260
+ file
261
+ end
262
+
263
+ should "output the runner using the original environmnet" do
264
+ assert_match two_hours + %( cd /silly/path && script/runner -e silly 'blahblah'), @output
265
+ end
266
+ end
267
+
268
+ context "prepare-ing the output" do
269
+ setup do
270
+ File.expects(:exists?).with('config/schedule.rb').returns(true)
271
+ end
272
+
273
+ should "not trim off the top lines of the file" do
274
+ @command = Whenever::CommandLine.new(:update => true, :identifier => 'My identifier', :cut => 0)
275
+ existing = <<-EXISTING_CRON
276
+ # Useless Comments
277
+ # at the top of the file
278
+
279
+ # Begin Whenever generated tasks for: My identifier
280
+ My whenever job that was already here
281
+ # End Whenever generated tasks for: My identifier
282
+ EXISTING_CRON
283
+
284
+ # here-doc adds an extra newline we need removed
285
+ assert_equal existing.strip, @command.send(:prepare, existing)
286
+ end
287
+
288
+ should "trim off the top lines of the file" do
289
+ @command = Whenever::CommandLine.new(:update => true, :identifier => 'My identifier', :cut => '3')
290
+ existing = <<-EXISTING_CRON
291
+ # Useless Comments
292
+ # at the top of the file
293
+
294
+ # Begin Whenever generated tasks for: My identifier
295
+ My whenever job that was already here
296
+ # End Whenever generated tasks for: My identifier
297
+ EXISTING_CRON
298
+
299
+ new_cron = <<-NEW_CRON
300
+ # Begin Whenever generated tasks for: My identifier
301
+ My whenever job that was already here
302
+ # End Whenever generated tasks for: My identifier
303
+ NEW_CRON
304
+
305
+ # here-doc adds an extra newline we need removed
306
+ assert_equal new_cron.strip, @command.send(:prepare, existing)
307
+ end
308
+ end
309
+
310
+ end
@@ -0,0 +1,251 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../test_helper")
2
+
3
+ class OutputAtTest < Test::Unit::TestCase
4
+
5
+ context "weekday at a (single) given time" do
6
+ setup do
7
+ @output = Whenever.cron \
8
+ <<-file
9
+ set :job_template, nil
10
+ every "weekday", :at => '5:02am' do
11
+ command "blahblah"
12
+ end
13
+ file
14
+ end
15
+
16
+ should "output the command using that time" do
17
+ assert_match '2 5 * * 1-5 blahblah', @output
18
+ end
19
+ end
20
+
21
+ context "weekday at a multiple diverse times, via an array" do
22
+ setup do
23
+ @output = Whenever.cron \
24
+ <<-file
25
+ set :job_template, nil
26
+ every "weekday", :at => %w(5:02am 3:52pm) do
27
+ command "blahblah"
28
+ end
29
+ file
30
+ end
31
+
32
+ should "output the commands for both times given" do
33
+ assert_match '2 5 * * 1-5 blahblah', @output
34
+ assert_match '52 15 * * 1-5 blahblah', @output
35
+ end
36
+ end
37
+
38
+ context "weekday at a multiple diverse times, comma separated" do
39
+ setup do
40
+ @output = Whenever.cron \
41
+ <<-file
42
+ set :job_template, nil
43
+ every "weekday", :at => '5:02am, 3:52pm' do
44
+ command "blahblah"
45
+ end
46
+ file
47
+ end
48
+
49
+ should "output the commands for both times given" do
50
+ assert_match '2 5 * * 1-5 blahblah', @output
51
+ assert_match '52 15 * * 1-5 blahblah', @output
52
+ end
53
+ end
54
+
55
+ context "weekday at a multiple aligned times" do
56
+ setup do
57
+ @output = Whenever.cron \
58
+ <<-file
59
+ set :job_template, nil
60
+ every "weekday", :at => '5:02am, 3:02pm' do
61
+ command "blahblah"
62
+ end
63
+ file
64
+ end
65
+
66
+ should "output the command using one entry because the times are aligned" do
67
+ assert_match '2 5,15 * * 1-5 blahblah', @output
68
+ end
69
+ end
70
+
71
+ context "various days at a various aligned times" do
72
+ setup do
73
+ @output = Whenever.cron \
74
+ <<-file
75
+ set :job_template, nil
76
+ every "mon,wed,fri", :at => '5:02am, 3:02pm' do
77
+ command "blahblah"
78
+ end
79
+ file
80
+ end
81
+
82
+ should "output the command using one entry because the times are aligned" do
83
+ assert_match '2 5,15 * * 1,3,5 blahblah', @output
84
+ end
85
+ end
86
+
87
+ context "various days at a various aligned times using a runner" do
88
+ setup do
89
+ @output = Whenever.cron \
90
+ <<-file
91
+ set :job_template, nil
92
+ set :path, '/your/path'
93
+ every "mon,wed,fri", :at => '5:02am, 3:02pm' do
94
+ runner "blahblah"
95
+ end
96
+ file
97
+ end
98
+
99
+ should "output the runner using one entry because the times are aligned" do
100
+ assert_match %(2 5,15 * * 1,3,5 cd /your/path && script/runner -e production 'blahblah'), @output
101
+ end
102
+ end
103
+
104
+ context "various days at a various aligned times using a rake task" do
105
+ setup do
106
+ @output = Whenever.cron \
107
+ <<-file
108
+ set :job_template, nil
109
+ set :path, '/your/path'
110
+ every "mon,wed,fri", :at => '5:02am, 3:02pm' do
111
+ rake "blah:blah"
112
+ end
113
+ file
114
+ end
115
+
116
+ should "output the rake task using one entry because the times are aligned" do
117
+ assert_match '2 5,15 * * 1,3,5 cd /your/path && RAILS_ENV=production rake blah:blah --silent', @output
118
+ end
119
+ end
120
+
121
+ context "A command every 1.month at very diverse times" do
122
+ setup do
123
+ @output = Whenever.cron \
124
+ <<-file
125
+ set :job_template, nil
126
+ every [1.month, 1.day], :at => 'january 5:02am, june 17th at 2:22pm, june 3rd at 3:33am' do
127
+ command "blahblah"
128
+ end
129
+ file
130
+ end
131
+
132
+ should "output 6 commands since none align" do
133
+ # The 1.month commands
134
+ assert_match '2 5 1 * * blahblah', @output
135
+ assert_match '22 14 17 * * blahblah', @output
136
+ assert_match '33 3 3 * * blahblah', @output
137
+
138
+ # The 1.day commands
139
+ assert_match '2 5 * * * blahblah', @output
140
+ assert_match '22 14 * * * blahblah', @output
141
+ assert_match '33 3 * * * blahblah', @output
142
+ end
143
+ end
144
+
145
+ context "Multiple commands output every :reboot" do
146
+ setup do
147
+ @output = Whenever.cron \
148
+ <<-file
149
+ set :job_template, nil
150
+ every :reboot do
151
+ command "command_1"
152
+ command "command_2"
153
+ end
154
+ file
155
+ end
156
+
157
+ should "output both commands @reboot" do
158
+ assert_match "@reboot command_1", @output
159
+ assert_match "@reboot command_2", @output
160
+ end
161
+ end
162
+
163
+ context "Many different job types output every :day" do
164
+ setup do
165
+ @output = Whenever.cron \
166
+ <<-file
167
+ set :job_template, nil
168
+ set :path, '/your/path'
169
+ every :day do
170
+ rake "blah:blah"
171
+ runner "runner_1"
172
+ command "command_1"
173
+ runner "runner_2"
174
+ command "command_2"
175
+ end
176
+ file
177
+ end
178
+
179
+ should "output all of the commands @daily" do
180
+ assert_match '@daily cd /your/path && RAILS_ENV=production rake blah:blah --silent', @output
181
+ assert_match %(@daily cd /your/path && script/runner -e production 'runner_1'), @output
182
+ assert_match '@daily command_1', @output
183
+ assert_match %(@daily cd /your/path && script/runner -e production 'runner_2'), @output
184
+ assert_match '@daily command_2', @output
185
+ end
186
+ end
187
+
188
+ context "every 5 minutes but but starting at 1" do
189
+ setup do
190
+ @output = Whenever.cron \
191
+ <<-file
192
+ set :job_template, nil
193
+ every 5.minutes, :at => 1 do
194
+ command "blahblah"
195
+ end
196
+ file
197
+ end
198
+
199
+ should "output the command using that time" do
200
+ assert_match '1,6,11,16,21,26,31,36,41,46,51,56 * * * * blahblah', @output
201
+ end
202
+ end
203
+
204
+ context "every 4 minutes but starting at 2" do
205
+ setup do
206
+ @output = Whenever.cron \
207
+ <<-file
208
+ set :job_template, nil
209
+ every 4.minutes, :at => 2 do
210
+ command "blahblah"
211
+ end
212
+ file
213
+ end
214
+
215
+ should "output the command using that time" do
216
+ assert_match '2,6,10,14,18,22,26,30,34,38,42,46,50,54,58 * * * * blahblah', @output
217
+ end
218
+ end
219
+
220
+ context "every 3 minutes but starting at 7" do
221
+ setup do
222
+ @output = Whenever.cron \
223
+ <<-file
224
+ set :job_template, nil
225
+ every 3.minutes, :at => 7 do
226
+ command "blahblah"
227
+ end
228
+ file
229
+ end
230
+
231
+ should "output the command using that time" do
232
+ assert_match '7,10,13,16,19,22,25,28,31,34,37,40,43,46,49,52,55,58 * * * * blahblah', @output
233
+ end
234
+ end
235
+
236
+ context "every 2 minutes but starting at 27" do
237
+ setup do
238
+ @output = Whenever.cron \
239
+ <<-file
240
+ set :job_template, nil
241
+ every 2.minutes, :at => 27 do
242
+ command "blahblah"
243
+ end
244
+ file
245
+ end
246
+
247
+ should "output the command using that time" do
248
+ assert_match '27,29,31,33,35,37,39,41,43,45,47,49,51,53,55,57,59 * * * * blahblah', @output
249
+ end
250
+ end
251
+ end