Capistrano and Whenever Stage Variables
Asked Answered
P

3

5

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

Phenica answered 1/3, 2013 at 4:52 Comment(2)
I get an error - undefined method `defer'. Do I need to include anything else other than whenever/capistrano?Kindig
@VivekRao I figured out a solution to this, I posted it as a separate answer below.Operation
C
5

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

Citystate answered 1/3, 2013 at 6:10 Comment(3)
The problem is that in our case, environment/RAILS_ENV is always equal to "production". I need to get at the capistrano stage.Phenica
i haven't tried this out yet but I think what set :whenever_environment, defer { stage } does is it sets the whenever environment to the value of stage.Citystate
Thanks for your help @jvnill. See my update for how I solved my problem. I think your whenever_command solution probably would have worked, too.Phenica
O
3

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
Operation answered 15/11, 2016 at 23:26 Comment(0)
A
0

@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

Archaeozoic answered 12/4, 2014 at 16:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.