whenever 0.9.7 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.travis.yml +12 -9
- data/Appraisals +19 -0
- data/CHANGELOG.md +33 -1
- data/Gemfile +1 -1
- data/LICENSE +1 -1
- data/README.md +89 -20
- data/bin/whenever +3 -0
- data/bin/wheneverize +5 -2
- data/gemfiles/activesupport4.1.gemfile +3 -1
- data/gemfiles/activesupport4.2.gemfile +3 -1
- data/gemfiles/activesupport5.0.gemfile +7 -0
- data/gemfiles/activesupport5.1.gemfile +7 -0
- data/gemfiles/activesupport5.2.gemfile +7 -0
- data/lib/whenever/capistrano/v2/recipes.rb +3 -2
- data/lib/whenever/capistrano/v3/tasks/whenever.rake +17 -4
- data/lib/whenever/command_line.rb +39 -19
- data/lib/whenever/cron.rb +43 -15
- data/lib/whenever/job.rb +2 -1
- data/lib/whenever/job_list.rb +50 -20
- data/lib/whenever/numeric.rb +1 -1
- data/lib/whenever/setup.rb +4 -0
- data/lib/whenever/version.rb +1 -1
- data/test/functional/command_line_test.rb +159 -32
- data/test/functional/output_at_test.rb +39 -0
- data/test/functional/output_jobs_with_mailto_test.rb +168 -0
- data/test/test_helper.rb +18 -8
- data/test/unit/cron_test.rb +178 -4
- data/test/unit/executable_test.rb +142 -0
- data/whenever.gemspec +1 -0
- metadata +25 -3
data/lib/whenever/cron.rb
CHANGED
@@ -3,16 +3,20 @@ require 'chronic'
|
|
3
3
|
module Whenever
|
4
4
|
module Output
|
5
5
|
class Cron
|
6
|
+
DAYS = %w(sun mon tue wed thu fri sat)
|
7
|
+
MONTHS = %w(jan feb mar apr may jun jul aug sep oct nov dec)
|
6
8
|
KEYWORDS = [:reboot, :yearly, :annually, :monthly, :weekly, :daily, :midnight, :hourly]
|
7
|
-
REGEX = /^(@(#{KEYWORDS.join '|'})|((\*?[\d\/,\-]*)\s
|
9
|
+
REGEX = /^(@(#{KEYWORDS.join '|'})|((\*?[\d\/,\-]*)\s){3}(\*?([\d\/,\-]|(#{MONTHS.join '|'}))*\s)(\*?([\d\/,\-]|(#{DAYS.join '|'}))*))$/i
|
8
10
|
|
9
11
|
attr_accessor :time, :task
|
10
12
|
|
11
|
-
def initialize(time = nil, task = nil, at = nil)
|
13
|
+
def initialize(time = nil, task = nil, at = nil, options = {})
|
14
|
+
chronic_options = options[:chronic_options] || {}
|
15
|
+
|
12
16
|
@at_given = at
|
13
17
|
@time = time
|
14
18
|
@task = task
|
15
|
-
@at = at.is_a?(String) ? (Chronic.parse(at) || 0) : (at || 0)
|
19
|
+
@at = at.is_a?(String) ? (Chronic.parse(at, chronic_options) || 0) : (at || 0)
|
16
20
|
end
|
17
21
|
|
18
22
|
def self.enumerate(item, detect_cron = true)
|
@@ -30,10 +34,10 @@ module Whenever
|
|
30
34
|
items
|
31
35
|
end
|
32
36
|
|
33
|
-
def self.output(times, job)
|
37
|
+
def self.output(times, job, options = {})
|
34
38
|
enumerate(times).each do |time|
|
35
39
|
enumerate(job.at, false).each do |at|
|
36
|
-
yield new(time, job.output, at).output
|
40
|
+
yield new(time, job.output, at, options).output
|
37
41
|
end
|
38
42
|
end
|
39
43
|
end
|
@@ -54,18 +58,18 @@ module Whenever
|
|
54
58
|
|
55
59
|
protected
|
56
60
|
def day_given?
|
57
|
-
|
58
|
-
@at_given.is_a?(String) && months.any? { |m| @at_given.downcase.index(m) }
|
61
|
+
@at_given.is_a?(String) && (MONTHS.any? { |m| @at_given.downcase.index(m) } || @at_given[/\d\/\d/])
|
59
62
|
end
|
60
63
|
|
61
64
|
def parse_symbol
|
62
65
|
shortcut = case @time
|
63
66
|
when *KEYWORDS then "@#{@time}" # :reboot => '@reboot'
|
64
|
-
when :year then Whenever.seconds(
|
67
|
+
when :year then Whenever.seconds(1, :year)
|
65
68
|
when :day then Whenever.seconds(1, :day)
|
66
69
|
when :month then Whenever.seconds(1, :month)
|
67
70
|
when :week then Whenever.seconds(1, :week)
|
68
71
|
when :hour then Whenever.seconds(1, :hour)
|
72
|
+
when :minute then Whenever.seconds(1, :minute)
|
69
73
|
end
|
70
74
|
|
71
75
|
if shortcut.is_a?(Numeric)
|
@@ -92,23 +96,36 @@ module Whenever
|
|
92
96
|
timing[0] = comma_separated_timing(minute_frequency, 59, @at || 0)
|
93
97
|
when Whenever.seconds(1, :hour)...Whenever.seconds(1, :day)
|
94
98
|
hour_frequency = (@time / 60 / 60).round
|
95
|
-
timing[0] = @at.is_a?(Time) ? @at.min : @at
|
99
|
+
timing[0] = @at.is_a?(Time) ? @at.min : range_or_integer(@at, 0..59, 'Minute')
|
96
100
|
timing[1] = comma_separated_timing(hour_frequency, 23)
|
97
101
|
when Whenever.seconds(1, :day)...Whenever.seconds(1, :month)
|
98
102
|
day_frequency = (@time / 24 / 60 / 60).round
|
99
103
|
timing[0] = @at.is_a?(Time) ? @at.min : 0
|
100
|
-
timing[1] = @at.is_a?(Time) ? @at.hour : @at
|
104
|
+
timing[1] = @at.is_a?(Time) ? @at.hour : range_or_integer(@at, 0..23, 'Hour')
|
101
105
|
timing[2] = comma_separated_timing(day_frequency, 31, 1)
|
102
|
-
when Whenever.seconds(1, :month)
|
103
|
-
month_frequency = (@time / 30
|
106
|
+
when Whenever.seconds(1, :month)...Whenever.seconds(1, :year)
|
107
|
+
month_frequency = (@time / 30 / 24 / 60 / 60).round
|
104
108
|
timing[0] = @at.is_a?(Time) ? @at.min : 0
|
105
109
|
timing[1] = @at.is_a?(Time) ? @at.hour : 0
|
106
110
|
timing[2] = if @at.is_a?(Time)
|
107
111
|
day_given? ? @at.day : 1
|
108
112
|
else
|
109
|
-
@at
|
113
|
+
@at == 0 ? 1 : range_or_integer(@at, 1..31, 'Day')
|
110
114
|
end
|
111
115
|
timing[3] = comma_separated_timing(month_frequency, 12, 1)
|
116
|
+
when Whenever.seconds(1, :year)
|
117
|
+
timing[0] = @at.is_a?(Time) ? @at.min : 0
|
118
|
+
timing[1] = @at.is_a?(Time) ? @at.hour : 0
|
119
|
+
timing[2] = if @at.is_a?(Time)
|
120
|
+
day_given? ? @at.day : 1
|
121
|
+
else
|
122
|
+
1
|
123
|
+
end
|
124
|
+
timing[3] = if @at.is_a?(Time)
|
125
|
+
day_given? ? @at.month : 1
|
126
|
+
else
|
127
|
+
@at == 0 ? 1 : range_or_integer(@at, 1..12, 'Month')
|
128
|
+
end
|
112
129
|
else
|
113
130
|
return parse_as_string
|
114
131
|
end
|
@@ -126,11 +143,22 @@ module Whenever
|
|
126
143
|
return (timing << '1-5') * " " if string.downcase.index('weekday')
|
127
144
|
return (timing << '6,0') * " " if string.downcase.index('weekend')
|
128
145
|
|
129
|
-
|
146
|
+
DAYS.each_with_index do |day, i|
|
130
147
|
return (timing << i) * " " if string.downcase.index(day)
|
131
148
|
end
|
132
149
|
|
133
|
-
raise ArgumentError, "Couldn't parse: #{@time}"
|
150
|
+
raise ArgumentError, "Couldn't parse: #{@time.inspect}"
|
151
|
+
end
|
152
|
+
|
153
|
+
def range_or_integer(at, valid_range, name)
|
154
|
+
must_be_between = "#{name} must be between #{valid_range.min}-#{valid_range.max}"
|
155
|
+
if at.is_a?(Range)
|
156
|
+
raise ArgumentError, "#{must_be_between}, #{at.min} given" unless valid_range.include?(at.min)
|
157
|
+
raise ArgumentError, "#{must_be_between}, #{at.max} given" unless valid_range.include?(at.max)
|
158
|
+
return "#{at.min}-#{at.max}"
|
159
|
+
end
|
160
|
+
raise ArgumentError, "#{must_be_between}, #{at} given" unless valid_range.include?(at)
|
161
|
+
at
|
134
162
|
end
|
135
163
|
|
136
164
|
def comma_separated_timing(frequency, max, start = 0)
|
data/lib/whenever/job.rb
CHANGED
@@ -2,12 +2,13 @@ require 'shellwords'
|
|
2
2
|
|
3
3
|
module Whenever
|
4
4
|
class Job
|
5
|
-
attr_reader :at, :roles
|
5
|
+
attr_reader :at, :roles, :mailto
|
6
6
|
|
7
7
|
def initialize(options = {})
|
8
8
|
@options = options
|
9
9
|
@at = options.delete(:at)
|
10
10
|
@template = options.delete(:template)
|
11
|
+
@mailto = options.fetch(:mailto, :default_mailto)
|
11
12
|
@job_template = options.delete(:job_template) || ":job"
|
12
13
|
@roles = Array(options.delete(:roles))
|
13
14
|
@options[:output] = options.has_key?(:output) ? Whenever::Output::Redirection.new(options[:output]).to_s : ''
|
data/lib/whenever/job_list.rb
CHANGED
@@ -30,10 +30,17 @@ module Whenever
|
|
30
30
|
return if @pre_set_variables[variable]
|
31
31
|
|
32
32
|
instance_variable_set("@#{variable}".to_sym, value)
|
33
|
-
self.class.send(:attr_reader, variable.to_sym)
|
34
33
|
@set_variables[variable] = value
|
35
34
|
end
|
36
35
|
|
36
|
+
def method_missing(name, *args, &block)
|
37
|
+
@set_variables.has_key?(name) ? @set_variables[name] : super
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.respond_to?(name, include_private = false)
|
41
|
+
@set_variables.has_key?(name) || super
|
42
|
+
end
|
43
|
+
|
37
44
|
def env(variable, value)
|
38
45
|
@env[variable.to_s] = value
|
39
46
|
end
|
@@ -50,13 +57,16 @@ module Whenever
|
|
50
57
|
options = { :task => task, :template => template }
|
51
58
|
options.merge!(args[0]) if args[0].is_a? Hash
|
52
59
|
|
60
|
+
options[:mailto] ||= @options.fetch(:mailto, :default_mailto)
|
61
|
+
|
53
62
|
# :cron_log was an old option for output redirection, it remains for backwards compatibility
|
54
63
|
options[:output] = (options[:cron_log] || @cron_log) if defined?(@cron_log) || options.has_key?(:cron_log)
|
55
64
|
# :output is the newer, more flexible option.
|
56
65
|
options[:output] = @output if defined?(@output) && !options.has_key?(:output)
|
57
66
|
|
58
|
-
@jobs[
|
59
|
-
@jobs[@current_time_scope]
|
67
|
+
@jobs[options.fetch(:mailto)] ||= {}
|
68
|
+
@jobs[options.fetch(:mailto)][@current_time_scope] ||= []
|
69
|
+
@jobs[options.fetch(:mailto)][@current_time_scope] << Whenever::Job.new(@options.merge(@set_variables).merge(options))
|
60
70
|
end
|
61
71
|
end
|
62
72
|
end
|
@@ -125,31 +135,51 @@ module Whenever
|
|
125
135
|
entries.map { |entry| entry.join(' ') }
|
126
136
|
end
|
127
137
|
|
138
|
+
def cron_jobs_of_time(time, jobs)
|
139
|
+
shortcut_jobs, regular_jobs = [], []
|
140
|
+
|
141
|
+
jobs.each do |job|
|
142
|
+
next unless roles.empty? || roles.any? do |r|
|
143
|
+
job.has_role?(r)
|
144
|
+
end
|
145
|
+
Whenever::Output::Cron.output(time, job, :chronic_options => @chronic_options) do |cron|
|
146
|
+
cron << "\n\n"
|
147
|
+
|
148
|
+
if cron[0,1] == "@"
|
149
|
+
shortcut_jobs << cron
|
150
|
+
else
|
151
|
+
regular_jobs << cron
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
shortcut_jobs.join + combine(regular_jobs).join
|
157
|
+
end
|
158
|
+
|
128
159
|
def cron_jobs
|
129
160
|
return if @jobs.empty?
|
130
161
|
|
131
|
-
|
132
|
-
regular_jobs = []
|
162
|
+
output = []
|
133
163
|
|
134
|
-
|
135
|
-
@jobs.each do |time, jobs|
|
136
|
-
|
137
|
-
|
138
|
-
job.has_role?(r)
|
139
|
-
end
|
140
|
-
Whenever::Output::Cron.output(time, job) do |cron|
|
141
|
-
cron << "\n\n"
|
164
|
+
# jobs with default mailto's must be output before the ones with non-default mailto's.
|
165
|
+
@jobs.delete(:default_mailto) { Hash.new }.each do |time, jobs|
|
166
|
+
output << cron_jobs_of_time(time, jobs)
|
167
|
+
end
|
142
168
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
end
|
169
|
+
@jobs.each do |mailto, time_and_jobs|
|
170
|
+
output_jobs = []
|
171
|
+
|
172
|
+
time_and_jobs.each do |time, jobs|
|
173
|
+
output_jobs << cron_jobs_of_time(time, jobs)
|
149
174
|
end
|
175
|
+
|
176
|
+
output_jobs.reject! { |output_job| output_job.empty? }
|
177
|
+
|
178
|
+
output << "MAILTO=#{mailto}\n\n" unless output_jobs.empty?
|
179
|
+
output << output_jobs
|
150
180
|
end
|
151
181
|
|
152
|
-
|
182
|
+
output.join
|
153
183
|
end
|
154
184
|
end
|
155
185
|
end
|
data/lib/whenever/numeric.rb
CHANGED
data/lib/whenever/setup.rb
CHANGED
@@ -5,6 +5,10 @@ set :environment, "production"
|
|
5
5
|
# Path defaults to the directory `whenever` was run from
|
6
6
|
set :path, Whenever.path
|
7
7
|
|
8
|
+
# Custom Chronic configuration for time parsing, empty by default
|
9
|
+
# Full list of options at: https://github.com/mojombo/chronic/blob/master/lib/chronic/parser.rb
|
10
|
+
set :chronic_options, {}
|
11
|
+
|
8
12
|
# All jobs are wrapped in this template.
|
9
13
|
# http://blog.scoutapp.com/articles/2010/09/07/rvm-and-cron-in-production
|
10
14
|
set :job_template, "/bin/bash -l -c ':job'"
|
data/lib/whenever/version.rb
CHANGED
@@ -2,6 +2,7 @@ require 'test_helper'
|
|
2
2
|
|
3
3
|
class CommandLineWriteTest < Whenever::TestCase
|
4
4
|
setup do
|
5
|
+
Time.stubs(:now).returns(Time.new(2017, 2, 24, 16, 21, 30, '+01:00'))
|
5
6
|
File.expects(:exist?).with('config/schedule.rb').returns(true)
|
6
7
|
@command = Whenever::CommandLine.new(:write => true, :identifier => 'My identifier')
|
7
8
|
@task = "#{two_hours} /my/command"
|
@@ -10,9 +11,9 @@ class CommandLineWriteTest < Whenever::TestCase
|
|
10
11
|
|
11
12
|
should "output the cron job with identifier blocks" do
|
12
13
|
output = <<-EXPECTED
|
13
|
-
# Begin Whenever generated tasks for: My identifier
|
14
|
+
# Begin Whenever generated tasks for: My identifier at: 2017-02-24 16:21:30 +0100
|
14
15
|
#{@task}
|
15
|
-
# End Whenever generated tasks for: My identifier
|
16
|
+
# End Whenever generated tasks for: My identifier at: 2017-02-24 16:21:30 +0100
|
16
17
|
EXPECTED
|
17
18
|
|
18
19
|
assert_equal output, @command.send(:whenever_cron)
|
@@ -26,6 +27,7 @@ end
|
|
26
27
|
|
27
28
|
class CommandLineUpdateTest < Whenever::TestCase
|
28
29
|
setup do
|
30
|
+
Time.stubs(:now).returns(Time.new(2017, 2, 24, 16, 21, 30, '+01:00'))
|
29
31
|
File.expects(:exist?).with('config/schedule.rb').returns(true)
|
30
32
|
@command = Whenever::CommandLine.new(:update => true, :identifier => 'My identifier')
|
31
33
|
@task = "#{two_hours} /my/command"
|
@@ -39,9 +41,9 @@ class CommandLineUpdateTest < Whenever::TestCase
|
|
39
41
|
new_cron = <<-EXPECTED
|
40
42
|
#{existing}
|
41
43
|
|
42
|
-
# Begin Whenever generated tasks for: My identifier
|
44
|
+
# Begin Whenever generated tasks for: My identifier at: 2017-02-24 16:21:30 +0100
|
43
45
|
#{@task}
|
44
|
-
# End Whenever generated tasks for: My identifier
|
46
|
+
# End Whenever generated tasks for: My identifier at: 2017-02-24 16:21:30 +0100
|
45
47
|
EXPECTED
|
46
48
|
|
47
49
|
assert_equal new_cron, @command.send(:updated_crontab)
|
@@ -50,7 +52,71 @@ EXPECTED
|
|
50
52
|
assert @command.run
|
51
53
|
end
|
52
54
|
|
53
|
-
should "replace an existing block if the identifier matches" do
|
55
|
+
should "replace an existing block if the identifier matches and the timestamp doesn't" do
|
56
|
+
existing = <<-EXISTING_CRON
|
57
|
+
# Something
|
58
|
+
|
59
|
+
# Begin Whenever generated tasks for: My identifier at: 2017-01-03 08:02:22 +0500
|
60
|
+
My whenever job that was already here
|
61
|
+
# End Whenever generated tasks for: My identifier at: 2017-01-03 08:22:22 +0500
|
62
|
+
|
63
|
+
# Begin Whenever generated tasks for: Other identifier at: 2017-02-24 16:21:30 +0100
|
64
|
+
This shouldn't get replaced
|
65
|
+
# End Whenever generated tasks for: Other identifier at: 2017-02-24 16:21:30 +0100
|
66
|
+
EXISTING_CRON
|
67
|
+
|
68
|
+
new_cron = <<-NEW_CRON
|
69
|
+
# Something
|
70
|
+
|
71
|
+
# Begin Whenever generated tasks for: My identifier at: 2017-02-24 16:21:30 +0100
|
72
|
+
#{@task}
|
73
|
+
# End Whenever generated tasks for: My identifier at: 2017-02-24 16:21:30 +0100
|
74
|
+
|
75
|
+
# Begin Whenever generated tasks for: Other identifier at: 2017-02-24 16:21:30 +0100
|
76
|
+
This shouldn't get replaced
|
77
|
+
# End Whenever generated tasks for: Other identifier at: 2017-02-24 16:21:30 +0100
|
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
|
+
|
87
|
+
should "replace an existing block if the identifier matches and the UTC timestamp doesn't" do
|
88
|
+
existing = <<-EXISTING_CRON
|
89
|
+
# Something
|
90
|
+
|
91
|
+
# Begin Whenever generated tasks for: My identifier at: 2017-01-03 08:02:22 UTC
|
92
|
+
My whenever job that was already here
|
93
|
+
# End Whenever generated tasks for: My identifier at: 2017-01-03 08:22:22 UTC
|
94
|
+
|
95
|
+
# Begin Whenever generated tasks for: Other identifier at: 2017-02-24 16:21:30 +0100
|
96
|
+
This shouldn't get replaced
|
97
|
+
# End Whenever generated tasks for: Other identifier at: 2017-02-24 16:21:30 +0100
|
98
|
+
EXISTING_CRON
|
99
|
+
|
100
|
+
new_cron = <<-NEW_CRON
|
101
|
+
# Something
|
102
|
+
|
103
|
+
# Begin Whenever generated tasks for: My identifier at: 2017-02-24 16:21:30 +0100
|
104
|
+
#{@task}
|
105
|
+
# End Whenever generated tasks for: My identifier at: 2017-02-24 16:21:30 +0100
|
106
|
+
|
107
|
+
# Begin Whenever generated tasks for: Other identifier at: 2017-02-24 16:21:30 +0100
|
108
|
+
This shouldn't get replaced
|
109
|
+
# End Whenever generated tasks for: Other identifier at: 2017-02-24 16:21:30 +0100
|
110
|
+
NEW_CRON
|
111
|
+
|
112
|
+
@command.expects(:read_crontab).at_least_once.returns(existing)
|
113
|
+
assert_equal new_cron, @command.send(:updated_crontab)
|
114
|
+
|
115
|
+
@command.expects(:write_crontab).with(new_cron).returns(true)
|
116
|
+
assert @command.run
|
117
|
+
end
|
118
|
+
|
119
|
+
should "replace an existing block if the identifier matches and it doesn't contain a timestamp" do
|
54
120
|
existing = <<-EXISTING_CRON
|
55
121
|
# Something
|
56
122
|
|
@@ -58,21 +124,21 @@ EXPECTED
|
|
58
124
|
My whenever job that was already here
|
59
125
|
# End Whenever generated tasks for: My identifier
|
60
126
|
|
61
|
-
# Begin Whenever generated tasks for: Other identifier
|
127
|
+
# Begin Whenever generated tasks for: Other identifier at: 2017-02-24 16:21:30 +0100
|
62
128
|
This shouldn't get replaced
|
63
|
-
# End Whenever generated tasks for: Other identifier
|
129
|
+
# End Whenever generated tasks for: Other identifier at: 2017-02-24 16:21:30 +0100
|
64
130
|
EXISTING_CRON
|
65
131
|
|
66
132
|
new_cron = <<-NEW_CRON
|
67
133
|
# Something
|
68
134
|
|
69
|
-
# Begin Whenever generated tasks for: My identifier
|
135
|
+
# Begin Whenever generated tasks for: My identifier at: 2017-02-24 16:21:30 +0100
|
70
136
|
#{@task}
|
71
|
-
# End Whenever generated tasks for: My identifier
|
137
|
+
# End Whenever generated tasks for: My identifier at: 2017-02-24 16:21:30 +0100
|
72
138
|
|
73
|
-
# Begin Whenever generated tasks for: Other identifier
|
139
|
+
# Begin Whenever generated tasks for: Other identifier at: 2017-02-24 16:21:30 +0100
|
74
140
|
This shouldn't get replaced
|
75
|
-
# End Whenever generated tasks for: Other identifier
|
141
|
+
# End Whenever generated tasks for: Other identifier at: 2017-02-24 16:21:30 +0100
|
76
142
|
NEW_CRON
|
77
143
|
|
78
144
|
@command.expects(:read_crontab).at_least_once.returns(existing)
|
@@ -85,10 +151,11 @@ end
|
|
85
151
|
|
86
152
|
class CommandLineUpdateWithBackslashesTest < Whenever::TestCase
|
87
153
|
setup do
|
154
|
+
Time.stubs(:now).returns(Time.new(2017, 2, 24, 16, 21, 30, '+01:00'))
|
88
155
|
@existing = <<-EXISTING_CRON
|
89
|
-
# Begin Whenever generated tasks for: My identifier
|
156
|
+
# Begin Whenever generated tasks for: My identifier at: 2017-02-24 16:21:30 +0100
|
90
157
|
script/runner -e production 'puts '\\''hello'\\'''
|
91
|
-
# End Whenever generated tasks for: My identifier
|
158
|
+
# End Whenever generated tasks for: My identifier at: 2017-02-24 16:21:30 +0100
|
92
159
|
EXISTING_CRON
|
93
160
|
File.expects(:exist?).with('config/schedule.rb').returns(true)
|
94
161
|
@command = Whenever::CommandLine.new(:update => true, :identifier => 'My identifier')
|
@@ -104,12 +171,12 @@ end
|
|
104
171
|
class CommandLineUpdateToSimilarCrontabTest < Whenever::TestCase
|
105
172
|
setup do
|
106
173
|
@existing = <<-EXISTING_CRON
|
107
|
-
# Begin Whenever generated tasks for: WheneverExisting
|
108
|
-
# End Whenever generated tasks for: WheneverExisting
|
174
|
+
# Begin Whenever generated tasks for: WheneverExisting at: 2017-02-24 16:21:30 +0100
|
175
|
+
# End Whenever generated tasks for: WheneverExisting at: 2017-02-24 16:21:30 +0100
|
109
176
|
EXISTING_CRON
|
110
177
|
@new = <<-NEW_CRON
|
111
|
-
# Begin Whenever generated tasks for: Whenever
|
112
|
-
# End Whenever generated tasks for: Whenever
|
178
|
+
# Begin Whenever generated tasks for: Whenever at: 2017-02-24 16:21:30 +0100
|
179
|
+
# End Whenever generated tasks for: Whenever at: 2017-02-24 16:21:30 +0100
|
113
180
|
NEW_CRON
|
114
181
|
File.expects(:exist?).with('config/schedule.rb').returns(true)
|
115
182
|
@command = Whenever::CommandLine.new(:update => true, :identifier => 'Whenever')
|
@@ -124,12 +191,71 @@ end
|
|
124
191
|
|
125
192
|
class CommandLineClearTest < Whenever::TestCase
|
126
193
|
setup do
|
194
|
+
Time.stubs(:now).returns(Time.new(2017, 2, 24, 16, 21, 30, '+01:00'))
|
127
195
|
File.expects(:exist?).with('config/schedule.rb').returns(true)
|
128
196
|
@command = Whenever::CommandLine.new(:clear => true, :identifier => 'My identifier')
|
129
197
|
@task = "#{two_hours} /my/command"
|
130
198
|
end
|
131
199
|
|
132
|
-
should "clear an existing block if the identifier matches" do
|
200
|
+
should "clear an existing block if the identifier matches and the timestamp doesn't" do
|
201
|
+
existing = <<-EXISTING_CRON
|
202
|
+
# Something
|
203
|
+
|
204
|
+
# Begin Whenever generated tasks for: My identifier at: 2017-01-03 08:20:02 +0500
|
205
|
+
My whenever job that was already here
|
206
|
+
# End Whenever generated tasks for: My identifier at: 2017-01-03 08:20:02 +0500
|
207
|
+
|
208
|
+
# Begin Whenever generated tasks for: Other identifier at: 2017-02-24 16:21:30 +0100
|
209
|
+
This shouldn't get replaced
|
210
|
+
# End Whenever generated tasks for: Other identifier at: 2017-02-24 16:21:30 +0100
|
211
|
+
EXISTING_CRON
|
212
|
+
|
213
|
+
@command.expects(:read_crontab).at_least_once.returns(existing)
|
214
|
+
|
215
|
+
new_cron = <<-NEW_CRON
|
216
|
+
# Something
|
217
|
+
|
218
|
+
# Begin Whenever generated tasks for: Other identifier at: 2017-02-24 16:21:30 +0100
|
219
|
+
This shouldn't get replaced
|
220
|
+
# End Whenever generated tasks for: Other identifier at: 2017-02-24 16:21:30 +0100
|
221
|
+
NEW_CRON
|
222
|
+
|
223
|
+
assert_equal new_cron, @command.send(:updated_crontab)
|
224
|
+
|
225
|
+
@command.expects(:write_crontab).with(new_cron).returns(true)
|
226
|
+
assert @command.run
|
227
|
+
end
|
228
|
+
|
229
|
+
should "clear an existing block if the identifier matches and the UTC timestamp doesn't" do
|
230
|
+
existing = <<-EXISTING_CRON
|
231
|
+
# Something
|
232
|
+
|
233
|
+
# Begin Whenever generated tasks for: My identifier at: 2017-01-03 08:20:02 UTC
|
234
|
+
My whenever job that was already here
|
235
|
+
# End Whenever generated tasks for: My identifier at: 2017-01-03 08:20:02 UTC
|
236
|
+
|
237
|
+
# Begin Whenever generated tasks for: Other identifier at: 2017-02-24 16:21:30 +0100
|
238
|
+
This shouldn't get replaced
|
239
|
+
# End Whenever generated tasks for: Other identifier at: 2017-02-24 16:21:30 +0100
|
240
|
+
EXISTING_CRON
|
241
|
+
|
242
|
+
@command.expects(:read_crontab).at_least_once.returns(existing)
|
243
|
+
|
244
|
+
new_cron = <<-NEW_CRON
|
245
|
+
# Something
|
246
|
+
|
247
|
+
# Begin Whenever generated tasks for: Other identifier at: 2017-02-24 16:21:30 +0100
|
248
|
+
This shouldn't get replaced
|
249
|
+
# End Whenever generated tasks for: Other identifier at: 2017-02-24 16:21:30 +0100
|
250
|
+
NEW_CRON
|
251
|
+
|
252
|
+
assert_equal new_cron, @command.send(:updated_crontab)
|
253
|
+
|
254
|
+
@command.expects(:write_crontab).with(new_cron).returns(true)
|
255
|
+
assert @command.run
|
256
|
+
end
|
257
|
+
|
258
|
+
should "clear an existing block if the identifier matches and it doesn't have a timestamp" do
|
133
259
|
existing = <<-EXISTING_CRON
|
134
260
|
# Something
|
135
261
|
|
@@ -137,9 +263,9 @@ class CommandLineClearTest < Whenever::TestCase
|
|
137
263
|
My whenever job that was already here
|
138
264
|
# End Whenever generated tasks for: My identifier
|
139
265
|
|
140
|
-
# Begin Whenever generated tasks for: Other identifier
|
266
|
+
# Begin Whenever generated tasks for: Other identifier at: 2017-02-24 16:21:30 +0100
|
141
267
|
This shouldn't get replaced
|
142
|
-
# End Whenever generated tasks for: Other identifier
|
268
|
+
# End Whenever generated tasks for: Other identifier at: 2017-02-24 16:21:30 +0100
|
143
269
|
EXISTING_CRON
|
144
270
|
|
145
271
|
@command.expects(:read_crontab).at_least_once.returns(existing)
|
@@ -147,9 +273,9 @@ EXISTING_CRON
|
|
147
273
|
new_cron = <<-NEW_CRON
|
148
274
|
# Something
|
149
275
|
|
150
|
-
# Begin Whenever generated tasks for: Other identifier
|
276
|
+
# Begin Whenever generated tasks for: Other identifier at: 2017-02-24 16:21:30 +0100
|
151
277
|
This shouldn't get replaced
|
152
|
-
# End Whenever generated tasks for: Other identifier
|
278
|
+
# End Whenever generated tasks for: Other identifier at: 2017-02-24 16:21:30 +0100
|
153
279
|
NEW_CRON
|
154
280
|
|
155
281
|
assert_equal new_cron, @command.send(:updated_crontab)
|
@@ -173,13 +299,14 @@ end
|
|
173
299
|
|
174
300
|
class CommandLineUpdateWithNoIdentifierTest < Whenever::TestCase
|
175
301
|
setup do
|
302
|
+
Time.stubs(:now).returns(Time.new(2017, 2, 24, 16, 21, 30, '+01:00'))
|
176
303
|
File.expects(:exist?).with('config/schedule.rb').returns(true)
|
177
304
|
Whenever::CommandLine.any_instance.expects(:default_identifier).returns('DEFAULT')
|
178
|
-
@command = Whenever::CommandLine.new(:update => true
|
305
|
+
@command = Whenever::CommandLine.new(:update => true)
|
179
306
|
end
|
180
307
|
|
181
308
|
should "use the default identifier" do
|
182
|
-
assert_equal "Whenever generated tasks for: DEFAULT", @command.send(:comment_base)
|
309
|
+
assert_equal "Whenever generated tasks for: DEFAULT at: 2017-02-24 16:21:30 +0100", @command.send(:comment_base)
|
183
310
|
end
|
184
311
|
end
|
185
312
|
|
@@ -287,9 +414,9 @@ class PreparingOutputTest < Whenever::TestCase
|
|
287
414
|
# Useless Comments
|
288
415
|
# at the top of the file
|
289
416
|
|
290
|
-
# Begin Whenever generated tasks for: My identifier
|
417
|
+
# Begin Whenever generated tasks for: My identifier at: 2017-02-24 16:21:30 +0100
|
291
418
|
My whenever job that was already here
|
292
|
-
# End Whenever generated tasks for: My identifier
|
419
|
+
# End Whenever generated tasks for: My identifier at: 2017-02-24 16:21:30 +0100
|
293
420
|
EXISTING_CRON
|
294
421
|
|
295
422
|
assert_equal existing, @command.send(:prepare, existing)
|
@@ -301,15 +428,15 @@ EXISTING_CRON
|
|
301
428
|
# Useless Comments
|
302
429
|
# at the top of the file
|
303
430
|
|
304
|
-
# Begin Whenever generated tasks for: My identifier
|
431
|
+
# Begin Whenever generated tasks for: My identifier at: 2017-02-24 16:21:30 +0100
|
305
432
|
My whenever job that was already here
|
306
|
-
# End Whenever generated tasks for: My identifier
|
433
|
+
# End Whenever generated tasks for: My identifier at: 2017-02-24 16:21:30 +0100
|
307
434
|
EXISTING_CRON
|
308
435
|
|
309
436
|
new_cron = <<-NEW_CRON
|
310
|
-
# Begin Whenever generated tasks for: My identifier
|
437
|
+
# Begin Whenever generated tasks for: My identifier at: 2017-02-24 16:21:30 +0100
|
311
438
|
My whenever job that was already here
|
312
|
-
# End Whenever generated tasks for: My identifier
|
439
|
+
# End Whenever generated tasks for: My identifier at: 2017-02-24 16:21:30 +0100
|
313
440
|
NEW_CRON
|
314
441
|
|
315
442
|
assert_equal new_cron, @command.send(:prepare, existing)
|
@@ -318,9 +445,9 @@ NEW_CRON
|
|
318
445
|
should "preserve terminating newlines in files" do
|
319
446
|
@command = Whenever::CommandLine.new(:update => true, :identifier => 'My identifier')
|
320
447
|
existing = <<-EXISTING_CRON
|
321
|
-
# Begin Whenever generated tasks for: My identifier
|
448
|
+
# Begin Whenever generated tasks for: My identifier at: 2017-02-24 16:21:30 +0100
|
322
449
|
My whenever job that was already here
|
323
|
-
# End Whenever generated tasks for: My identifier
|
450
|
+
# End Whenever generated tasks for: My identifier at: 2017-02-24 16:21:30 +0100
|
324
451
|
|
325
452
|
# A non-Whenever task
|
326
453
|
My non-whenever job that was already here
|
@@ -204,4 +204,43 @@ class OutputAtTest < Whenever::TestCase
|
|
204
204
|
|
205
205
|
assert_match '0 0 27,31 * * blahblah', output
|
206
206
|
end
|
207
|
+
|
208
|
+
test "using custom Chronic configuration to specify time using 24 hour clock" do
|
209
|
+
output = Whenever.cron \
|
210
|
+
<<-file
|
211
|
+
set :job_template, nil
|
212
|
+
set :chronic_options, :hours24 => true
|
213
|
+
every 1.day, :at => '03:00' do
|
214
|
+
command "blahblah"
|
215
|
+
end
|
216
|
+
file
|
217
|
+
|
218
|
+
assert_match '0 3 * * * blahblah', output
|
219
|
+
end
|
220
|
+
|
221
|
+
test "using custom Chronic configuration to specify date using little endian preference" do
|
222
|
+
output = Whenever.cron \
|
223
|
+
<<-file
|
224
|
+
set :job_template, nil
|
225
|
+
set :chronic_options, :endian_precedence => :little
|
226
|
+
every 1.month, :at => '02/03 10:15' do
|
227
|
+
command "blahblah"
|
228
|
+
end
|
229
|
+
file
|
230
|
+
|
231
|
+
assert_match '15 10 2 * * blahblah', output
|
232
|
+
end
|
233
|
+
|
234
|
+
test "using custom Chronic configuration to specify time using 24 hour clock and date using little endian preference" do
|
235
|
+
output = Whenever.cron \
|
236
|
+
<<-file
|
237
|
+
set :job_template, nil
|
238
|
+
set :chronic_options, :hours24 => true, :endian_precedence => :little
|
239
|
+
every 1.month, :at => '01/02 04:30' do
|
240
|
+
command "blahblah"
|
241
|
+
end
|
242
|
+
file
|
243
|
+
|
244
|
+
assert_match '30 4 1 * * blahblah', output
|
245
|
+
end
|
207
246
|
end
|