Skip to content

Instantly share code, notes, and snippets.

@dsandstrom
Forked from twetzel/deploy.rb
Last active December 26, 2019 22:17
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save dsandstrom/4e6d118b4ca22e0fc7d40d40c5a8f22d to your computer and use it in GitHub Desktop.
Save dsandstrom/4e6d118b4ca22e0fc7d40d40c5a8f22d to your computer and use it in GitHub Desktop.
Compile assets locally with capistrano 3.5.0 and rails 4.2.x (Nginx-Unicorn zero downtime)
# Runs rake assets:clean
# Defaults to nil (no asset cleanup is performed)
# If you use Rails 4+ and you'd like to clean up old assets after each deploy,
# set this to the number of versions to keep
set :keep_assets, 2
# Clear existing task so we can replace it rather than "add" to it.
Rake::Task["deploy:compile_assets"].clear
namespace :deploy do
desc 'Compile assets'
task :compile_assets => [:set_rails_env] do
# invoke 'deploy:assets:precompile'
invoke 'deploy:assets:copy_manifest'
invoke 'deploy:assets:precompile_local'
invoke 'deploy:assets:backup_manifest'
end
namespace :assets do
local_dir = "./public/assets/"
# Download the asset manifest file so a new one isn't generated. This makes
# the app use the latest assets and gives Sprockets a complete manifest so
# it knows which files to delete when it cleans up.
desc 'Copy assets manifest'
task copy_manifest: [:set_rails_env] do
on roles(fetch(:assets_roles, [:web])) do
remote_dir = "#{fetch(:ssh_options).fetch(:user)}@#{host.hostname}:#{shared_path}/public/assets/"
run_locally do
begin
execute "mkdir #{local_dir}"
execute "scp '#{remote_dir}.sprockets-manifest-*' #{local_dir}"
rescue
# no manifest yet
end
end
end
end
desc "Precompile assets locally and then rsync to web servers"
task :precompile_local do
# compile assets locally
run_locally do
execute "RAILS_ENV=#{fetch(:stage)} bundle exec rake assets:precompile"
end
# rsync to each server
on roles(fetch(:assets_roles, [:web])) do
# this needs to be done outside run_locally in order for host to exist
remote_dir = "#{fetch(:ssh_options).fetch(:user)}@#{host.hostname}:#{shared_path}/public/assets/"
run_locally do
execute "rsync -av #{local_dir} #{remote_dir}"
end
end
# clean up
run_locally { execute "rm -rf #{local_dir}" }
end
end
end
@dsandstrom
Copy link
Author

Downloads the manifest file before compiling locally. This way, a new manifest is not generated. This makes the app always use the latest assets and gives Sprockets a complete list of old assets that it can clean up.

@jkarnesPerfectCube
Copy link

jkarnesPerfectCube commented Feb 20, 2017

Consider amending fetch(:user) to fetch(:ssh_options).fetch(:user) to match latest capistrano SSH settings. This is how our SSHKit hash is set up:

# Global options
# --------------
 set :ssh_options, {
   user: "dev",
   keys: %w(/home/justin/.ssh/<REDACTED>),
   forward_agent: true,
   auth_methods: %w(publickey)
   # password: "please use keys"
 }

@dsandstrom
Copy link
Author

Seems to require ungrouping the therubyracer gem, if you use it. I had it in the production group, but had problems precompiling until I moved the gem out of the group.

@dsandstrom
Copy link
Author

@jkarnesPerfectCube Excellent point. I had:

set :user, 'deploy'
set :ssh_options, user: fetch(:user)

so I didn't experience the bug.

@charusat09
Copy link

if anyone using pem file instead of ssh then refer this: https://gist.github.com/charusat09/eda660d4f8cb587d26c937d72d4ffa48

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment