diff --git a/Gemfile b/Gemfile index 5b7a6c7db..91610629b 100644 --- a/Gemfile +++ b/Gemfile @@ -8,8 +8,8 @@ gem "activesupport" gem "faraday-retry" gem "octokit" gem "omniauth-github" +gem "puma" gem "sinatra" -gem "unicorn" group :development do gem "guard" diff --git a/Gemfile.lock b/Gemfile.lock index 11d3cccb9..c99618508 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -47,7 +47,6 @@ GEM concurrent-ruby (~> 1.0) json (2.7.1) jwt (2.7.1) - kgio (2.11.4) language_server-protocol (3.17.0.3) listen (3.8.0) rb-fsevent (~> 0.10, >= 0.10.3) @@ -62,6 +61,7 @@ GEM nenv (0.3.0) net-http (0.4.1) uri + nio4r (2.7.0) notiffany (0.1.3) nenv (~> 0.1) shellany (~> 0.0) @@ -93,6 +93,8 @@ GEM coderay (~> 1.1) method_source (~> 1.0) public_suffix (5.0.4) + puma (6.4.2) + nio4r (~> 2.0) racc (1.7.3) rack (3.0.8) rack-protection (4.0.0) @@ -101,7 +103,6 @@ GEM rack-session (2.0.0) rack (>= 3.0.0) rainbow (3.1.1) - raindrops (0.20.1) rb-fsevent (0.11.2) rb-inotify (0.10.1) ffi (~> 1.0) @@ -142,9 +143,6 @@ GEM tzinfo (2.0.6) concurrent-ruby (~> 1.0) unicode-display_width (2.5.0) - unicorn (6.1.0) - kgio (~> 2.6) - raindrops (~> 0.7) uri (0.13.0) version_gem (1.1.3) @@ -158,9 +156,9 @@ DEPENDENCIES guard-process octokit omniauth-github + puma rubocop sinatra - unicorn RUBY VERSION ruby 3.2.3p157 diff --git a/Guardfile b/Guardfile index ed535fff2..8ac6a5e95 100644 --- a/Guardfile +++ b/Guardfile @@ -4,5 +4,5 @@ guard "process", name: "server", command: "script/server" do watch "config.ru" watch "Gemfile.lock" watch "web/app.rb" - watch "web/unicorn.rb" + watch "web/puma.rb" end diff --git a/README.md b/README.md index 9622aadf2..b8014ceaa 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ Strap is also available as a Docker image on [Docker Hub (`mikemcquaid/strap`)]( - `GITHUB_KEY`: the GitHub.com Application Client ID. - `GITHUB_SECRET`: the GitHub.com Application Client Secret. - `SESSION_SECRET`: the secret used for cookie session storage. -- `WEB_CONCURRENCY`: the number of Unicorn (web server) processes to run (defaults to 3). +- `WEB_CONCURRENCY`: the number of Puma (web server) threads to run (defaults to 3). - `STRAP_ISSUES_URL`: the URL where users should file issues (defaults to no URL). - `STRAP_BEFORE_INSTALL`: instructions displayed in the web application for users to follow before installing Strap (wrapped in `
  • ` tags). - `CUSTOM_HOMEBREW_TAP`: an optional Homebrew tap to install with `brew tap`. Specify multiple arguments to brew tap by separating values with spaces. diff --git a/script/server b/script/server index 45aaa55e4..69a6a45fc 100755 --- a/script/server +++ b/script/server @@ -4,4 +4,4 @@ set -euo pipefail cd "$(dirname "$0")/.." export PORT="${PORT:-3000}" -bundle exec unicorn --port "$PORT" --config-file web/unicorn.rb +bundle exec puma --port "$PORT" --config web/puma.rb diff --git a/script/tests b/script/tests index 5513dc437..44e857d92 100755 --- a/script/tests +++ b/script/tests @@ -1,7 +1,10 @@ #!/bin/bash set -xeuo pipefail + cd "$(dirname "$0")/.." +export PUMA_PIDFILE="puma.pid" + tests_cleanup() { if [[ -n ${SERVER_PID-} ]]; then kill "${SERVER_PID}" @@ -11,14 +14,12 @@ tests_cleanup() { trap "tests_cleanup" EXIT script/bootstrap -script/server &>/dev/null & -SERVER_PID="$!" +script/server & +sleep 5 -sleep 15 +SERVER_PID=$(cat "${PUMA_PIDFILE}") curl -O http://localhost:3000/strap.sh curl -sSL -D - -o /dev/null http://localhost:3000/strap.sh | grep -i "x-frame-options: DENY" kill "$SERVER_PID" -wait "$SERVER_PID" || true -unset SERVER_PID diff --git a/web/puma.rb b/web/puma.rb new file mode 100644 index 000000000..f3be60b2c --- /dev/null +++ b/web/puma.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +# 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. +max_threads_count = ENV.fetch("WEB_CONCURRENCY", 3) +min_threads_count = ENV.fetch("WEB_CONCURRENCY") { max_threads_count } +threads min_threads_count, max_threads_count + +# Specifies the `worker_timeout` threshold that Puma will use to wait before +# terminating a worker in development environments. +worker_timeout 3600 if ENV.fetch("RACK_ENV", "development") == "development" + +# 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("RACK_ENV", "development") + +# Optionally specifies the `pidfile` that Puma will use. +if (puma_pidfile = ENV.fetch("PUMA_PIDFILE", nil)) + pidfile puma_pidfile +end + +# needed to avoid multiple workers from having different session secrets +require "securerandom" +ENV["SESSION_SECRET"] = SecureRandom.hex(64) unless ENV["SESSION_SECRET"] diff --git a/web/unicorn.rb b/web/unicorn.rb deleted file mode 100644 index 7201a594d..000000000 --- a/web/unicorn.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -worker_processes ENV.fetch("WEB_CONCURRENCY", 3).to_i - -# needed to avoid multiple workers from having different session secrets -require "securerandom" -ENV["SESSION_SECRET"] = SecureRandom.hex(64) unless ENV["SESSION_SECRET"]