-
-
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 |
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...)
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