diff --git a/Capfile b/Capfile index d04de115b..b810212e1 100644 --- a/Capfile +++ b/Capfile @@ -1,4 +1,140 @@ -load 'deploy' if respond_to?(:namespace) # cap2 differentiator -Dir['vendor/gems/*/recipes/*.rb','vendor/plugins/*/recipes/*.rb'].each { |plugin| load(plugin) } +# Load DSL and set up stages +require 'capistrano/setup' -load 'config/deploy' # remove this line to skip loading any of the default tasks \ No newline at end of file +# Include default deployment tasks +require 'capistrano/deploy' + +# Include tasks from other gems included in your Gemfile +require 'capistrano/rbenv' +require 'capistrano/rails' +require 'whenever/capistrano' +require 'capistrano3/unicorn' + +# Load custom tasks from `lib/capistrano/tasks` if you have any defined +Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r } + +namespace :local_config do + desc "Link the local config files" + task :link_local_files do + on roles(:app) do + execute :ln, "-s", "#{deploy_to}/shared/config/danbooru_local_config.rb", "#{release_path}/config/danbooru_local_config.rb" + execute :ln, "-s", "#{deploy_to}/shared/config/database.yml", "#{release_path}/config/database.yml" + execute :ln, "-s", "#{deploy_to}/shared/config/newrelic.yml", "#{release_path}/config/newrelic.yml" + end + end +end + +namespace :data do + task :link_directories do + on roles(:app) do + execute :rm, "-f", "#{release_path}/public/data" + execute :ln, "-s", "#{deploy_to}/shared/data", "#{release_path}/public/data" + + execute :mkdir, "-p", "#{release_path}/public/cache" + execute :mkdir, "-p", "#{deploy_to}/shared/system/cache" + execute :touch, "#{deploy_to}/shared/system/cache/tags.json" + execute :ln, "-s", "#{deploy_to}/shared/system/cache/tags.json", "#{release_path}/public/cache/tags.json" + execute :touch, "#{deploy_to}/shared/system/cache/tags.json.gz" + execute :ln, "-s", "#{deploy_to}/shared/system/cache/tags.json.gz", "#{release_path}/public/cache/tags.json.gz" + end + end +end + +namespace :web do + desc "Present a maintenance page to visitors." + task :disable do + on roles(:app) do + maintenance_html_path = "#{current_path}/public/maintenance.html.bak" + if test("[ -e #{maintenance_html_path} ]") + execute :mv, maintenance_html_path, "#{current_path}/public/maintenance.html" + end + end + end + + desc "Makes the application web-accessible again." + task :enable do + on roles(:app) do + maintenance_html_path = "#{current_path}/public/maintenance.html" + if test("[ -e #{maintenance_html_path} ]") + execute :mv, maintenance_html_path, "#{current_path}/public/maintenance.html.bak" + end + end + end +end + +namespace :nginx do + desc "Shut down Nginx" + task :stop do + on roles(:web) do + as :user => "root" do + execute "/etc/init.d/nginx", "stop" + end + end + end + + desc "Start Nginx" + task :start do + on roles(:web) do + as :user => "root" do + execute "/etc/init.d/nginx", "start" + end + end + end + + desc "Reload Nginx" + task :reload do + on roles(:web) do + as :user => "root" do + execute "/etc/init.d/nginx", "reload" + end + end + end +end + +namespace :delayed_job do + desc "Start delayed_job process" + task :start do + on roles(:app) do + within current_path do + hostname = capture("hostname").strip + execute :bundle, "exec", "script/delayed_job", "--queues=default,#{hostname}", "-n 2", "start" + end + end + end + + desc "Stop delayed_job process" + task :stop do + on roles(:app) do + within current_path do + execute :bundle, "exec", "script/delayed_job", "stop" + end + end + end + + desc "Restart delayed_job process" + task :restart do + on roles(:app) do + find_and_execute_task("delayed_job:stop") + find_and_execute_task("delayed_job:start") + end + end + + task :kill do + on roles(:app) do + procs = capture("ps -A -o pid,command").split(/\r\n|\r|\n/).grep(/delayed_job/).map(&:to_i) + + if procs.any? + execute "for i in #{procs.join(' ')} ; do kill -s TERM $i ; done" + end + end + end +end + +after "delayed_job:stop", "delayed_job:kill" +after "deploy:symlink:shared", "local_config:link_local_files" +after "deploy:symlink:shared", "data:link_directories" +before "deploy:started", "web:disable" +before "deploy:started", "delayed_job:stop" +after "deploy:published", "delayed_job:start" +after "deploy:published", "unicorn:reload" +after "deploy:published", "web:enable" diff --git a/Gemfile b/Gemfile index 39c79f2b1..3fe4e4a1e 100644 --- a/Gemfile +++ b/Gemfile @@ -41,8 +41,9 @@ gem 'diff-lcs', :require => "diff/lcs/array", :git => "https://github.com/halost gem 'bcrypt-ruby', :require => "bcrypt" gem 'awesome_print' gem 'statistics2' -gem 'capistrano' -gem 'capistrano-ext' +gem 'capistrano', '~> 3.4.0' +gem 'capistrano-rails' +gem 'capistrano-rbenv' gem 'radix62', '~> 1.0.1' gem 'streamio-ffmpeg' gem 'rubyzip', :require => "zip" @@ -51,16 +52,20 @@ gem 'stripe' gem 'twitter' gem 'aws-sdk', '~> 2' gem 'responders' +gem 'highline' # needed for looser jpeg header compat gem 'ruby-imagespec', :require => "image_spec", :git => "https://github.com/r888888888/ruby-imagespec.git", :branch => "exif-fixes" +group :production, :staging do + gem 'unicorn', :platforms => :ruby + gem 'capistrano3-unicorn' +end + group :production do gem 'newrelic_rpm' - gem 'unicorn', :platforms => :ruby # gem 'unicorn-worker-killer' gem 'gctools', :platforms => :ruby - gem 'capistrano-unicorn', :require => false end group :development do diff --git a/Gemfile.lock b/Gemfile.lock index 384d7eb03..f61479045 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -68,16 +68,21 @@ GEM buftok (0.2.0) builder (3.2.2) byebug (6.0.0) - capistrano (2.15.6) - highline - net-scp (>= 1.0.0) - net-sftp (>= 2.0.0) - net-ssh (>= 2.0.14) - net-ssh-gateway (>= 1.1.0) - capistrano-ext (1.2.1) - capistrano (>= 1.0.0) - capistrano-unicorn (0.2.0) - capistrano (< 3.0) + capistrano (3.4.0) + i18n + rake (>= 10.0.0) + sshkit (~> 1.3) + capistrano-bundler (1.1.4) + capistrano (~> 3.1) + sshkit (~> 1.2) + capistrano-rails (1.1.3) + capistrano (~> 3.1) + capistrano-bundler (~> 1.1) + capistrano-rbenv (2.0.3) + capistrano (~> 3.1) + sshkit (~> 1.3) + capistrano3-unicorn (0.2.1) + capistrano (~> 3.1, >= 3.1.0) chronic (0.10.2) coderay (1.1.0) coffee-rails (4.1.0) @@ -89,6 +94,7 @@ GEM coffee-script-source (1.9.1.1) coinbase (4.0.7) bigdecimal + colorize (0.7.7) crack (0.4.2) safe_yaml (~> 1.0.0) crass (1.0.2) @@ -160,8 +166,6 @@ GEM net-sftp (2.1.2) net-ssh (>= 2.6.5) net-ssh (2.9.2) - net-ssh-gateway (1.2.0) - net-ssh (>= 2.6.5) netrc (0.10.3) newrelic_rpm (3.13.0.299) nokogiri (1.6.6.2) @@ -265,6 +269,10 @@ GEM actionpack (>= 3.0) activesupport (>= 3.0) sprockets (>= 2.8, < 4.0) + sshkit (1.7.1) + colorize (>= 0.7.0) + net-scp (>= 1.1.2) + net-ssh (>= 2.8.0) statistics2 (0.54) streamio-ffmpeg (1.0.0) stripe (1.25.0) @@ -324,9 +332,10 @@ DEPENDENCIES aws-sdk (~> 2) bcrypt-ruby byebug - capistrano - capistrano-ext - capistrano-unicorn + capistrano (~> 3.4.0) + capistrano-rails + capistrano-rbenv + capistrano3-unicorn coffee-rails coinbase daemons @@ -337,6 +346,7 @@ DEPENDENCIES factory_girl ffaker gctools + highline kgio mechanize memcache-client diff --git a/config/deploy.rb b/config/deploy.rb index c3817033c..f5d5c0742 100644 --- a/config/deploy.rb +++ b/config/deploy.rb @@ -1,165 +1,8 @@ set :stages, %w(production development staging) set :default_stage, "staging" -set :unicorn_env, defer {stage} -require 'capistrano/ext/multistage' - -require 'bundler/capistrano' -set :bundle_flags, "--deployment --quiet --binstubs --shebang ruby" - -set :default_environment, { - "PATH" => '$HOME/.rbenv/shims:$HOME/.rbenv/bin:$PATH' -} - -set :whenever_command, "bundle exec whenever" -set :whenever_environment, defer {stage} -require 'whenever/capistrano' - -require 'securerandom' -set :secret_1, SecureRandom.base64(32) -set :secret_2, SecureRandom.base64(32) - set :application, "danbooru" -set :repository, "git://github.com/r888888888/danbooru.git" +set :repo_url, "git://github.com/r888888888/danbooru.git" set :scm, :git -set :user, "danbooru" set :deploy_to, "/var/www/danbooru2" - -require 'capistrano-unicorn' - -default_run_options[:pty] = true - -namespace :local_config do - desc "Create the shared config directory" - task :setup_shared_directory do - run "mkdir -p #{deploy_to}/shared/config" - end - - desc "Initialize the secrets" - task :setup_secrets do - run "mkdir -p ~/.danbooru" - run "if [[ ! -e ~/.danbooru/session_secret_key ]] ; then echo '#{secret_1}' > ~/.danbooru/session_secret_key ; fi" - run "if [[ ! -e ~/.danbooru/secret_token ]] ; then echo '#{secret_2}' > ~/.danbooru/secret_token ; fi" - run "chmod 600 ~/.danbooru/secret_token" - run "chmod 600 ~/.danbooru/session_secret_key" - run "chown -R #{user}:#{user} ~/.danbooru" - end - - desc "Initialize local config files" - task :setup_local_files do - run "curl -s https://raw.githubusercontent.com/r888888888/danbooru/master/script/install/danbooru_local_config.rb.templ > #{deploy_to}/shared/config/danbooru_local_config.rb" - run "curl -s https://raw.githubusercontent.com/r888888888/danbooru/master/script/install/database.yml.templ > #{deploy_to}/shared/config/database.yml" - end - - desc "Link the local config files" - task :link_local_files do - run "ln -s #{deploy_to}/shared/config/danbooru_local_config.rb #{release_path}/config/danbooru_local_config.rb" - run "ln -s #{deploy_to}/shared/config/database.yml #{release_path}/config/database.yml" - run "ln -s #{deploy_to}/shared/config/newrelic.yml #{release_path}/config/newrelic.yml" - end -end - -namespace :data do - task :setup_directories do - run "mkdir -p #{deploy_to}/shared/data" - run "mkdir #{deploy_to}/shared/data/preview" - run "mkdir #{deploy_to}/shared/data/sample" - end - - task :link_directories do - run "rm -f #{release_path}/public/data" - run "ln -s #{deploy_to}/shared/data #{release_path}/public/data" - - run "rm -f #{release_path}/public/images/advertisements" - run "ln -s #{deploy_to}/shared/advertisements #{release_path}/public/images/advertisements" - - run "mkdir -p #{release_path}/public/cache" - run "mkdir -p #{deploy_to}/shared/system/cache" - run "touch #{deploy_to}/shared/system/cache/tags.json" - run "ln -s #{deploy_to}/shared/system/cache/tags.json #{release_path}/public/cache/tags.json" - run "touch #{deploy_to}/shared/system/cache/tags.json.gz" - run "ln -s #{deploy_to}/shared/system/cache/tags.json.gz #{release_path}/public/cache/tags.json.gz" - end -end - -desc "Change ownership of common directory to user" -task :reset_ownership_of_common_directory do - sudo "chown -R #{user}:#{user} #{deploy_to}" -end - -namespace :deploy do - namespace :web do - desc "Present a maintenance page to visitors." - task :disable do - maintenance_html_path = "#{current_path}/public/maintenance.html.bak" - run "if [ -e #{maintenance_html_path} ] ; then mv #{maintenance_html_path} #{current_path}/public/maintenance.html ; fi" - end - - desc "Makes the application web-accessible again." - task :enable do - maintenance_html_path = "#{current_path}/public/maintenance.html" - run "if [ -e #{maintenance_html_path} ] ; then mv #{maintenance_html_path} #{current_path}/public/maintenance.html.bak ; fi" - end - end - - namespace :nginx do - desc "Shut down Nginx" - task :stop do - sudo "/etc/init.d/nginx stop" - end - - desc "Start Nginx" - task :start do - sudo "/etc/init.d/nginx start" - end - end - - desc "Precompiles assets" - task :precompile_assets do - run "cd #{current_path}; RAILS_ENV=#{rails_env} bundle exec rake assets:precompile" - # run "cd #{current_path}/public/assets; cp application-*.js application.js ; cp application-*.css application.css" - end -end - -namespace :delayed_job do - desc "Start delayed_job process" - task :start, :roles => :app do - run "cd #{current_path}; RAILS_ENV=#{rails_env} bundle exec ruby script/delayed_job --queues=default,`hostname` -n 2 start" - end - - desc "Stop delayed_job process" - task :stop, :roles => :app do - run "cd #{current_path}; RAILS_ENV=#{rails_env} bundle exec ruby script/delayed_job stop" - end - - desc "Restart delayed_job process" - task :restart, :roles => :app do - find_and_execute_task("delayed_job:stop") - find_and_execute_task("delayed_job:start") - end - - task :kill, :roles => :app do - procs = capture("ps -A -o pid,command").split(/\r\n|\r|\n/).grep(/delayed_job/).map(&:to_i) - - if procs.any? - run "for i in #{procs.join(' ')} ; do kill -s TERM $i ; done" - end - end -end - -after "deploy:setup", "reset_ownership_of_common_directory" -after "deploy:setup", "local_config:setup_shared_directory" -after "deploy:setup", "local_config:setup_local_files" -after "deploy:setup", "data:setup_directories" -after "deploy:setup", "local_config:setup_secrets" -after "deploy:create_symlink", "local_config:link_local_files" -after "deploy:create_symlink", "data:link_directories" -after "deploy:start", "delayed_job:start" -after "deploy:stop", "delayed_job:stop" -before "deploy:update", "deploy:web:disable" -after "deploy:update", "delayed_job:restart" -after "deploy:update", "deploy:migrate" -after "deploy:update", "unicorn:reload" -after "deploy:update", "unicorn:restart" -after "deploy:update", "deploy:precompile_assets" -after "deploy:update", "deploy:web:enable" -after "delayed_job:stop", "delayed_job:kill" \ No newline at end of file +set :rbenv_ruby, "2.1.5" +set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle') diff --git a/config/deploy/development.rb b/config/deploy/development.rb index 729153f71..fedaa31b5 100644 --- a/config/deploy/development.rb +++ b/config/deploy/development.rb @@ -1 +1 @@ -server "localhost", :web, :app, :db, :primary => true +server "localhost", :roles => %w(web app db), :primary => true diff --git a/config/deploy/production.rb b/config/deploy/production.rb index 8568fcf19..13355d807 100644 --- a/config/deploy/production.rb +++ b/config/deploy/production.rb @@ -1,3 +1,3 @@ set :user, "albert" -server "sonohara.donmai.us", :web, :app, :db, :primary => true -server "hijiribe.donmai.us", :web, :app +server "sonohara.donmai.us", :roles => %w(web app db), :primary => true, :user => "albert" +server "hijiribe.donmai.us", :roles => %w(web app), :user => "albert" diff --git a/config/deploy/staging.rb b/config/deploy/staging.rb index 1fa48f7ad..8056f1bdd 100644 --- a/config/deploy/staging.rb +++ b/config/deploy/staging.rb @@ -1 +1 @@ -server "testbooru.donmai.us", :web, :app, :db, :primary => true +server "testbooru.donmai.us", :roles => %w(web app db), :primary => true, :user => "danbooru" diff --git a/config/environments/development.rb b/config/environments/development.rb index b55e2144b..d982cc766 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -38,4 +38,6 @@ Rails.application.configure do # Raises error for missing translations # config.action_view.raise_on_missing_translations = true + + config.eager_load = false end diff --git a/config/environments/production.rb b/config/environments/production.rb index 3468752c4..dde8016ca 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -77,4 +77,5 @@ Rails.application.configure do # Do not dump schema after migrations. config.active_record.dump_schema_after_migration = false + config.eager_load = true end diff --git a/config/environments/staging.rb b/config/environments/staging.rb new file mode 100644 index 000000000..dde8016ca --- /dev/null +++ b/config/environments/staging.rb @@ -0,0 +1,81 @@ +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # Code is not reloaded between requests. + config.cache_classes = true + + # Eager load code on boot. This eager loads most of Rails and + # your application in memory, allowing both threaded web servers + # and those relying on copy on write to perform better. + # Rake tasks automatically ignore this option for performance. + config.eager_load = true + + # Full error reports are disabled and caching is turned on. + config.consider_all_requests_local = false + config.action_controller.perform_caching = true + + # Enable Rack::Cache to put a simple HTTP cache in front of your application + # Add `rack-cache` to your Gemfile before enabling this. + # For large-scale production use, consider using a caching reverse proxy like + # NGINX, varnish or squid. + # config.action_dispatch.rack_cache = true + + # Disable serving static files from the `/public` folder by default since + # Apache or NGINX already handles this. + config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present? + + # Compress JavaScripts and CSS. + config.assets.js_compressor = :uglifier + # config.assets.css_compressor = :sass + + # Do not fallback to assets pipeline if a precompiled asset is missed. + config.assets.compile = true + + # Asset digests allow you to set far-future HTTP expiration dates on all assets, + # yet still be able to expire them through the digest params. + config.assets.digest = true + + # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb + + # Specifies the header that your server uses for sending files. + # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache + # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX + + # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. + # config.force_ssl = true + + # Use the lowest log level to ensure availability of diagnostic information + # when problems arise. + config.log_level = :error + + # Prepend all log lines with the following tags. + # config.log_tags = [ :subdomain, :uuid ] + + # Use a different logger for distributed setups. + # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new) + + # Use a different cache store in production. + # config.cache_store = :mem_cache_store + + # Enable serving of images, stylesheets, and JavaScripts from an asset server. + # config.action_controller.asset_host = 'http://assets.example.com' + + # Ignore bad email addresses and do not raise email delivery errors. + # Set this to true and configure the email server for immediate delivery to raise delivery errors. + # config.action_mailer.raise_delivery_errors = false + + # Enable locale fallbacks for I18n (makes lookups for any locale fall back to + # the I18n.default_locale when a translation cannot be found). + config.i18n.fallbacks = true + + # Send deprecation notices to registered listeners. + config.active_support.deprecation = :notify + + # Use default logging formatter so that PID and timestamp are not suppressed. + config.log_formatter = ::Logger::Formatter.new + + # Do not dump schema after migrations. + config.active_record.dump_schema_after_migration = false + + config.eager_load = true +end diff --git a/config/environments/test.rb b/config/environments/test.rb index 1c19f08b2..41c02c0d4 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -39,4 +39,6 @@ Rails.application.configure do # Raises error for missing translations # config.action_view.raise_on_missing_translations = true + + config.eager_load = false end diff --git a/config/initializers/unicorn.rb b/config/initializers/unicorn.rb index f5fc7c6f5..6fe2062c6 100644 --- a/config/initializers/unicorn.rb +++ b/config/initializers/unicorn.rb @@ -1,7 +1,7 @@ # Ensure the agent is started using Unicorn. # This is needed when using Unicorn and preload_app is not set to true. # See https://newrelic.com/docs/ruby/no-data-with-unicorn -if defined? Unicorn +if defined? ::NewRelic ::NewRelic::Agent.manual_start() ::NewRelic::Agent.after_fork(:force_reconnect => true) end