Capistrano deploy and assets:precompile too slow - ruby-on-rails

"rake assets:precompile" and "cap deploy" consume extremely high amount of time whenever I call it (usually more then an hour). Sometimes deploy hang at all.
I use Rails 3.2.13, Ruby 1.9.3, OSX and Backbone's Chaplin Framework for frontend.
How can I speed up assets precompile and deploy task and what can cause such freezing?
My deploy.rb config:
# -*- encoding : utf-8 -*-
require 'bundler/capistrano'
load 'deploy/assets'
set :application, "eyelashes"
set :rails_env, "production"
set :repository, "git#github.com:eyelasher/repo.git"
set :scm, :git
set :deploy_via, :checkout
set :ssh_options, { :forward_agent => true }
default_run_options[:pty] = true
server "75.223.145.3", :app, :web, :db, :primary => true
set :bundle_without, [:test]
set :user, 'deployer'
set :deploy_to, "/home/deployer/eyelasher"
set :branch, "master" unless exists?(:branch)
set :use_sudo, false
set :rvm_type, :user
set :rvm_ruby_string, :local
set :deploy_via, :checkout
before 'deploy:setup', 'rvm:create_gemset'
set :unicorn_conf, "#{deploy_to}/current/config/unicorn.rb"
set :unicorn_pid, "#{deploy_to}/shared/pids/unicorn.pid"
after "deploy", "deploy:migrate"
after "deploy", "deploy:cleanup"
require 'rvm/capistrano'
require 'thinking_sphinx/deploy/capistrano'
#after 'deploy:update_code', :roles => :app do
#run "rm -f #{current_release}/config/database.yml"
#run "ln -s #{deploy_to}/shared/config/database.yml #{current_release}/config/database.yml"
#end
namespace :deploy do
task :restart do
run "if [ -f #{unicorn_pid} ]; then kill -USR2 `cat #{unicorn_pid}`; else cd #{deploy_to}/current && bundle exec unicorn -c #{unicorn_conf} -E #{rails_env} -D; fi"
end
task :start do
run "cd #{deploy_to}/current && bundle exec unicorn -c #{unicorn_conf} -E #{rails_env} -D;"
end
task :stop do
run "if [ -f #{unicorn_pid} ] && [ -e /proc/$(cat #{unicorn_pid}) ]; then kill -QUIT `cat #{unicorn_pid}`; fi"
end
end
# Thinking Sphinx typing shortcuts
namespace :ts do
task :conf do
thinking_sphinx.configure
end
task :in do
thinking_sphinx.index
end
task :start do
thinking_sphinx.start
end
task :stop do
thinking_sphinx.stop
end
task :restart do
thinking_sphinx.restart
end
task :rebuild do
thinking_sphinx.rebuild
end
end
# http://github.com/jamis/capistrano/blob/master/lib/capistrano/recipes/deploy.rb
# :default -> update, restart
# :update -> update_code, symlink
namespace :deploy do
desc "Link up Sphinx's indexes."
task :symlink_sphinx_indexes, :roles => [:app] do
run "ln -nfs #{shared_path}/db/sphinx #{release_path}/db/sphinx"
end
task :activate_sphinx, :roles => [:app] do
symlink_sphinx_indexes
thinking_sphinx.configure
#thinking_sphinx.stop
#thinking_sphinx.start
end
task :copy_images do
run "cp -R #{shared_path}/public/images #{release_path}/public/images"
end
before 'deploy:update_code', 'thinking_sphinx:stop'
after 'deploy:update_code', 'deploy:activate_sphinx'
after 'deploy:update_code', 'deploy:copy_images'
end
Maybe I can speedup somehow by making changes in deploy configuration?

If you are deploying to a memory constrained VPS that sounds plausible. I'd recommend precompiling the assets on a a faster machine and checking them in to your repository.
There are various Gems and packages for speeding up asset precompilation by parallesing them, however in your situation that will likely make things MUCH worse!

Related

Capistrano Rollback breaking Whenever Cronjob

The issue seems to be that during a capistrano deploy the created cron job has RAILS_ENV=staging as expected since the deployment environment is staging. However, in a capistrano rollback the created cron job has RAILS_ENV=new_staging where new_staging is the capistrano stage being rolled back.
my schedule file
set :job_template, nil
job_type :rake, "cd :path && :environment_variable=:environment bundle exec rake :task :output"
every 15.minute, roles: [:db] do
rake "jobs:publish", output: lambda { "2>&1 >> /path/to/capistrano_directory/shared/log/jobs.log" }
end
My deploy/new_staging.rb file
set :branch, "develop"
set :deploy_env, 'staging'
set :rails_env, 'staging'
server "user#server_ip", :web, :app, :db, :metrics
role :db, "user#server_ip", :primary => true # This is where Rails migrations will run
ssh_options[:forward_agent] = false # use local SSH keys remotely
ssh_options[:paranoid] = false
set :use_sudo, false
set :deploy_to, "/path/to/capistrano_directory"
set :unicorn_conf, "#{deploy_to}/current/config/environments/#{deploy_env}/unicorn.rb"
set :unicorn_pid, "#{deploy_to}/shared/pids/unicorn.pid"
before 'deploy:finalize_update', 'set_current_release'
before "deploy:finalize_update", "deploy:update_crontab"
after 'deploy:update_code', 'deploy:symlink_db'
namespace :deploy do
task :symlink_db, :roles => :app do
run "ln -nfs #{deploy_to}/shared/config/database.yml #{release_path}/config/database.yml"
end
task :start, :roles => :app, :except => { :no_release => true } do
run "cd #{deploy_to}/current && bundle exec unicorn -c #{unicorn_conf} -E #{deploy_env} -D"
end
task :stop do
run "#{try_sudo} kill -QUIT `cat #{unicorn_pid}`"
end
task :restart, :roles => :app, :except => { :no_release => true } do
run "#{try_sudo} kill -s USR2 `cat #{unicorn_pid}`"
end
end
task :set_current_release, :roles => :app, :except => { :no_release => true } do
set :current_release, latest_release
end
And my deploy.rb
require 'bundler/capistrano'
require 'capistrano/ext/multistage'
set :whenever_command, "bundle exec whenever"
set :whenever_environment, defer { stage }
set :whenever_roles, [:db, :metrics]
require "whenever/capistrano"
set :stages, %w(production staging new_staging)
set :application, "###"
set :repository, "###"
set :deploy_via, :remote_cache
set :scm, :git
default_run_options[:shell] = '/bin/bash --login'
ssh_options[:forward_agent] = false
ssh_options[:paranoid] = false
namespace :deploy do
desc "Update the crontab file"
task :update_crontab do
run "cd #{release_path} && RAILS_ENV=#{fetch(:rails_env)} bundle exec whenever --update-crontab #{application} --set environment=#{fetch(:rails_env)}"
end
end
Whenever Version (0.9.7)
Capistrano Version (2.12.0)
What is causing the rollback to use the capistrano stage instead of the rails_env when running Whenever gem? And how can I get it to properly use the rails_env?
I'm a little confused by your staging setup (what is the difference between staging and new_staging?). That said, you should be able to do this by changing your whenever_environment to use rails_env instead of the stage value set by capistrano:
so
set :whenever_environment, defer { stage }
Would become:
set :whenever_environment, defer { rails_env }
whenever README

Going Through a Deployment Railscast Recipes Looking for RVM

I spent hours on this railscast, http://railscasts.com/episodes/335-deploying-to-a-vps and this tutorial, https://coderwall.com/p/yz8cha(which is based on the railscast)
I am getting this when I do cap deploy:setup or bundle exec cap deploy:setup
I am not quite familiar with the scripts used on the railscast, mainly copy and paste/augment path (insert username/projectname) on the root path. I suspect that I configured the scripts incorrectly?
cap deploy:setup
triggering load callbacks
* 2013-09-06 01:21:56 executing `deploy:setup'
* executing "mkdir -p /home/deployer2/apps/lintong /home/deployer2/apps/lintong/releases /home/deployer2/apps/lintong/shared /home/deployer2/apps/lintong/shared/system /home/deployer2/apps/lintong/shared/log /home/deployer2/apps/lintong/shared/pids"
servers: ["192.241.241.204"]
[192.241.241.204] executing command
** [out :: 192.241.241.204] bash: /home/deployer2/.rvm/bin/rvm-shell: No such file or directory
command finished in 9ms
failed: "rvm_path=$HOME/.rvm $HOME/.rvm/bin/rvm-shell 'default' -c 'mkdir -p /home/deployer2/apps/lintong /home/deployer2/apps/lintong/releases /home/deployer2/apps/lintong/shared /home/deployer2/apps/lintong/shared/system /home/deployer2/apps/lintong/shared/log /home/deployer2/apps/lintong/shared/pids'" on 192.241.241.204
here is my deploy.rb file
require "bundler/capistrano"
require "rvm/capistrano"
server "192.241.241.204", :web, :app, :db, primary: true
set :application, "lintong"
set :user, "deployer2"
set :port, 7000
set :deploy_to, "/home/#{user}/apps/#{application}"
set :deploy_via, :remote_cache
set :use_sudo, false
set :scm, "git"
set :repository, "git#github.com:Jngai/#{application}.git"
set :branch, "master"
default_run_options[:pty] = true
ssh_options[:forward_agent] = true
after "deploy", "deploy:cleanup" # keep only the last 5 releases
namespace :deploy do
%w[start stop restart].each do |command|
desc "#{command} unicorn server"
task command, roles: :app, except: {no_release: true} do
run "/etc/init.d/unicorn_#{application} #{command}"
end
end
task :setup_config, roles: :app do
sudo "ln -nfs #{current_path}/config/nginx.conf /etc/nginx/sites-enabled/#{application}"
sudo "ln -nfs #{current_path}/config/unicorn_init.sh /etc/init.d/unicorn_#{application}"
run "mkdir -p #{shared_path}/config"
put File.read("config/database.example.yml"), "#{shared_path}/config/database.yml"
puts "Now edit the config files in #{shared_path}."
end
after "deploy:setup", "deploy:setup_config"
task :symlink_config, roles: :app do
run "ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml"
end
after "deploy:finalize_update", "deploy:symlink_config"
desc "Make sure local git is in sync with remote."
task :check_revision, roles: :web do
unless `git rev-parse HEAD` == `git rev-parse origin/master`
puts "WARNING: HEAD is not the same as origin/master"
puts "Run `git push` to sync changes."
exit
end
end
before "deploy", "deploy:check_revision"
end
its looking for rvm in the wrong place? its living in usr/local. is anyone familiar with deployment using Capistrano ?
I was lacking this in my deploy.rb
set :rvm_ruby_string, :local # use the same ruby as used locally for deployment
before 'deploy:setup', 'rvm:install_rvm' # install/update RVM
before 'deploy:setup', 'rvm:install_ruby' # install Ruby and create gemset, OR:

Rails app deployment with capistrano Killing assets precompile

on cap deploy:cold ro cap deploy, is triggered an error
[out :: xxx.xxx.xxx.xxx] Killed
command finished in 9020ms
*** [deploy:update_code] rolling back
* executing [#<Capistrano::Command::Tree::ElseBranch:0x00000100dc5478 #condition="else", #command="rm -rf /home/yasinishyn/apps/mkv/releases/20130506084016; true", #callback=#<Proc:0x00000100dd5da0#/usr/local/rvm/gems/ruby-2.0.0-p0/gems/capistrano-2.15.3/lib/capistrano/configuration/actions/invocation.rb:13>, #options={}, #skip=false>]
servers: ["xxx.xxx.xxx.xxx"]
[xxx.xxx.xxx.xxx] executing command
command finished in 386ms
failed: "sh -c 'cd -- /home/yasinishyn/apps/mkv/releases/20130506084016 && bundle exec rake RAILS_ENV=production RAILS_GROUPS=assets assets:precompile'" on xxx.xxx.xxx.xxx
I have tryed many advises from stack, but nosing works for me.
my deploy.rb
deploy.rb:
require "bundler/capistrano"
server "xxx.xxx.xxx.xxx", :web, :app, :db, primary: true
set :application, "app"
set :user, "user"
set :deploy_to, "/home/#{user}/apps/#{application}"
set :deploy_via, :remote_cache
set :use_sudo, false
set :scm, "git"
set :repository, "git#github.com:git_user/#{application}.git"
set :branch, "master"
default_run_options[:pty] = true
ssh_options[:forward_agent] = true
after "deploy", "deploy:cleanup" # keep only the last 5 releases
namespace :deploy do
%w[start stop restart].each do |command|
desc "#{command} unicorn server"
task command, roles: :app, except: {no_release: true} do
run "/etc/init.d/unicorn_#{application} #{command}"
end
end
task :setup_config, roles: :app do
sudo "ln -nfs #{current_path}/config/nginx.conf /etc/nginx/sites-enabled/#{application}"
sudo "ln -nfs #{current_path}/config/unicorn_init.sh /etc/init.d/unicorn_#{application}"
run "mkdir -p #{shared_path}/config"
put File.read("config/database.example.yml"), "#{shared_path}/config/database.yml"
puts "Now edit the config files in #{shared_path}."
end
after "deploy:setup", "deploy:setup_config"
task :symlink_config, roles: :app do
run "ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml"
end
after "deploy:finalize_update", "deploy:symlink_config"
desc "Make sure local git is in sync with remote."
task :check_revision, roles: :web do
unless `git rev-parse HEAD` == `git rev-parse origin/master`
puts "WARNING: HEAD is not the same as origin/master"
puts "Run `git push` to sync changes."
exit
end
end
before "deploy", "deploy:check_revision"
#rake seed task
desc "Seed the database on already deployed code"
task :seed, :only => {:primary => true}, :except => { :no_release => true } do
run "cd #{current_path}; RAILS_ENV=#{rails_env} bundle exec rake db:seed"
end
desc "Seed the database on already deployed code"
task :drop, :only => {:primary => true}, :except => { :no_release => true } do
run "cd #{current_path}; RAILS_ENV=#{rails_env} bundle exec rake db:drop:all"
run "cd #{current_path}; RAILS_ENV=#{rails_env} bundle exec rake db:create:all"
run "cd #{current_path}; RAILS_ENV=#{rails_env} bundle exec rake db:migrate"
end
end
in my production.rb I have
config.assets.compress = true
and my capfile
load 'deploy'
# Uncomment if you are using Rails' asset pipeline
load 'deploy/assets'
Dir['vendor/gems/*/recipes/*.rb','vendor/plugins/*/recipes/*.rb'].each { |plugin| load(plugin) }
load 'config/deploy' # remove this line to skip loading any of the default tasks
local precompile with "bundle exec rake assets:precompile RAILS_ENV=production --trace" executes without any errors.
Where is my mistake? Hot to debug it? Or maybe somewhere is some log file for capistano in which a can look for more details?
I find an answer by my own
delete "load 'deploy/assets'" from capfile, and run
cap deploy:cold
this will work without an error, but only on initial deploy. Then as usual "sudo service nginx restart" on server, and add back deleted snippet.
And BAMM!! It works :)
You are out of RAM by the sounds of it, this question and answer helped me out - I increased the swap on digital ocean server and everything worked fine: deploy with capistrano failing
For anyone who face the same problem and Andrey answer don't work stop the server "sudo service nginx stop" then cap deploy and then start the server again "sudo service nginx start". It worked for me.

Capistrano Deploy Error

I've recently had to make some updates to an app that I haven't touched in about a year. When attempting to deploy with Capistrano (via Github), I get this error:
[deploy:update_code] exception while rolling back: IOError, closed stream
Full logged error here: https://gist.github.com/2829751
I reinstalled my server's SSH key after the Github SSH security scare. Nothing should have changed on the remote server, and deploying worked fine previously. The only significant change on my local system is moving to RVM.
Any ideas what's causing the error?
Here's my deploy.rb file, if that helps:
default_run_options[:pty] = true
set :domain, 'xxx.xxx.xxx'
set :repository, "XXX MY REPO XXX"
set :branch, 'master'
set :password, 'XXXXXXX'
set :deploy_to, "/var/www/#{domain}"
set :scm, :git
set :repository_cache, "git_cache"
set :deploy_via, :remote_cache
ssh_options[:paranoid] = false
set :user, "XXX"
set :runner, user
set :use_sudo, true
set :rails_env, 'production'
role :app, domain # multiple domains can be added here for parallel deployment (i.e. test_app)
role :web, domain
role :db, domain, :primary => true
namespace :deploy do
task :start, :roles => :app do
run "touch #{release_path}/tmp/restart.txt"
end
task :stop, :roles => :app do
# Do nothing.
end
desc "Restart Application"
task :restart, :roles => :app do
run "touch #{release_path}/tmp/restart.txt"
end
end
deploy.task :cold do
deploy.update
deploy.create_db
deploy.migrate
deploy.restart # Change to start if we're using mongrels
end
after "deploy:update_code", :update_config
after "deploy:restart", "delayed_job:restart"
after "deploy", "deploy:cleanup"
#links config files from shared to the release path and mongrel path after deployment
desc "Create all symlinks and files needed for app activation ofter deployment"
task :update_config, :roles => :web do
run "ln -s -f /var/www/#{domain}/shared/database.yml #{release_path}/config/database.yml"
run "ln -s -f /var/www/#{domain}/shared/app.yml #{release_path}/config/app.yml"
run "ln -s -f /var/www/#{domain}/shared/cache #{release_path}/public/cache"
run "ln -s -f /var/www/#{domain}/shared/survey_cache #{release_path}/public/surveys"
run "ln -s -f /var/www/#{domain}/shared/surveys #{release_path}/surveys"
end
desc "changes ownership to cbdsm:git"
task :update_permissions, :roles => :web do
sudo "chown -R #{user}:git /var/www/#{domain}"
end
namespace :delayed_job do
desc "Start the delayed_job process"
task :start, :roles => :app do
run "cd #{current_path} && RAILS_ENV=#{rails_env} script/delayed_job -n 3 start"
end
desc "Stop the delayed_job process"
task :stop, :roles => :app do
run "cd #{current_path} && RAILS_ENV=#{rails_env} script/delayed_job stop"
end
desc "Restart the delayed_job process"
task :restart, :roles => :app do
delayed_job.stop
delayed_job.start
end
end
UPDATE: This seems to be a problem set :use_sudo, true. Removing that line and any commands which require sudo seemed to fix the problem. It's still not entirely clear to me what changed--that made that line problematic. It worked fine before.
Additionally, I removed the default_run_options[:pty] = true line.
As posted above:
This seems to be a problem set :use_sudo, true. Removing that line and any commands which require sudo seemed to fix the problem. It's still not entirely clear to me what changed--that made that line problematic. It worked fine before.
Additionally, I removed the default_run_options[:pty] = true line.
In these cases post the /config/deploy.rb would help...
BTW, how do you set the :deploy_via setting? Try to change this to :remote_cache (from :copy):
set :deploy_via, :remote_cache
and see what happens.

Sudo doesn't have access to shell commands when deploying with Capistrano

I'm deploying my Rails 3 app using capistrano.
I have on user (deploy) who's been added to sudoers. This is the user I'm deploying with.
When I log on to the server as deploy I have access to all of the gem commands I need .ie: bundle, whenever etc.
Capistrano seems to be running as sudo though, and when I try:
sudo whenever
I get
sudo: whenever: command not found
This means each time I try to deploy, it fails and rolls back.
I've tried setting :use_sudo to false in my deploy.rb file but still no luck
set :user, "deploy"
set :runner, user
set :use_sudo, false
Any suggestions?
Here's my complete deploy script in case there's anything in there I've missed:
require 'config/boot'
require 'hoptoad_notifier/capistrano'
require 'capistrano/ext/multistage'
require "whenever/capistrano"
#
set :whenever_command, "bundle exec whenever"
set :application, "MYAPP"
set :repository, "git#github.com:myAccount/myRepos.git"
# only keep 3 previous releases after cleanup
set :keep_releases, 3
set :scm, "git"
set :scm_user, "me"
set :branch, lambda {rails_env}
set :deploy_to, lambda {"/var/www/#{application}/#{rails_env}"}
default_run_options[:pty] = true
role :web, "xxx.xxx.xxx.xxx" # Your HTTP server, Apache/etc
role :app, "xxx.xxx.xxx.xxx" # This may be the same as your `Web` server
role :db, "xxx.xxx.xxx.xxx", :primary => true # This is where Rails migrations will run
set :user, "deploy"
set :runner, user
set :use_sudo, false
ssh_options[:paranoid] = false
ssh_options[:port] = 22
namespace :deploy do
task :start do ; end
task :stop do ; end
task :restart, :roles => :app do
run " touch #{File.join(current_path,'tmp','restart.txt')}"
end
end
namespace :bundle do
desc "run bundle install"
task :install do
run "cd #{current_release} && bundle install"
end
end
namespace :tail do
desc "Tail the current environment's log file"
task :log, :roles => :app do
stream "tail -f #{shared_path}/log/#{rails_env}.log"
end
desc "Tail the new relic log file"
task :new_relic, :roles => :app do
stream "tail -f #{shared_path}/log/new_relic.log"
end
end
before "deploy:restart", "bundle:install"
after "deploy:restart", "deploy:cleanup"
after "deploy:restart", "whenever:update_crontab"
on server run which whenever or whereis whenever you should get full path to the command put it into script:
set :whenever_command, "path_to-whenever"
It's not clean solution but might work.
Another solution might be sudo reconfiguration, go to /etc/sudoers and have a look on env_keep adding PATH might have been important, to keep all the stuff important for application you could use rvm, capistrano-rvm integration and put all the displayed variables from rvm info to env_keep, theoreticaly it should work, just be careful to not mess anything

Resources