diff --git a/Capfile b/Capfile index 0c2b1b008..7c2f07157 100644 --- a/Capfile +++ b/Capfile @@ -4,6 +4,9 @@ require 'capistrano/setup' # Include default deployment tasks require 'capistrano/deploy' +require "capistrano/scm/git" +install_plugin Capistrano::SCM::Git + # Include tasks from other gems included in your Gemfile require 'capistrano/rbenv' require 'capistrano/rails' @@ -14,5 +17,3 @@ require 'new_relic/recipes' # Load custom tasks from `lib/capistrano/tasks` if you have any defined Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r } - -after "deploy:updated", "newrelic:notice_deployment" diff --git a/config/deploy.rb b/config/deploy.rb index f40d859a5..794578a47 100644 --- a/config/deploy.rb +++ b/config/deploy.rb @@ -2,8 +2,16 @@ set :stages, %w(production development staging) set :default_stage, "staging" set :application, "danbooru" set :repo_url, "git://github.com/r888888888/danbooru.git" -set :scm, :git set :deploy_to, "/var/www/danbooru2" set :rbenv_ruby, "2.5.1" -set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle') +append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "vendor/bundle" set :branch, ENV.fetch("branch", "master") + +# skip migrations if files in db/migrate weren't modified +set :conditionally_migrate, true + +# run migrations on the primary app server +set :migration_role, :app + +# how long unicorn:legacy_restart (used by deploy:rolling) waits until killing the old unicorn. +set :unicorn_restart_sleep_time, 10 diff --git a/config/deploy/production.rb b/config/deploy/production.rb index 697e1f9a9..62ccddb58 100644 --- a/config/deploy/production.rb +++ b/config/deploy/production.rb @@ -1,9 +1,11 @@ set :user, "danbooru" set :rails_env, "production" -server "kagamihara", :roles => %w(web app db), :primary => true +set :rbenv_path, "/home/danbooru/.rbenv" +append :linked_files, ".env.production" + +server "kagamihara", :roles => %w(web app), :primary => true server "shima", :roles => %w(web app) server "saitou", :roles => %w(web app) server "oogaki", :roles => %w(worker) -set :linked_files, fetch(:linked_files, []).push(".env.production") -set :rbenv_path, "/home/danbooru/.rbenv" \ No newline at end of file +after "deploy:finished", "newrelic:notice_deployment" diff --git a/lib/capistrano/tasks/app.rake b/lib/capistrano/tasks/app.rake new file mode 100644 index 000000000..1a0677fb9 --- /dev/null +++ b/lib/capistrano/tasks/app.rake @@ -0,0 +1,32 @@ +namespace :app do + set :rolling_deploy, false + + before "deploy:migrate", "app:disable" + after "deploy:published", "app:enable" + + task :disable do + if fetch(:rolling_deploy) + # do nothing + else + invoke "web:disable" + invoke "unicorn:terminate" + end + end + + task :enable do + if fetch(:rolling_deploy) + invoke "unicorn:legacy_restart" + else + invoke "unicorn:start" + invoke "web:enable" + end + end +end + +namespace :deploy do + desc "Deploy a rolling update without taking the site down for maintenance" + task :rolling do + set :rolling_deploy, true + invoke "deploy" + end +end diff --git a/lib/capistrano/tasks/unicorn.rake b/lib/capistrano/tasks/unicorn.rake index 1c7e41f1b..d747dfb2b 100644 --- a/lib/capistrano/tasks/unicorn.rake +++ b/lib/capistrano/tasks/unicorn.rake @@ -1,20 +1,25 @@ +# https://bogomips.org/unicorn/SIGNALS.html namespace :unicorn do desc "Terminate unicorn processes (blocks until complete)" task :terminate do on roles(:app) do - execute "[[ -n $(pgrep -f unicorn) ]] && pgrep -f unicorn | xargs kill -SIGTERM" - sleep(5) + within current_path do + kill_unicorn("SIGQUIT") + sleep(10) + kill_unicorn("SIGTERM") + sleep(2) + kill_unicorn("SIGKILL") + end end end - desc "Kills unicorn processes (blocks until complete)" - task :kill do - on roles(:app) do - execute "[[ -n $(pgrep -f unicorn) ]] && pgrep -f unicorn | xargs kill -SIGKILL" + def unicorn_running? + test("[ -f #{fetch(:unicorn_pid)} ] && pkill --count --pidfile #{fetch(:unicorn_pid)}") + end + + def kill_unicorn(signal) + if unicorn_running? + execute :pkill, "--signal #{signal}", "--pidfile #{fetch(:unicorn_pid)}" end end end - -after "deploy:published", "unicorn:terminate" -after "deploy:published", "unicorn:kill" -after "deploy:published", "unicorn:start" diff --git a/lib/capistrano/tasks/web.rake b/lib/capistrano/tasks/web.rake index b39eb24e8..7a4e024ad 100644 --- a/lib/capistrano/tasks/web.rake +++ b/lib/capistrano/tasks/web.rake @@ -19,6 +19,3 @@ namespace :web do end end end - -before "deploy:started", "web:disable" -after "deploy:published", "web:enable"