whenever 0.5.3 → 0.6.8

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.
@@ -2,7 +2,7 @@ module Whenever
2
2
  class JobList
3
3
 
4
4
  def initialize(options)
5
- @jobs, @env, @set_variables = {}, {}, {}
5
+ @jobs, @env, @set_variables, @pre_set_variables = {}, {}, {}, {}
6
6
 
7
7
  case options
8
8
  when String
@@ -16,16 +16,14 @@ module Whenever
16
16
  pre_set(options[:set])
17
17
  end
18
18
 
19
- # Load all job type files.
20
- Dir["#{File.expand_path(File.dirname(__FILE__))}/job_types/*.rb"].each do |file|
21
- eval(File.read(file))
22
- end
19
+ setup = File.read("#{File.expand_path(File.dirname(__FILE__))}/setup.rb")
23
20
 
24
- eval(config)
21
+ eval(setup + config)
25
22
  end
26
23
 
27
24
  def set(variable, value)
28
- return if instance_variable_defined?("@#{variable}".to_sym)
25
+ variable = variable.to_sym
26
+ return if @pre_set_variables[variable]
29
27
 
30
28
  instance_variable_set("@#{variable}".to_sym, value)
31
29
  self.class.send(:attr_reader, variable.to_sym)
@@ -59,9 +57,7 @@ module Whenever
59
57
  end
60
58
  end
61
59
 
62
- def generate_cron_output
63
- set_path_environment_variable
64
-
60
+ def generate_cron_output
65
61
  [environment_variables, cron_jobs].compact.join
66
62
  end
67
63
 
@@ -79,29 +75,20 @@ module Whenever
79
75
  pairs.each do |pair|
80
76
  next unless pair.index('=')
81
77
  variable, value = *pair.split('=')
82
- set(variable.strip.to_sym, value.strip) unless variable.blank? || value.blank?
78
+ unless variable.blank? || value.blank?
79
+ variable = variable.strip.to_sym
80
+ set(variable, value.strip)
81
+ @pre_set_variables[variable] = value
82
+ end
83
83
  end
84
84
  end
85
-
86
- def set_path_environment_variable
87
- return if path_should_not_be_set_automatically?
88
- @env[:PATH] = read_path unless read_path.blank?
89
- end
90
-
91
- def read_path
92
- ENV['PATH'] if ENV
93
- end
94
-
95
- def path_should_not_be_set_automatically?
96
- @set_path_automatically === false || @env[:PATH] || @env["PATH"]
97
- end
98
85
 
99
86
  def environment_variables
100
87
  return if @env.empty?
101
88
 
102
89
  output = []
103
90
  @env.each do |key, val|
104
- output << "#{key}=#{val}\n"
91
+ output << "#{key}=#{val.blank? ? '""' : val}\n"
105
92
  end
106
93
  output << "\n"
107
94
 
@@ -1,60 +1,58 @@
1
1
  module Whenever
2
2
  module Output
3
- class Cron
4
- class OutputRedirection
5
-
6
- def initialize(output)
7
- @output = output
8
- end
9
-
10
- def to_s
11
- return '' unless defined?(@output)
12
- case @output
13
- when String then redirect_from_string
14
- when Hash then redirect_from_hash
15
- when NilClass then ">> /dev/null 2>&1"
16
- else ''
17
- end
18
- end
19
-
20
- protected
21
-
22
- def stdout
23
- return unless @output.has_key?(:standard)
24
- @output[:standard].nil? ? '/dev/null' : @output[:standard]
25
- end
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
26
25
 
27
- def stderr
28
- return unless @output.has_key?(:error)
29
- @output[:error].nil? ? '/dev/null' : @output[:error]
30
- end
26
+ def stderr
27
+ return unless @output.has_key?(:error)
28
+ @output[:error].nil? ? '/dev/null' : @output[:error]
29
+ end
31
30
 
32
- def redirect_from_hash
33
- case
34
- when stdout == '/dev/null' && stderr == '/dev/null'
35
- "> /dev/null 2>&1"
36
- when stdout && stderr == '/dev/null'
37
- ">> #{stdout} 2> /dev/null"
38
- when stdout && stderr
39
- ">> #{stdout} 2>> #{stderr}"
40
- when stderr == '/dev/null'
41
- "2> /dev/null"
42
- when stderr
43
- "2>> #{stderr}"
44
- when stdout == '/dev/null'
45
- "> /dev/null"
46
- when stdout
47
- ">> #{stdout}"
48
- else
49
- ''
50
- end
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
+ ''
51
49
  end
50
+ end
52
51
 
53
- def redirect_from_string
54
- ">> #{@output} 2>&1"
55
- end
56
-
52
+ def redirect_from_string
53
+ ">> #{@output} 2>&1"
57
54
  end
55
+
58
56
  end
59
57
  end
60
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
@@ -1,3 +1,3 @@
1
1
  module Whenever
2
- VERSION = '0.5.3'
3
- end unless defined?(Whenever::VERSION)
2
+ VERSION = '0.6.8'
3
+ end
data/lib/whenever.rb CHANGED
@@ -1,10 +1,22 @@
1
1
  require 'chronic'
2
2
  require 'active_support/all'
3
+ require 'thread'
3
4
 
4
- require 'whenever/base'
5
5
  require 'whenever/job_list'
6
6
  require 'whenever/job'
7
7
  require 'whenever/cron'
8
8
  require 'whenever/output_redirection'
9
9
  require 'whenever/command_line'
10
- require 'whenever/version'
10
+ require 'whenever/version'
11
+
12
+ module Whenever
13
+
14
+ def self.cron(options)
15
+ Whenever::JobList.new(options).generate_cron_output
16
+ end
17
+
18
+ def self.path
19
+ Dir.pwd
20
+ end
21
+
22
+ end
@@ -120,35 +120,18 @@ NEW_CRON
120
120
  end
121
121
 
122
122
  should "append the similarly named command" do
123
- assert_equal @existing + "\n\n" + @new, @command.send(:updated_crontab)
123
+ assert_equal @existing + "\n" + @new, @command.send(:updated_crontab)
124
124
  end
125
125
  end
126
126
 
127
- context "A command line delete" do
127
+ context "A command line clear" do
128
128
  setup do
129
129
  File.expects(:exists?).with('config/schedule.rb').returns(true)
130
130
  @command = Whenever::CommandLine.new(:clear => true, :identifier => 'My identifier')
131
131
  @task = "#{two_hours} /my/command"
132
132
  end
133
133
 
134
- should "add an empty identifier block if there is no existing one" do
135
- existing = '# Existing crontab'
136
- @command.expects(:read_crontab).at_least_once.returns(existing)
137
-
138
- new_cron = <<-EXPECTED
139
- #{existing}
140
-
141
- # Begin Whenever generated tasks for: My identifier
142
- # End Whenever generated tasks for: My identifier
143
- EXPECTED
144
-
145
- assert_equal new_cron, @command.send(:updated_crontab)
146
-
147
- @command.expects(:write_crontab).with(new_cron).returns(true)
148
- assert @command.run
149
- end
150
-
151
- should "delete an existing block if the identifier matches" do
134
+ should "clear an existing block if the identifier matches" do
152
135
  existing = <<-EXISTING_CRON
153
136
  # Something
154
137
 
@@ -162,20 +145,17 @@ This shouldn't get replaced
162
145
  EXISTING_CRON
163
146
 
164
147
  @command.expects(:read_crontab).at_least_once.returns(existing)
165
-
148
+
166
149
  new_cron = <<-NEW_CRON
167
150
  # Something
168
151
 
169
- # Begin Whenever generated tasks for: My identifier
170
- # End Whenever generated tasks for: My identifier
171
-
172
152
  # Begin Whenever generated tasks for: Other identifier
173
153
  This shouldn't get replaced
174
154
  # End Whenever generated tasks for: Other identifier
175
155
  NEW_CRON
176
-
156
+
177
157
  assert_equal new_cron, @command.send(:updated_crontab)
178
-
158
+
179
159
  @command.expects(:write_crontab).with(new_cron).returns(true)
180
160
  assert @command.run
181
161
  end
@@ -217,6 +197,7 @@ NEW_CRON
217
197
  setup do
218
198
  @output = Whenever.cron :set => 'environment=serious', :string => \
219
199
  <<-file
200
+ set :job_template, nil
220
201
  set :environment, :silly
221
202
  set :path, '/my/path'
222
203
  every 2.hours do
@@ -234,6 +215,7 @@ NEW_CRON
234
215
  setup do
235
216
  @output = Whenever.cron :set => 'environment=serious&path=/serious/path', :string => \
236
217
  <<-file
218
+ set :job_template, nil
237
219
  set :environment, :silly
238
220
  set :path, '/silly/path'
239
221
  every 2.hours do
@@ -251,6 +233,7 @@ NEW_CRON
251
233
  setup do
252
234
  @output = Whenever.cron :set => ' environment = serious& path =/serious/path', :string => \
253
235
  <<-file
236
+ set :job_template, nil
254
237
  set :environment, :silly
255
238
  set :path, '/silly/path'
256
239
  every 2.hours do
@@ -268,6 +251,7 @@ NEW_CRON
268
251
  setup do
269
252
  @output = Whenever.cron :set => ' environment=', :string => \
270
253
  <<-file
254
+ set :job_template, nil
271
255
  set :environment, :silly
272
256
  set :path, '/silly/path'
273
257
  every 2.hours do
@@ -297,8 +281,7 @@ My whenever job that was already here
297
281
  # End Whenever generated tasks for: My identifier
298
282
  EXISTING_CRON
299
283
 
300
- # here-doc adds an extra newline we need removed
301
- assert_equal existing.strip, @command.send(:prepare, existing)
284
+ assert_equal existing, @command.send(:prepare, existing)
302
285
  end
303
286
 
304
287
  should "trim off the top lines of the file" do
@@ -318,8 +301,21 @@ My whenever job that was already here
318
301
  # End Whenever generated tasks for: My identifier
319
302
  NEW_CRON
320
303
 
321
- # here-doc adds an extra newline we need removed
322
- assert_equal new_cron.strip, @command.send(:prepare, existing)
304
+ assert_equal new_cron, @command.send(:prepare, existing)
305
+ end
306
+
307
+ should "preserve terminating newlines in files" do
308
+ @command = Whenever::CommandLine.new(:update => true, :identifier => 'My identifier')
309
+ existing = <<-EXISTING_CRON
310
+ # Begin Whenever generated tasks for: My identifier
311
+ My whenever job that was already here
312
+ # End Whenever generated tasks for: My identifier
313
+
314
+ # A non-Whenever task
315
+ My non-whenever job that was already here
316
+ EXISTING_CRON
317
+
318
+ assert_equal existing, @command.send(:prepare, existing)
323
319
  end
324
320
  end
325
321
 
@@ -6,6 +6,7 @@ class OutputAtTest < Test::Unit::TestCase
6
6
  setup do
7
7
  @output = Whenever.cron \
8
8
  <<-file
9
+ set :job_template, nil
9
10
  every "weekday", :at => '5:02am' do
10
11
  command "blahblah"
11
12
  end
@@ -21,6 +22,7 @@ class OutputAtTest < Test::Unit::TestCase
21
22
  setup do
22
23
  @output = Whenever.cron \
23
24
  <<-file
25
+ set :job_template, nil
24
26
  every "weekday", :at => %w(5:02am 3:52pm) do
25
27
  command "blahblah"
26
28
  end
@@ -37,6 +39,7 @@ class OutputAtTest < Test::Unit::TestCase
37
39
  setup do
38
40
  @output = Whenever.cron \
39
41
  <<-file
42
+ set :job_template, nil
40
43
  every "weekday", :at => '5:02am, 3:52pm' do
41
44
  command "blahblah"
42
45
  end
@@ -53,6 +56,7 @@ class OutputAtTest < Test::Unit::TestCase
53
56
  setup do
54
57
  @output = Whenever.cron \
55
58
  <<-file
59
+ set :job_template, nil
56
60
  every "weekday", :at => '5:02am, 3:02pm' do
57
61
  command "blahblah"
58
62
  end
@@ -68,6 +72,7 @@ class OutputAtTest < Test::Unit::TestCase
68
72
  setup do
69
73
  @output = Whenever.cron \
70
74
  <<-file
75
+ set :job_template, nil
71
76
  every "mon,wed,fri", :at => '5:02am, 3:02pm' do
72
77
  command "blahblah"
73
78
  end
@@ -83,6 +88,7 @@ class OutputAtTest < Test::Unit::TestCase
83
88
  setup do
84
89
  @output = Whenever.cron \
85
90
  <<-file
91
+ set :job_template, nil
86
92
  set :path, '/your/path'
87
93
  every "mon,wed,fri", :at => '5:02am, 3:02pm' do
88
94
  runner "blahblah"
@@ -99,6 +105,7 @@ class OutputAtTest < Test::Unit::TestCase
99
105
  setup do
100
106
  @output = Whenever.cron \
101
107
  <<-file
108
+ set :job_template, nil
102
109
  set :path, '/your/path'
103
110
  every "mon,wed,fri", :at => '5:02am, 3:02pm' do
104
111
  rake "blah:blah"
@@ -107,7 +114,7 @@ class OutputAtTest < Test::Unit::TestCase
107
114
  end
108
115
 
109
116
  should "output the rake task using one entry because the times are aligned" do
110
- assert_match '2 5,15 * * 1,3,5 cd /your/path && RAILS_ENV=production /usr/bin/env rake blah:blah', @output
117
+ assert_match '2 5,15 * * 1,3,5 cd /your/path && RAILS_ENV=production rake blah:blah --silent', @output
111
118
  end
112
119
  end
113
120
 
@@ -115,6 +122,7 @@ class OutputAtTest < Test::Unit::TestCase
115
122
  setup do
116
123
  @output = Whenever.cron \
117
124
  <<-file
125
+ set :job_template, nil
118
126
  every [1.month, 1.day], :at => 'january 5:02am, june 17th at 2:22pm, june 3rd at 3:33am' do
119
127
  command "blahblah"
120
128
  end
@@ -138,6 +146,7 @@ class OutputAtTest < Test::Unit::TestCase
138
146
  setup do
139
147
  @output = Whenever.cron \
140
148
  <<-file
149
+ set :job_template, nil
141
150
  every :reboot do
142
151
  command "command_1"
143
152
  command "command_2"
@@ -155,8 +164,9 @@ class OutputAtTest < Test::Unit::TestCase
155
164
  setup do
156
165
  @output = Whenever.cron \
157
166
  <<-file
167
+ set :job_template, nil
158
168
  set :path, '/your/path'
159
- every :day do
169
+ every :daily do
160
170
  rake "blah:blah"
161
171
  runner "runner_1"
162
172
  command "command_1"
@@ -167,7 +177,7 @@ class OutputAtTest < Test::Unit::TestCase
167
177
  end
168
178
 
169
179
  should "output all of the commands @daily" do
170
- assert_match '@daily cd /your/path && RAILS_ENV=production /usr/bin/env rake blah:blah', @output
180
+ assert_match '@daily cd /your/path && RAILS_ENV=production rake blah:blah --silent', @output
171
181
  assert_match %(@daily cd /your/path && script/runner -e production 'runner_1'), @output
172
182
  assert_match '@daily command_1', @output
173
183
  assert_match %(@daily cd /your/path && script/runner -e production 'runner_2'), @output
@@ -179,6 +189,7 @@ class OutputAtTest < Test::Unit::TestCase
179
189
  setup do
180
190
  @output = Whenever.cron \
181
191
  <<-file
192
+ set :job_template, nil
182
193
  every 5.minutes, :at => 1 do
183
194
  command "blahblah"
184
195
  end
@@ -194,6 +205,7 @@ class OutputAtTest < Test::Unit::TestCase
194
205
  setup do
195
206
  @output = Whenever.cron \
196
207
  <<-file
208
+ set :job_template, nil
197
209
  every 4.minutes, :at => 2 do
198
210
  command "blahblah"
199
211
  end
@@ -209,6 +221,7 @@ class OutputAtTest < Test::Unit::TestCase
209
221
  setup do
210
222
  @output = Whenever.cron \
211
223
  <<-file
224
+ set :job_template, nil
212
225
  every 3.minutes, :at => 7 do
213
226
  command "blahblah"
214
227
  end
@@ -224,6 +237,7 @@ class OutputAtTest < Test::Unit::TestCase
224
237
  setup do
225
238
  @output = Whenever.cron \
226
239
  <<-file
240
+ set :job_template, nil
227
241
  every 2.minutes, :at => 27 do
228
242
  command "blahblah"
229
243
  end
@@ -234,4 +248,21 @@ class OutputAtTest < Test::Unit::TestCase
234
248
  assert_match '27,29,31,33,35,37,39,41,43,45,47,49,51,53,55,57,59 * * * * blahblah', @output
235
249
  end
236
250
  end
251
+
252
+ context "using raw cron syntax" do
253
+ setup do
254
+ @output = Whenever.cron \
255
+ <<-file
256
+ set :job_template, nil
257
+ every '0 0 27,31 * *' do
258
+ command "blahblah"
259
+ end
260
+ file
261
+ end
262
+
263
+ should "output the command using the same cron syntax" do
264
+ assert_match '0 0 27,31 * * blahblah', @output
265
+ end
266
+ end
267
+
237
268
  end
@@ -4,10 +4,11 @@ class OutputDefaultDefinedJobsTest < Test::Unit::TestCase
4
4
 
5
5
  # command
6
6
 
7
- context "A plain command" do
7
+ context "A plain command with the job template set to nil" do
8
8
  setup do
9
9
  @output = Whenever.cron \
10
10
  <<-file
11
+ set :job_template, nil
11
12
  every 2.hours do
12
13
  command "blahblah"
13
14
  end
@@ -19,12 +20,64 @@ class OutputDefaultDefinedJobsTest < Test::Unit::TestCase
19
20
  end
20
21
  end
21
22
 
23
+ context "A plain command with no job template set" do
24
+ setup do
25
+ @output = Whenever.cron \
26
+ <<-file
27
+ every 2.hours do
28
+ command "blahblah"
29
+ end
30
+ file
31
+ end
32
+
33
+ should "output the command with the default job template" do
34
+ assert_match /^.+ .+ .+ .+ \/bin\/bash -l -c 'blahblah'$/, @output
35
+ end
36
+ end
37
+
38
+ context "A plain command that overrides the job_template set" do
39
+ setup do
40
+ @output = Whenever.cron \
41
+ <<-file
42
+ set :job_template, "/bin/bash -l -c ':job'"
43
+ every 2.hours do
44
+ command "blahblah", :job_template => "/bin/sh -l -c ':job'"
45
+ end
46
+ file
47
+ end
48
+
49
+ should "output the command using that job_template" do
50
+ assert_match /^.+ .+ .+ .+ \/bin\/sh -l -c 'blahblah'$/, @output
51
+ assert_no_match /bash/, @output
52
+ end
53
+ end
54
+
55
+ context "A plain command that is conditional on default environent and path" do
56
+ setup do
57
+ Whenever.expects(:path).at_least_once.returns('/what/you/want')
58
+ @output = Whenever.cron \
59
+ <<-file
60
+ set :job_template, nil
61
+ if environment == 'production' && path == '/what/you/want'
62
+ every 2.hours do
63
+ command "blahblah"
64
+ end
65
+ end
66
+ file
67
+ end
68
+
69
+ should "output the command" do
70
+ assert_match /blahblah/, @output
71
+ end
72
+ end
73
+
22
74
  # runner
23
75
 
24
76
  context "A runner with path set" do
25
77
  setup do
26
78
  @output = Whenever.cron \
27
79
  <<-file
80
+ set :job_template, nil
28
81
  set :path, '/my/path'
29
82
  every 2.hours do
30
83
  runner 'blahblah'
@@ -41,6 +94,7 @@ class OutputDefaultDefinedJobsTest < Test::Unit::TestCase
41
94
  setup do
42
95
  @output = Whenever.cron \
43
96
  <<-file
97
+ set :job_template, nil
44
98
  set :path, '/my/path'
45
99
  every 2.hours do
46
100
  runner "blahblah", :path => '/some/other/path'
@@ -53,12 +107,31 @@ class OutputDefaultDefinedJobsTest < Test::Unit::TestCase
53
107
  end
54
108
  end
55
109
 
110
+ context "A runner for a Rails 3 app" do
111
+ setup do
112
+ Whenever.expects(:path).at_least_once.returns('/my/path')
113
+ File.expects(:exists?).with('/my/path/script/rails').returns(true)
114
+ @output = Whenever.cron \
115
+ <<-file
116
+ set :job_template, nil
117
+ every 2.hours do
118
+ runner 'blahblah'
119
+ end
120
+ file
121
+ end
122
+
123
+ should "use the Rails 3 runner job by default" do
124
+ assert_match two_hours + %( cd /my/path && script/rails runner -e production 'blahblah'), @output
125
+ end
126
+ end
127
+
56
128
  # rake
57
129
 
58
130
  context "A rake command with path set" do
59
131
  setup do
60
132
  @output = Whenever.cron \
61
133
  <<-file
134
+ set :job_template, nil
62
135
  set :path, '/my/path'
63
136
  every 2.hours do
64
137
  rake "blahblah"
@@ -67,7 +140,7 @@ class OutputDefaultDefinedJobsTest < Test::Unit::TestCase
67
140
  end
68
141
 
69
142
  should "output the rake command using that path" do
70
- assert_match two_hours + ' cd /my/path && RAILS_ENV=production /usr/bin/env rake blahblah', @output
143
+ assert_match two_hours + ' cd /my/path && RAILS_ENV=production rake blahblah --silent', @output
71
144
  end
72
145
  end
73
146
 
@@ -75,6 +148,7 @@ class OutputDefaultDefinedJobsTest < Test::Unit::TestCase
75
148
  setup do
76
149
  @output = Whenever.cron \
77
150
  <<-file
151
+ set :job_template, nil
78
152
  set :path, '/my/path'
79
153
  every 2.hours do
80
154
  rake "blahblah", :path => '/some/other/path'
@@ -83,7 +157,7 @@ class OutputDefaultDefinedJobsTest < Test::Unit::TestCase
83
157
  end
84
158
 
85
159
  should "output the rake command using that path" do
86
- assert_match two_hours + ' cd /some/other/path && RAILS_ENV=production /usr/bin/env rake blahblah', @output
160
+ assert_match two_hours + ' cd /some/other/path && RAILS_ENV=production rake blahblah --silent', @output
87
161
  end
88
162
  end
89
163