Creating a Capistrano task that performs different tasks based on role
The standard way to do this in Capistrano:
task :whatever, :roles => [:x, :y, :z] do
x_tasks
y_tasks
z_tasks
end
task :x_tasks, :roles => :x do
#...
end
task :y_tasks, :roles => :y do
#...
end
task :z_tasks, :roles => :z do
#...
end
So yes, you do need to write separate tasks, but you can call them from a parent task and they will filter appropriately.
Can Capistrano set variables based on a role?
There is no way to have custom variable values per role.
You can instead use the multistage extension from capistrano-ext to have different stages for your two different roles.
If different stages doesn't make sense for your deployment, you could write your own bundle:install task and run different commands based on roles
run "bundle --deployment --quiet", :roles => :web
run "bundle --deployment", :roles => :app
As noted in the comment below, this approach, however, will raise errors if the role does not have a server defined. It will also run each command serially. To work around both those issues, use the parallel helper.
parallel do |session|
session.when 'in?(:web)', "bundle --deployment --quiet"
session.when 'in?(:app)', "bundle --deployment"
end
Capistrano duplicate tasks for each role
Have a look at the multistage extension. While fairly easy to set up the tasks you need yourself, the multistage extension will do it all for you.
If you'd rather do it yourself, see the calling tasks section of the handbook. The trick is that you can invoke different tasks in order from the command line.
How to run a capistrano task within a whenever task?
Jan, you may find documentation very useful https://github.com/javan/whenever. The code example below - I just copied and edited it from the doc.
schedule.rb
# run this task only on servers with the :app role in Capistrano
# see Capistrano roles section below
every :day, at: '12:20am', roles: [:web] do
rake "app_server:task"
end
lib/tasks/test_task.rb
namespace :my_app do
desc 'test'
task :test do
puts "the task runs"
end
end
I believe it's easier to create Rake task and run it via Whenever. You can choose the Role, so basically you don't need to use Capistrano task (I believe you want to use it just because of Role).
Invoking a capistrano task on another environment
First, I think it is better to use the stage parameter of the cap
command to designate the remote stage servers rather than your local stage servers. This means your command assumes :vagrant
as always being the local stage.
Then if vagrant
stage servers have a role which the remote servers don't have, you can execute different tasks on each stage via the following:
# Assuming the following stage definitions in deploy/production.rb and deploy/vagrant.rb respectively
server 'production.example.com', roles: %w{web app}
server 'vagrant.local', roles: %w{web localhost}
# the following will execute tasks on each host
desc 'sync database'
task :sync_database do
# executed on remote server(s)
on roles(:app) do |host|
# dump database and download it
end
# Load the servers in deploy/vagrant.rb
invoke(:vagrant)
# executed on vagrant box server(s)
on roles(:localhost) do |host|
# Create database and load dump from remote
end
end
This works because roles(...)
returns all servers loaded with the given role and since each stage has a unique role, you can retrieve only what servers you want by specifying their respective role.
Normally, without invoke(:vagrant)
, roles(:localhost)
in the example above wouldn't return anything since Capistrano only loads the servers defined in the given stage by default. To get around this, you can force load servers in your vagrant
stage using invoke(:vagrant)
. So then, roles(:app)
returns the servers for the given stage and roles(:localhost)
returns your vagrant servers.
Related Topics
Rails: Dynamic Columns/Attributes on Models
Micropost's Comments on Users Page (Ruby on Rails)
Why Doesn't Rails' "Errors.Full_Messages" Replace Attribute and Message Variables
Rails: Plus Sign in Get-Request Replaced by Space
Difference Between '%{}', '%Q{}', '%Q{}' in Ruby String Delimiters
Could Not Find 'Cocoapods' (>= 0) Among N Total Gem(S) (Gem::Loaderror)
Error When Doing Rake Db:Migrate on Heroku
Retrieving a Braintree Customer's Subscriptions
How to Determine the Md5 Digest of a Given Asset in the Rails Asset Pipeline
Devise: How to Override Devise Error Messages on Password Change
Rendering a Partial from a Controller in Rails
Factorygirl Association Model Trouble: "Systemstackerror: Stack Level Too Deep"
How to Use the Rails Helper "Distance_Of_Time_In_Words" in Plain Old Ruby (Non-Rails)
Convert an Array of Integers into an Array of Strings in Ruby
Why Pg::Uniqueviolation: Error: Duplicate Key Value Violates Unique Constraint
Failed to Build Gem Native Extension' on Windows 7 (The System Cannot Find the Path Specified)