Merge pull request #2895 from betagouv/puma

Puma
This commit is contained in:
LeSim 2018-10-24 12:30:00 +02:00 committed by GitHub
commit 5b8c64081e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 139 additions and 225 deletions

View file

@ -92,24 +92,6 @@ jobs:
- run: - run:
name: Run linters name: Run linters
command: bundle exec rake lint command: bundle exec rake lint
deploy:
<<: *defaults
steps:
- checkout
- *bundle_restore_cache
- *bundle_install
- add_ssh_keys:
fingerprints:
- "0e:db:db:9c:54:ac:60:1a:d3:ba:28:03:2e:7d:0e:9a"
- deploy:
command: |
if [ "${CIRCLE_BRANCH}" == "dev" ]; then
bundle exec rake deploy to=staging
fi
if [ "${CIRCLE_BRANCH}" == "master" ]; then
bundle exec rake deploy to=production
fi
workflows: workflows:
version: 2 version: 2
@ -122,12 +104,3 @@ workflows:
- lint: - lint:
requires: requires:
- build - build
- deploy:
filters:
branches:
only:
- dev
- master
requires:
- test
- lint

View file

@ -17,8 +17,8 @@ gem 'deep_cloneable'
gem 'warden', git: 'https://github.com/hassox/warden.git', branch: 'master' gem 'warden', git: 'https://github.com/hassox/warden.git', branch: 'master'
# Use Unicorn as the app server # Use Puma as the app server
gem 'unicorn' gem 'puma'
# serializer # serializer
gem 'active_model_serializers' gem 'active_model_serializers'
@ -171,7 +171,7 @@ group :development, :test do
gem 'rspec-rails' gem 'rspec-rails'
# Deploy # Deploy
gem 'mina', ref: '343a7', git: 'https://github.com/mina-deploy/mina.git' gem 'mina', git: 'https://github.com/mina-deploy/mina.git'
gem 'rspec_junit_formatter' gem 'rspec_junit_formatter'
end end

View file

@ -8,10 +8,9 @@ GIT
GIT GIT
remote: https://github.com/mina-deploy/mina.git remote: https://github.com/mina-deploy/mina.git
revision: 343a7ab672d8b4f0ddb84ec240cde7d94b46397a revision: 0dd5fdb8bb82a180d35e1fc033de2fac48257e30
ref: 343a7
specs: specs:
mina (0.3.8) mina (1.2.3)
open4 (~> 1.3.4) open4 (~> 1.3.4)
rake rake
@ -450,7 +449,6 @@ GEM
activerecord activerecord
kaminari-core (= 1.1.1) kaminari-core (= 1.1.1)
kaminari-core (1.1.1) kaminari-core (1.1.1)
kgio (2.11.2)
launchy (2.4.3) launchy (2.4.3)
addressable (~> 2.3) addressable (~> 2.3)
letter_opener (1.6.0) letter_opener (1.6.0)
@ -558,6 +556,7 @@ GEM
byebug (~> 10.0) byebug (~> 10.0)
pry (~> 0.10) pry (~> 0.10)
public_suffix (3.0.2) public_suffix (3.0.2)
puma (3.12.0)
rack (2.0.5) rack (2.0.5)
rack-handlers (0.7.3) rack-handlers (0.7.3)
rack rack
@ -607,7 +606,6 @@ GEM
rake (>= 0.8.7) rake (>= 0.8.7)
thor (>= 0.19.0, < 2.0) thor (>= 0.19.0, < 2.0)
rainbow (3.0.0) rainbow (3.0.0)
raindrops (0.19.0)
rake (12.3.1) rake (12.3.1)
rb-fsevent (0.10.3) rb-fsevent (0.10.3)
rb-inotify (0.9.10) rb-inotify (0.9.10)
@ -764,9 +762,6 @@ GEM
unf_ext unf_ext
unf_ext (0.0.7.5) unf_ext (0.0.7.5)
unicode-display_width (1.4.0) unicode-display_width (1.4.0)
unicorn (5.4.1)
kgio (~> 2.6)
raindrops (~> 0.7)
validate_email (0.1.6) validate_email (0.1.6)
activemodel (>= 3.0) activemodel (>= 3.0)
mail (>= 2.2.5) mail (>= 2.2.5)
@ -863,6 +858,7 @@ DEPENDENCIES
prawn_rails prawn_rails
premailer-rails premailer-rails
pry-byebug pry-byebug
puma
rack-handlers rack-handlers
rack-mini-profiler rack-mini-profiler
rails rails
@ -891,7 +887,6 @@ DEPENDENCIES
timecop timecop
turbolinks turbolinks
typhoeus typhoeus
unicorn
vcr vcr
warden! warden!
web-console web-console

View file

@ -13,91 +13,47 @@ require 'mina/rbenv'
# forward_agent - SSH forward_agent # forward_agent - SSH forward_agent
# user - Username in the server to SSH to # user - Username in the server to SSH to
if !["staging", "production"].include?(ENV['to']) set :domain, ENV.fetch('domain')
raise "missing or incorrect `to` (should be 'staging' or 'production')"
end
if ENV['domain'].nil?
raise "missing `domain`"
end
set :domain, ENV['domain']
set :repository, 'https://github.com/betagouv/tps.git' set :repository, 'https://github.com/betagouv/tps.git'
set :port, 2200 deploy_to = '/var/www/ds'
set :rails_env, 'production' set :deploy_to, deploy_to
set :rbenv_path, "/usr/local/rbenv/bin/rbenv" set :user, 'ds'
set :forward_agent, true set :branch, ENV.fetch('branch')
# Manually create these paths in shared/ (eg: shared/config/database.yml) in your server. # Manually create these paths in shared/ (eg: shared/config/database.yml) in your server.
# They will be linked in the 'deploy:link_shared_paths' step. # They will be linked in the 'deploy:link_shared_paths' step.
set :shared_paths, [ set :shared_dirs, [
'.env',
'log', 'log',
'uploads', 'sockets',
'tmp/pids', 'tmp/pids',
'tmp/cache', 'tmp/cache'
'tmp/sockets',
'public/system',
'public/uploads',
'config/unicorn.rb'
] ]
case ENV["to"] set :rbenv_path, "/home/ds/.rbenv/bin/rbenv"
when "staging" set :forward_agent, true # SSH forward_agent.
set :branch, ENV['branch'] || 'dev'
set :deploy_to, '/var/www/tps_dev'
set :user, 'tps_dev'
appname = 'tps_dev'
when "production"
set :branch, ENV['branch'] || 'master'
set :deploy_to, '/var/www/tps'
set :user, 'tps'
appname = 'tps'
end
print "Deploy to #{ENV['to']} environment branch #{branch}\n" puts "Deploy to #{ENV.fetch('domain')}, branch: #{ENV.fetch('branch')}"
# This task is the environment that is loaded for most commands, such as # This task is the environment that is loaded for most commands, such as
# `mina deploy` or `mina rake`. # `mina deploy` or `mina rake`.
task :setup => :environment do task :setup do
queue! %[mkdir -p "#{deploy_to}/shared/log"] command %[mkdir -p "#{deploy_to}/shared/log"]
queue! %[chmod g+rx,u+rwx "#{deploy_to}/shared/log"] command %[chmod g+rx,u+rwx "#{deploy_to}/shared/log"]
queue! %[mkdir -p "#{deploy_to}/shared/bin"] command %[mkdir -p "#{deploy_to}/shared/tmp/pids"]
queue! %[chmod g+rx,u+rwx "#{deploy_to}/shared/bin"] command %[chmod g+rx,u+rwx "#{deploy_to}/shared/tmp/pids"]
queue! %[mkdir -p "#{deploy_to}/shared/tmp/pids"] command %[mkdir -p "#{deploy_to}/shared/tmp/cache"]
queue! %[chmod g+rx,u+rwx "#{deploy_to}/shared/tmp/pids"] command %[chmod g+rx,u+rwx "#{deploy_to}/shared/tmp/cache"]
queue! %[mkdir -p "#{deploy_to}/shared/tmp/cache"] command %[mkdir -p "#{deploy_to}/shared/sockets"]
queue! %[chmod g+rx,u+rwx "#{deploy_to}/shared/tmp/cache"] command %[chmod g+rx,u+rwx "#{deploy_to}/shared/sockets"]
queue! %[mkdir -p "#{deploy_to}/shared/tmp/sockets"]
queue! %[chmod g+rx,u+rwx "#{deploy_to}/shared/tmp/sockets"]
queue! %[mkdir -p "#{deploy_to}/shared/public/system"]
queue! %[chmod g+rx,u+rwx "#{deploy_to}/shared/public/system"]
queue! %[mkdir -p "#{deploy_to}/shared/public/uploads"]
queue! %[chmod g+rx,u+rwx "#{deploy_to}/shared/public/uploads"]
queue! %[mkdir -p "#{deploy_to}/shared/config"]
queue! %[chmod g+rx,u+rwx "#{deploy_to}/shared/config"]
queue! %[mkdir -p "#{deploy_to}/shared/app"]
queue! %[chmod g+rx,u+rwx "#{deploy_to}/shared/app"]
queue! %[mkdir -p "#{deploy_to}/shared/views/layouts"]
queue! %[chmod g+rx,u+rwx "#{deploy_to}/shared/views/layouts"]
queue! %[mkdir -p "#{deploy_to}/shared/config/locales/dynamics"]
queue! %[chmod g+rx,u+rwx "#{deploy_to}/shared/config/locales/dynamics"]
end end
namespace :yarn do namespace :yarn do
desc "Install package dependencies using yarn." desc "Install package dependencies using yarn."
task :install do task :install do
queue %{ command %{
echo "-----> Installing package dependencies using yarn" echo "-----> Installing package dependencies using yarn"
#{echo_cmd %[yarn install --non-interactive]} #{echo_cmd %[yarn install --non-interactive]}
} }
@ -107,34 +63,52 @@ end
namespace :after_party do namespace :after_party do
desc "Run after_party tasks." desc "Run after_party tasks."
task :run do task :run do
queue %{ command %{
echo "-----> Running deploy tasks" echo "-----> Running deploy tasks"
#{echo_cmd %[#{rake} after_party:run]} #{echo_cmd %[bundle exec rake after_party:run]}
}
end
end
namespace :service do
desc "Restart puma"
task :restart_puma do
command %{
echo "-----> Restarting puma service"
#{echo_cmd %[sudo systemctl restart puma]}
echo "-----> Reloading nginx service"
#{echo_cmd %[sudo systemctl reload nginx]}
}
end
desc "Restart delayed_job"
task :restart_delayed_job do
command %{
echo "-----> Restarting delayed_job service"
#{echo_cmd %[sudo systemctl restart delayed_job]}
} }
end end
end end
desc "Deploys the current version to the server." desc "Deploys the current version to the server."
task :deploy => :environment do task :deploy do
queue 'export PATH=$PATH:/usr/local/rbenv/bin:/usr/local/rbenv/shims' command 'export PATH=$PATH:/home/ds/.rbenv/bin:/home/ds/.rbenv/shims'
command 'source /home/ds/.profile'
deploy do deploy do
queue %[sudo service delayed_job_#{user!} stop || true]
# Put things that will set up an empty directory into a fully set-up # Put things that will set up an empty directory into a fully set-up
# instance of your project. # instance of your project.
invoke :'git:clone' invoke :'git:clone'
invoke :'deploy:link_shared_paths' invoke :'deploy:link_shared_paths'
invoke :'bundle:install' invoke :'bundle:install'
invoke :'yarn:install' invoke :'yarn:install'
invoke :'rails:db_migrate' invoke :'rails:db_migrate'
invoke :'after_party:run' invoke :'after_party:run'
invoke :'rails:assets_precompile:force' invoke :'rails:assets_precompile'
to :launch do on :launch do
queue "/etc/init.d/#{user} upgrade " invoke :'service:restart_puma'
queue! %[sudo service delayed_job_#{user!} start] invoke :'service:restart_delayed_job'
# If you are deploying a review app on a fresh testing environment,
# now can be a good time to seed the database.
end end
end end
end end

56
config/puma.rb Normal file
View file

@ -0,0 +1,56 @@
# Puma can serve each request in a thread from an internal thread pool.
# The `threads` method setting takes two numbers: a minimum and maximum.
# Any libraries that use thread pools should be configured to match
# the maximum value specified for Puma. Default is set to 5 threads for minimum
# and maximum; this matches the default thread size of Active Record.
#
threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
threads threads_count, threads_count
# Specifies the `port` that Puma will listen on to receive requests; default is 3000.
#
port ENV.fetch("PORT") { 3000 }
# Specifies the `environment` that Puma will run in.
#
environment ENV.fetch("RAILS_ENV") { "development" }
# Specifies the number of `workers` to boot in clustered mode.
# Workers are forked webserver processes. If using threads and workers together
# the concurrency of the application would be max `threads` * `workers`.
# Workers do not work on JRuby or Windows (both of which do not support
# processes).
#
# workers ENV.fetch("WEB_CONCURRENCY") { 2 }
# Use the `preload_app!` method when specifying a `workers` number.
# This directive tells Puma to first boot the application and load code
# before forking the application. This takes advantage of Copy On Write
# process behavior so workers use less memory. If you use this option
# you need to make sure to reconnect any threads in the `on_worker_boot`
# block.
#
# preload_app!
# If you are preloading your application and using Active Record, it's
# recommended that you close any connections to the database before workers
# are forked to prevent connection leakage.
#
# before_fork do
# ActiveRecord::Base.connection_pool.disconnect! if defined?(ActiveRecord)
# end
# The code in the `on_worker_boot` will be called if you are using
# clustered mode by specifying a number of `workers`. After each worker
# process is booted, this block will be run. If you are using the `preload_app!`
# option, you will want to use this block to reconnect to any threads
# or connections that may have been created at application boot, as Ruby
# cannot share connections between processes.
#
# on_worker_boot do
# ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
# end
#
# Allow puma to be restarted by `rails restart` command.
plugin :tmp_restart

View file

@ -1,105 +0,0 @@
# Sample verbose configuration file for Unicorn (not Rack)
#
# This configuration file documents many features of Unicorn
# that may not be needed for some applications. See
# http://unicorn.bogomips.org/examples/unicorn.conf.minimal.rb
# for a much simpler configuration file.
#
# See http://unicorn.bogomips.org/Unicorn/Configurator.html for complete
# documentation.
# Use at least one worker per core if you're on a dedicated server,
# more will usually help for _short_ waits on databases/caches.
worker_processes 2
# Since Unicorn is never exposed to outside clients, it does not need to
# run on the standard HTTP port (80), there is no reason to start Unicorn
# as root unless it's from system init scripts.
# If running the master process as root and the workers as an unprivileged
# user, do this to switch euid/egid in the workers (also chowns logs):
# user "unprivileged_user", "unprivileged_group"
# Help ensure your application will always spawn in the symlinked
# "current" directory that Capistrano sets up.
# listen on both a Unix domain socket and a TCP port,
# we use a shorter backlog for quicker failover when busy
listen "127.0.0.1:3000", :tcp_nopush => true
timeout 60
# By default, the Unicorn logger will write to stderr.
# Additionally, ome applications/frameworks log to stderr or stdout,
# so prevent them from going to /dev/null when daemonized here:
# combine Ruby 2.0.0dev or REE with "preload_app true" for memory savings
# http://rubyenterpriseedition.com/faq.html#adapt_apps_for_cow
preload_app true
GC.respond_to?(:copy_on_write_friendly=) and
GC.copy_on_write_friendly = true
# Enable this flag to have unicorn test client connections by writing the
# beginning of the HTTP headers before calling the application. This
# prevents calling the application for connections that have disconnected
# while queued. This is only guaranteed to detect clients on the same
# host unicorn runs on, and unlikely to detect disconnects even on a
# fast LAN.
check_client_connection false
# local variable to guard against running a hook multiple times
run_once = true
before_fork do |server, worker|
# the following is highly recomended for Rails + "preload_app true"
# as there's no need for the master process to hold a connection
defined?(ActiveRecord::Base) and
ActiveRecord::Base.connection.disconnect!
# Occasionally, it may be necessary to run non-idempotent code in the
# master before forking. Keep in mind the above disconnect! example
# is idempotent and does not need a guard.
if run_once
# do_something_once_here ...
run_once = false # prevent from firing again
end
# The following is only recommended for memory/DB-constrained
# installations. It is not needed if your system can house
# twice as many worker_processes as you have configured.
#
# # This allows a new master process to incrementally
# # phase out the old master process with SIGTTOU to avoid a
# # thundering herd (especially in the "preload_app false" case)
# # when doing a transparent upgrade. The last worker spawned
# # will then kill off the old master process with a SIGQUIT.
old_pid = "#{server.config[:pid]}.oldbin"
if old_pid != server.pid
begin
sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
Process.kill(sig, File.read(old_pid).to_i)
rescue Errno::ENOENT, Errno::ESRCH
end
end
#
# Throttle the master from forking too quickly by sleeping. Due
# to the implementation of standard Unix signal handlers, this
# helps (but does not completely) prevent identical, repeated signals
# from being lost when the receiving process is busy.
sleep 1
end
after_fork do |server, worker|
# per-process listener ports for debugging/admin/migrations
# addr = "127.0.0.1:#{9293 + worker.nr}"
# server.listen(addr, :tries => -1, :delay => 5, :tcp_nopush => true)
# the following is *required* for Rails + "preload_app true",
defined?(ActiveRecord::Base) and
ActiveRecord::Base.establish_connection
# if preload_app is true, then you may also want to check and
# restart any other shared sockets/descriptors such as Memcached,
# and Redis. TokyoCabinet file handles are safe to reuse
# between any number of forked children (assuming your kernel
# correctly implements pread()/pwrite() system calls)
end

View file

@ -1,6 +1,27 @@
task :deploy do def domains_from_env(env)
domains = ['149.202.72.152', '149.202.198.6'] case env
domains.each do |domain| when 'dev'
sh "mina deploy domain=#{domain}" ['web1.dev', 'web2.dev']
when 'prod'
['web1', 'web2']
else
raise "STAGE #{env} is unknown. It must be either dev or prod"
end
end
task :deploy do
domains = domains_from_env(ENV.fetch('STAGE'))
branch = ENV.fetch('BRANCH')
domains.each do |domain|
sh "mina deploy domain=#{domain} branch=#{branch} force_asset_precompile=true"
end
end
task :setup do
domains = domains_from_env(ENV['STAGE'])
domains.each do |domain|
sh "mina setup domain=#{domain} force_asset_precompile=true"
end end
end end