namespace :shopapp do def deployment_settings target = ENV['target'] || 'production' Rails.configuration.settings['deployment']['default'].to_h.merge( Rails.configuration.settings['deployment'][target].to_h ) end def deployment_targets Rails.configuration.settings['deployment'].to_h.keys - ['default'] end def fetchdb(timestamp) user = deployment_settings['dbuser'] || deployment_settings['user'] server = deployment_settings['dbserver'] || deployment_settings['server'] db_name = deployment_settings['dbname'] || Rails.configuration.database_configuration['production']['database'] dump_filename = "#{db_name}_#{timestamp}.dump" puts "Creating production db backup from #{db_name} to #{dump_filename}..." host_flag = if deployment_settings['dbhost'].present? "-h #{deployment_settings['dbhost']}" end system "ssh #{user}@#{server} 'pg_dump -Fc -c --no-owner #{host_flag} #{db_name} > #{dump_filename}'" mkdir_p Rails.root.join('tmp') puts "Copying to local..." system "scp #{user}@#{server}:#{dump_filename} #{Rails.root.join('tmp')}" end def restoredb(timestamp) db_name = deployment_settings['dbname'] || Rails.configuration.database_configuration['production']['database'] dump_filename = "#{db_name}_#{timestamp}.dump" restoredb_from_file(dump_filename) end def restoredb_from_file(dump_filepath) dev_db_name = Rails.configuration.database_configuration['development']['database'] puts "Restoring to local development database from #{dump_filepath}..." system "pg_restore --no-owner --verbose -c --no-acl -n public --dbname #{dev_db_name} #{Rails.root.join('tmp', dump_filepath)}" puts "Done restoring the database from #{dump_filepath} to local development." end desc 'list existing targets' task targets: :environment do puts deployment_targets.join(', ') end desc 'pull prod db to local dev' task pulldb: :environment do timestamp = Time.now.strftime('%Y%m%d%H%M%S') fetchdb(timestamp) restoredb(timestamp) end desc 'fetch prod db to local tmp folder' task fetchdb: :environment do timestamp = Time.now.strftime('%Y%m%d%H%M%S') fetchdb(timestamp) end desc 'execute command on production server' task run: :environment do ARGV.each { |a| task a.to_sym do ; end } user = deployment_settings['user'] server = deployment_settings['server'] deployment_folder_name = (deployment_settings['folder']) || "#{(Rails.configuration.settings['shopapp_name'] || Rails.application.class.parent_name).to_s.downcase.parameterize.underscore}/current" cmd = %(ssh -t #{user}@#{server} 'cd #{deployment_folder_name}; bash --login -c "#{ARGV[1..-1].join(' ')}"') exec cmd end desc "tails and follows target's log/production.log" task :tail do exec %(target=#{ENV['target']} rake shopapp:run "tail -f log/production.log") end desc "opens bash prompt on target" task :bash do exec %(target=#{ENV['target']} rake shopapp:run "/bin/bash") end desc "opens rails console on target" task :console do exec %(target=#{ENV['target']} rake shopapp:run "rails c") end desc "executes rake task(s) on target" task rake: :environment do exec %(target=#{ENV['target']} rake shopapp:run "rake #{ARGV[1]}") end desc 'help about these rakes tasks' task :help do puts case ENV['cmd'] when 'console' 'Opens rails console on the target. No parameters allowed.' when 'tail' 'Tails main production log on target, until CTRL+C. No parameters allowed.' when 'bash' 'Opens the bash terminal on target with application user in the deployment folder. No parameters allowed.' when 'run' 'Executes on target in deployment directory under deployment user arbitrary command specified by parameters.' when 'rake' "Executes a rake task on target in deployment directory under deployment user.\n" + "First parameter is task name (possiblly with namespace(s)), other parameters are passed to rake task." when 'pulldb' 'Dumps target production database and restores it to local development db. No parameters allowed.' when 'fetchdb' 'Dumps target production database and copies it to local tmp folder.' when 'restoredb' "Restores database dump fetched with fetchdb from tmp folder.\n" + "Parameter is the database name without dump suffix). Default is the latest dump." when 'help' "Com'on, for real!" else "There is no command #{ENV['cmd']}" end end task restoredb: :environment do dump_filepath ||= if ENV['timestamp'] Rails.root.join "tmp/#{deployment_settings['dbname']}_#{ENV['timestamp']}.dump" else ENV['filepath'] || Dir[Rails.root.join("tmp/#{deployment_settings['dbname']}_*.dump")].sort.last end restoredb_from_file(dump_filepath) end end