whenever-benlangfeld 0.9.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +6 -0
  3. data/.travis.yml +18 -0
  4. data/CHANGELOG.md +333 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE +22 -0
  7. data/README.md +260 -0
  8. data/Rakefile +10 -0
  9. data/bin/whenever +41 -0
  10. data/bin/wheneverize +68 -0
  11. data/gemfiles/activesupport4.1.gemfile +5 -0
  12. data/gemfiles/activesupport4.2.gemfile +5 -0
  13. data/lib/whenever.rb +34 -0
  14. data/lib/whenever/capistrano.rb +7 -0
  15. data/lib/whenever/capistrano/v2/hooks.rb +8 -0
  16. data/lib/whenever/capistrano/v2/recipes.rb +48 -0
  17. data/lib/whenever/capistrano/v2/support.rb +53 -0
  18. data/lib/whenever/capistrano/v3/tasks/whenever.rake +45 -0
  19. data/lib/whenever/command_line.rb +135 -0
  20. data/lib/whenever/cron.rb +153 -0
  21. data/lib/whenever/job.rb +54 -0
  22. data/lib/whenever/job_list.rb +155 -0
  23. data/lib/whenever/numeric.rb +13 -0
  24. data/lib/whenever/numeric_seconds.rb +48 -0
  25. data/lib/whenever/os.rb +7 -0
  26. data/lib/whenever/output_redirection.rb +57 -0
  27. data/lib/whenever/setup.rb +26 -0
  28. data/lib/whenever/tasks/whenever.rake +1 -0
  29. data/lib/whenever/version.rb +3 -0
  30. data/test/functional/command_line_test.rb +331 -0
  31. data/test/functional/output_at_test.rb +207 -0
  32. data/test/functional/output_default_defined_jobs_test.rb +296 -0
  33. data/test/functional/output_defined_job_test.rb +85 -0
  34. data/test/functional/output_env_test.rb +29 -0
  35. data/test/functional/output_jobs_for_roles_test.rb +65 -0
  36. data/test/functional/output_redirection_test.rb +248 -0
  37. data/test/test_case.rb +32 -0
  38. data/test/test_helper.rb +37 -0
  39. data/test/unit/capistrano_support_test.rb +147 -0
  40. data/test/unit/cron_test.rb +244 -0
  41. data/test/unit/job_test.rb +114 -0
  42. data/whenever.gemspec +27 -0
  43. metadata +167 -0
@@ -0,0 +1,26 @@
1
+ # Environment variable defaults to RAILS_ENV
2
+ set :environment_variable, "RAILS_ENV"
3
+ # Environment defaults to production
4
+ set :environment, "production"
5
+ # Path defaults to the directory `whenever` was run from
6
+ set :path, Whenever.path
7
+
8
+ # All jobs are wrapped in this template.
9
+ # http://blog.scoutapp.com/articles/2010/09/07/rvm-and-cron-in-production
10
+ set :job_template, "/bin/bash -l -c ':job'"
11
+
12
+ set :runner_command, case
13
+ when Whenever.bin_rails?
14
+ "bin/rails runner"
15
+ when Whenever.script_rails?
16
+ "script/rails runner"
17
+ else
18
+ "script/runner"
19
+ end
20
+
21
+ set :bundle_command, Whenever.bundler? ? "bundle exec" : ""
22
+
23
+ job_type :command, ":task :output"
24
+ job_type :rake, "cd :path && :environment_variable=:environment :bundle_command rake :task --silent :output"
25
+ job_type :script, "cd :path && :environment_variable=:environment :bundle_command script/:task :output"
26
+ job_type :runner, "cd :path && :bundle_command :runner_command -e :environment ':task' :output"
@@ -0,0 +1 @@
1
+ ../capistrano/v3/tasks/whenever.rake
@@ -0,0 +1,3 @@
1
+ module Whenever
2
+ VERSION = '0.9.5'
3
+ end
@@ -0,0 +1,331 @@
1
+ require 'test_helper'
2
+
3
+ class CommandLineWriteTest < Whenever::TestCase
4
+ setup do
5
+ File.expects(:exist?).with('config/schedule.rb').returns(true)
6
+ @command = Whenever::CommandLine.new(:write => true, :identifier => 'My identifier')
7
+ @task = "#{two_hours} /my/command"
8
+ Whenever.expects(:cron).returns(@task)
9
+ end
10
+
11
+ should "output the cron job with identifier blocks" do
12
+ output = <<-EXPECTED
13
+ # Begin Whenever generated tasks for: My identifier
14
+ #{@task}
15
+ # End Whenever generated tasks for: My identifier
16
+ EXPECTED
17
+
18
+ assert_equal output, @command.send(:whenever_cron)
19
+ end
20
+
21
+ should "write the crontab when run" do
22
+ @command.expects(:write_crontab).returns(true)
23
+ assert @command.run
24
+ end
25
+ end
26
+
27
+ class CommandLineUpdateTest < Whenever::TestCase
28
+ setup do
29
+ File.expects(:exist?).with('config/schedule.rb').returns(true)
30
+ @command = Whenever::CommandLine.new(:update => true, :identifier => 'My identifier')
31
+ @task = "#{two_hours} /my/command"
32
+ Whenever.expects(:cron).returns(@task)
33
+ end
34
+
35
+ should "add the cron to the end of the file if there is no existing identifier block" do
36
+ existing = '# Existing crontab'
37
+ @command.expects(:read_crontab).at_least_once.returns(existing)
38
+
39
+ new_cron = <<-EXPECTED
40
+ #{existing}
41
+
42
+ # Begin Whenever generated tasks for: My identifier
43
+ #{@task}
44
+ # End Whenever generated tasks for: My identifier
45
+ EXPECTED
46
+
47
+ assert_equal new_cron, @command.send(:updated_crontab)
48
+
49
+ @command.expects(:write_crontab).with(new_cron).returns(true)
50
+ assert @command.run
51
+ end
52
+
53
+ should "replace an existing block if the identifier matches" do
54
+ existing = <<-EXISTING_CRON
55
+ # Something
56
+
57
+ # Begin Whenever generated tasks for: My identifier
58
+ My whenever job that was already here
59
+ # End Whenever generated tasks for: My identifier
60
+
61
+ # Begin Whenever generated tasks for: Other identifier
62
+ This shouldn't get replaced
63
+ # End Whenever generated tasks for: Other identifier
64
+ EXISTING_CRON
65
+
66
+ new_cron = <<-NEW_CRON
67
+ # Something
68
+
69
+ # Begin Whenever generated tasks for: My identifier
70
+ #{@task}
71
+ # End Whenever generated tasks for: My identifier
72
+
73
+ # Begin Whenever generated tasks for: Other identifier
74
+ This shouldn't get replaced
75
+ # End Whenever generated tasks for: Other identifier
76
+ NEW_CRON
77
+
78
+ @command.expects(:read_crontab).at_least_once.returns(existing)
79
+ assert_equal new_cron, @command.send(:updated_crontab)
80
+
81
+ @command.expects(:write_crontab).with(new_cron).returns(true)
82
+ assert @command.run
83
+ end
84
+ end
85
+
86
+ class CommandLineUpdateWithBackslashesTest < Whenever::TestCase
87
+ setup do
88
+ @existing = <<-EXISTING_CRON
89
+ # Begin Whenever generated tasks for: My identifier
90
+ script/runner -e production 'puts '\\''hello'\\'''
91
+ # End Whenever generated tasks for: My identifier
92
+ EXISTING_CRON
93
+ File.expects(:exist?).with('config/schedule.rb').returns(true)
94
+ @command = Whenever::CommandLine.new(:update => true, :identifier => 'My identifier')
95
+ @command.expects(:read_crontab).at_least_once.returns(@existing)
96
+ @command.expects(:whenever_cron).returns(@existing)
97
+ end
98
+
99
+ should "replace the existing block with the backslashes in tact" do
100
+ assert_equal @existing, @command.send(:updated_crontab)
101
+ end
102
+ end
103
+
104
+ class CommandLineUpdateToSimilarCrontabTest < Whenever::TestCase
105
+ setup do
106
+ @existing = <<-EXISTING_CRON
107
+ # Begin Whenever generated tasks for: WheneverExisting
108
+ # End Whenever generated tasks for: WheneverExisting
109
+ EXISTING_CRON
110
+ @new = <<-NEW_CRON
111
+ # Begin Whenever generated tasks for: Whenever
112
+ # End Whenever generated tasks for: Whenever
113
+ NEW_CRON
114
+ File.expects(:exist?).with('config/schedule.rb').returns(true)
115
+ @command = Whenever::CommandLine.new(:update => true, :identifier => 'Whenever')
116
+ @command.expects(:read_crontab).at_least_once.returns(@existing)
117
+ @command.expects(:whenever_cron).returns(@new)
118
+ end
119
+
120
+ should "append the similarly named command" do
121
+ assert_equal @existing + "\n" + @new, @command.send(:updated_crontab)
122
+ end
123
+ end
124
+
125
+ class CommandLineClearTest < Whenever::TestCase
126
+ setup do
127
+ File.expects(:exist?).with('config/schedule.rb').returns(true)
128
+ @command = Whenever::CommandLine.new(:clear => true, :identifier => 'My identifier')
129
+ @task = "#{two_hours} /my/command"
130
+ end
131
+
132
+ should "clear an existing block if the identifier matches" do
133
+ existing = <<-EXISTING_CRON
134
+ # Something
135
+
136
+ # Begin Whenever generated tasks for: My identifier
137
+ My whenever job that was already here
138
+ # End Whenever generated tasks for: My identifier
139
+
140
+ # Begin Whenever generated tasks for: Other identifier
141
+ This shouldn't get replaced
142
+ # End Whenever generated tasks for: Other identifier
143
+ EXISTING_CRON
144
+
145
+ @command.expects(:read_crontab).at_least_once.returns(existing)
146
+
147
+ new_cron = <<-NEW_CRON
148
+ # Something
149
+
150
+ # Begin Whenever generated tasks for: Other identifier
151
+ This shouldn't get replaced
152
+ # End Whenever generated tasks for: Other identifier
153
+ NEW_CRON
154
+
155
+ assert_equal new_cron, @command.send(:updated_crontab)
156
+
157
+ @command.expects(:write_crontab).with(new_cron).returns(true)
158
+ assert @command.run
159
+ end
160
+ end
161
+
162
+ class CommandLineClearWithNoScheduleTest < Whenever::TestCase
163
+ setup do
164
+ File.expects(:exist?).with('config/schedule.rb').returns(false)
165
+ @command = Whenever::CommandLine.new(:clear => true, :identifier => 'My identifier')
166
+ end
167
+
168
+ should "run successfully" do
169
+ @command.expects(:write_crontab).returns(true)
170
+ assert @command.run
171
+ end
172
+ end
173
+
174
+ class CommandLineUpdateWithNoIdentifierTest < Whenever::TestCase
175
+ setup do
176
+ File.expects(:exist?).with('config/schedule.rb').returns(true)
177
+ Whenever::CommandLine.any_instance.expects(:default_identifier).returns('DEFAULT')
178
+ @command = Whenever::CommandLine.new(:update => true, :file => @file)
179
+ end
180
+
181
+ should "use the default identifier" do
182
+ assert_equal "Whenever generated tasks for: DEFAULT", @command.send(:comment_base)
183
+ end
184
+ end
185
+
186
+ class CombinedParamsTest < Whenever::TestCase
187
+ setup do
188
+ Whenever::CommandLine.any_instance.expects(:exit)
189
+ Whenever::CommandLine.any_instance.expects(:warn)
190
+ File.expects(:exist?).with('config/schedule.rb').returns(true)
191
+ end
192
+
193
+ should "exit with write and clear" do
194
+ @command = Whenever::CommandLine.new(:write => true, :clear => true)
195
+ end
196
+
197
+ should "exit with write and update" do
198
+ @command = Whenever::CommandLine.new(:write => true, :update => true)
199
+ end
200
+
201
+ should "exit with update and clear" do
202
+ @command = Whenever::CommandLine.new(:update => true, :clear => true)
203
+ end
204
+ end
205
+
206
+ class RunnerOverwrittenWithSetOptionTest < Whenever::TestCase
207
+ setup do
208
+ @output = Whenever.cron :set => 'environment=serious', :string => \
209
+ <<-file
210
+ set :job_template, nil
211
+ set :environment, :silly
212
+ set :path, '/my/path'
213
+ every 2.hours do
214
+ runner "blahblah"
215
+ end
216
+ file
217
+ end
218
+
219
+ should "output the runner using the override environment" do
220
+ assert_match two_hours + %( cd /my/path && bundle exec script/runner -e serious 'blahblah'), @output
221
+ end
222
+ end
223
+
224
+
225
+ class EnvironmentAndPathOverwrittenWithSetOptionTest < Whenever::TestCase
226
+ setup do
227
+ @output = Whenever.cron :set => 'environment=serious&path=/serious/path', :string => \
228
+ <<-file
229
+ set :job_template, nil
230
+ set :environment, :silly
231
+ set :path, '/silly/path'
232
+ every 2.hours do
233
+ runner "blahblah"
234
+ end
235
+ file
236
+ end
237
+
238
+ should "output the runner using the overridden path and environment" do
239
+ assert_match two_hours + %( cd /serious/path && bundle exec script/runner -e serious 'blahblah'), @output
240
+ end
241
+ end
242
+
243
+ class EnvironmentAndPathOverwrittenWithSetOptionWithSpacesTest < Whenever::TestCase
244
+ setup do
245
+ @output = Whenever.cron :set => ' environment = serious& path =/serious/path', :string => \
246
+ <<-file
247
+ set :job_template, nil
248
+ set :environment, :silly
249
+ set :path, '/silly/path'
250
+ every 2.hours do
251
+ runner "blahblah"
252
+ end
253
+ file
254
+ end
255
+
256
+ should "output the runner using the overridden path and environment" do
257
+ assert_match two_hours + %( cd /serious/path && bundle exec script/runner -e serious 'blahblah'), @output
258
+ end
259
+ end
260
+
261
+ class EnvironmentOverwrittenWithoutValueTest < Whenever::TestCase
262
+ setup do
263
+ @output = Whenever.cron :set => ' environment=', :string => \
264
+ <<-file
265
+ set :job_template, nil
266
+ set :environment, :silly
267
+ set :path, '/silly/path'
268
+ every 2.hours do
269
+ runner "blahblah"
270
+ end
271
+ file
272
+ end
273
+
274
+ should "output the runner using the original environmnet" do
275
+ assert_match two_hours + %( cd /silly/path && bundle exec script/runner -e silly 'blahblah'), @output
276
+ end
277
+ end
278
+
279
+ class PreparingOutputTest < Whenever::TestCase
280
+ setup do
281
+ File.expects(:exist?).with('config/schedule.rb').returns(true)
282
+ end
283
+
284
+ should "not trim off the top lines of the file" do
285
+ @command = Whenever::CommandLine.new(:update => true, :identifier => 'My identifier', :cut => 0)
286
+ existing = <<-EXISTING_CRON
287
+ # Useless Comments
288
+ # at the top of the file
289
+
290
+ # Begin Whenever generated tasks for: My identifier
291
+ My whenever job that was already here
292
+ # End Whenever generated tasks for: My identifier
293
+ EXISTING_CRON
294
+
295
+ assert_equal existing, @command.send(:prepare, existing)
296
+ end
297
+
298
+ should "trim off the top lines of the file" do
299
+ @command = Whenever::CommandLine.new(:update => true, :identifier => 'My identifier', :cut => '3')
300
+ existing = <<-EXISTING_CRON
301
+ # Useless Comments
302
+ # at the top of the file
303
+
304
+ # Begin Whenever generated tasks for: My identifier
305
+ My whenever job that was already here
306
+ # End Whenever generated tasks for: My identifier
307
+ EXISTING_CRON
308
+
309
+ new_cron = <<-NEW_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
+ NEW_CRON
314
+
315
+ assert_equal new_cron, @command.send(:prepare, existing)
316
+ end
317
+
318
+ should "preserve terminating newlines in files" do
319
+ @command = Whenever::CommandLine.new(:update => true, :identifier => 'My identifier')
320
+ existing = <<-EXISTING_CRON
321
+ # Begin Whenever generated tasks for: My identifier
322
+ My whenever job that was already here
323
+ # End Whenever generated tasks for: My identifier
324
+
325
+ # A non-Whenever task
326
+ My non-whenever job that was already here
327
+ EXISTING_CRON
328
+
329
+ assert_equal existing, @command.send(:prepare, existing)
330
+ end
331
+ end
@@ -0,0 +1,207 @@
1
+ require 'test_helper'
2
+
3
+ class OutputAtTest < Whenever::TestCase
4
+ test "weekday at a (single) given time" do
5
+ output = Whenever.cron \
6
+ <<-file
7
+ set :job_template, nil
8
+ every "weekday", :at => '5:02am' do
9
+ command "blahblah"
10
+ end
11
+ file
12
+
13
+ assert_match '2 5 * * 1-5 blahblah', output
14
+ end
15
+
16
+ test "weekday at a multiple diverse times, via an array" do
17
+ output = Whenever.cron \
18
+ <<-file
19
+ set :job_template, nil
20
+ every "weekday", :at => %w(5:02am 3:52pm) do
21
+ command "blahblah"
22
+ end
23
+ file
24
+
25
+ assert_match '2 5 * * 1-5 blahblah', output
26
+ assert_match '52 15 * * 1-5 blahblah', output
27
+ end
28
+
29
+ test "weekday at a multiple diverse times, comma separated" do
30
+ output = Whenever.cron \
31
+ <<-file
32
+ set :job_template, nil
33
+ every "weekday", :at => '5:02am, 3:52pm' do
34
+ command "blahblah"
35
+ end
36
+ file
37
+
38
+ assert_match '2 5 * * 1-5 blahblah', output
39
+ assert_match '52 15 * * 1-5 blahblah', output
40
+ end
41
+
42
+ test "weekday at a multiple aligned times" do
43
+ output = Whenever.cron \
44
+ <<-file
45
+ set :job_template, nil
46
+ every "weekday", :at => '5:02am, 3:02pm' do
47
+ command "blahblah"
48
+ end
49
+ file
50
+
51
+ assert_match '2 5,15 * * 1-5 blahblah', output
52
+ end
53
+
54
+ test "various days at a various aligned times" do
55
+ output = Whenever.cron \
56
+ <<-file
57
+ set :job_template, nil
58
+ every "mon,wed,fri", :at => '5:02am, 3:02pm' do
59
+ command "blahblah"
60
+ end
61
+ file
62
+
63
+ assert_match '2 5,15 * * 1,3,5 blahblah', output
64
+ end
65
+
66
+ test "various days at a various aligned times using a runner" do
67
+ output = Whenever.cron \
68
+ <<-file
69
+ set :job_template, nil
70
+ set :path, '/your/path'
71
+ every "mon,wed,fri", :at => '5:02am, 3:02pm' do
72
+ runner "Worker.perform_async(1.day.ago)"
73
+ end
74
+ file
75
+
76
+ assert_match %(2 5,15 * * 1,3,5 cd /your/path && bundle exec script/runner -e production 'Worker.perform_async(1.day.ago)'), output
77
+ end
78
+
79
+ test "various days at a various aligned times using a rake task" do
80
+ output = Whenever.cron \
81
+ <<-file
82
+ set :job_template, nil
83
+ set :path, '/your/path'
84
+ every "mon,wed,fri", :at => '5:02am, 3:02pm' do
85
+ rake "blah:blah"
86
+ end
87
+ file
88
+
89
+ assert_match '2 5,15 * * 1,3,5 cd /your/path && RAILS_ENV=production bundle exec rake blah:blah --silent', output
90
+ end
91
+
92
+ test "A command every 1.month at very diverse times" do
93
+ output = Whenever.cron \
94
+ <<-file
95
+ set :job_template, nil
96
+ every [1.month, 1.day], :at => 'january 5:02am, june 17th at 2:22pm, june 3rd at 3:33am' do
97
+ command "blahblah"
98
+ end
99
+ file
100
+
101
+ # The 1.month commands
102
+ assert_match '2 5 1 * * blahblah', output
103
+ assert_match '22 14 17 * * blahblah', output
104
+ assert_match '33 3 3 * * blahblah', output
105
+
106
+ # The 1.day commands
107
+ assert_match '2 5 * * * blahblah', output
108
+ assert_match '22 14 * * * blahblah', output
109
+ assert_match '33 3 * * * blahblah', output
110
+ end
111
+
112
+ test "Multiple commands output every :reboot" do
113
+ output = Whenever.cron \
114
+ <<-file
115
+ set :job_template, nil
116
+ every :reboot do
117
+ command "command_1"
118
+ command "command_2"
119
+ end
120
+ file
121
+
122
+ assert_match "@reboot command_1", output
123
+ assert_match "@reboot command_2", output
124
+ end
125
+
126
+ test "Many different job types output every :day" do
127
+ output = Whenever.cron \
128
+ <<-file
129
+ set :job_template, nil
130
+ set :path, '/your/path'
131
+ every :daily do
132
+ rake "blah:blah"
133
+ runner "runner_1"
134
+ command "command_1"
135
+ runner "runner_2"
136
+ command "command_2"
137
+ end
138
+ file
139
+
140
+ assert_match '@daily cd /your/path && RAILS_ENV=production bundle exec rake blah:blah --silent', output
141
+ assert_match %(@daily cd /your/path && bundle exec script/runner -e production 'runner_1'), output
142
+ assert_match '@daily command_1', output
143
+ assert_match %(@daily cd /your/path && bundle exec script/runner -e production 'runner_2'), output
144
+ assert_match '@daily command_2', output
145
+ end
146
+
147
+ test "every 5 minutes but but starting at 1" do
148
+ output = Whenever.cron \
149
+ <<-file
150
+ set :job_template, nil
151
+ every 5.minutes, :at => 1 do
152
+ command "blahblah"
153
+ end
154
+ file
155
+
156
+ assert_match '1,6,11,16,21,26,31,36,41,46,51,56 * * * * blahblah', output
157
+ end
158
+
159
+ test "every 4 minutes but starting at 2" do
160
+ output = Whenever.cron \
161
+ <<-file
162
+ set :job_template, nil
163
+ every 4.minutes, :at => 2 do
164
+ command "blahblah"
165
+ end
166
+ file
167
+
168
+ assert_match '2,6,10,14,18,22,26,30,34,38,42,46,50,54,58 * * * * blahblah', output
169
+ end
170
+
171
+ test "every 3 minutes but starting at 7" do
172
+ output = Whenever.cron \
173
+ <<-file
174
+ set :job_template, nil
175
+ every 3.minutes, :at => 7 do
176
+ command "blahblah"
177
+ end
178
+ file
179
+
180
+
181
+ assert_match '7,10,13,16,19,22,25,28,31,34,37,40,43,46,49,52,55,58 * * * * blahblah', output
182
+ end
183
+
184
+ test "every 2 minutes but starting at 27" do
185
+ output = Whenever.cron \
186
+ <<-file
187
+ set :job_template, nil
188
+ every 2.minutes, :at => 27 do
189
+ command "blahblah"
190
+ end
191
+ file
192
+
193
+ assert_match '27,29,31,33,35,37,39,41,43,45,47,49,51,53,55,57,59 * * * * blahblah', output
194
+ end
195
+
196
+ test "using raw cron syntax" do
197
+ output = Whenever.cron \
198
+ <<-file
199
+ set :job_template, nil
200
+ every '0 0 27,31 * *' do
201
+ command "blahblah"
202
+ end
203
+ file
204
+
205
+ assert_match '0 0 27,31 * * blahblah', output
206
+ end
207
+ end