-
-
Save chipotle/5506641 to your computer and use it in GitHub Desktop.
# Capistrano Laravel 4 Deployment Tasks | |
# Watts Martin (layotl at gmail com) | |
# https://gist.github.com/chipotle/5506641 | |
# updated 14-Aug-2013 | |
# Assumptions: | |
# | |
# - You are using a .gitignore similar to Laravel's default, so your | |
# vendor directory and composer(.phar) are *not* under version control | |
# - Composer is installed as an executable at /usr/local/bin/composer | |
# | |
# If you don't have Composer installed globally, modify the appropriate task | |
# (:composer_install). Or just install Composer globally! | |
set :application, "Application Name" | |
set :repository, "[email protected]:username/project.git" | |
set :scm, :git | |
set :scm_username, "username" | |
role :web, "example.net" | |
role :app, "example.net" | |
role :db, "example.net", :primary => true | |
set :deploy_to, "/opt/nginx/sites/example.net" | |
set :deploy_via, :remote_cache | |
set :use_sudo, false | |
set :ssh_options, {:forward_agent => true} | |
set :copy_exclude, [".git", ".gitignore", ".tags", ".tags_sorted_by_file"] | |
set :keep_releases, 4 | |
# Nginx requires the php_fpm:reload task; other servers may not | |
after :deploy, "php_fpm:reload" | |
namespace :deploy do | |
task :update do | |
transaction do | |
update_code | |
copy_config | |
composer_install | |
link_shared | |
fix_permissions | |
clear_cache | |
cleanup | |
end | |
end | |
task :finalize_update do | |
transaction do | |
run "chmod -R g+w #{releases_path}/#{release_name}" | |
symlink | |
end | |
end | |
task :symlink do | |
transaction do | |
run "ln -nfs #{current_release} #{deploy_to}/#{current_dir}" | |
end | |
end | |
desc "Link Laravel shared directories." | |
task :link_shared do | |
transaction do | |
run "ln -nfs #{shared_path}/system #{current_release}/public/system" | |
end | |
end | |
desc "Run Artisan migrate task." | |
task :migrate do | |
run "php #{current_release}/artisan migrate" | |
end | |
desc "Deploy and execute pending migrations." | |
task :migrations do | |
update_code | |
copy_config | |
composer_install | |
link_shared | |
fix_permissions | |
migrate | |
end | |
desc "Set Laravel storage directory world-writable." | |
task :fix_permissions do | |
transaction do | |
run "chmod -R a+w #{current_release}/app/storage" | |
end | |
end | |
desc "Install dependencies with Composer" | |
task :composer_install do | |
transaction do | |
run "cd #{current_release};/usr/local/bin/composer install --no-dev --no-progress" | |
end | |
end | |
desc "Copy server-specific configuration files." | |
task :copy_config do | |
transaction do | |
run "cp #{shared_path}/config/* #{current_release}/app/config/" | |
end | |
end | |
end | |
# This command is tested on Arch Linux; other distributions/OSes may need a | |
# different configuration (or may not require this at all). | |
namespace :php_fpm do | |
desc "Reload PHP-FPM (requires sudo access to systemctl)." | |
task :reload, :roles => :app do | |
run "sudo /usr/bin/systemctl reload-or-restart php-fpm" | |
end | |
end | |
# Database dump task adapted from https://gist.github.com/rgo/318312 | |
namespace :db do | |
task :backup_name, :roles => :db do | |
now = Time.now | |
run "mkdir -p #{shared_path}/db_backups" | |
backup_time = [now.year, now.month, now.day, now.hour, now.min].join('-') | |
set :backup_file, "#{shared_path}/db_backups/#{database}-#{backup_time}.sql" | |
end | |
desc "Backup MySQL or PostgreSQL database to shared_path/db_backups" | |
task :dump, :roles => :db do | |
run("php -r '$db=include\"#{shared_path}/config/database.php\";echo json_encode($db,JSON_UNESCAPED_SLASHES);'") { |channel, stream, data| @environment_info = YAML.load(data) } | |
default = @environment_info['default'] | |
connection = @environment_info['connections'][default] | |
dbuser = connection['username'] | |
dbpass = connection['password'] | |
database = connection['database'] | |
dbhost = connection['host'] | |
set :database, database | |
backup_name | |
if connection['driver'] == 'mysql' | |
run "mysqldump --add-drop-table -u #{dbuser} -h #{dbhost} -p #{database} | bzip2 -c > #{backup_file}.bz2" do |ch, stream, out | | |
ch.send_data "#{dbpass}\n" if out=~ /^Enter password:/ | |
end | |
else | |
run "pg_dump -W -c -U #{dbuser} -h #{dbhost} #{database} | bzip2 -c > #{backup_file}.bz2" do |ch, stream, out | | |
ch.send_data "#{dbpass}\n" if out=~ /^Password:/ | |
end | |
end | |
end | |
desc "Sync production database to your local workstation" | |
task :clone_to_local, :roles => :db, :only => {:primary => true} do | |
dump | |
get "#{backup_file}.bz2", "/tmp/#{application}.sql.bz2" | |
data = `php -r '$db=include"app/config/database.php";echo json_encode($db,JSON_UNESCAPED_SLASHES);'` | |
development_info = YAML.load(data) | |
default = development_info['default'] | |
connection = development_info['connections'][default] | |
dbuser = connection['username'] | |
dbpass = connection['password'] | |
database = connection['database'] | |
dbhost = connection['host'] | |
if connection['driver'] == 'mysql' | |
run_str = "bzcat '/tmp/#{application}.sql.bz2' | mysql -u #{dbuser} --password='#{dbpass}' -h #{dbhost} #{database}" | |
else | |
run_str = "PGPASSWORD=#{dbpass} bzcat '/tmp/#{application}.sql.bz2' | psql -U #{dbuser} -h #{dbhost} #{database}" | |
end | |
%x!#{run_str}! | |
end | |
end |
should you be linking a file level rollback (deploy:rollback) with a db level rollback (:laravel_rollback)?
IMHO you might not have db migration every time you update your laravel code
ref #101
what i find interesting is that you can use call 'php artisan down' before update and call 'php artisan up' after each update
Railsless-deploy isn't required, no.
And, you're right about the db migration. This is still a work in progress, tweaked when my assumptions collide with the real world. :) The current iteration (as of today) doesn't attempt to do any database rollback -- while that seemed like a good idea when I wrote it, in practice it didn't work. There should probably be a Capistrano task for doing that on remote servers manually here, though.
First, thanks for this. I've hooked it up with multistage and it works nicely, with a few tweaks.
However, it doesn't seem to respect the keep_releases
setting. After several deployments, all my old releases were still there. You need to add the cleanup
task to the end of the deploy:update
:
task :update do
transaction do
update_code
copy_config
composer_install
link_shared
fix_permissions
clear_cache
cleanup
end
end
@cviebrock mind posting how you got it to work in multistage
?
I've updated the original gist—finally!—based on @cviebrock's comment above. (As you might guess, I haven't been using this for a while...)
is railsless-deploy required in the cap file?