whenever 0.9.7 → 1.0.0
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.
- 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
|