whenever 0.7.3 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +4 -0
- data/CHANGELOG.md +24 -0
- data/LICENSE +1 -1
- data/README.md +76 -13
- data/bin/whenever +4 -1
- data/lib/whenever/capistrano.rb +3 -59
- data/lib/whenever/capistrano/recipes.rb +71 -0
- data/lib/whenever/job.rb +6 -1
- data/lib/whenever/job_list.rb +34 -24
- data/lib/whenever/setup.rb +2 -0
- data/lib/whenever/version.rb +1 -1
- data/test/functional/output_default_defined_jobs_test.rb +77 -21
- data/test/unit/job_test.rb +9 -0
- data/whenever.gemspec +1 -1
- metadata +47 -16
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,27 @@
|
|
1
|
+
### 0.9.0 (unreleased)
|
2
|
+
|
3
|
+
* Time zone support
|
4
|
+
|
5
|
+
|
6
|
+
### 0.8.0 / November 8th, 2012
|
7
|
+
|
8
|
+
* Separate Capistrano recipes to allow custom execution. [Bogdan Gusiev]
|
9
|
+
|
10
|
+
* Execute `whenever:update_crontab` before `deploy:finalize_update`, not `deploy:restart`. [Michal Wrobel]
|
11
|
+
|
12
|
+
* Added a new `script` job type. [Ján Suchal]
|
13
|
+
|
14
|
+
* Use correct path in Cap task. [Alex Dean]
|
15
|
+
|
16
|
+
* Fix that setup.rb and schedule.rb were eval'd together. [Niklas H]
|
17
|
+
|
18
|
+
* New Capistrano roles feature. [Wes Morgan]
|
19
|
+
|
20
|
+
* Stop clearing the crontab during a deploy. [Javan Makhmali]
|
21
|
+
|
22
|
+
* Bump Chronic gem dependency. [rainchen]
|
23
|
+
|
24
|
+
|
1
25
|
### 0.7.3 / February 23rd, 2012
|
2
26
|
|
3
27
|
* Make included Capistrano task compatible with both new and old versions of Cap. [Giacomo Macrì]
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -2,7 +2,7 @@ Whenever is a Ruby gem that provides a clear syntax for writing and deploying cr
|
|
2
2
|
|
3
3
|
### Installation
|
4
4
|
|
5
|
-
```sh
|
5
|
+
```sh
|
6
6
|
$ gem install whenever
|
7
7
|
```
|
8
8
|
|
@@ -11,7 +11,7 @@ Or with Bundler in your Gemfile.
|
|
11
11
|
```ruby
|
12
12
|
gem 'whenever', :require => false
|
13
13
|
```
|
14
|
-
|
14
|
+
|
15
15
|
### Getting started
|
16
16
|
|
17
17
|
```sh
|
@@ -23,14 +23,14 @@ This will create an initial `config/schedule.rb` file for you.
|
|
23
23
|
|
24
24
|
### Example schedule.rb file
|
25
25
|
|
26
|
-
```ruby
|
26
|
+
```ruby
|
27
27
|
every 3.hours do
|
28
|
-
runner "MyModel.some_process"
|
29
|
-
rake "my:rake:task"
|
28
|
+
runner "MyModel.some_process"
|
29
|
+
rake "my:rake:task"
|
30
30
|
command "/usr/bin/my_great_command"
|
31
31
|
end
|
32
32
|
|
33
|
-
every 1.day, :at => '4:30 am' do
|
33
|
+
every 1.day, :at => '4:30 am' do
|
34
34
|
runner "MyModel.task_to_run_at_four_thirty_in_the_morning"
|
35
35
|
end
|
36
36
|
|
@@ -38,13 +38,19 @@ every :hour do # Many shortcuts available: :hour, :day, :month, :year, :reboot
|
|
38
38
|
runner "SomeModel.ladeeda"
|
39
39
|
end
|
40
40
|
|
41
|
-
every :sunday, :at => '12pm' do # Use any day of the week or :weekend, :weekday
|
41
|
+
every :sunday, :at => '12pm' do # Use any day of the week or :weekend, :weekday
|
42
42
|
runner "Task.do_something_great"
|
43
43
|
end
|
44
44
|
|
45
45
|
every '0 0 27-31 * *' do
|
46
46
|
command "echo 'you can use raw cron syntax too'"
|
47
47
|
end
|
48
|
+
|
49
|
+
# run this task only on servers with the :app role in Capistrano
|
50
|
+
# see Capistrano roles section below
|
51
|
+
every :day, :at => '12:20am', :roles => [:app] do
|
52
|
+
rake "app_server:task"
|
53
|
+
end
|
48
54
|
```
|
49
55
|
|
50
56
|
### Define your own job types
|
@@ -60,7 +66,7 @@ every 2.hours do
|
|
60
66
|
awesome "party", :fun_level => "extreme"
|
61
67
|
end
|
62
68
|
```
|
63
|
-
|
69
|
+
|
64
70
|
Would run `/usr/local/bin/awesome party extreme` every two hours. `:task` is always replaced with the first argument, and any additional `:whatevers` are replaced with the options passed in or by variables that have been defined with `set`.
|
65
71
|
|
66
72
|
The default job types that ship with Whenever are defined like so:
|
@@ -69,6 +75,7 @@ The default job types that ship with Whenever are defined like so:
|
|
69
75
|
job_type :command, ":task :output"
|
70
76
|
job_type :rake, "cd :path && RAILS_ENV=:environment bundle exec rake :task --silent :output"
|
71
77
|
job_type :runner, "cd :path && script/rails runner -e :environment ':task' :output"
|
78
|
+
job_type :script, "cd :path && RAILS_ENV=:environment bundle exec script/:task :output"
|
72
79
|
```
|
73
80
|
|
74
81
|
Pre-Rails 3 apps and apps that don't use Bundler will redefine the `rake` and `runner` jobs respectively to function correctly.
|
@@ -82,7 +89,7 @@ You can change this by setting your own `:job_template`.
|
|
82
89
|
```ruby
|
83
90
|
set :job_template, "bash -l -c ':job'"
|
84
91
|
```
|
85
|
-
|
92
|
+
|
86
93
|
Or set the job_template to nil to have your jobs execute normally.
|
87
94
|
|
88
95
|
```ruby
|
@@ -99,7 +106,7 @@ In your "config/deploy.rb" file:
|
|
99
106
|
require "whenever/capistrano"
|
100
107
|
```
|
101
108
|
|
102
|
-
Take a look at the recipe for options you can set. <http://github.com/javan/whenever/blob/master/lib/whenever/capistrano.rb>
|
109
|
+
Take a look at the recipe for options you can set. <http://github.com/javan/whenever/blob/master/lib/whenever/capistrano/recipes.rb>
|
103
110
|
For example, if you're using bundler do this:
|
104
111
|
|
105
112
|
```ruby
|
@@ -124,6 +131,62 @@ set :whenever_identifier, defer { "#{application}_#{stage}" }
|
|
124
131
|
require "whenever/capistrano"
|
125
132
|
```
|
126
133
|
|
134
|
+
### Capistrano roles
|
135
|
+
|
136
|
+
The first thing to know about the new roles support is that it is entirely
|
137
|
+
optional and backwards-compatible. If you don't need different jobs running on
|
138
|
+
different servers in your capistrano deployment, then you can safely stop reading
|
139
|
+
now and everything should just work the same way it always has.
|
140
|
+
|
141
|
+
When you define a job in your schedule.rb file, by default it will be deployed to
|
142
|
+
all servers in the whenever_roles list (which defaults to [:db]).
|
143
|
+
|
144
|
+
However, if you want to restrict certain jobs to only run on subset of servers,
|
145
|
+
you can add a :roles => [...] argument to their definitions. **Make sure to add
|
146
|
+
that role to the whenever_roles list in your deploy.rb.**
|
147
|
+
|
148
|
+
When you run `cap deploy`, jobs with a :roles list specified will only be added to
|
149
|
+
the crontabs on servers with one or more of the roles in that list.
|
150
|
+
|
151
|
+
Jobs with no :roles argument will be deployed to all servers in the whenever_roles
|
152
|
+
list. This is to maintain backward compatibility with previous releases of whenever.
|
153
|
+
|
154
|
+
So, for example, with the default whenever_roles of [:db], a job like this would be
|
155
|
+
deployed to all servers with the :db role:
|
156
|
+
|
157
|
+
```ruby
|
158
|
+
every :day, :at => '12:20am' do
|
159
|
+
rake 'foo:bar'
|
160
|
+
end
|
161
|
+
```
|
162
|
+
|
163
|
+
If we set whenever_roles to [:db, :app] in deploy.rb, and have the following
|
164
|
+
jobs in schedule.rb:
|
165
|
+
|
166
|
+
```ruby
|
167
|
+
every :day, :at => '1:37pm', :roles => [:app] do
|
168
|
+
rake 'app:task' # will only be added to crontabs of :app servers
|
169
|
+
end
|
170
|
+
|
171
|
+
every :hour, :roles => [:db] do
|
172
|
+
rake 'db:task' # will only be added to crontabs of :db servers
|
173
|
+
end
|
174
|
+
|
175
|
+
every :day, :at => '12:02am' do
|
176
|
+
command "run_this_everywhere" # will be deployed to :db and :app servers
|
177
|
+
end
|
178
|
+
```
|
179
|
+
|
180
|
+
Here are the basic rules:
|
181
|
+
|
182
|
+
1. If a server's role isn't listed in whenever_roles, it will *never* have jobs
|
183
|
+
added to its crontab.
|
184
|
+
1. If a server's role is listed in the whenever_roles, then it will have all
|
185
|
+
jobs added to its crontab that either list that role in their :roles arg or
|
186
|
+
that don't have a :roles arg.
|
187
|
+
1. If a job has a :roles arg but that role isn't in the whenever_roles list,
|
188
|
+
that job *will not* be deployed to any server.
|
189
|
+
|
127
190
|
### RVM Integration
|
128
191
|
|
129
192
|
If your production environment uses RVM (Ruby Version Manager) you will run into a gotcha that causes your cron jobs to hang. This is not directly related to Whenever, and can be tricky to debug. Your .rvmrc files must be trusted or else the cron jobs will hang waiting for the file to be trusted. A solution is to disable the prompt by adding this line to your user rvm file in `~/.rvmrc`
|
@@ -138,7 +201,7 @@ This tells rvm to trust all rvmrc files, which is documented here: http://waynee
|
|
138
201
|
$ cd /apps/my-great-project
|
139
202
|
$ whenever
|
140
203
|
```
|
141
|
-
|
204
|
+
|
142
205
|
This will simply show you your `schedule.rb` file converted to cron syntax. It does not read or write your crontab file. Run `whenever --help` for a complete list of options.
|
143
206
|
|
144
207
|
### Credit
|
@@ -158,8 +221,8 @@ It's a little bit dated now, but remains a good introduction.
|
|
158
221
|
|
159
222
|
----
|
160
223
|
|
161
|
-
Compatible with Ruby 1.8.7-1.9.
|
224
|
+
Compatible with Ruby 1.8.7-1.9.3, JRuby, and Rubinius. [![Build Status](https://secure.travis-ci.org/javan/whenever.png)](http://travis-ci.org/javan/whenever)
|
162
225
|
|
163
226
|
----
|
164
227
|
|
165
|
-
Copyright ©
|
228
|
+
Copyright © 2012 Javan Makhmali
|
data/bin/whenever
CHANGED
@@ -26,12 +26,15 @@ OptionParser.new do |opts|
|
|
26
26
|
opts.on('-f', '--load-file [schedule file]', 'Default: config/schedule.rb') do |file|
|
27
27
|
options[:file] = file if file
|
28
28
|
end
|
29
|
-
opts.on('-u', '--user [user]', 'Default: current user') do |user|
|
29
|
+
opts.on('-u', '--user [user]', 'Default: current user') do |user|
|
30
30
|
options[:user] = user if user
|
31
31
|
end
|
32
32
|
opts.on('-k', '--cut [lines]', 'Cut lines from the top of the cronfile') do |lines|
|
33
33
|
options[:cut] = lines.to_i if lines
|
34
34
|
end
|
35
|
+
opts.on('-r', '--roles [role1,role2]', 'Comma-separated list of server roles to generate cron jobs for') do |roles|
|
36
|
+
options[:roles] = roles.split(',').map(&:to_sym) if roles
|
37
|
+
end
|
35
38
|
opts.on('-v', '--version') { puts "Whenever v#{Whenever::VERSION}"; exit(0) }
|
36
39
|
end.parse!
|
37
40
|
|
data/lib/whenever/capistrano.rb
CHANGED
@@ -1,64 +1,8 @@
|
|
1
|
-
|
2
|
-
_cset(:whenever_roles) { :db }
|
3
|
-
_cset(:whenever_options) { {:roles => fetch(:whenever_roles)} }
|
4
|
-
_cset(:whenever_command) { "whenever" }
|
5
|
-
_cset(:whenever_identifier) { fetch :application }
|
6
|
-
_cset(:whenever_environment) { fetch :rails_env, "production" }
|
7
|
-
_cset(:whenever_variables) { "environment=#{fetch :whenever_environment}" }
|
8
|
-
_cset(:whenever_update_flags) { "--update-crontab #{fetch :whenever_identifier} --set #{fetch :whenever_variables}" }
|
9
|
-
_cset(:whenever_clear_flags) { "--clear-crontab #{fetch :whenever_identifier}" }
|
1
|
+
require "whenever/capistrano/recipes"
|
10
2
|
|
11
|
-
|
12
|
-
after "deploy:update_code", "whenever:clear_crontab"
|
3
|
+
Capistrano::Configuration.instance(:must_exist).load do
|
13
4
|
# Write the new cron jobs near the end.
|
14
|
-
before "deploy:
|
5
|
+
before "deploy:finalize_update", "whenever:update_crontab"
|
15
6
|
# If anything goes wrong, undo.
|
16
7
|
after "deploy:rollback", "whenever:update_crontab"
|
17
|
-
|
18
|
-
namespace :whenever do
|
19
|
-
desc <<-DESC
|
20
|
-
Update application's crontab entries using Whenever. You can configure \
|
21
|
-
the command used to invoke Whenever by setting the :whenever_command \
|
22
|
-
variable, which can be used with Bundler to set the command to \
|
23
|
-
"bundle exec whenever". You can configure the identifier used by setting \
|
24
|
-
the :whenever_identifier variable, which defaults to the same value configured \
|
25
|
-
for the :application variable. You can configure the environment by setting \
|
26
|
-
the :whenever_environment variable, which defaults to the same value \
|
27
|
-
configured for the :rails_env variable which itself defaults to "production". \
|
28
|
-
Finally, you can completely override all arguments to the Whenever command \
|
29
|
-
by setting the :whenever_update_flags variable. Additionally you can configure \
|
30
|
-
which servers the crontab is updated on by setting the :whenever_roles variable.
|
31
|
-
DESC
|
32
|
-
task :update_crontab do
|
33
|
-
options = fetch(:whenever_options)
|
34
|
-
|
35
|
-
if find_servers(options).any?
|
36
|
-
on_rollback do
|
37
|
-
if fetch :previous_release
|
38
|
-
run "cd #{fetch :previous_release} && #{fetch :whenever_command} #{fetch :whenever_update_flags}", options
|
39
|
-
else
|
40
|
-
run "cd #{fetch :release_path} && #{fetch :whenever_command} #{fetch :whenever_clear_flags}", options
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
run "cd #{fetch :current_path} && #{fetch :whenever_command} #{fetch :whenever_update_flags}", options
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
desc <<-DESC
|
49
|
-
Clear application's crontab entries using Whenever. You can configure \
|
50
|
-
the command used to invoke Whenever by setting the :whenever_command \
|
51
|
-
variable, which can be used with Bundler to set the command to \
|
52
|
-
"bundle exec whenever". You can configure the identifier used by setting \
|
53
|
-
the :whenever_identifier variable, which defaults to the same value configured \
|
54
|
-
for the :application variable. Finally, you can completely override all \
|
55
|
-
arguments to the Whenever command by setting the :whenever_clear_flags variable. \
|
56
|
-
Additionally you can configure which servers the crontab is cleared on by setting \
|
57
|
-
the :whenever_roles variable.
|
58
|
-
DESC
|
59
|
-
task :clear_crontab do
|
60
|
-
options = fetch(:whenever_options)
|
61
|
-
run "cd #{fetch :latest_release} && #{fetch :whenever_command} #{fetch :whenever_clear_flags}", options if find_servers(options).any?
|
62
|
-
end
|
63
|
-
end
|
64
8
|
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
Capistrano::Configuration.instance(:must_exist).load do
|
2
|
+
_cset(:whenever_roles) { :db }
|
3
|
+
_cset(:whenever_options) { {:roles => fetch(:whenever_roles)} }
|
4
|
+
_cset(:whenever_command) { "whenever" }
|
5
|
+
_cset(:whenever_identifier) { fetch :application }
|
6
|
+
_cset(:whenever_environment) { fetch :rails_env, "production" }
|
7
|
+
_cset(:whenever_variables) { "environment=#{fetch :whenever_environment}" }
|
8
|
+
_cset(:whenever_update_flags) { "--update-crontab #{fetch :whenever_identifier} --set #{fetch :whenever_variables}" }
|
9
|
+
_cset(:whenever_clear_flags) { "--clear-crontab #{fetch :whenever_identifier}" }
|
10
|
+
|
11
|
+
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
|
25
|
+
task :update_crontab do
|
26
|
+
options = fetch(:whenever_options)
|
27
|
+
roles = [options[:roles]].flatten if options[:roles]
|
28
|
+
|
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?
|
32
|
+
|
33
|
+
roles.each do |role|
|
34
|
+
if role == :__none
|
35
|
+
role_arg = ''
|
36
|
+
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
|
47
|
+
end
|
48
|
+
|
49
|
+
run "cd #{fetch :latest_release} && #{fetch :whenever_command} #{fetch :whenever_update_flags}#{role_arg}", options
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
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
|
+
|
66
|
+
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?
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/whenever/job.rb
CHANGED
@@ -2,13 +2,14 @@ require 'shellwords'
|
|
2
2
|
|
3
3
|
module Whenever
|
4
4
|
class Job
|
5
|
-
attr_reader :at
|
5
|
+
attr_reader :at, :roles
|
6
6
|
|
7
7
|
def initialize(options = {})
|
8
8
|
@options = options
|
9
9
|
@at = options.delete(:at)
|
10
10
|
@template = options.delete(:template)
|
11
11
|
@job_template = options.delete(:job_template) || ":job"
|
12
|
+
@roles = Array.wrap(options.delete(:roles))
|
12
13
|
@options[:output] = Whenever::Output::Redirection.new(options[:output]).to_s if options.has_key?(:output)
|
13
14
|
@options[:environment] ||= :production
|
14
15
|
@options[:path] = Shellwords.shellescape(@options[:path] || Whenever.path)
|
@@ -23,6 +24,10 @@ module Whenever
|
|
23
24
|
out.gsub(/%/, '\%')
|
24
25
|
end
|
25
26
|
|
27
|
+
def has_role?(role)
|
28
|
+
roles.empty? || roles.include?(role)
|
29
|
+
end
|
30
|
+
|
26
31
|
protected
|
27
32
|
|
28
33
|
def process_template(template, options)
|
data/lib/whenever/job_list.rb
CHANGED
@@ -1,66 +1,72 @@
|
|
1
1
|
module Whenever
|
2
2
|
class JobList
|
3
|
+
attr_reader :roles
|
4
|
+
|
3
5
|
def initialize(options)
|
4
6
|
@jobs, @env, @set_variables, @pre_set_variables = {}, {}, {}, {}
|
5
|
-
|
7
|
+
|
6
8
|
if options.is_a? String
|
7
9
|
options = { :string => options }
|
8
10
|
end
|
9
11
|
|
10
12
|
pre_set(options[:set])
|
11
|
-
|
12
|
-
|
13
|
+
|
14
|
+
@roles = options[:roles] || []
|
15
|
+
|
16
|
+
setup_file = File.expand_path('../setup.rb', __FILE__)
|
17
|
+
setup = File.read(setup_file)
|
13
18
|
schedule = if options[:string]
|
14
19
|
options[:string]
|
15
20
|
elsif options[:file]
|
16
21
|
File.read(options[:file])
|
17
22
|
end
|
18
|
-
|
19
|
-
instance_eval(setup
|
23
|
+
|
24
|
+
instance_eval(setup, setup_file)
|
25
|
+
instance_eval(schedule, options[:file] || '<eval>')
|
20
26
|
end
|
21
|
-
|
27
|
+
|
22
28
|
def set(variable, value)
|
23
29
|
variable = variable.to_sym
|
24
30
|
return if @pre_set_variables[variable]
|
25
|
-
|
31
|
+
|
26
32
|
instance_variable_set("@#{variable}".to_sym, value)
|
27
33
|
self.class.send(:attr_reader, variable.to_sym)
|
28
34
|
@set_variables[variable] = value
|
29
35
|
end
|
30
|
-
|
36
|
+
|
31
37
|
def env(variable, value)
|
32
38
|
@env[variable.to_s] = value
|
33
39
|
end
|
34
|
-
|
40
|
+
|
35
41
|
def every(frequency, options = {})
|
36
42
|
@current_time_scope = frequency
|
37
43
|
@options = options
|
38
44
|
yield
|
39
45
|
end
|
40
|
-
|
46
|
+
|
41
47
|
def job_type(name, template)
|
42
48
|
class_eval do
|
43
49
|
define_method(name) do |task, *args|
|
44
50
|
options = { :task => task, :template => template }
|
45
51
|
options.merge!(args[0]) if args[0].is_a? Hash
|
46
|
-
|
52
|
+
|
47
53
|
# :cron_log was an old option for output redirection, it remains for backwards compatibility
|
48
54
|
options[:output] = (options[:cron_log] || @cron_log) if defined?(@cron_log) || options.has_key?(:cron_log)
|
49
55
|
# :output is the newer, more flexible option.
|
50
56
|
options[:output] = @output if defined?(@output) && !options.has_key?(:output)
|
51
|
-
|
57
|
+
|
52
58
|
@jobs[@current_time_scope] ||= []
|
53
59
|
@jobs[@current_time_scope] << Whenever::Job.new(@options.merge(@set_variables).merge(options))
|
54
60
|
end
|
55
61
|
end
|
56
62
|
end
|
57
|
-
|
58
|
-
def generate_cron_output
|
63
|
+
|
64
|
+
def generate_cron_output
|
59
65
|
[environment_variables, cron_jobs].compact.join
|
60
66
|
end
|
61
|
-
|
67
|
+
|
62
68
|
private
|
63
|
-
|
69
|
+
|
64
70
|
#
|
65
71
|
# Takes a string like: "variable1=something&variable2=somethingelse"
|
66
72
|
# and breaks it into variable/value pairs. Used for setting variables at runtime from the command line.
|
@@ -68,7 +74,7 @@ module Whenever
|
|
68
74
|
#
|
69
75
|
def pre_set(variable_string = nil)
|
70
76
|
return if variable_string.blank?
|
71
|
-
|
77
|
+
|
72
78
|
pairs = variable_string.split('&')
|
73
79
|
pairs.each do |pair|
|
74
80
|
next unless pair.index('=')
|
@@ -80,19 +86,19 @@ module Whenever
|
|
80
86
|
end
|
81
87
|
end
|
82
88
|
end
|
83
|
-
|
89
|
+
|
84
90
|
def environment_variables
|
85
91
|
return if @env.empty?
|
86
|
-
|
92
|
+
|
87
93
|
output = []
|
88
94
|
@env.each do |key, val|
|
89
95
|
output << "#{key}=#{val.blank? ? '""' : val}\n"
|
90
96
|
end
|
91
97
|
output << "\n"
|
92
|
-
|
98
|
+
|
93
99
|
output.join
|
94
100
|
end
|
95
|
-
|
101
|
+
|
96
102
|
#
|
97
103
|
# Takes the standard cron output that Whenever generates and finds
|
98
104
|
# similar entries that can be combined. For example: If a job should run
|
@@ -121,15 +127,19 @@ module Whenever
|
|
121
127
|
|
122
128
|
def cron_jobs
|
123
129
|
return if @jobs.empty?
|
124
|
-
|
130
|
+
|
125
131
|
shortcut_jobs = []
|
126
132
|
regular_jobs = []
|
127
|
-
|
133
|
+
|
134
|
+
output_all = roles.empty?
|
128
135
|
@jobs.each do |time, jobs|
|
129
136
|
jobs.each do |job|
|
137
|
+
next unless output_all || roles.any? do |r|
|
138
|
+
job.has_role?(r)
|
139
|
+
end
|
130
140
|
Whenever::Output::Cron.output(time, job) do |cron|
|
131
141
|
cron << "\n\n"
|
132
|
-
|
142
|
+
|
133
143
|
if cron.starts_with?("@")
|
134
144
|
shortcut_jobs << cron
|
135
145
|
else
|
data/lib/whenever/setup.rb
CHANGED
@@ -12,8 +12,10 @@ job_type :command, ":task :output"
|
|
12
12
|
# Run rake through bundler if possible
|
13
13
|
if Whenever.bundler?
|
14
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"
|
15
16
|
else
|
16
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"
|
17
19
|
end
|
18
20
|
|
19
21
|
# Create a runner job that's appropriate for the Rails version,
|
data/lib/whenever/version.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + "/../test_helper")
|
2
2
|
|
3
3
|
class OutputDefaultDefinedJobsTest < Test::Unit::TestCase
|
4
|
-
|
4
|
+
|
5
5
|
# command
|
6
|
-
|
6
|
+
|
7
7
|
context "A plain command with the job template set to nil" do
|
8
8
|
setup do
|
9
9
|
@output = Whenever.cron \
|
@@ -14,12 +14,12 @@ class OutputDefaultDefinedJobsTest < Test::Unit::TestCase
|
|
14
14
|
end
|
15
15
|
file
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
should "output the command" do
|
19
19
|
assert_match /^.+ .+ .+ .+ blahblah$/, @output
|
20
20
|
end
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
context "A plain command with no job template set" do
|
24
24
|
setup do
|
25
25
|
@output = Whenever.cron \
|
@@ -29,12 +29,12 @@ class OutputDefaultDefinedJobsTest < Test::Unit::TestCase
|
|
29
29
|
end
|
30
30
|
file
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
should "output the command with the default job template" do
|
34
34
|
assert_match /^.+ .+ .+ .+ \/bin\/bash -l -c 'blahblah'$/, @output
|
35
35
|
end
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
38
|
context "A plain command that overrides the job_template set" do
|
39
39
|
setup do
|
40
40
|
@output = Whenever.cron \
|
@@ -45,13 +45,13 @@ class OutputDefaultDefinedJobsTest < Test::Unit::TestCase
|
|
45
45
|
end
|
46
46
|
file
|
47
47
|
end
|
48
|
-
|
48
|
+
|
49
49
|
should "output the command using that job_template" do
|
50
50
|
assert_match /^.+ .+ .+ .+ \/bin\/sh -l -c 'blahblah'$/, @output
|
51
51
|
assert_no_match /bash/, @output
|
52
52
|
end
|
53
53
|
end
|
54
|
-
|
54
|
+
|
55
55
|
context "A plain command that is conditional on default environent and path" do
|
56
56
|
setup do
|
57
57
|
Whenever.expects(:path).at_least_once.returns('/what/you/want')
|
@@ -65,14 +65,14 @@ class OutputDefaultDefinedJobsTest < Test::Unit::TestCase
|
|
65
65
|
end
|
66
66
|
file
|
67
67
|
end
|
68
|
-
|
68
|
+
|
69
69
|
should "output the command" do
|
70
70
|
assert_match /blahblah/, @output
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
74
|
# runner
|
75
|
-
|
75
|
+
|
76
76
|
context "A runner with path set" do
|
77
77
|
setup do
|
78
78
|
@output = Whenever.cron \
|
@@ -84,12 +84,12 @@ class OutputDefaultDefinedJobsTest < Test::Unit::TestCase
|
|
84
84
|
end
|
85
85
|
file
|
86
86
|
end
|
87
|
-
|
87
|
+
|
88
88
|
should "output the runner using that path" do
|
89
89
|
assert_match two_hours + %( cd /my/path && script/runner -e production 'blahblah'), @output
|
90
90
|
end
|
91
91
|
end
|
92
|
-
|
92
|
+
|
93
93
|
context "A runner that overrides the path set" do
|
94
94
|
setup do
|
95
95
|
@output = Whenever.cron \
|
@@ -101,12 +101,12 @@ class OutputDefaultDefinedJobsTest < Test::Unit::TestCase
|
|
101
101
|
end
|
102
102
|
file
|
103
103
|
end
|
104
|
-
|
104
|
+
|
105
105
|
should "output the runner using that path" do
|
106
106
|
assert_match two_hours + %( cd /some/other/path && script/runner -e production 'blahblah'), @output
|
107
107
|
end
|
108
108
|
end
|
109
|
-
|
109
|
+
|
110
110
|
context "A runner for a Rails 3 app" do
|
111
111
|
setup do
|
112
112
|
Whenever.expects(:path).at_least_once.returns('/my/path')
|
@@ -119,14 +119,14 @@ class OutputDefaultDefinedJobsTest < Test::Unit::TestCase
|
|
119
119
|
end
|
120
120
|
file
|
121
121
|
end
|
122
|
-
|
122
|
+
|
123
123
|
should "use the Rails 3 runner job by default" do
|
124
124
|
assert_match two_hours + %( cd /my/path && script/rails runner -e production 'blahblah'), @output
|
125
125
|
end
|
126
126
|
end
|
127
|
-
|
127
|
+
|
128
128
|
# rake
|
129
|
-
|
129
|
+
|
130
130
|
context "A rake command with path set" do
|
131
131
|
setup do
|
132
132
|
@output = Whenever.cron \
|
@@ -138,7 +138,7 @@ class OutputDefaultDefinedJobsTest < Test::Unit::TestCase
|
|
138
138
|
end
|
139
139
|
file
|
140
140
|
end
|
141
|
-
|
141
|
+
|
142
142
|
should "output the rake command using that path" do
|
143
143
|
assert_match two_hours + ' cd /my/path && RAILS_ENV=production bundle exec rake blahblah --silent', @output
|
144
144
|
end
|
@@ -161,7 +161,7 @@ class OutputDefaultDefinedJobsTest < Test::Unit::TestCase
|
|
161
161
|
assert_match two_hours + ' cd /my/path && RAILS_ENV=production rake blahblah --silent', @output
|
162
162
|
end
|
163
163
|
end
|
164
|
-
|
164
|
+
|
165
165
|
context "A rake command that overrides the path set" do
|
166
166
|
setup do
|
167
167
|
@output = Whenever.cron \
|
@@ -173,10 +173,66 @@ class OutputDefaultDefinedJobsTest < Test::Unit::TestCase
|
|
173
173
|
end
|
174
174
|
file
|
175
175
|
end
|
176
|
-
|
176
|
+
|
177
177
|
should "output the rake command using that path" do
|
178
178
|
assert_match two_hours + ' cd /some/other/path && RAILS_ENV=production bundle exec rake blahblah --silent', @output
|
179
179
|
end
|
180
180
|
end
|
181
|
-
|
181
|
+
|
182
|
+
|
183
|
+
# script
|
184
|
+
|
185
|
+
context "A script command with path set" do
|
186
|
+
setup do
|
187
|
+
@output = Whenever.cron \
|
188
|
+
<<-file
|
189
|
+
set :job_template, nil
|
190
|
+
set :path, '/my/path'
|
191
|
+
every 2.hours do
|
192
|
+
script "blahblah"
|
193
|
+
end
|
194
|
+
file
|
195
|
+
end
|
196
|
+
|
197
|
+
should "output the script command using that path" do
|
198
|
+
assert_match two_hours + ' cd /my/path && RAILS_ENV=production bundle exec script/blahblah', @output
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
context "A script command for a non-bundler app" do
|
203
|
+
setup do
|
204
|
+
Whenever.expects(:path).at_least_once.returns('/my/path')
|
205
|
+
Whenever.expects(:bundler?).returns(false)
|
206
|
+
@output = Whenever.cron \
|
207
|
+
<<-file
|
208
|
+
set :job_template, nil
|
209
|
+
every 2.hours do
|
210
|
+
script 'blahblah'
|
211
|
+
end
|
212
|
+
file
|
213
|
+
end
|
214
|
+
|
215
|
+
should "not use invoke through bundler" do
|
216
|
+
assert_match two_hours + ' cd /my/path && RAILS_ENV=production script/blahblah', @output
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
context "A script command that uses output" do
|
221
|
+
setup do
|
222
|
+
@output = Whenever.cron \
|
223
|
+
<<-file
|
224
|
+
set :job_template, nil
|
225
|
+
set :output, '/log/file'
|
226
|
+
set :path, '/my/path'
|
227
|
+
every 2.hours do
|
228
|
+
script "blahblah", :path => '/some/other/path'
|
229
|
+
end
|
230
|
+
file
|
231
|
+
end
|
232
|
+
|
233
|
+
should "output the script command using that path" do
|
234
|
+
assert_match two_hours + ' cd /some/other/path && RAILS_ENV=production bundle exec script/blahblah >> /log/file 2>&1', @output
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
182
238
|
end
|
data/test/unit/job_test.rb
CHANGED
@@ -7,6 +7,15 @@ class JobTest < Test::Unit::TestCase
|
|
7
7
|
assert_equal 'foo', new_job(:at => 'foo').at
|
8
8
|
end
|
9
9
|
|
10
|
+
should "return the :roles set when #roles is called" do
|
11
|
+
assert_equal ['foo', 'bar'], new_job(:roles => ['foo', 'bar']).roles
|
12
|
+
end
|
13
|
+
|
14
|
+
should "return whether it has a role from #has_role?" do
|
15
|
+
assert new_job(:roles => 'foo').has_role?('foo')
|
16
|
+
assert_equal false, new_job(:roles => 'bar').has_role?('foo')
|
17
|
+
end
|
18
|
+
|
10
19
|
should "substitute the :task when #output is called" do
|
11
20
|
job = new_job(:template => ":task", :task => 'abc123')
|
12
21
|
assert_equal 'abc123', job.output
|
data/whenever.gemspec
CHANGED
@@ -16,7 +16,7 @@ Gem::Specification.new do |s|
|
|
16
16
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
17
|
s.require_paths = ["lib"]
|
18
18
|
|
19
|
-
s.add_dependency "chronic", "
|
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"
|
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.
|
4
|
+
version: 0.8.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,22 +9,27 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-11-08 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: chronic
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
|
-
- -
|
19
|
+
- - ! '>='
|
20
20
|
- !ruby/object:Gem::Version
|
21
21
|
version: 0.6.3
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.6.3
|
25
30
|
- !ruby/object:Gem::Dependency
|
26
31
|
name: activesupport
|
27
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
28
33
|
none: false
|
29
34
|
requirements:
|
30
35
|
- - ! '>='
|
@@ -32,10 +37,15 @@ dependencies:
|
|
32
37
|
version: 2.3.4
|
33
38
|
type: :runtime
|
34
39
|
prerelease: false
|
35
|
-
version_requirements:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 2.3.4
|
36
46
|
- !ruby/object:Gem::Dependency
|
37
47
|
name: shoulda
|
38
|
-
requirement:
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
39
49
|
none: false
|
40
50
|
requirements:
|
41
51
|
- - ! '>='
|
@@ -43,10 +53,15 @@ dependencies:
|
|
43
53
|
version: 2.1.1
|
44
54
|
type: :development
|
45
55
|
prerelease: false
|
46
|
-
version_requirements:
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 2.1.1
|
47
62
|
- !ruby/object:Gem::Dependency
|
48
63
|
name: mocha
|
49
|
-
requirement:
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
50
65
|
none: false
|
51
66
|
requirements:
|
52
67
|
- - ! '>='
|
@@ -54,10 +69,15 @@ dependencies:
|
|
54
69
|
version: 0.9.5
|
55
70
|
type: :development
|
56
71
|
prerelease: false
|
57
|
-
version_requirements:
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 0.9.5
|
58
78
|
- !ruby/object:Gem::Dependency
|
59
79
|
name: rake
|
60
|
-
requirement:
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
61
81
|
none: false
|
62
82
|
requirements:
|
63
83
|
- - ! '>='
|
@@ -65,10 +85,15 @@ dependencies:
|
|
65
85
|
version: '0'
|
66
86
|
type: :development
|
67
87
|
prerelease: false
|
68
|
-
version_requirements:
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
69
94
|
- !ruby/object:Gem::Dependency
|
70
95
|
name: i18n
|
71
|
-
requirement:
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
72
97
|
none: false
|
73
98
|
requirements:
|
74
99
|
- - ! '>='
|
@@ -76,7 +101,12 @@ dependencies:
|
|
76
101
|
version: '0'
|
77
102
|
type: :development
|
78
103
|
prerelease: false
|
79
|
-
version_requirements:
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
80
110
|
description: Clean ruby syntax for writing and deploying cron jobs.
|
81
111
|
email:
|
82
112
|
- javan@javan.us
|
@@ -97,6 +127,7 @@ files:
|
|
97
127
|
- bin/wheneverize
|
98
128
|
- lib/whenever.rb
|
99
129
|
- lib/whenever/capistrano.rb
|
130
|
+
- lib/whenever/capistrano/recipes.rb
|
100
131
|
- lib/whenever/command_line.rb
|
101
132
|
- lib/whenever/cron.rb
|
102
133
|
- lib/whenever/job.rb
|
@@ -134,7 +165,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
134
165
|
version: '0'
|
135
166
|
requirements: []
|
136
167
|
rubyforge_project:
|
137
|
-
rubygems_version: 1.8.
|
168
|
+
rubygems_version: 1.8.23
|
138
169
|
signing_key:
|
139
170
|
specification_version: 3
|
140
171
|
summary: Cron jobs in ruby.
|