How do I keep whenever/capistrano from overwriting jobs for other environments?

963 Views Asked by At

I have two environments, staging and production, on one server, being deployed with capistrano 3. The deploys for each environment clobber each other, fully replacing the other environment's jobs.

  • If I deploy staging, then all of the cronjobs are removed and replaced with jobs referencing the staging release path and environment. All of the production jobs are removed.
  • If I deploy production, then all of the cronjobs are removed and replaced with jobs referencing the production release path and environment. All of the staging jobs are removed.
  • If I do a case statement in schedule.rb on @environment, and only have jobs set for a when 'production' situation, then when staging is deployed it completely clears the cronjobs. All of the jobs are gone.

I need to get to either of these two situations:

  • Have two sets of jobs (one for staging and one for production) that each persist through either environment's deploy (so, in my example at the bottom, there would be two jobs listed - one for the staging release and one for the production release)
  • One set of jobs (just for production) that persists through either environment's deploy (so, the staging deploy should not remove it)

Can anyone explain how this is done? I've included my current configuration, below, in case it's helpful.

Versions

  • capistrano: 3.3.5
  • whenever: 0.9.4
  • ruby: 2.1.5
  • rails: 3.2.21

Capfile

require 'whenever/capistrano'

Relevant line in config/deploy/deploy.rb

set :application, 'application_name'

config/deploy/production.rb

server '1.2.3.4', user: 'username', roles: %w{web app}
set :branch, 'master'
set :deploy_to, '/home/username/production'
set :rails_env, 'production'
set :stage, :production
set :whenever_environment, -> { fetch(:stage) }
set :whenever_identifier, -> { "#{fetch(:application)}_#{fetch(:stage)}" }

config/deploy/staging.rb

server '1.2.3.4', user: 'username', roles: %w{web app}
set :branch, 'staging'
set :deploy_to, '/home/username/staging'
set :rails_env, 'staging'
set :stage, :staging
set :whenever_environment, -> { fetch(:stage) }
set :whenever_identifier, -> { "#{fetch(:application)}_#{fetch(:stage)}" }

config/schedule.rb

set :output, '/log/cron.log'
every 10.minutes do
  runner 'ModelName.method_name'
end

The resulting cronjob after a staging deploy

# Begin Whenever generated tasks for: application_name
0,10,20,30,40,50 * * * * /bin/bash -l -c 'cd /home/username/staging/releases/20150317012814 && script/rails runner -e staging '\''ModelName.method_name'\'' >> /log/cron.log 2>&1'

# End Whenever generated tasks for: application_name
1

There are 1 best solutions below

1
Philip Hallstrom On

You don't have any comment blocks surrounding the actual cron jobs? I have an old Rails 3 app that uses this (and just this) and it works. Maybe it will help:

config/deploy.rb:set :whenever_environment, defer { stage }
config/deploy.rb:set :whenever_identifier, defer { "#{application}_#{stage}" }
config/deploy.rb:set :whenever_command, 'bundle exec whenever'