Skip to content

Instantly share code, notes, and snippets.

@toekneestuck
Forked from fstrube/Rakefile
Created June 8, 2012 14:42
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save toekneestuck/2895972 to your computer and use it in GitHub Desktop.
Save toekneestuck/2895972 to your computer and use it in GitHub Desktop.
Rake tasks for deploying a web app via rsync, and comparing local / remote file changes
CONFIG = {
## -- Rsync Deploy config -- ##
# Be sure you have setup public / private key authentication
:ssh_host => "user@hostname", # The hostname can be an alias in ~/.ssh/config
:ssh_port => nil, # Default - use ~/.ssh/config
:document_root => "/var/www", # Remote document root
:rsync_delete => true, # Whether or not to delete remote files
:deploy_default => "rsync", # Not used
:restart_apache => nil, # Remote command to restart apache
## -- Misc Configs -- ##
:site_dir => "." # Local site directory (sync this folder to the remote document_root)
}
## -- Rake Tasks -- ##
desc "Deploy website via rsync (e.g. rake deploy [path=...] [options=<extra rsync options>])"
task :deploy do
# Run commands
puts "## Deploying website via Rsync"
puts "-----------\nCommand: #{rsync_command '--dry-run'}\n-----------"
system(rsync_command '--dry-run')
# Prompt for continuance
puts
proceed = get_stdin "The above actions will be taken. Continue? (This cannot be undone) [No]: "
# The real deal
if "y yes".split.include? proceed.downcase
ok_failed system(rsync_command)
if CONFIG[:restart_apache]
restart_apache, ssh_port, ssh_host = CONFIG.values_at :restart_apache, :ssh_port, :ssh_host
puts
puts "## Restarting Apache server"
ok_failed system("ssh #{"-p "+ssh_port.to_s unless ssh_port == nil} #{ssh_host} '#{restart_apache}'")
end
else
puts "Deployment cancelled by user."
end
end
namespace :remote do
desc "Connect to the remote console"
task :console do
puts "## Initializing remote console"
puts "----------\nCommand: #{ssh_command}\n----------"
system(ssh_command)
end
desc "Show differences between local and remote files"
task :diff do
document_root, site_dir = CONFIG.values_at :document_root, :site_dir
# Get the local path
local_path = ENV['path'] ? ENV['path'] : site_dir
if File.exists?(local_path)
local_path = File.expand_path(local_path)
local_path = local_path + '/' if File.directory?(local_path)
end
# Build the remote path
remote_path = "#{document_root}/#{local_path.sub(File.expand_path(site_dir), '')}".gsub(/\/+/, '/')
# Files get compared straight-up
if File.file?(local_path)
system(%Q:bash -c 'diff -Naur#{'w' unless ENV['ignorewhitespace'].nil?} "#{local_path}" <(#{ssh_command "cat #{remote_path}"})':)
# Directories process each file
else
changes = `#{rsync_command '--dry-run'}`
num_changes = changes.lines.count
proceed = get_stdin "#{changes.lines.count} file(s) will be compared. Continue? [No]: " if num_changes > 10
if proceed == nil or "y yes".split.include? proceed.downcase
changes.each_line do |line|
action, file = line.chomp.split(' ', 2)
system %Q:bash -c 'diff -Naur#{'w' unless ENV['ignorewhitespace'].nil?} "#{local_path + file}" <(#{ssh_command "cat #{remote_path + file}"})':
end
end
end
end
end
## -- Utility functions -- ##
def ssh_command(command=nil)
ssh_port, ssh_host = CONFIG.values_at :ssh_port, :ssh_host
"ssh #{"-p "+ssh_port.to_s unless ssh_port == nil} #{ssh_host} #{%Q'"#{command}"' unless command == nil}"
end
def rsync_command(options=nil)
document_root, rsync_delete, site_dir, ssh_port, ssh_host =
CONFIG.values_at :document_root, :rsync_delete, :site_dir, :ssh_port, :ssh_host
# Get the local path
local_path = ENV['path'] ? ENV['path'] : site_dir
if File.exists?(local_path)
local_path = File.expand_path(local_path)
local_path = local_path + '/' if File.directory?(local_path)
end
# Build the remote path
remote_path = "#{document_root}/#{local_path.sub(File.expand_path(site_dir), '')}".gsub(/\/+/, '/')
# Exclude file
exclude = ""
if File.exists?('./deploy-exclude')
exclude="--exclude-from '#{File.expand_path('./deploy-exclude')}'"
end
# Build rsync options
rsync_options =
"--archive --no-group --no-owner --no-perms --no-times --update " +
"--human-readable --compress --checksum " +
"--itemize-changes #{exclude} " +
"#{"--rsh='ssh -p #{ssh_port}' " unless ssh_port == nil}" +
"#{"--delete " unless rsync_delete == false}" +
"#{options} #{ENV['options']} " +
"#{local_path} #{ssh_host}:#{remote_path}"
return "rsync #{rsync_options}"
end
def ok_failed(condition)
if (condition)
puts "OK"
else
puts "FAILED"
end
end
def get_stdin(message)
print message
STDIN.gets.chomp
end
def ask(message, valid_options)
if valid_options
answer = get_stdin("#{message} #{valid_options.to_s.gsub(/"/, '').gsub(/, /,'/')} ") while !valid_options.include?(answer)
else
answer = get_stdin(message)
end
answer
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment