From 03f84567015ec9d1da207afa094a31d6f3f96262 Mon Sep 17 00:00:00 2001 From: Richard Schneeman Date: Wed, 27 Nov 2024 09:49:14 -0600 Subject: [PATCH] Change default process type host to IPv6 `::` (#354) * Change default process type host to IPv6 `::` IPv6 is the future. Here's some more context heroku/roadmap#40. Related https://github.com/heroku/ruby-getting-started/pull/165 * Update gems * Use puma to support IPv6 and IPv4 in local tests * Changelog --- buildpacks/ruby/CHANGELOG.md | 6 ++++++ buildpacks/ruby/src/steps/get_default_process.rs | 3 ++- .../ruby/tests/fixtures/default_ruby/Gemfile | 3 ++- .../tests/fixtures/default_ruby/Gemfile.lock | 16 ++++++++++++---- buildpacks/ruby/tests/integration_test.rs | 11 ++++++----- docs/application_contract.md | 4 ++-- 6 files changed, 30 insertions(+), 13 deletions(-) diff --git a/buildpacks/ruby/CHANGELOG.md b/buildpacks/ruby/CHANGELOG.md index e7e2aebf..ea799222 100644 --- a/buildpacks/ruby/CHANGELOG.md +++ b/buildpacks/ruby/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- Default process types defined by the Ruby buildpack now use IPv6 host `::` which is equivalent of IPv4 host `0.0.0.0`. This will only affect applications that do not define a `web` process type via the `Procfile` and [Procfile Cloud Native Buildpack](https://github.com/heroku/buildpacks-procfile). Those applications must make sure to update their configuration to bind to an IPv6 host. ([#354](https://github.com/heroku/buildpacks-ruby/pull/354)) + +### Added + - The buildpack now warns the user when environmental variables used in running the default process are not defined. ([#307](https://github.com/heroku/buildpacks-ruby/pull/307)) ## [3.0.0] - 2024-05-17 diff --git a/buildpacks/ruby/src/steps/get_default_process.rs b/buildpacks/ruby/src/steps/get_default_process.rs index 503ac958..90e70dae 100644 --- a/buildpacks/ruby/src/steps/get_default_process.rs +++ b/buildpacks/ruby/src/steps/get_default_process.rs @@ -71,8 +71,8 @@ fn default_rack() -> Process { "-c", &[ "bundle exec rackup", + "--host \"[::]\"", "--port \"${PORT:?Error: PORT env var is not set!}\"", - "--host \"0.0.0.0\"", ] .join(" "), ]) @@ -86,6 +86,7 @@ fn default_rails() -> Process { "-c", &[ "bin/rails server", + "--binding \"[::]\"", "--port \"${PORT:?Error: PORT env var is not set!}\"", "--environment \"$RAILS_ENV\"", ] diff --git a/buildpacks/ruby/tests/fixtures/default_ruby/Gemfile b/buildpacks/ruby/tests/fixtures/default_ruby/Gemfile index 237066dd..7fb164a0 100644 --- a/buildpacks/ruby/tests/fixtures/default_ruby/Gemfile +++ b/buildpacks/ruby/tests/fixtures/default_ruby/Gemfile @@ -2,4 +2,5 @@ source "https://rubygems.org" gem 'rack' gem 'rake' -gem 'webrick' +gem 'puma' +gem 'rackup' diff --git a/buildpacks/ruby/tests/fixtures/default_ruby/Gemfile.lock b/buildpacks/ruby/tests/fixtures/default_ruby/Gemfile.lock index 7219363d..e12918dc 100644 --- a/buildpacks/ruby/tests/fixtures/default_ruby/Gemfile.lock +++ b/buildpacks/ruby/tests/fixtures/default_ruby/Gemfile.lock @@ -1,14 +1,22 @@ GEM remote: https://rubygems.org/ specs: - rack (2.2.3) - rake (13.0.6) - webrick (1.7.0) + nio4r (2.7.4) + puma (6.5.0) + nio4r (~> 2.0) + rack (3.1.8) + rackup (2.2.1) + rack (>= 3) + rake (13.2.1) PLATFORMS ruby DEPENDENCIES + puma rack + rackup rake - webrick + +BUNDLED WITH + 2.5.23 diff --git a/buildpacks/ruby/tests/integration_test.rs b/buildpacks/ruby/tests/integration_test.rs index f9bf6c7c..ece3ea13 100644 --- a/buildpacks/ruby/tests/integration_test.rs +++ b/buildpacks/ruby/tests/integration_test.rs @@ -55,7 +55,7 @@ fn test_default_app_ubuntu20() { context.pack_stdout, r#"`BUNDLE_BIN="/layers/heroku_ruby/gems/bin" BUNDLE_CLEAN="1" BUNDLE_DEPLOYMENT="1" BUNDLE_GEMFILE="/workspace/Gemfile" BUNDLE_PATH="/layers/heroku_ruby/gems" BUNDLE_WITHOUT="development:test" bundle install`"#); - assert_contains!(context.pack_stdout, "Installing webrick"); + assert_contains!(context.pack_stdout, "Installing puma"); }, ); } @@ -72,7 +72,7 @@ fn test_default_app_ubuntu22() { context.pack_stdout, r#"`BUNDLE_BIN="/layers/heroku_ruby/gems/bin" BUNDLE_CLEAN="1" BUNDLE_DEPLOYMENT="1" BUNDLE_GEMFILE="/workspace/Gemfile" BUNDLE_PATH="/layers/heroku_ruby/gems" BUNDLE_WITHOUT="development:test" bundle install`"#); - assert_contains!(context.pack_stdout, "Installing webrick"); + assert_contains!(context.pack_stdout, "Installing puma"); }, ); } @@ -91,7 +91,7 @@ fn test_default_app_latest_distro() { context.pack_stdout, r#"`BUNDLE_BIN="/layers/heroku_ruby/gems/bin" BUNDLE_CLEAN="1" BUNDLE_DEPLOYMENT="1" BUNDLE_GEMFILE="/workspace/Gemfile" BUNDLE_PATH="/layers/heroku_ruby/gems" BUNDLE_WITHOUT="development:test" bundle install`"#); - assert_contains!(context.pack_stdout, "Installing webrick"); + assert_contains!(context.pack_stdout, "Installing puma"); let config = context.config.clone(); context.rebuild(config, |rebuild_context| { @@ -107,8 +107,9 @@ fn test_default_app_latest_distro() { let body = response.into_string().unwrap(); let server_logs = container.logs_now(); - assert_contains!(server_logs.stderr, "WEBrick::HTTPServer#start"); - assert_empty!(server_logs.stdout); + + assert_contains!(server_logs.stdout, "Puma starting"); + assert_empty!(server_logs.stderr); assert_contains!(body, "ruby_version"); }, diff --git a/docs/application_contract.md b/docs/application_contract.md index df365d19..effac1da 100644 --- a/docs/application_contract.md +++ b/docs/application_contract.md @@ -61,9 +61,9 @@ Once an application has passed the detect phase, the build phase will execute to - We will delete the least recently used (LRU) files first. Detected via file mtime. - Process types: - Given an application with the `railties` gem: - - We will default the web process to `bin/rails server` while specifying `-p $PORT` and `-e $RAILS_ENV"`. Use the `Procfile` to override this default. + - We will default the web process to `bin/rails server` while specifying `--port $PORT`, `--environment $RAILS_ENV"` and an IPv6 host with `--binding "::"` (equivalent of IPv4 host `0.0.0.0`). Use the `Procfile` to override this default. - If `railties` gem is not found but `rack` gem is present and a `config.ru` file exists on root: - - We will default the web process to `rackup` while specifying `-p $PORT` and `-h 0.0.0.0`. Use the `Procfile` to override this default. . + - We will default the web process to `rackup` while specifying `--port $PORT` and IPv6 host with `--host "::"` (equivalent of IPv4 host `0.0.0.0`). Use the `Procfile` to override this default. . - Environment variable defaults - We will set a default for the following environment variables: - `JRUBY_OPTS="-Xcompile.invokedynamic=false"` - Invoke dynamic is a feature of the JVM intended to enhance support for dynamicaly typed languages (such as Ruby). This caused issues with Physion Passenger 4.0.16 and was disabled [details](https://github.com/heroku/heroku-buildpack-ruby/issues/145). You can override this value. - `RACK_ENV=${RACK_ENV:-"production"}` - An environment variable that may affect the behavior of Rack based webservers and webapps. You can override this value.