所以我有一个使用puma Web服务器的ROR项目。有时,当代码被部署时(平台上有许多活动用户),这使我的构建不稳定,通过不稳定,我的意思是它在诸如undefined method to_sym' for nil:NilClass
,NoMethodError: undefined method -@' for nil:NilClass
之类的怪异地方抛出了完全随机的错误。当我重新部署代码时,错误会消失。
lock '3.5.0'
set :scm, :git
set :keep_releases, 5
set :user, 'ubuntu'
set :puma_threads, [2, 12]
set :puma_workers, Proc.new { fetch(:stage) == "production" ? 2 : 1 }
set :pty, false
set :use_sudo, true
set :rails_env, Proc.new { fetch :stage }
set :deploy_via, :remote_cache
set :deploy_to, "/home/#{fetch(:user)}/apps/#{fetch(:application)}"
set :puma_bind, "unix://#{shared_path}/tmp/sockets/#{fetch(:application)}-puma.sock"
set :puma_state, "#{shared_path}/tmp/pids/puma.state"
set :puma_pid, "#{shared_path}/tmp/pids/puma.pid"
set :puma_access_log, "#{shared_path}/log/puma.error.log"
set :puma_error_log, "#{shared_path}/log/puma.access.log"
set :puma_preload_app, true
set :puma_conf, "#{release_path}/config/puma.rb"
set :puma_worker_timeout, nil
set :puma_init_active_record, true # Change to false when not using ActiveRecord
set :ssh_options, { forward_agent: true, user: fetch(:user), keys: %w(~/.ssh/role.pem) }
set :primary_server, "35.154.8.144"
set :jenkins_user, "role"
set :jenkins_token, "29f3b5fb3862b427429f04d5cef8732b"
set :cron_file, "/var/spool/cron/crontabs/ubuntu"
set :sidekiq_role, :sidekiq
set :sidekiq_config, "#{release_path}/config/sidekiq.yml"
set :sidekiq_env, Proc.new { fetch :stage }
set :sidekiq_log => File.join(shared_path, 'log', 'sidekiq.log')
set :rollbar_token, 'e1e66e1a03274620b05b9e69f5776587'
set :rollbar_env, Proc.new { fetch :stage }
set :rollbar_role, Proc.new { :app }
set :sqs_polling_pid, Proc.new { "#{shared_path}/tmp/pids/sqs_polling.pid" }
set :test_log, Proc.new { "log/capistrano.test.log" }
set :whenever_identifier, ->{ "#{fetch(:application)}_#{fetch(:stage)}" }
set :whenever_path, ->{ current_path }
set :whenever_roles, ->{ :cron }
set :linked_dirs, %w{log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system public/source-maps public/attachments attachments config/settings config/cron}
namespace :puma do
desc 'Create Directories for Puma Pids and Socket'
task :make_dirs do
on roles(:all) do
execute "mkdir #{shared_path}/tmp/sockets -p"
execute "mkdir #{shared_path}/tmp/pids -p"
end
end
before :start, :make_dirs
end
namespace :sqs_polling do
desc 'Stop sqs_polling ghost processes'
task :clean do
on roles :sqs_polling do
execute "pkill -f sqs_polling_app > /dev/null 2>&1"
end
end
desc 'Stop sqs_polling'
task :stop do
on roles(:sqs_polling) do
within current_path do
execute "if [ -d #{current_path} ] && [ -f #{fetch(:sqs_polling_pid)} ] && kill `cat #{fetch(:sqs_polling_pid)}` > /dev/null 2>&1; then rm #{fetch(:sqs_polling_pid)} ; else echo 'sqs_polling is not running'; fi"
end
end
end
desc 'Start sqs_polling'
task :start do
on roles(:sqs_polling) do
within current_path do
with rails_env: fetch(:stage) do
execute :bundle, "exec rails runner lib/sqs_polling_app.rb >> #{current_path}/log/sqs_polling.log 2>&1 & echo $! > #{fetch(:sqs_polling_pid)}", pty: false
execute "ps aux | grep 'sqs_polling_app'"
end
end
end
end
desc 'Restart sqs_polling'
task :restart do
on roles(:sqs_polling) do
invoke 'sqs_polling:stop'
invoke 'sqs_polling:start'
end
end
end
namespace :deploy do
desc "Runs test before deploying, can't deploy unless they pass"
task :run_tests do
puts "--> Running tests, please wait ..."
unless system "bundle exec rspec spec > #{fetch(:test_log)} 2>&1" #' > /dev/null'
system "cat #{fetch(:test_log)}"
exit
else
puts "--> Tests passed"
system "rm #{fetch(:test_log)}"
end
end
task :seed do
puts "\n=== Seeding Database ===\n"
on roles(:backend) do
within current_path do
with rails_env: fetch(:stage) do
execute :rake, 'db:seed'
end
end
end
end
task :rake do
on roles(:backend) do
within current_path do
with rails_env: fetch(:stage) do
execute :rake, "#{ENV["task"]}"
end
end
end
end
desc "Make sure local git is in sync with remote."
task :check_revision do
on roles(:all) do
if fetch(:stage) == :production
unless `git rev-parse HEAD` == `git rev-parse origin/master`
puts "WARNING: HEAD is not the same as origin/master"
puts "Run `git push` to sync changes."
exit
end
end
end
end
task :nginx_restart do
on roles(:role) do
if fetch(:rails_env) == :staging
execute "sudo ln -nfs '/home/ubuntu/apps/dashboard/current/config/nginx.staging.conf' '/etc/nginx/sites-enabled/dashboard'"
execute "sudo service nginx restart"
else
execute "sudo ln -nfs '/home/ubuntu/apps/dashboard/current/config/nginx.role.conf' '/etc/nginx/sites-enabled/dashboard'"
execute "sudo service nginx restart"
end
end
end
task :config_files do
on roles(:all) do
within current_path do
execute "sudo scp -i #{fetch(:ssh_options)[:keys].first} ubuntu@#{fetch(:primary_server)}:/home/ubuntu/aws/settings/#{fetch(:rails_env)}.yml /home/ubuntu/apps/dashboard/shared/config/settings/#{fetch(:rails_env)}.yml"
end
end
end
task :copy_to_s3 do
on roles(:app) do
within release_path do
with rails_env: fetch(:rails_env) do
execute :rake, "s3:sync"
end
end
end
end
task :source_map_to_rollbar do
on roles(:app) do
within release_path do
with rails_env: fetch(:rails_env) do
execute :rake, "s3:source_map_to_rollbar"
end
end
end
end
task :clean_assets do
on roles(:all) do
within current_path do
with rails_env: fetch(:rails_env) do
execute :rake, "assets:clean[5]"
end
end
end
end
desc 'Initial Deploy'
task :initial do
on roles(:sqs_polling) do
invoke 'sqs_polling:clean'
end
on roles(:app) do
before 'deploy:restart', 'puma:start'
invoke 'deploy'
end
end
desc 'Restart application'
task :restart do
on roles(:sqs_polling), in: :sequence, wait: 5 do
invoke 'sqs_polling:restart'
end
on roles(:app), in: :sequence, wait: 5 do
within release_path do
with rails_env: fetch(:rails_env) do
execute :rake, "s3:deployed"
invoke 'puma:restart'
invoke 'sqs_polling:restart'
end
end
end
end
before :clean_assets, :config_files
after :config_files, :nginx_restart
before :starting, :check_revision
after :finishing, :compile_assets
before :compile_assets, :clean_assets
after :compile_assets, :copy_to_s3
after :copy_to_s3, :source_map_to_rollbar
after :finishing, :cleanup
after :finishing, :restart
end