Skip to content

Instantly share code, notes, and snippets.

@tomdavies
Created November 27, 2012 12:16
Show Gist options
  • Save tomdavies/4153939 to your computer and use it in GitHub Desktop.
Save tomdavies/4153939 to your computer and use it in GitHub Desktop.
Deploying ExpressionEngine 2 with Capistrano
set :deploy_to, "/var/www/default"
set :branch, 'master'
#Remote DB info
set :dbuser, ""
set :dbname, ""
set :dbhost, ""
set :dbpass, ""
set :deploy_to, "/var/www/staging"
#Remote DB info
set :dbuser, ""
set :dbname, ""
set :dbhost, ""
set :dbpass, ""
# ask you which branch you want to deploy from (defaulting to the most recent tag)
set :branch do
puts `git branch`.split("\n").inspect
default_branch = `git branch`.split("\n").detect{|b| b =~ /^\* / }.gsub(/^\* /, '')
branch = Capistrano::CLI.ui.ask "Branch to deploy (make sure to push the branch first): [#{default_branch}] "
branch = default_branch if branch.empty?
branch
end
namespace :deploy do
desc "Stop bots from indexing the site"
task :deny_robots, :roles => :app do
robots = %q{#Disallow all robots
User-Agent: *
Disallow: /
}
put robots, "#{deploy_to}/current/public/robots.txt"
end
end
################################################################################
# Capistrano recipe for deploying ExpressionEngine websites from Git #
# Adapted from starting point by Dan Benjamin - http://example.com/ #
# #
################################################################################
#configure capistranp for multistage deployment
set :stages, %w(staging production local)
set :default_stage, "staging"
require 'capistrano/ext/multistage'
begin
require 'capistrano/ext/multistage'
rescue LoadError
puts 'Capistrano Extension not found'
puts 'sudo gem install capistrano-ext'
exit
end
# the application name
set :application, "myapp"
# the name hostname of the remote server
set :domain, "www.example.com"
set :port, 40012
# the name of your system directory, which you may have customised
set :ee_system, "system/expressionengine"
# the git-clone url for your repository - branch is set in stage file
set :repository, "[email protected]:user/myapp.git"
# the name of the deployment user-account on the server
set :user, "deployuser"
set :runner, "deployuser"
set :use_sudo, true
default_run_options[:pty] = true
#custom ssh port number
#ssh_options[:port] = 28069
#local development settings
set :local_dbhost, ""
set :local_dbuser, ""
set :local_dbname, ""
set :local_dbpass, ""
#directory for DB dumps
set :dump_directory, "db"
set :no_of_dumps_kept, "10"
#remote directory for uploads grab - relative to :deploy_to path
set :path_to_uploads_dir, "public/uploads"
set :path_to_assets_dir, "public/assets"
# SCM settings
set :scm, :git
#set :ssh_options, { :forward_agent => true }
set :deploy_via, :remote_cache
set :copy_strategy, :checkout
set :keep_releases, 5
set :copy_compression, :bz2
set :copy_exclude, [".git", ".gitignore"]
# Roles
role :app, domain
role :web, domain
role :db, domain, :primary => true
# Deployment process
after "deploy:setup", "deploy:makedirs"
after "deploy", "deploy:cleanup", "deploy:create_symlinks", "deploy:set_permissions"
# Custom deployment tasks
namespace :deploy do
desc "This is here to overide the original :restart"
task :restart, :roles => :app do
# do nothing but override the default
end
task :finalize_update, :roles => :app do
run "chmod -R g+w #{latest_release}" if fetch(:group_writable, true)
# override the rest of the default method
end
desc "Create additional EE directories and set permissions after initial setup"
task :makedirs, :roles => :app do
# create public directory
run "mkdir #{shared_path}/public"
# create upload directories
run "mkdir #{shared_path}/#{path_to_uploads_dir}"
run "mkdir #{shared_path}/#{path_to_uploads_dir}/files"
run "mkdir #{shared_path}/#{path_to_uploads_dir}/images"
run "mkdir #{shared_path}/#{path_to_uploads_dir}/images/banners"
run "mkdir #{shared_path}/#{path_to_uploads_dir}/images/banners/home"
run "mkdir #{shared_path}/#{path_to_uploads_dir}/images/banners/landing"
run "mkdir #{shared_path}/#{path_to_uploads_dir}/images/drivers"
run "mkdir #{shared_path}/#{path_to_uploads_dir}/images/events"
run "mkdir #{shared_path}/#{path_to_uploads_dir}/images/galleries"
run "mkdir #{shared_path}/#{path_to_uploads_dir}/images/modules"
run "mkdir #{shared_path}/#{path_to_uploads_dir}/images/news"
run "mkdir #{shared_path}/#{path_to_uploads_dir}/images/pages"
# set permissions on uploads dirs
run "chmod 755 #{shared_path}/#{path_to_uploads_dir}/files"
run "chmod 755 #{shared_path}/#{path_to_uploads_dir}/images"
run "chmod 755 #{shared_path}/#{path_to_uploads_dir}/images/banners"
run "chmod 755 #{shared_path}/#{path_to_uploads_dir}/images/banners/home"
run "chmod 755 #{shared_path}/#{path_to_uploads_dir}/images/banners/landing"
run "chmod 755 #{shared_path}/#{path_to_uploads_dir}/images/drivers"
run "chmod 755 #{shared_path}/#{path_to_uploads_dir}/images/events"
run "chmod 755 #{shared_path}/#{path_to_uploads_dir}/images/galleries"
run "chmod 755 #{shared_path}/#{path_to_uploads_dir}/images/modules"
run "chmod 755 #{shared_path}/#{path_to_uploads_dir}/images/news"
run "chmod 755 #{shared_path}/#{path_to_uploads_dir}/images/pages"
end
desc "Set the correct permissions for the config files and cache folder"
task :set_permissions, :roles => :app do
sudo "chmod -R 777 #{current_release}/#{path_to_assets_dir}/cache/"
sudo "chmod -R 777 #{current_release}/#{ee_system}/cache"
sudo "chmod -R 777 #{current_release}/#{path_to_uploads_dir}"
end
desc "Create symlinks to shared data such as config files and uploaded images"
task :create_symlinks, :roles => :app do
# upload directories
run "ln -s #{shared_path}/#{path_to_uploads_dir}/ #{current_release}/public/"
run "ln -s #{shared_path}/.htaccess #{current_release}/public/"
end
desc "Clear the ExpressionEngine caches"
task :clear_cache, :roles => :app do
sudo "if [ -e #{current_release}/#{ee_system}/cache/db_cache ]; then rm -r #{current_release}/#{ee_system}/cache/db_cache/*; fi"
sudo "if [ -e #{current_release}/#{ee_system}/cache/lg_cache ]; then rm -r #{current_release}/#{ee_system}/cache/lg_cache/*; fi"
sudo "if [ -e #{current_release}/#{ee_system}/cache/magpie_cache ]; then rm -r #{current_release}/#{ee_system}/cache/magpie_cache/*; fi"
sudo "if [ -e #{current_release}/#{ee_system}/cache/page_cache ]; then rm -r #{current_release}/#{ee_system}/cache/page_cache/*; fi"
sudo "if [ -e #{current_release}/#{ee_system}/cache/sql_cache ]; then rm -r #{current_release}/#{ee_system}/cache/sql_cache/*; fi"
sudo "if [ -e #{current_release}/#{ee_system}/cache/tag_cache ]; then rm -r #{current_release}/#{ee_system}/cache/tag_cache/*; fi"
end
end
namespace :db do
desc "Generates a name for the remote backup file"
task :backup_name do
now = Time.now
run "mkdir -p #{shared_path}/#{dump_directory}/"
backup_time = [now.year, now.month, now.day, now.hour, now.min, now.sec].join('-')
set :backup_file, "#{shared_path}/#{dump_directory}/#{dbname}-snapshot-#{backup_time}.sql"
end
desc "Dumps a database to dump folder"
task :dump do
backup_name
run "mysqldump --add-drop-table -u #{dbuser} -p #{dbname} | bzip2 -c > #{backup_file}.bz2" do |ch, stream, out|
ch.send_data "#{dbpass}\n" if out=~ /^Enter password:/
end
end
#TODO rm cmd not working at the moment
desc "Cleans up remote dump folder"
task :cleanup do
run "cd /#{shared_path}/#{dump_directory}; (ls -t|head -n #{no_of_dumps_kept};ls)|sort|uniq -u|xargs rm"
end
desc "Generates a name for the local backup file"
task :local_backup_name do
now = Time.now
run_locally "mkdir -p #{dump_directory}/development"
backup_time = [now.year, now.month, now.day, now.hour, now.min, now.sec].join('-')
set :local_backup_file, "#{dump_directory}/development/#{local_dbname}-snapshot-#{backup_time}.sql"
end
desc "Performs a local db dump and bzips the result"
task :local_dump do
local_backup_name
run_locally "mysqldump --host=#{local_dbhost} --add-drop-table -u #{local_dbuser} -p#{local_dbpass} #{local_dbname} | bzip2 -c > #{local_backup_file}.bz2"
end
desc "Takes a passed remote sql dump and imports to local db"
task :import_dump do
run_locally "bzcat /tmp/#{application}.sql.bz2 | mysql --host=#{local_dbhost} -u #{local_dbuser} -p#{local_dbpass} #{local_dbname}"
end
#Sync dbs
desc "Dumps the DB from the specified stage, backs up the local DB and imports the remote dump"
task :to_local do
#remove old sql file if exists
if File.exist? "/tmp/#{application}.sql"
run_locally "rm /tmp/#{application}.sql"
end
backup_name
dump
get "#{backup_file}.bz2", "/tmp/#{application}.sql.bz2"
local_backup_name
local_dump
import_dump
end
desc "Pushes the database on to staging - be very sure that you want to do this on production!"
task :deploy_db do
backup_name
dump
local_backup_name
local_dump
upload("#{local_backup_file}.bz2", "#{shared_path}/#{dump_directory}/#{local_dbname}-from-local.bz2", :mode => 0666)
begin
run "cd #{shared_path}/#{dump_directory}/; bzcat #{local_dbname}-from-local.bz2 | mysql -u #{dbuser} -p #{dbname}", options={ :shell => false} do |ch, stream, out|
logger.info "[#{stream}] #{out}"
ch.send_data "#{dbpass}\n" if out=~ /^Enter password:/
end
rescue Exception => error
puts "something broke: #{error}"
end
end
end
namespace :uploads do
desc "Mirrors the remote uploads directory with your local copy, doesn't download symlinks"
task :to_local do
run_locally("rsync -rtzvPO --rsh=ssh --progress #{user}@#{domain}:#{shared_path}/#{path_to_uploads_dir}/ #{path_to_uploads_dir}/")
end
end
namespace :cache do
desc "Clear Asset caches"
task :clear_assets, :roles => :app do
run "if [ -e #{current_release}/#{path_to_assets_dir}/cache ]; then rm -r #{current_release}/#{path_to_assets_dir}/cache/*; fi"
end
end
def time_string
Time.now.strftime("%Y-%m-%d-%H-%M-%S")
end
def delete_files(*args)
run "rm -f #{args.join(' ')}"
end
def delete_directories(*args)
run "rm -rf #{args.join(' ')}"
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment