whenever 0.8.0 → 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -3,6 +3,19 @@
3
3
  * Time zone support
4
4
 
5
5
 
6
+ ### 0.8.1 / December 22nd, 2012
7
+
8
+ * Fix multiserver roles bug. [Wes Morgan]
9
+
10
+ * Refactor Cap recipes and add tests for them. [Wes Morgan]
11
+
12
+ * Fix file not found error when running under JRuby. [Wes Morgan]
13
+
14
+ * Stop interpolating template attributes with no corresponding value. [Vincent Boisard]
15
+
16
+ * Support for raw cron separated by tabs. [Étienne Barrié]
17
+
18
+
6
19
  ### 0.8.0 / November 8th, 2012
7
20
 
8
21
  * Separate Capistrano recipes to allow custom execution. [Bogdan Gusiev]
data/lib/whenever.rb CHANGED
@@ -2,19 +2,19 @@ require 'thread'
2
2
  require 'active_support/all'
3
3
 
4
4
  module Whenever
5
- autoload :JobList, 'whenever/job_list'
6
- autoload :Job, 'whenever/job'
7
- autoload :CommandLine, 'whenever/command_line'
8
-
5
+ autoload :JobList, 'whenever/job_list'
6
+ autoload :Job, 'whenever/job'
7
+ autoload :CommandLine, 'whenever/command_line'
8
+
9
9
  module Output
10
10
  autoload :Cron, 'whenever/cron'
11
11
  autoload :Redirection, 'whenever/output_redirection'
12
12
  end
13
-
13
+
14
14
  def self.cron(options)
15
15
  Whenever::JobList.new(options).generate_cron_output
16
16
  end
17
-
17
+
18
18
  def self.path
19
19
  Dir.pwd
20
20
  end
@@ -1,4 +1,8 @@
1
+ require 'whenever/capistrano/support'
2
+
1
3
  Capistrano::Configuration.instance(:must_exist).load do
4
+ Whenever::CapistranoSupport.load_into(self)
5
+
2
6
  _cset(:whenever_roles) { :db }
3
7
  _cset(:whenever_options) { {:roles => fetch(:whenever_roles)} }
4
8
  _cset(:whenever_command) { "whenever" }
@@ -9,63 +13,42 @@ Capistrano::Configuration.instance(:must_exist).load do
9
13
  _cset(:whenever_clear_flags) { "--clear-crontab #{fetch :whenever_identifier}" }
10
14
 
11
15
  namespace :whenever do
12
- desc <<-DESC
13
- Update application's crontab entries using Whenever. You can configure \
14
- the command used to invoke Whenever by setting the :whenever_command \
15
- variable, which can be used with Bundler to set the command to \
16
- "bundle exec whenever". You can configure the identifier used by setting \
17
- the :whenever_identifier variable, which defaults to the same value configured \
18
- for the :application variable. You can configure the environment by setting \
19
- the :whenever_environment variable, which defaults to the same value \
20
- configured for the :rails_env variable which itself defaults to "production". \
21
- Finally, you can completely override all arguments to the Whenever command \
22
- by setting the :whenever_update_flags variable. Additionally you can configure \
23
- which servers the crontab is updated on by setting the :whenever_roles variable.
24
- DESC
16
+ desc "Update application's crontab entries using Whenever"
25
17
  task :update_crontab do
26
- options = fetch(:whenever_options)
27
- roles = [options[:roles]].flatten if options[:roles]
18
+ args = {
19
+ :command => fetch(:whenever_command),
20
+ :flags => fetch(:whenever_update_flags),
21
+ :path => fetch(:release_path)
22
+ }
28
23
 
29
- if find_servers(options).any?
30
- # make sure we go through the roles.each loop at least once
31
- roles << :__none if roles.empty?
24
+ if whenever_servers.any?
25
+ whenever_run_commands(args)
32
26
 
33
- roles.each do |role|
34
- if role == :__none
35
- role_arg = ''
27
+ on_rollback do
28
+ if fetch(:previous_release)
29
+ # rollback to the previous release's crontab
30
+ args[:path] = fetch(:previous_release)
36
31
  else
37
- options[:roles] = role
38
- role_arg = " --roles #{role}"
39
- end
40
-
41
- on_rollback do
42
- if fetch :previous_release
43
- run "cd #{fetch :previous_release} && #{fetch :whenever_command} #{fetch :whenever_update_flags}#{role_arg}", options
44
- else
45
- run "cd #{fetch :release_path} && #{fetch :whenever_command} #{fetch :whenever_clear_flags}", options
46
- end
32
+ # clear the crontab if no previous release
33
+ args[:flags] = fetch(:whenever_clear_flags)
47
34
  end
48
35
 
49
- run "cd #{fetch :latest_release} && #{fetch :whenever_command} #{fetch :whenever_update_flags}#{role_arg}", options
36
+ whenever_run_commands(args)
50
37
  end
51
38
  end
52
39
  end
53
40
 
54
- desc <<-DESC
55
- Clear application's crontab entries using Whenever. You can configure \
56
- the command used to invoke Whenever by setting the :whenever_command \
57
- variable, which can be used with Bundler to set the command to \
58
- "bundle exec whenever". You can configure the identifier used by setting \
59
- the :whenever_identifier variable, which defaults to the same value configured \
60
- for the :application variable. Finally, you can completely override all \
61
- arguments to the Whenever command by setting the :whenever_clear_flags variable. \
62
- Additionally you can configure which servers the crontab is cleared on by setting \
63
- the :whenever_roles variable.
64
- DESC
65
-
41
+ desc "Clear application's crontab entries using Whenever"
66
42
  task :clear_crontab do
67
- options = fetch(:whenever_options)
68
- run "cd #{fetch :latest_release} && #{fetch :whenever_command} #{fetch :whenever_clear_flags}", options if find_servers(options).any?
43
+ if whenever_servers.any?
44
+ args = {
45
+ :command => fetch(:whenever_command),
46
+ :flags => fetch(:whenever_clear_flags),
47
+ :path => fetch(:latest_release)
48
+ }
49
+
50
+ whenever_run_commands(args)
51
+ end
69
52
  end
70
53
  end
71
54
  end
@@ -0,0 +1,41 @@
1
+ module Whenever
2
+ module CapistranoSupport
3
+ def self.load_into(capistrano_configuration)
4
+ capistrano_configuration.load do
5
+
6
+ def whenever_options
7
+ fetch(:whenever_options)
8
+ end
9
+
10
+ def whenever_roles
11
+ Array(whenever_options[:roles])
12
+ end
13
+
14
+ def whenever_servers
15
+ find_servers(whenever_options)
16
+ end
17
+
18
+ def whenever_server_roles
19
+ whenever_servers.inject({}) do |map, server|
20
+ map[server] = role_names_for_host(server) & whenever_roles
21
+ map
22
+ end
23
+ end
24
+
25
+ def whenever_run_commands(args)
26
+ unless [:command, :path, :flags].all? { |a| args.include?(a) }
27
+ raise ArgumentError, ":command, :path, & :flags are required"
28
+ end
29
+
30
+ whenever_server_roles.each do |server, roles|
31
+ roles_arg = roles.empty? ? "" : " --roles #{roles.join(',')}"
32
+
33
+ command = "cd #{args[:path]} && #{args[:command]} #{args[:flags]}#{roles_arg}"
34
+ run command, whenever_options.merge(:hosts => server.host)
35
+ end
36
+ end
37
+
38
+ end
39
+ end
40
+ end
41
+ end
@@ -66,22 +66,23 @@ module Whenever
66
66
  end
67
67
 
68
68
  def write_crontab(contents)
69
- tmp_cron_file = Tempfile.new('whenever_tmp_cron').path
70
- File.open(tmp_cron_file, File::WRONLY | File::APPEND) do |file|
71
- file << contents
72
- end
69
+ tmp_cron_file = Tempfile.open('whenever_tmp_cron')
70
+ tmp_cron_file << contents
71
+ tmp_cron_file.fsync
73
72
 
74
73
  command = ['crontab']
75
74
  command << "-u #{@options[:user]}" if @options[:user]
76
- command << tmp_cron_file
75
+ command << tmp_cron_file.path
77
76
 
78
77
  if system(command.join(' '))
79
78
  action = 'written' if @options[:write]
80
79
  action = 'updated' if @options[:update]
81
80
  puts "[write] crontab file #{action}"
81
+ tmp_cron_file.close!
82
82
  exit(0)
83
83
  else
84
84
  warn "[fail] Couldn't write crontab; try running `whenever' with no options to ensure your schedule file is valid."
85
+ tmp_cron_file.close!
85
86
  exit(1)
86
87
  end
87
88
  end
data/lib/whenever/cron.rb CHANGED
@@ -4,7 +4,7 @@ module Whenever
4
4
  module Output
5
5
  class Cron
6
6
  KEYWORDS = [:reboot, :yearly, :annually, :monthly, :weekly, :daily, :midnight, :hourly]
7
- REGEX = /^(@(#{KEYWORDS.join '|'})|.+ .+ .+ .+ .+.?)$/
7
+ REGEX = /^(@(#{KEYWORDS.join '|'})|.+\s+.+\s+.+\s+.+\s+.+.?)$/
8
8
 
9
9
  attr_accessor :time, :task
10
10
 
data/lib/whenever/job.rb CHANGED
@@ -10,7 +10,7 @@ module Whenever
10
10
  @template = options.delete(:template)
11
11
  @job_template = options.delete(:job_template) || ":job"
12
12
  @roles = Array.wrap(options.delete(:roles))
13
- @options[:output] = Whenever::Output::Redirection.new(options[:output]).to_s if options.has_key?(:output)
13
+ @options[:output] = options.has_key?(:output) ? Whenever::Output::Redirection.new(options[:output]).to_s : ''
14
14
  @options[:environment] ||= :production
15
15
  @options[:path] = Shellwords.shellescape(@options[:path] || Whenever.path)
16
16
  end
@@ -33,7 +33,7 @@ module Whenever
33
33
  def process_template(template, options)
34
34
  template.gsub(/:\w+/) do |key|
35
35
  before_and_after = [$`[-1..-1], $'[0..0]]
36
- option = options[key.sub(':', '').to_sym]
36
+ option = options[key.sub(':', '').to_sym] || key
37
37
 
38
38
  if before_and_after.all? { |c| c == "'" }
39
39
  escape_single_quotes(option)
@@ -1,3 +1,3 @@
1
1
  module Whenever
2
- VERSION = '0.8.0'
2
+ VERSION = '0.8.1'
3
3
  end
@@ -1,7 +1,7 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + "/../test_helper")
2
2
 
3
3
  class CommandLineTest < Test::Unit::TestCase
4
-
4
+
5
5
  context "A command line write" do
6
6
  setup do
7
7
  File.expects(:exists?).with('config/schedule.rb').returns(true)
@@ -16,16 +16,16 @@ class CommandLineTest < Test::Unit::TestCase
16
16
  #{@task}
17
17
  # End Whenever generated tasks for: My identifier
18
18
  EXPECTED
19
-
19
+
20
20
  assert_equal output, @command.send(:whenever_cron)
21
21
  end
22
-
22
+
23
23
  should "write the crontab when run" do
24
24
  @command.expects(:write_crontab).returns(true)
25
25
  assert @command.run
26
26
  end
27
27
  end
28
-
28
+
29
29
  context "A command line update" do
30
30
  setup do
31
31
  File.expects(:exists?).with('config/schedule.rb').returns(true)
@@ -37,7 +37,7 @@ EXPECTED
37
37
  should "add the cron to the end of the file if there is no existing identifier block" do
38
38
  existing = '# Existing crontab'
39
39
  @command.expects(:read_crontab).at_least_once.returns(existing)
40
-
40
+
41
41
  new_cron = <<-EXPECTED
42
42
  #{existing}
43
43
 
@@ -45,13 +45,13 @@ EXPECTED
45
45
  #{@task}
46
46
  # End Whenever generated tasks for: My identifier
47
47
  EXPECTED
48
-
48
+
49
49
  assert_equal new_cron, @command.send(:updated_crontab)
50
-
50
+
51
51
  @command.expects(:write_crontab).with(new_cron).returns(true)
52
52
  assert @command.run
53
53
  end
54
-
54
+
55
55
  should "replace an existing block if the identifier matches" do
56
56
  existing = <<-EXISTING_CRON
57
57
  # Something
@@ -76,15 +76,15 @@ EXISTING_CRON
76
76
  This shouldn't get replaced
77
77
  # End Whenever generated tasks for: Other identifier
78
78
  NEW_CRON
79
-
79
+
80
80
  @command.expects(:read_crontab).at_least_once.returns(existing)
81
81
  assert_equal new_cron, @command.send(:updated_crontab)
82
-
82
+
83
83
  @command.expects(:write_crontab).with(new_cron).returns(true)
84
84
  assert @command.run
85
85
  end
86
86
  end
87
-
87
+
88
88
  context "A command line update that contains backslashes" do
89
89
  setup do
90
90
  @existing = <<-EXISTING_CRON
@@ -97,12 +97,12 @@ EXISTING_CRON
97
97
  @command.expects(:read_crontab).at_least_once.returns(@existing)
98
98
  @command.expects(:whenever_cron).returns(@existing)
99
99
  end
100
-
100
+
101
101
  should "replace the existing block with the backslashes in tact" do
102
102
  assert_equal @existing, @command.send(:updated_crontab)
103
103
  end
104
104
  end
105
-
105
+
106
106
  context "A command line update with an identifier similar to an existing one in the crontab already" do
107
107
  setup do
108
108
  @existing = <<-EXISTING_CRON
@@ -118,7 +118,7 @@ NEW_CRON
118
118
  @command.expects(:read_crontab).at_least_once.returns(@existing)
119
119
  @command.expects(:whenever_cron).returns(@new)
120
120
  end
121
-
121
+
122
122
  should "append the similarly named command" do
123
123
  assert_equal @existing + "\n" + @new, @command.send(:updated_crontab)
124
124
  end
@@ -160,7 +160,7 @@ NEW_CRON
160
160
  assert @command.run
161
161
  end
162
162
  end
163
-
163
+
164
164
  context "A command line update with no identifier" do
165
165
  setup do
166
166
  File.expects(:exists?).with('config/schedule.rb').returns(true)
@@ -183,7 +183,7 @@ NEW_CRON
183
183
  should "exit with write and clear" do
184
184
  @command = Whenever::CommandLine.new(:write => true, :clear => true)
185
185
  end
186
-
186
+
187
187
  should "exit with write and update" do
188
188
  @command = Whenever::CommandLine.new(:write => true, :update => true)
189
189
  end
@@ -192,7 +192,7 @@ NEW_CRON
192
192
  @command = Whenever::CommandLine.new(:update => true, :clear => true)
193
193
  end
194
194
  end
195
-
195
+
196
196
  context "A runner where the environment is overridden using the :set option" do
197
197
  setup do
198
198
  @output = Whenever.cron :set => 'environment=serious', :string => \
@@ -205,12 +205,12 @@ NEW_CRON
205
205
  end
206
206
  file
207
207
  end
208
-
208
+
209
209
  should "output the runner using the override environment" do
210
210
  assert_match two_hours + %( cd /my/path && script/runner -e serious 'blahblah'), @output
211
211
  end
212
212
  end
213
-
213
+
214
214
  context "A runner where the environment and path are overridden using the :set option" do
215
215
  setup do
216
216
  @output = Whenever.cron :set => 'environment=serious&path=/serious/path', :string => \
@@ -223,12 +223,12 @@ NEW_CRON
223
223
  end
224
224
  file
225
225
  end
226
-
226
+
227
227
  should "output the runner using the overridden path and environment" do
228
228
  assert_match two_hours + %( cd /serious/path && script/runner -e serious 'blahblah'), @output
229
229
  end
230
230
  end
231
-
231
+
232
232
  context "A runner where the environment and path are overridden using the :set option with spaces in the string" do
233
233
  setup do
234
234
  @output = Whenever.cron :set => ' environment = serious& path =/serious/path', :string => \
@@ -241,12 +241,12 @@ NEW_CRON
241
241
  end
242
242
  file
243
243
  end
244
-
244
+
245
245
  should "output the runner using the overridden path and environment" do
246
246
  assert_match two_hours + %( cd /serious/path && script/runner -e serious 'blahblah'), @output
247
247
  end
248
248
  end
249
-
249
+
250
250
  context "A runner where the environment is overridden using the :set option but no value is given" do
251
251
  setup do
252
252
  @output = Whenever.cron :set => ' environment=', :string => \
@@ -259,7 +259,7 @@ NEW_CRON
259
259
  end
260
260
  file
261
261
  end
262
-
262
+
263
263
  should "output the runner using the original environmnet" do
264
264
  assert_match two_hours + %( cd /silly/path && script/runner -e silly 'blahblah'), @output
265
265
  end
@@ -283,7 +283,7 @@ EXISTING_CRON
283
283
 
284
284
  assert_equal existing, @command.send(:prepare, existing)
285
285
  end
286
-
286
+
287
287
  should "trim off the top lines of the file" do
288
288
  @command = Whenever::CommandLine.new(:update => true, :identifier => 'My identifier', :cut => '3')
289
289
  existing = <<-EXISTING_CRON
@@ -303,7 +303,7 @@ NEW_CRON
303
303
 
304
304
  assert_equal new_cron, @command.send(:prepare, existing)
305
305
  end
306
-
306
+
307
307
  should "preserve terminating newlines in files" do
308
308
  @command = Whenever::CommandLine.new(:update => true, :identifier => 'My identifier')
309
309
  existing = <<-EXISTING_CRON
@@ -1,7 +1,7 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + "/../test_helper")
2
2
 
3
3
  class OutputDefinedJobTest < Test::Unit::TestCase
4
-
4
+
5
5
  context "A defined job with a :task" do
6
6
  setup do
7
7
  @output = Whenever.cron \
@@ -13,12 +13,12 @@ class OutputDefinedJobTest < Test::Unit::TestCase
13
13
  end
14
14
  file
15
15
  end
16
-
16
+
17
17
  should "output the defined job with the task" do
18
18
  assert_match /^.+ .+ .+ .+ before during after$/, @output
19
19
  end
20
20
  end
21
-
21
+
22
22
  context "A defined job with a :task and some options" do
23
23
  setup do
24
24
  @output = Whenever.cron \
@@ -30,12 +30,12 @@ class OutputDefinedJobTest < Test::Unit::TestCase
30
30
  end
31
31
  file
32
32
  end
33
-
33
+
34
34
  should "output the defined job with the task and options" do
35
35
  assert_match /^.+ .+ .+ .+ before during after happy birthday$/, @output
36
36
  end
37
37
  end
38
-
38
+
39
39
  context "A defined job with a :task and an option where the option is set globally" do
40
40
  setup do
41
41
  @output = Whenever.cron \
@@ -48,12 +48,12 @@ class OutputDefinedJobTest < Test::Unit::TestCase
48
48
  end
49
49
  file
50
50
  end
51
-
51
+
52
52
  should "output the defined job with the task and options" do
53
53
  assert_match /^.+ .+ .+ .+ before during after happy$/, @output
54
54
  end
55
55
  end
56
-
56
+
57
57
  context "A defined job with a :task and an option where the option is set globally and locally" do
58
58
  setup do
59
59
  @output = Whenever.cron \
@@ -66,12 +66,12 @@ class OutputDefinedJobTest < Test::Unit::TestCase
66
66
  end
67
67
  file
68
68
  end
69
-
69
+
70
70
  should "output the defined job using the local option" do
71
71
  assert_match /^.+ .+ .+ .+ before during after local$/, @output
72
72
  end
73
73
  end
74
-
74
+
75
75
  context "A defined job with a :task and an option that is not set" do
76
76
  setup do
77
77
  @output = Whenever.cron \
@@ -83,16 +83,16 @@ class OutputDefinedJobTest < Test::Unit::TestCase
83
83
  end
84
84
  file
85
85
  end
86
-
87
- should "output the defined job with that option removed" do
88
- assert_match /^.+ .+ .+ .+ before during after$/, @output
86
+
87
+ should "output the defined job with that option left untouched" do
88
+ assert_match /^.+ .+ .+ .+ before during after :option1$/, @output
89
89
  end
90
90
  end
91
-
91
+
92
92
  context "A defined job that uses a :path where none is explicitly set" do
93
93
  setup do
94
94
  Whenever.stubs(:path).returns('/my/path')
95
-
95
+
96
96
  @output = Whenever.cron \
97
97
  <<-file
98
98
  set :job_template, nil
@@ -102,10 +102,10 @@ class OutputDefinedJobTest < Test::Unit::TestCase
102
102
  end
103
103
  file
104
104
  end
105
-
105
+
106
106
  should "default to using the Whenever.path" do
107
107
  assert_match two_hours + %( cd /my/path && blahblah), @output
108
108
  end
109
109
  end
110
110
 
111
- end
111
+ end
@@ -0,0 +1,84 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../test_helper")
2
+
3
+ class OutputJobsForRolesTest < Test::Unit::TestCase
4
+ context "with one role requested and specified on the job" do
5
+ setup do
6
+ @output = Whenever.cron :roles => [:role1], :string => \
7
+ <<-file
8
+ every 2.hours, :roles => [:role1] do
9
+ command "blahblah"
10
+ end
11
+ file
12
+ end
13
+
14
+ should "output the cron job" do
15
+ assert_equal two_hours + " /bin/bash -l -c 'blahblah'\n\n", @output
16
+ end
17
+ end
18
+
19
+ context "with one role requested but none specified on the job" do
20
+ setup do
21
+ @output = Whenever.cron :roles => [:role1], :string => \
22
+ <<-file
23
+ every 2.hours do
24
+ command "blahblah"
25
+ end
26
+ file
27
+ end
28
+
29
+ # this should output the job because not specifying a role means "all roles"
30
+ should "output the cron job" do
31
+ assert_equal two_hours + " /bin/bash -l -c 'blahblah'\n\n", @output
32
+ end
33
+ end
34
+
35
+ context "with no roles requested but one specified on the job" do
36
+ setup do
37
+ @output = Whenever.cron \
38
+ <<-file
39
+ every 2.hours, :roles => [:role1] do
40
+ command "blahblah"
41
+ end
42
+ file
43
+ end
44
+
45
+ # this should output the job because not requesting roles means "all roles"
46
+ should "output the cron job" do
47
+ assert_equal two_hours + " /bin/bash -l -c 'blahblah'\n\n", @output
48
+ end
49
+ end
50
+
51
+ context "with a different role requested than the one specified on the job" do
52
+ setup do
53
+ @output = Whenever.cron :roles => [:role1], :string => \
54
+ <<-file
55
+ every 2.hours, :roles => [:role2] do
56
+ command "blahblah"
57
+ end
58
+ file
59
+ end
60
+
61
+ should "not output the cron job" do
62
+ assert_equal "", @output
63
+ end
64
+ end
65
+
66
+ context "with 2 roles requested and a job defined for each" do
67
+ setup do
68
+ @output = Whenever.cron :roles => [:role1, :role2], :string => \
69
+ <<-file
70
+ every 2.hours, :roles => [:role1] do
71
+ command "role1_cmd"
72
+ end
73
+
74
+ every :hour, :roles => [:role2] do
75
+ command "role2_cmd"
76
+ end
77
+ file
78
+ end
79
+
80
+ should "output both jobs" do
81
+ assert_equal two_hours + " /bin/bash -l -c 'role1_cmd'\n\n0 * * * * /bin/bash -l -c 'role2_cmd'\n\n", @output
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,138 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../test_helper")
2
+ require File.expand_path(File.dirname(__FILE__) + "/../../lib/whenever/capistrano/support")
3
+
4
+ class CapistranoSupportTestSubject
5
+ include Whenever::CapistranoSupport
6
+ end
7
+
8
+ class CapistranoSupportTest < Test::Unit::TestCase
9
+ context "when using capistrano support module" do
10
+ setup do
11
+ @capistrano = CapistranoSupportTestSubject.new
12
+ configuration = mock
13
+ configuration.stubs(:load).yields(@capistrano)
14
+ Whenever::CapistranoSupport.load_into(configuration)
15
+ end
16
+
17
+ context "#whenever_options" do
18
+ should "return fetch(:whenever_options)" do
19
+ @capistrano.expects(:fetch).with(:whenever_options)
20
+ @capistrano.whenever_options
21
+ end
22
+ end
23
+
24
+ context "#whenever_roles with one role" do
25
+ setup do
26
+ @capistrano.stubs(:whenever_options).returns({:roles => :role1})
27
+ end
28
+
29
+ should "return whenever_options[:roles] as an array" do
30
+ assert_equal [:role1], @capistrano.whenever_roles
31
+ end
32
+ end
33
+
34
+ context "#whenever_roles with no defined roles" do
35
+ setup do
36
+ @capistrano.stubs(:whenever_options).returns({})
37
+ end
38
+
39
+ should "return an empty array" do
40
+ assert_equal [], @capistrano.whenever_roles
41
+ end
42
+ end
43
+
44
+ context "#whenever_servers" do
45
+ should "return the list of servers returned by find_servers" do
46
+ @capistrano.stubs(:whenever_options).returns({})
47
+ @capistrano.stubs(:find_servers).returns([:server1, :server2])
48
+
49
+ assert_equal [:server1, :server2], @capistrano.whenever_servers
50
+ end
51
+ end
52
+
53
+ context "#whenever_server_roles" do
54
+ setup do
55
+ @mock_servers = ["foo", "bar"]
56
+ @capistrano.stubs(:whenever_servers).returns(@mock_servers)
57
+ end
58
+
59
+ should "return a map of servers to their role(s)" do
60
+ @capistrano.stubs(:whenever_roles).returns([:role1, :role2])
61
+ @capistrano.stubs(:role_names_for_host).with("foo").returns([:role1])
62
+ @capistrano.stubs(:role_names_for_host).with("bar").returns([:role2])
63
+ assert_equal({"foo" => [:role1], "bar" => [:role2]}, @capistrano.whenever_server_roles)
64
+ end
65
+
66
+ should "exclude non-requested roles" do
67
+ @capistrano.stubs(:whenever_roles).returns([:role1, :role2])
68
+ @capistrano.stubs(:role_names_for_host).with("foo").returns([:role1, :role3])
69
+ @capistrano.stubs(:role_names_for_host).with("bar").returns([:role2])
70
+ assert_equal({"foo" => [:role1], "bar" => [:role2]}, @capistrano.whenever_server_roles)
71
+ end
72
+
73
+ should "include all roles for servers w/ >1 when they're requested" do
74
+ @capistrano.stubs(:whenever_roles).returns([:role1, :role2, :role3])
75
+ @capistrano.stubs(:role_names_for_host).with("foo").returns([:role1, :role3])
76
+ @capistrano.stubs(:role_names_for_host).with("bar").returns([:role2])
77
+ assert_equal({"foo" => [:role1, :role3], "bar" => [:role2]}, @capistrano.whenever_server_roles)
78
+ end
79
+ end
80
+
81
+ context "#whenever_run_commands" do
82
+ should "require :command arg" do
83
+ assert_raise ArgumentError do
84
+ @capistrano.whenever_run_commands(:options => {}, :path => {}, :flags => {})
85
+ end
86
+ end
87
+
88
+ should "require :path arg" do
89
+ assert_raise ArgumentError do
90
+ @capistrano.whenever_run_commands(:options => {}, :command => {}, :flags => {})
91
+ end
92
+ end
93
+
94
+ should "require :flags arg" do
95
+ assert_raise ArgumentError do
96
+ @capistrano.whenever_run_commands(:options => {}, :path => {}, :command => {})
97
+ end
98
+ end
99
+
100
+ context "with some servers defined" do
101
+ setup do
102
+ @mock_server1, @mock_server2 = mock(), mock()
103
+ @mock_server1.stubs(:host).returns("server1.foo.com")
104
+ @mock_server2.stubs(:host).returns("server2.foo.com")
105
+ @mock_servers = [@mock_server1, @mock_server2]
106
+ end
107
+
108
+ should "call run for each host w/ appropriate role args" do
109
+ @capistrano.stubs(:role_names_for_host).with(@mock_server1).returns([:role1])
110
+ @capistrano.stubs(:role_names_for_host).with(@mock_server2).returns([:role2])
111
+ @capistrano.stubs(:whenever_servers).returns(@mock_servers)
112
+ roles = [:role1, :role2]
113
+ @capistrano.stubs(:whenever_options).returns({:roles => roles})
114
+
115
+ @capistrano.expects(:run).once.with('cd /foo/bar && whenever --flag1 --flag2 --roles role1', {:roles => [:role1, :role2], :hosts => 'server1.foo.com'})
116
+ @capistrano.expects(:run).once.with('cd /foo/bar && whenever --flag1 --flag2 --roles role2', {:roles => [:role1, :role2], :hosts => 'server2.foo.com'})
117
+
118
+ @capistrano.whenever_run_commands(:command => "whenever",
119
+ :path => "/foo/bar",
120
+ :flags => "--flag1 --flag2")
121
+ end
122
+
123
+ should "call run w/ all role args for servers w/ >1 role" do
124
+ @capistrano.stubs(:role_names_for_host).with(@mock_server1).returns([:role1, :role3])
125
+ @capistrano.stubs(:whenever_servers).returns([@mock_servers.first])
126
+ roles = [:role1, :role2, :role3]
127
+ @capistrano.stubs(:whenever_options).returns({:roles => roles})
128
+
129
+ @capistrano.expects(:run).once.with('cd /foo/bar && whenever --flag1 --flag2 --roles role1,role3', {:roles => [:role1, :role2, :role3], :hosts => 'server1.foo.com'})
130
+
131
+ @capistrano.whenever_run_commands(:command => "whenever",
132
+ :path => "/foo/bar",
133
+ :flags => "--flag1 --flag2")
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
@@ -218,6 +218,7 @@ class CronTest < Test::Unit::TestCase
218
218
  context "When given raw cron sytax" do
219
219
  should "return the same cron sytax" do
220
220
  crons = ['0 0 27-31 * *', '* * * * *', '2/3 1,9,22 11-26 1-6 *',
221
+ "*\t*\t*\t*\t*",
221
222
  '@reboot', '@yearly', '@annually', '@monthly', '@weekly',
222
223
  '@daily', '@midnight', '@hourly']
223
224
  crons.each do |cron|
@@ -30,6 +30,10 @@ class JobTest < Test::Unit::TestCase
30
30
  assert_equal '/my/path', new_job(:template => ':path').output
31
31
  end
32
32
 
33
+ should "not substitute parameters for which no value is set" do
34
+ assert_equal 'Hello :world', new_job(:template => ':matching :world', :matching => 'Hello').output
35
+ end
36
+
33
37
  should "escape the :path" do
34
38
  assert_equal '/my/spacey\ path', new_job(:template => ':path', :path => '/my/spacey path').output
35
39
  end
data/whenever.gemspec CHANGED
@@ -15,17 +15,11 @@ Gem::Specification.new do |s|
15
15
  s.test_files = `git ls-files -- test/{functional,unit}/*`.split("\n")
16
16
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
17
  s.require_paths = ["lib"]
18
-
18
+
19
19
  s.add_dependency "chronic", ">= 0.6.3"
20
20
  s.add_dependency "activesupport", ">= 2.3.4"
21
-
21
+
22
22
  s.add_development_dependency "shoulda", ">= 2.1.1"
23
23
  s.add_development_dependency "mocha", ">= 0.9.5"
24
24
  s.add_development_dependency "rake"
25
-
26
- # I'm not sure why this isn't installed along with activesupport,
27
- # but for whatever reason running `bundle install` doesn't install
28
- # i18n so I'm adding it here for now.
29
- # https://github.com/rails/rails/blob/master/activesupport/activesupport.gemspec#L19 ?
30
- s.add_development_dependency "i18n"
31
25
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: whenever
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.8.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-08 00:00:00.000000000 Z
12
+ date: 2012-12-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: chronic
@@ -91,22 +91,6 @@ dependencies:
91
91
  - - ! '>='
92
92
  - !ruby/object:Gem::Version
93
93
  version: '0'
94
- - !ruby/object:Gem::Dependency
95
- name: i18n
96
- requirement: !ruby/object:Gem::Requirement
97
- none: false
98
- requirements:
99
- - - ! '>='
100
- - !ruby/object:Gem::Version
101
- version: '0'
102
- type: :development
103
- prerelease: false
104
- version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
- requirements:
107
- - - ! '>='
108
- - !ruby/object:Gem::Version
109
- version: '0'
110
94
  description: Clean ruby syntax for writing and deploying cron jobs.
111
95
  email:
112
96
  - javan@javan.us
@@ -128,6 +112,7 @@ files:
128
112
  - lib/whenever.rb
129
113
  - lib/whenever/capistrano.rb
130
114
  - lib/whenever/capistrano/recipes.rb
115
+ - lib/whenever/capistrano/support.rb
131
116
  - lib/whenever/command_line.rb
132
117
  - lib/whenever/cron.rb
133
118
  - lib/whenever/job.rb
@@ -140,8 +125,10 @@ files:
140
125
  - test/functional/output_default_defined_jobs_test.rb
141
126
  - test/functional/output_defined_job_test.rb
142
127
  - test/functional/output_env_test.rb
128
+ - test/functional/output_jobs_for_roles_test.rb
143
129
  - test/functional/output_redirection_test.rb
144
130
  - test/test_helper.rb
131
+ - test/unit/capistrano_support_test.rb
145
132
  - test/unit/cron_test.rb
146
133
  - test/unit/job_test.rb
147
134
  - whenever.gemspec
@@ -175,6 +162,8 @@ test_files:
175
162
  - test/functional/output_default_defined_jobs_test.rb
176
163
  - test/functional/output_defined_job_test.rb
177
164
  - test/functional/output_env_test.rb
165
+ - test/functional/output_jobs_for_roles_test.rb
178
166
  - test/functional/output_redirection_test.rb
167
+ - test/unit/capistrano_support_test.rb
179
168
  - test/unit/cron_test.rb
180
169
  - test/unit/job_test.rb