whenever 0.8.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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