Capistrano and Whenever Stage Variables

6.9k Views Asked by At

On our staging server we run our Rails application in the production environment so as to be as similar as possible to our production server. We're using whenever to create our crontab. However, we need to run a slightly different rake task for our sitemap generation so it doesn't ping Google and Bing.

In deploy.rb, we have: set :stages, %w(production staging), but in both deploy/staging.rb and deploy/production.rb we have :rails_env, "production" set, so I can't use Rails.env.

In schedule.rb, I want to do something like:

every :day, at: '1am' do
  if @stage == 'production'
    rake 'sitemap:refresh'
  else
    rake 'sitemap:refresh:no_ping'
  end
end

How can I make that variable available?

Update

I was able to solve it by putting

set :whenever_variables, defer { "stage=#{stage}" }

into my deploy/staging.rb. I then had access to @stage in schedule.rb

3

There are 3 best solutions below

3
On

not really sure if this will work but worth a try (from the whenever readme)

# deploy.rb
set :whenever_environment, defer { stage }
require "whenever/capistrano"

then in your schedule.rb

set :environment, ENV['RAILS_ENV']

case environment
when 'production', 'staging'
  ...
when 'production'
  ...
when 'staging'
  ...
end

UPDATE: you can also use

set(:whenever_command) { "STAGE=#{stage} bundle exec whenever" }

so that you have access to a STAGE environment variable inside schedule.rb

0
On

The defer method doesn't appear to work in the later versions of Capistrano (3.4.1) / whenever (0.9.7). I was hitting an error with NoMethodError: undefined method 'defer' for main:Object. Here's what worked for me:

deploy.rb:

set :whenever_environment, Proc.new { fetch :stage }

schedule.rb:

if @environment == 'production'
  every 15.minutes, roles: [:my_custom_role] do
    rake 'my_rake_task'
  end
end
0
On

@jvnill has the right answer. If you're using config/deploy/ for separate environments, you can keep it a little neater by putting the setting in the proper stage.

# config/deploy/staging.rb
set :whenever_command, "STAGE=#{stage} bundle exec whenever"

# config/deploy/production.rb
set :whenever_command, "STAGE=production bundle exec whenever"

# config/deploy.rb
require "whenever/capistrano"

By requiring 'whenever/capistrano,' you take care of running the whenever after deploy:finalize_update.

https://github.com/javan/whenever/blob/master/lib/whenever/capistrano/v2/hooks.rb