diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index 6142ebc441b20..8e25c23b2fdcf 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,3 +1,11 @@ +* Enhanced `bin/dev` Script + + Previously, `bin/dev` would only start the Rails server. Gems requiring multiple processes override the `bin/dev` script to start Foreman instead, which prevents interaction with the Rails server console (debugger). + + This new `bin/dev` script starts Foreman in the background if a `Procfile.dev` is present and starts Rails in the foreground to allow debugging with breakpoints. + + *JoƩ Dupuis* + ## Rails 8.0.0.beta1 (September 26, 2024) ## * Exit `rails g` with code 1 if generator could not be found. diff --git a/railties/lib/rails/generators/rails/app/templates/bin/dev.tt b/railties/lib/rails/generators/rails/app/templates/bin/dev.tt index 89df11bc7ead3..7c9deb07b19e9 100644 --- a/railties/lib/rails/generators/rails/app/templates/bin/dev.tt +++ b/railties/lib/rails/generators/rails/app/templates/bin/dev.tt @@ -1 +1,37 @@ -exec "./bin/rails", "server", *ARGV +ENV["PORT"] ||= "3000" +VERBOSE = ARGV.include?("--verbose") || ARGV.include?("-v") || ENV["VERBOSE"] +RAILS_ARGS = ARGV - [ "--verbose", "-v" ] +PROCFILE = "Procfile.dev" +Process.exec(*%w[bundle exec rails server], *RAILS_ARGS) unless File.exist?(PROCFILE) + +Signal.trap("INT") { } + +if system(*%w[gem list --no-installed --exact --silent foreman]) + puts "Installing foreman..." + system(*%w[gem install foreman]) +end + +begin + in_r, in_w = IO.pipe + in_w.close + foreman_pid = Process.spawn( + *%w[foreman start -f Procfile.dev -m all=1,web=0 --env /dev/null], + in: in_r, + out: (VERBOSE ? STDOUT : "/dev/null"), + err: (VERBOSE ? STDOUT : "/dev/null"), + pgroup: true, + ) + foreman_pgid = Process.getpgid(foreman_pid) + pid = Process.spawn(*%w[bundle exec rails server], *RAILS_ARGS) + + Process.wait(pid) + pid = nil +ensure + Process.kill("INT", -foreman_pgid) + Process.wait(-foreman_pgid) + begin + Process.kill("KILL", pid) if pid + rescue Errno::ESRCH + end + in_r.close +end