Where should I put my deployment tasks when using Capistrano? - ruby-on-rails

I'm using Capistrano to deploy apps that I'm building in Sinatra and Rails. For a while now I've been writing all the stuff I need to get done during the deployment right into config/deploy.rb. It looks like I'm just writing Rake here. I was wondering if I could get some advice on if I'm putting these in the right place or if I could be more "Capistranorish" with my deployments.
Here are a few examples of things I'm doing here. I write pretty much everything that I need my deployments to do here.
# deploy.rb
task :initctl_reload_configuration do
on roles(:app), in: :sequence do
execute "sudo initctl reload-configuration"
end
end
task :rebuild_sitemap_no_ping do
on roles(:app), in: :sequence do
execute "cd /srv/app/#{environment}/current && RAILS_ENV=#{environment} bundle exec rake sitemap:refresh:no_ping"
end
end
task :rebuild_sitemap do
on roles(:app), in: :sequence do
execute "cd /srv/app/#{environment}/current && RAILS_ENV=#{environment} bundle exec rake sitemap:refresh"
end
end
task :restart_services do
on roles(:app), in: :sequence do
execute "sudo service tomcat6 restart"
execute "sudo service sunspot-solr restart"
execute "sudo service app-#{environment} restart"
execute "sudo service nginx restart"
end
end

If that's all you got, it might be just fine leaving it in deploy.rb.
If you really want to move those tasks somewhere, below contents of Capfile (you likely have it in the root of your project) should give you a hint:
# Load custom tasks from `lib/capistrano/tasks' if you have any defined
Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }
So just create a file in lib/capistrano/tasks/ ending with .rake and that should do it!

Related

Capistrano not restarting nginx

I have setup Capistrano and eveything is working fine except Capistrano is not restarting passenger after deployment. Eveytime after deployment I have to ssh into server and type touch tmp/restart.txt inside current directory. I tried different ways to restart passenger but nothing is working for me.
first attempt:
namespace :deploy do
task :restart do
on roles(:app) do
run "#{try_sudo} touch #{File.join(current_path,'tmp','restart.txt')}"
end
end
end
second attempt
namespace :deploy do
task :restart do
on roles(:app) do
within current_path do
execute :touch, 'tmp/restart.txt'
end
end
end
end
third attempt
namespace :deploy do
task :restart do
run "touch #{current_path}/tmp/restart.txt"
end
end
I found above code snippets in stackoverflow with similar problem to mine but none of them is restarting the server.
I am using capistrano (3.4.0) with Rails 4 (nginx + passenger)
It could be that your deploy:restart task is not being executed.
Capistrano 3.1.0 and higher (as explained in the Capistrano's CHANGELOG), does not automatically execute deploy:restart at the end of cap deploy.
You must therefore explicitly tell Capistrano to do so, by adding this to your deploy.rb:
after 'deploy:publishing', 'deploy:restart'

bundler: not executable: script/delayed_job

I'm trying to run the following command on my remote server (either via capistrano or ssh):
bundle exec RAILS_ENV=production script/delayed_job start
But I'm getting this error message: bundler: not executable: script/delayed_job
Never saw this before, and google had nothing for me. Any idea what might be the problem?
Maybe it does not have permissions to run? Try running this command
chmod +x script/delayed_job
and then executing the file again.
I am not sure if if it is a fundamental misunderstanding of the capistrano rbenv gem or some issue with the gem itself, but I had similar issue with delayed_job, where the bin/delayed_job file just would not get the executable permission when copied to the server by capistrano. So I wrote a task which I had run before invoking the delayed_job:restart task.
Note - Adding this answer because earlier one is from 2014, and also I wanted to show how to add the task, so the permission change can happen during deployment itself.
Created a task in lib/capistrano/tasks folder (in namespace delayed_job):
namespace :delayed_job do
desc 'Ensure that bin/delayed_job has the permission to be executable. Ideally, this should not have been needed.'
task :ensure_delayed_job_executable do
on roles(delayed_job_roles) do
within release_path do
execute :chmod, :'u+x', :'bin/delayed_job'
end
end
end
end
after 'deploy:publishing', 'deploy:restart'
namespace :deploy do
task :restart do
invoke 'delayed_job:ensure_delayed_job_executable'
invoke 'delayed_job:restart'
end
end

Task to execute migrations after publishing app in Capistrano

There is the following 'deploy.rb' code:
namespace :deploy do
desc 'Restart application'
task :restart do
on roles(:app), in: :sequence, wait: 5 do
# Your restart mechanism here, for example:
execute :touch, release_path.join('tmp/restart.txt')
end
end
after :publishing, :restart
end
This code deploys my app and then restarts my server, but there are some pending migrations after deploy. Can I add task to execute migrations automatically after uploading code? Thanks in advance.
Capistrano 2
If you want to run migrations everytime you deploy, add in your deploy.rb :
after "deploy:update_code", "deploy:migrate"
Or instead of modify deploy.rb, you can call cap deploy:migrations, this will run all pending migrations after your deploy
Capistrano 3
I presume you have installed capistano-rails gem.
If you want to run migrations automaticaly you can required in your Capfile
require 'capistrano/rails/migrations'
Or just run cap deploy:migrate
Sources : https://github.com/capistrano/rails#capistranorails and http://www.talkingquickly.co.uk/2014/01/deploying-rails-apps-to-a-vps-with-capistrano-v3/
Hope this helps

Capistrano 3 sudo task

I want to write a recipe with Capistrano 3 executing a task on the remote server with sudo.
With Capistrano 2 this could be done for example:
default_run_options[:pty] = true
task :hello do
run "#{sudo} cp ~/something /something"
end
With Capistrano 3 I found:
set :pty, true
But I could not get to execute a task running with sudo.
How can I run a task with sudo?
The Capistrano 3 guide recommends the use of passwordless sudo. This allows your less-priveleged user execute the sudo command without having to enter a password via the PTY.
You can use the task that Kentaro wrote above, and add something like the following to your /etc/sudoers file:
deploy ALL=NOPASSWD:/bin/cp ~/something /something
http://www.capistranorb.com/documentation/getting-started/authentication-and-authorisation/#toc_8
I usually write like this:
task :hello do
on roles(:all) do |host|
execute :sudo, :cp, '~/something', '/something'
end
end
Edit
Capistrano 3 does not support sudo with password.
However, I created a small gem, which enables you to use sudo with password in Capistrano 3 task.
Add sshkit-sudo to your application's Gemfile:
# Gemfile
gem 'sshkit-sudo'
And require 'sshkit/sudo' in you Capfile:
# Capfile
require 'sshkit/sudo'
Now, you can execute a command with sudo as follows:
task :hello do
on roles(:all) do
sudo :cp, '~/something', '/something'
end
end
To resolve this issue I needed to add set :pty, true to my deploy.rb file.
I can now run the following:
# config valid only for Capistrano 3.1
lock '3.1.0'
set :application, 'APP_NAME'
set :pty, true
set :ssh_options, {:forward_agent => true}
namespace :deploy do
desc 'Restart NGINX'
task :restart do
on roles(:app), in: :sequence, wait: 1 do
execute :sudo, "./restart.sh"
end
end
end
This task basically runs a shell script called restart.sh that has a command within sudo service nginx restart.
you want "as user do end", like
as "root" do
execute :something
end
If you really need to use sudo you can always map the command like SSHKit.config.command_map[:rm] = 'sudo rm' which will make execute :rm into the proper rm command invoked with sudo. If your deploy user is in the sudoers things will work as expected.

Rails deployment - how do you do rake db:reset with capistrano?

I am using Linode with Ubuntu 10.04 and Capistrano, Unicorn, & Nginx to deploy.
How do I do the equivalent of heroku run rake db:reset with this setup? Is it as simple as cap deploy:cold again to run the migrations?
I've already deployed and want to drop all databases and rerun all the migrations but am not sure which commands to run with this setup to do so.
I wrote a tiny little file you can copy to run arbitrary rake tasks via capistrano: http://jessewolgamott.com/blog/2012/09/10/the-one-where-you-run-rake-commands-with-capistrano/
once setup, you can:
cap sake:invoke task="db:reset"
For Capistrano 3 without actual dropping the database. Use bundle exec cap db:reset
namespace :db do
desc 'Resets DB without create/drop'
task :reset do
on primary :db do
within release_path do
with rails_env: fetch(:stage) do
execute :rake, 'db:schema:load'
execute :rake, 'db:seed'
end
end
end
end
end
You could add the following to your deploy.rb file
namespace :custom do
task :task do
run "cd #{current_path} && bundle exec rake db:reset RAILS_ENV=#{rails_env}"
end
end
Then run cap custom:task to clear the database.
If you are using Capistrano 3, consider using the capistrano-rails-collection.
You can also use copy the code directly from db.rake file from the repository.
Or, if you want a full-fledged solution to run all your rake tasks on a remote server, check out the Cape gem.

Resources