Skip to content

Commit 11a93a0

Browse files
dhhsampatbadhegmcgibbonfatkodimarafaelfranca
authored
Use Thruster by default to Rails 8 (rails#51793)
* Allow docker entrypoint script to have other preceeding commands in CMD and still run db:prepare if we are starting the server * Add Thruster by default * Include new binstub * Temporarily expose only 80 (via 3000) * Just expose 80 for now, Kamal will need to handle 443 * Correct typo in activerecord changelog [ci skip] Correct typo in activerecord changelog for -rails#50662 * Defer route drawing to the first request, or when url_helpers called. Executes the first routes reload in middleware, or when the route set url_helpers is called. Previously, this was executed unconditionally on boot, which can slow down boot time unnecessarily for larger apps with lots of routes. * Support `touch_all` in batches * Do not trigger devcontainer tests on pull requests We need to review the code before executing this workflow, so only trigger when someone merge to this repository. * Refactor `ActiveRecord::SignedId` to not rely on relation delegation Ref: rails#50396 Ref: rails#51776 `ActiveRecord::Relation` automatically delegates missing methods to the model class wrapped in a `scoping { }` block. This is to support scoping in user defined class methods. The problem however is that it's very error prone for the framework, because we can mistakenly call model methods from inside `Relation` and not realized we're applying a global scope. In the best case scenario it's just a waste of performance, but it can also lead to bugs like rails#51775 I'm planning to restrict this automatic delegation to methods defined in childs of `ActiveRecord::Base` only: rails#50396 but for this to work we must first refactor any Rails code that rely on it. * Refactor `ActiveRecord::TokenFor` to not rely on relation delegation Ref: rails#50396 Ref: rails#51776 `ActiveRecord::Relation` automatically delegates missing methods to the model class wrapped in a `scoping { }` block. This is to support scoping in user defined class methods. The problem however is that it's very error prone for the framework, because we can mistakenly call model methods from inside `Relation` and not realized we're applying a global scope. In the best case scenario it's just a waste of performance, but it can also lead to bugs like rails#51775 I'm planning to restrict this automatic delegation to methods defined in childs of `ActiveRecord::Base` only: rails#50396 but for this to work we must first refactor any Rails code that rely on it. * Fix: batch test assertion order Co-authored-by: Chedli Bourguiba <[email protected]> * Move `ActiveRecord::Base.delete` in `Relation` Ref: rails#50396 * Move `ActiveRecord::Base.destroy` in `Relation` Ref: rails#50396 * Move `ActiveRecord::Base.insert` in `Relation` Ref: rails#50396 As well as related methods. * Use `foreign_key` option for destroy_async test models This pull request replaces the deprecated `query_constraints:` option with `foreign_key` for destroy_async test models. Follow up rails#51571 - This commit addresses these two warnings below: ``` % bin/test test/activejob/destroy_association_async_test.rb Using sqlite3 DEPRECATION WARNING: Setting `query_constraints:` option on `Cpk::BookDestroyAsync.has_many :chapters` is deprecated. To maintain current behavior, use the `foreign_key` option instead. (called from new at /Users/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/reflection.rb:19) /Users/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/reflection.rb:19:in `new' /Users/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/reflection.rb:19:in `create' /Users/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/associations/builder/association.rb:50:in `create_reflection' /Users/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/associations/builder/association.rb:32:in `build' /Users/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/associations.rb:1531:in `has_many' /Users/yahonda/src/github.com/rails/rails/activerecord/test/models/cpk/book_destroy_async.rb:7:in `<class:BookDestroyAsync>' /Users/yahonda/src/github.com/rails/rails/activerecord/test/models/cpk/book_destroy_async.rb:4:in `<module:Cpk>' /Users/yahonda/src/github.com/rails/rails/activerecord/test/models/cpk/book_destroy_async.rb:3:in `<top (required)>' /Users/yahonda/.rbenv/versions/3.3.1/lib/ruby/3.3.0/bundled_gems.rb:74:in `require' /Users/yahonda/.rbenv/versions/3.3.1/lib/ruby/3.3.0/bundled_gems.rb:74:in `block (2 levels) in replace_require' /Users/yahonda/src/github.com/rails/rails/activerecord/test/activejob/destroy_association_async_test.rb:27:in `<top (required)>' /Users/yahonda/.rbenv/versions/3.3.1/lib/ruby/3.3.0/bundled_gems.rb:74:in `require' /Users/yahonda/.rbenv/versions/3.3.1/lib/ruby/3.3.0/bundled_gems.rb:74:in `block (2 levels) in replace_require' /Users/yahonda/src/github.com/rails/rails/railties/lib/rails/test_unit/runner.rb:61:in `block in load_tests' /Users/yahonda/src/github.com/rails/rails/railties/lib/rails/test_unit/runner.rb:60:in `each' /Users/yahonda/src/github.com/rails/rails/railties/lib/rails/test_unit/runner.rb:60:in `load_tests' /Users/yahonda/src/github.com/rails/rails/railties/lib/rails/test_unit/runner.rb:52:in `run' /Users/yahonda/src/github.com/rails/rails/activerecord/test/support/tools.rb:37:in `<top (required)>' bin/test:11:in `require_relative' bin/test:11:in `<main>' DEPRECATION WARNING: Setting `query_constraints:` option on `Cpk::ChapterDestroyAsync.belongs_to :book` is deprecated. To maintain current behavior, use the `foreign_key` option instead. (called from new at /Users/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/reflection.rb:19) /Users/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/reflection.rb:19:in `new' /Users/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/reflection.rb:19:in `create' /Users/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/associations/builder/association.rb:50:in `create_reflection' /Users/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/associations/builder/association.rb:32:in `build' /Users/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/associations.rb:1910:in `belongs_to' /Users/yahonda/src/github.com/rails/rails/activerecord/test/models/cpk/chapter_destroy_async.rb:8:in `<class:ChapterDestroyAsync>' /Users/yahonda/src/github.com/rails/rails/activerecord/test/models/cpk/chapter_destroy_async.rb:4:in `<module:Cpk>' /Users/yahonda/src/github.com/rails/rails/activerecord/test/models/cpk/chapter_destroy_async.rb:3:in `<top (required)>' /Users/yahonda/.rbenv/versions/3.3.1/lib/ruby/3.3.0/bundled_gems.rb:74:in `require' /Users/yahonda/.rbenv/versions/3.3.1/lib/ruby/3.3.0/bundled_gems.rb:74:in `block (2 levels) in replace_require' /Users/yahonda/src/github.com/rails/rails/activerecord/test/activejob/destroy_association_async_test.rb:28:in `<top (required)>' /Users/yahonda/.rbenv/versions/3.3.1/lib/ruby/3.3.0/bundled_gems.rb:74:in `require' /Users/yahonda/.rbenv/versions/3.3.1/lib/ruby/3.3.0/bundled_gems.rb:74:in `block (2 levels) in replace_require' /Users/yahonda/src/github.com/rails/rails/railties/lib/rails/test_unit/runner.rb:61:in `block in load_tests' /Users/yahonda/src/github.com/rails/rails/railties/lib/rails/test_unit/runner.rb:60:in `each' /Users/yahonda/src/github.com/rails/rails/railties/lib/rails/test_unit/runner.rb:60:in `load_tests' /Users/yahonda/src/github.com/rails/rails/railties/lib/rails/test_unit/runner.rb:52:in `run' /Users/yahonda/src/github.com/rails/rails/activerecord/test/support/tools.rb:37:in `<top (required)>' bin/test:11:in `require_relative' bin/test:11:in `<main>' Run options: --seed 24461 .................... Finished in 0.199597s, 100.2019 runs/s, 370.7471 assertions/s. 20 runs, 74 assertions, 0 failures, 0 errors, 0 skips % ``` * Suppress RuboCop output when there are no offenses in code generation Follow up rails#51782. > But it's overkill for the default case where people use the default style guide, > and it introduces both delay and console output as a cost. When there are no offenses with the coding style generated by code generation, outputting RuboCop results to the console was redundant. Since RuboCop has `--format=quiet` option that suppresses console output when there are no offenses, this PR adds that option: https://docs.rubocop.org/rubocop/1.63/formatters.html#quiet-formatter While this PR doesn't resolve any added execution speed by RuboCop, the frequency of using the generator is not high within the development flow. Therefore, depending on the execution speed, it might be possible to uncomment rails#51782, but this PR respects the defaults in rails#51782 and doesn't address that. * Enable Lint/Debugger This will prevent issues like be0cb4e, which would have resulted in: ``` guides/rails_guides/generator.rb:16:1: W: Lint/Debugger: Remove debugger entry point require "debug". require "debug" ^^^^^^^^^^^^^^^ ``` Disabled the cop in actionpack tests for screenshot_helper and page_dump_helper: ``` actionpack/test/controller/integration_test.rb:1369:9: W: Lint/Debugger: Remove debugger entry point save_and_open_page. save_and_open_page ^^^^^^^^^^^^^^^^^^ actionpack/test/controller/integration_test.rb:1381:11: W: Lint/Debugger: Remove debugger entry point save_and_open_page. save_and_open_page ^^^^^^^^^^^^^^^^^^ actionpack/test/controller/integration_test.rb:1391:39: W: Lint/Debugger: Remove debugger entry point save_and_open_page. assert_raise(InvalidResponse) { save_and_open_page } ^^^^^^^^^^^^^^^^^^ ``` ``` actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb:111:13: W: Lint/Debugger: Remove debugger entry point page.save_page(absolute_html_path). page.save_page(absolute_html_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb:115:13: W: Lint/Debugger: Remove debugger entry point page.save_screenshot(absolute_image _path). page.save_screenshot(absolute_image_path) ``` The DebuggerRequires option was first available in rubocop v1.63.0, in rubocop/rubocop#12766. * Support `duration` in `ActiveSupport::XmlMini` * Development of Rails 8.0 starts now :tada: * Reapply "Rails 8 will target Ruby 3.3+ only for new apps" This reverts commit 64ab211. * Clean CHANGELOG for 8.0 * Fix rubocop See rubocop/rubocop#12898 for the issue. * Add name to DevContainer compose file Currently when you generate a project the compose.yaml generated file does not include the top-level name property. Not having this top-level name property makes all containers / volumes started by devcontainer to be prepended with the folder name, which is `devcontainer` in the case of the .devcontainer/compose.yml` file. This is ok if you run only one project with devcontainer but starts to get problem if you run multiple projects. If you have one project that runs on postgresql 15 and a new one that runs on postgresql 16 it will fail to boot the postgresql container because both devcontainers is using the same volume: `devcontainer_postgres-data`. This commit fixes this by setting the top-lavel name property with the project name, which will make the containers and volumes to be prepended with the project name and not with `devcontainer`. * Remove support for oracle, sqlserver and JRuby specific database adapters from the new and db:system:change commands. The supported options are sqlite3, mysql, postgresql and trilogy. * Refactoring Database generators Extract all the DB information (gems, dockerfile packages, devcontainer etc.) into an object. This let's us remove the growing number of case statements in this code. * This will be released in 7.2 * Merge pull request rails#51766 from Shopify/revert-actionable-errors-retry Revert "Merge pull request rails#50941 from andrewn617/actionable-cli" * Point user to devcontainer for containerized dev environment * Add Highlights section in the Rails 7.1 release notes * Fix `ActiveRecord::Relation#touch_all` with custom attribute aliased as attribute for update * Remove jruby and oracle related gems from Gemfile We are only know goign to support mysql2, trilogy, postgresql and sqlite3 adapters in Rails. * Add Kamal by default to Rails 8 (rails#51798) * Add Kamal by default * Excess CR * Add Thruster for testing * Update comment to reflect shrunken responsibilities * Use latest Thruster --------- Co-authored-by: Sampat Badhe <[email protected]> Co-authored-by: Gannon McGibbon <[email protected]> Co-authored-by: fatkodima <[email protected]> Co-authored-by: Rafael Mendonça França <[email protected]> Co-authored-by: Jean Boussier <[email protected]> Co-authored-by: Akhil G Krishnan <[email protected]> Co-authored-by: Chedli Bourguiba <[email protected]> Co-authored-by: Yasuo Honda <[email protected]> Co-authored-by: Koichi ITO <[email protected]> Co-authored-by: zzak <[email protected]> Co-authored-by: heka1024 <[email protected]> Co-authored-by: Cadu Ribeiro <[email protected]> Co-authored-by: Andrew Novoselac <[email protected]>
1 parent 8e4a3c0 commit 11a93a0

File tree

10 files changed

+48
-5
lines changed

10 files changed

+48
-5
lines changed

Gemfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ gem "importmap-rails", ">= 1.2.3"
2222
gem "tailwindcss-rails"
2323
gem "dartsass-rails"
2424
gem "kamal", require: false
25+
gem "thruster", require: false
2526
# require: false so bcrypt is loaded only when has_secure_password is used.
2627
# This is to avoid Active Model (and by extension the entire framework)
2728
# being dependent on a binary library.

Gemfile.lock

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,9 @@ GEM
582582
terser (1.1.20)
583583
execjs (>= 0.3.0, < 3)
584584
thor (1.3.0)
585+
thruster (0.1.7)
586+
thruster (0.1.7-x86_64-darwin)
587+
thruster (0.1.7-x86_64-linux)
585588
timeout (0.4.1)
586589
tomlrb (2.0.3)
587590
trailblazer-option (0.1.2)
@@ -696,6 +699,7 @@ DEPENDENCIES
696699
syntax_tree (= 6.1.1)
697700
tailwindcss-rails
698701
terser (>= 1.1.4)
702+
thruster
699703
trilogy (>= 2.7.0)
700704
turbo-rails
701705
tzinfo-data
@@ -708,4 +712,4 @@ DEPENDENCIES
708712
websocket-client-simple!
709713

710714
BUNDLED WITH
711-
2.5.4
715+
2.5.16

railties/lib/rails/generators/app_base.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ def self.add_shared_options_for(name)
9999
class_option :skip_dev_gems, type: :boolean, default: nil,
100100
desc: "Skip development gems (e.g., web-console)"
101101

102+
class_option :skip_thruster, type: :boolean, default: nil,
103+
desc: "Skip Thruster setup"
104+
102105
class_option :skip_rubocop, type: :boolean, default: nil,
103106
desc: "Skip RuboCop setup"
104107

@@ -397,6 +400,10 @@ def skip_propshaft?
397400
skip_asset_pipeline? || options[:asset_pipeline] != "propshaft"
398401
end
399402

403+
def skip_thruster?
404+
options[:skip_thruster]
405+
end
406+
400407
def skip_rubocop?
401408
options[:skip_rubocop]
402409
end

railties/lib/rails/generators/rails/app/app_generator.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ def app
109109
end
110110

111111
def bin
112-
exclude_pattern = Regexp.union([(/rubocop/ if skip_rubocop?), (/brakeman/ if skip_brakeman?)].compact)
112+
exclude_pattern = Regexp.union([(/thrust/ if skip_thruster?), (/rubocop/ if skip_rubocop?), (/brakeman/ if skip_brakeman?)].compact)
113113
directory "bin", { exclude_pattern: exclude_pattern } do |content|
114114
"#{shebang}\n" + content
115115
end

railties/lib/rails/generators/rails/app/templates/Dockerfile.tt

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
# check=error=true
33

44
# This Dockerfile is designed for production, not development. Use with Kamal or build'n'run by hand:
5-
# docker build -t my-app .
6-
# docker run -d -p 80:80 -p 443:443 --name my-app -e RAILS_MASTER_KEY=<value from config/master.key> my-app
5+
# docker build -t <%= app_name %> .
6+
# docker run -d -p 80:<%= skip_thruster? ? 3000 : 80 %> -e RAILS_MASTER_KEY=<value from config/master.key> --name <%= app_name %> <%= app_name %>
7+
8+
# For a containerized dev environment, see Dev Containers: https://guides.rubyonrails.org/getting_started_with_devcontainer.html
79

810
# For a containerized dev environment, see Dev Containers: https://guides.rubyonrails.org/getting_started_with_devcontainer.html
911

@@ -108,6 +110,12 @@ USER 1000:1000
108110
# Entrypoint prepares the database.
109111
ENTRYPOINT ["/rails/bin/docker-entrypoint"]
110112

113+
<% if skip_thruster? -%>
111114
# Start the server by default, this can be overwritten at runtime
112115
EXPOSE 3000
113116
CMD ["./bin/rails", "server"]
117+
<% else -%>
118+
# Start server via Thruster by default, this can be overwritten at runtime
119+
EXPOSE 80
120+
CMD ["./bin/thrust", "./bin/rails", "server"]
121+
<% end -%>

railties/lib/rails/generators/rails/app/templates/Gemfile.tt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ gem "bootsnap", require: false
2424
# Deploy this application anywhere as a Docker container [https://kamal-deploy.org]
2525
gem "kamal", require: false
2626
<% end -%>
27+
<% unless options.skip_thruster? -%>
28+
29+
# Add HTTP asset caching/compression and X-Sendfile acceleration to Puma [https://github.com/basecamp/thruster/]
30+
gem "thruster", require: false
31+
<% end -%>
2732
<% unless skip_active_storage? -%>
2833

2934
# Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images]
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
require "rubygems"
2+
require "bundler/setup"
3+
4+
load Gem.bin_path("thruster", "thrust")

railties/lib/rails/generators/rails/app/templates/docker-entrypoint.tt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ fi
77

88
<% unless skip_active_record? -%>
99
# If running the rails server then create or migrate existing database
10-
if [ "${1}" == "./bin/rails" ] && [ "${2}" == "server" ]; then
10+
if [ "${@: -2:1}" == "./bin/rails" ] && [ "${@: -1:1}" == "server" ]; then
1111
./bin/rails db:prepare
1212
fi
1313

railties/lib/rails/generators/rails/plugin/plugin_generator.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ def test
122122
def generate_test_dummy(force = false)
123123
opts = options.transform_keys(&:to_sym).except(*DUMMY_IGNORE_OPTIONS)
124124
opts[:force] = force
125+
opts[:skip_thruster] = true
125126
opts[:skip_brakeman] = true
126127
opts[:skip_bundle] = true
127128
opts[:skip_ci] = true

railties/test/generators/app_generator_test.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
bin/rake
3939
bin/rubocop
4040
bin/setup
41+
bin/thrust
4142
config.ru
4243
config/application.rb
4344
config/boot.rb
@@ -556,6 +557,18 @@ def test_inclusion_of_a_debugger
556557
end
557558
end
558559

560+
def test_inclusion_of_thruster
561+
run_generator
562+
assert_gem "thruster"
563+
end
564+
565+
def test_thruster_is_skipped_if_required
566+
run_generator [destination_root, "--skip-thruster"]
567+
568+
assert_no_gem "thruster"
569+
assert_no_file "bin/thrust"
570+
end
571+
559572
def test_inclusion_of_rubocop
560573
run_generator
561574
assert_gem "rubocop-rails-omakase"

0 commit comments

Comments
 (0)