require 'open3' CONFIG = YAML.load_file("#{Rails.root}/config/depkit_config.yml") deployment_root = CONFIG['deployment_root'] release_dir_name = DateTime.now.strftime('%Y.%m.%d_%H.%M.%S') deploy_task_description = 'Deploy application to production.' # Adding additional ways to call the main deployment task. Intended as a command line convenience, # so all of these should work... # # bundle exec dep # bundle exec depl:dep # bundle exec depl:deploy # desc deploy_task_description task :dep => :environment do Rake::Task['depl:deploy'].invoke end namespace :depl do desc deploy_task_description task :dep => :environment do Rake::Task['depl:deploy'].invoke end desc deploy_task_description task :deploy => :environment do exec_remotely_in_dir( "#{deployment_root}/releases", "git clone #{CONFIG['repository_url']} #{release_dir_name}", 'Cloning repository...' ) exec_remotely_in_dir( "#{deployment_root}/releases/#{release_dir_name}", "bundle install --deployment --frozen --without development test --path=#{deployment_root}/shared/bundle", 'Running Bundler...' ) exec_remotely_in_dir( "#{deployment_root}/releases/#{release_dir_name}", "ln -svf #{deployment_root}/shared/assets #{deployment_root}/releases/#{release_dir_name}/public/assets", 'Linking up asset dir...' ) exec_remotely_in_dir( "#{deployment_root}/releases/#{release_dir_name}", "rm -Rfv ./log && ln -fsv #{deployment_root}/shared/log ./log", 'Linking log dir...' ) exec_remotely_in_dir( "#{deployment_root}/releases/#{release_dir_name}", "ln -fsv #{deployment_root}/shared/system system", 'Linking system dir...' ) exec_remotely_in_dir( deployment_root, "rm -f ./current && ln -fsv ./releases/#{release_dir_name} current", 'Linking system dir...' ) exec_remotely_in_dir( deployment_root, "ls -1dt releases/* | tail -n +#{CONFIG['keep_releases'] + 1} | xargs rm -Rf", "Deleting releases older than the #{CONFIG['keep_releases']} latest..." ) exec_remotely( "cd #{deployment_root}/releases/#{release_dir_name} && bundle exec rake ts:index RAILS_ENV=production && bundle exec rake ts:rebuild RAILS_ENV=production", 'Rebuilding Sphinx indexes...' ) print_to_console('', "\n\n") print_to_console('', "All done!\n\n") print_to_console('', "If you updated your JS, CSS, Sass, etc., don't forget to run `bundle exec rake depl:compile_assets`.\n\n") print_to_console('', "If you added any migrations, don't forget to run `bundle exec rake depl:migrate`.\n\n") end desc 'Compile assets on the production server.' task :compile_assets => :environment do exec_remotely_in_dir( "#{deployment_root}/current", "RAILS_ENV=production bundle exec rake assets:precompile", 'Compiling assets...' ) end desc 'Run migrations on the production server.' task :migrate => :environment do exec_remotely_in_dir( "#{deployment_root}/current", "RAILS_ENV=production bundle exec rake db:migrate", 'Running migrations...' ) end desc 'Roll back to previous release.' task :roll_back => :environment do end desc 'Prepare deployment dirs.' task :prep => :environment do end end def exec_remotely_in_dir(dir, command, announcement = nil) if announcement.present? exec_remotely("cd #{dir} && #{command}", announcement) else exec_remotely("cd #{dir} && #{command}") end end def exec_remotely(command, announcement = nil) remote_command = "ssh -t #{CONFIG['remote_username']}@#{CONFIG['target_server']} '#{command}'" puts '' print_to_console('', announcement) if announcement.present? print_to_console( "/-----<", "Executing: #{remote_command}" ) Open3.popen2e(remote_command) do |stdin, standard_out_and_standard_err_combined, process_status| while line = standard_out_and_standard_err_combined.gets print_to_console("| ", line) end exit_status = process_status.value unless exit_status.success? abort "\\-----> Error executing #{remote_command}" end print_to_console('\----->', process_status.value.inspect) end end def print_to_console(padding = '', message = '') puts sprintf( '%9s %s', padding, message ) end