whenever 0.8.2 → 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.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.travis.yml +20 -7
  4. data/Appraisals +19 -0
  5. data/CHANGELOG.md +116 -3
  6. data/Gemfile +3 -3
  7. data/LICENSE +2 -2
  8. data/README.md +133 -32
  9. data/Rakefile +3 -10
  10. data/bin/whenever +3 -0
  11. data/bin/wheneverize +8 -5
  12. data/gemfiles/activesupport4.1.gemfile +7 -0
  13. data/gemfiles/activesupport4.2.gemfile +7 -0
  14. data/gemfiles/activesupport5.0.gemfile +7 -0
  15. data/gemfiles/activesupport5.1.gemfile +7 -0
  16. data/gemfiles/activesupport5.2.gemfile +7 -0
  17. data/lib/whenever/capistrano/v2/hooks.rb +8 -0
  18. data/lib/whenever/capistrano/{recipes.rb → v2/recipes.rb} +7 -13
  19. data/lib/whenever/capistrano/{support.rb → v2/support.rb} +12 -0
  20. data/lib/whenever/capistrano/v3/tasks/whenever.rake +56 -0
  21. data/lib/whenever/capistrano.rb +5 -6
  22. data/lib/whenever/command_line.rb +69 -48
  23. data/lib/whenever/cron.rb +54 -25
  24. data/lib/whenever/job.rb +13 -14
  25. data/lib/whenever/job_list.rb +54 -24
  26. data/lib/whenever/numeric.rb +13 -0
  27. data/lib/whenever/numeric_seconds.rb +48 -0
  28. data/lib/whenever/os.rb +7 -0
  29. data/lib/whenever/output_redirection.rb +1 -0
  30. data/lib/whenever/setup.rb +19 -15
  31. data/lib/whenever/version.rb +2 -2
  32. data/lib/whenever.rb +19 -14
  33. data/test/functional/command_line_test.rb +379 -243
  34. data/test/functional/output_at_test.rb +227 -249
  35. data/test/functional/output_default_defined_jobs_test.rb +251 -193
  36. data/test/functional/output_defined_job_test.rb +65 -91
  37. data/test/functional/output_env_test.rb +22 -26
  38. data/test/functional/output_jobs_for_roles_test.rb +46 -65
  39. data/test/functional/output_jobs_with_mailto_test.rb +168 -0
  40. data/test/functional/output_redirection_test.rb +232 -291
  41. data/test/test_case.rb +32 -0
  42. data/test/test_helper.rb +44 -15
  43. data/test/unit/capistrano_support_test.rb +128 -134
  44. data/test/unit/cron_test.rb +373 -208
  45. data/test/unit/executable_test.rb +142 -0
  46. data/test/unit/job_test.rb +111 -117
  47. data/whenever.gemspec +7 -4
  48. metadata +63 -44
@@ -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
@@ -45,18 +52,21 @@ module Whenever
45
52
  end
46
53
 
47
54
  def job_type(name, template)
48
- class_eval do
55
+ singleton_class.class_eval do
49
56
  define_method(name) do |task, *args|
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[@current_time_scope] ||= []
59
- @jobs[@current_time_scope] << Whenever::Job.new(@options.merge(@set_variables).merge(options))
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
@@ -73,13 +83,13 @@ module Whenever
73
83
  # Only works for setting values as strings.
74
84
  #
75
85
  def pre_set(variable_string = nil)
76
- return if variable_string.blank?
86
+ return if variable_string.nil? || variable_string == ""
77
87
 
78
88
  pairs = variable_string.split('&')
79
89
  pairs.each do |pair|
80
90
  next unless pair.index('=')
81
91
  variable, value = *pair.split('=')
82
- unless variable.blank? || value.blank?
92
+ unless variable.nil? || variable == "" || value.nil? || value == ""
83
93
  variable = variable.strip.to_sym
84
94
  set(variable, value.strip)
85
95
  @pre_set_variables[variable] = value
@@ -92,7 +102,7 @@ module Whenever
92
102
 
93
103
  output = []
94
104
  @env.each do |key, val|
95
- output << "#{key}=#{val.blank? ? '""' : val}\n"
105
+ output << "#{key}=#{val.nil? || val == "" ? '""' : val}\n"
96
106
  end
97
107
  output << "\n"
98
108
 
@@ -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
- shortcut_jobs = []
132
- regular_jobs = []
162
+ output = []
133
163
 
134
- output_all = roles.empty?
135
- @jobs.each do |time, jobs|
136
- jobs.each do |job|
137
- next unless output_all || roles.any? do |r|
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
- if cron.starts_with?("@")
144
- shortcut_jobs << cron
145
- else
146
- regular_jobs << cron
147
- end
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
- shortcut_jobs.join + combine(regular_jobs).join
182
+ output.join
153
183
  end
154
184
  end
155
185
  end
@@ -0,0 +1,13 @@
1
+ Numeric.class_eval do
2
+ def respond_to?(method, include_private = false)
3
+ super || Whenever::NumericSeconds.public_method_defined?(method)
4
+ end
5
+
6
+ def method_missing(method, *args, &block)
7
+ if Whenever::NumericSeconds.public_method_defined?(method)
8
+ Whenever::NumericSeconds.new(self).send(method)
9
+ else
10
+ super
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,48 @@
1
+ module Whenever
2
+ class NumericSeconds
3
+ attr_reader :number
4
+
5
+ def self.seconds(number, units)
6
+ new(number).send(units)
7
+ end
8
+
9
+ def initialize(number)
10
+ @number = number.to_i
11
+ end
12
+
13
+ def seconds
14
+ number
15
+ end
16
+ alias :second :seconds
17
+
18
+ def minutes
19
+ number * 60
20
+ end
21
+ alias :minute :minutes
22
+
23
+ def hours
24
+ number * 3_600
25
+ end
26
+ alias :hour :hours
27
+
28
+ def days
29
+ number * 86_400
30
+ end
31
+ alias :day :days
32
+
33
+ def weeks
34
+ number * 604_800
35
+ end
36
+ alias :week :weeks
37
+
38
+ def months
39
+ number * 2_592_000
40
+ end
41
+ alias :month :months
42
+
43
+ def years
44
+ number * 31_557_600
45
+ end
46
+ alias :year :years
47
+ end
48
+ end
@@ -0,0 +1,7 @@
1
+ module Whenever
2
+ module OS
3
+ def self.solaris?
4
+ (/solaris/ =~ RUBY_PLATFORM)
5
+ end
6
+ end
7
+ end
@@ -11,6 +11,7 @@ module Whenever
11
11
  when String then redirect_from_string
12
12
  when Hash then redirect_from_hash
13
13
  when NilClass then ">> /dev/null 2>&1"
14
+ when Proc then @output.call
14
15
  else ''
15
16
  end
16
17
  end
@@ -1,26 +1,30 @@
1
+ # Environment variable defaults to RAILS_ENV
2
+ set :environment_variable, "RAILS_ENV"
1
3
  # Environment defaults to production
2
4
  set :environment, "production"
3
5
  # Path defaults to the directory `whenever` was run from
4
6
  set :path, Whenever.path
5
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
+
6
12
  # All jobs are wrapped in this template.
7
13
  # http://blog.scoutapp.com/articles/2010/09/07/rvm-and-cron-in-production
8
14
  set :job_template, "/bin/bash -l -c ':job'"
9
15
 
10
- job_type :command, ":task :output"
16
+ set :runner_command, case
17
+ when Whenever.bin_rails?
18
+ "bin/rails runner"
19
+ when Whenever.script_rails?
20
+ "script/rails runner"
21
+ else
22
+ "script/runner"
23
+ end
11
24
 
12
- # Run rake through bundler if possible
13
- if Whenever.bundler?
14
- job_type :rake, "cd :path && RAILS_ENV=:environment bundle exec rake :task --silent :output"
15
- job_type :script, "cd :path && RAILS_ENV=:environment bundle exec script/:task :output"
16
- else
17
- job_type :rake, "cd :path && RAILS_ENV=:environment rake :task --silent :output"
18
- job_type :script, "cd :path && RAILS_ENV=:environment script/:task :output"
19
- end
25
+ set :bundle_command, Whenever.bundler? ? "bundle exec" : ""
20
26
 
21
- # Create a runner job that's appropriate for the Rails version,
22
- if Whenever.rails3?
23
- job_type :runner, "cd :path && script/rails runner -e :environment ':task' :output"
24
- else
25
- job_type :runner, "cd :path && script/runner -e :environment ':task' :output"
26
- end
27
+ job_type :command, ":task :output"
28
+ job_type :rake, "cd :path && :environment_variable=:environment :bundle_command rake :task --silent :output"
29
+ job_type :script, "cd :path && :environment_variable=:environment :bundle_command script/:task :output"
30
+ job_type :runner, "cd :path && :bundle_command :runner_command -e :environment ':task' :output"
@@ -1,3 +1,3 @@
1
1
  module Whenever
2
- VERSION = '0.8.2'
3
- end
2
+ VERSION = '1.0.0'
3
+ end
data/lib/whenever.rb CHANGED
@@ -1,29 +1,34 @@
1
- require 'thread'
2
- require 'active_support/all'
1
+ require 'whenever/numeric'
2
+ require 'whenever/numeric_seconds'
3
+ require 'whenever/job_list'
4
+ require 'whenever/job'
5
+ require 'whenever/command_line'
6
+ require 'whenever/cron'
7
+ require 'whenever/output_redirection'
8
+ require 'whenever/os'
3
9
 
4
10
  module Whenever
5
- autoload :JobList, 'whenever/job_list'
6
- autoload :Job, 'whenever/job'
7
- autoload :CommandLine, 'whenever/command_line'
8
-
9
- module Output
10
- autoload :Cron, 'whenever/cron'
11
- autoload :Redirection, 'whenever/output_redirection'
12
- end
13
-
14
11
  def self.cron(options)
15
12
  Whenever::JobList.new(options).generate_cron_output
16
13
  end
17
14
 
15
+ def self.seconds(number, units)
16
+ Whenever::NumericSeconds.seconds(number, units)
17
+ end
18
+
18
19
  def self.path
19
20
  Dir.pwd
20
21
  end
21
22
 
22
- def self.rails3?
23
- File.exists?(File.join(path, 'script', 'rails'))
23
+ def self.bin_rails?
24
+ File.exist?(File.join(path, 'bin', 'rails'))
25
+ end
26
+
27
+ def self.script_rails?
28
+ File.exist?(File.join(path, 'script', 'rails'))
24
29
  end
25
30
 
26
31
  def self.bundler?
27
- File.exists?(File.join(path, 'Gemfile'))
32
+ File.exist?(File.join(path, 'Gemfile'))
28
33
  end
29
34
  end