railties 8.0.3 → 8.1.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +103 -205
- data/lib/minitest/rails_plugin.rb +48 -12
- data/lib/rails/application/bootstrap.rb +5 -0
- data/lib/rails/application/configuration.rb +31 -9
- data/lib/rails/application/default_middleware_stack.rb +1 -1
- data/lib/rails/application/finisher.rb +2 -1
- data/lib/rails/application/routes_reloader.rb +0 -1
- data/lib/rails/application.rb +1 -3
- data/lib/rails/code_statistics.rb +4 -1
- data/lib/rails/command/base.rb +0 -2
- data/lib/rails/command/environment_argument.rb +0 -1
- data/lib/rails/command.rb +1 -1
- data/lib/rails/commands/app/update_command.rb +1 -0
- data/lib/rails/commands/console/irb_console.rb +4 -4
- data/lib/rails/commands/credentials/credentials_command.rb +25 -5
- data/lib/rails/commands/encrypted/encrypted_command.rb +0 -1
- data/lib/rails/engine.rb +0 -1
- data/lib/rails/gem_version.rb +3 -3
- data/lib/rails/generators/actions.rb +2 -3
- data/lib/rails/generators/app_base.rb +49 -28
- data/lib/rails/generators/database.rb +1 -1
- data/lib/rails/generators/erb/authentication/authentication_generator.rb +2 -0
- data/lib/rails/generators/erb/scaffold/templates/partial.html.erb.tt +2 -2
- data/lib/rails/generators/generated_attribute.rb +1 -1
- data/lib/rails/generators/migration.rb +0 -1
- data/lib/rails/generators/rails/app/app_generator.rb +16 -5
- data/lib/rails/generators/rails/app/templates/Dockerfile.tt +19 -15
- data/lib/rails/generators/rails/app/templates/Gemfile.tt +6 -1
- data/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb.tt +5 -0
- data/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +1 -0
- data/lib/rails/generators/rails/app/templates/bin/bundler-audit.tt +5 -0
- data/lib/rails/generators/rails/app/templates/bin/ci.tt +5 -0
- data/lib/rails/generators/rails/app/templates/bin/rubocop.tt +1 -1
- data/lib/rails/generators/rails/app/templates/bin/setup.tt +1 -0
- data/lib/rails/generators/rails/app/templates/config/bundler-audit.yml.tt +5 -0
- data/lib/rails/generators/rails/app/templates/config/ci.rb.tt +38 -0
- data/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt +9 -1
- data/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml.tt +10 -2
- data/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml.tt +1 -1
- data/lib/rails/generators/rails/app/templates/config/databases/trilogy.yml.tt +9 -1
- data/lib/rails/generators/rails/app/templates/config/deploy.yml.tt +8 -5
- data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +8 -0
- data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +2 -2
- data/lib/rails/generators/rails/app/templates/config/initializers/content_security_policy.rb.tt +4 -0
- data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_8_1.rb.tt +93 -0
- data/lib/rails/generators/rails/app/templates/config/puma.rb.tt +3 -2
- data/lib/rails/generators/rails/app/templates/config/storage.yml.tt +0 -7
- data/lib/rails/generators/rails/app/templates/docker-entrypoint.tt +0 -6
- data/lib/rails/generators/rails/app/templates/github/ci.yml.tt +107 -21
- data/lib/rails/generators/rails/app/templates/github/dependabot.yml +2 -2
- data/lib/rails/generators/rails/app/templates/kamal-secrets.tt +3 -0
- data/lib/rails/generators/rails/app/templates/public/400.html +1 -1
- data/lib/rails/generators/rails/app/templates/public/404.html +2 -2
- data/lib/rails/generators/rails/app/templates/public/422.html +1 -1
- data/lib/rails/generators/rails/app/templates/public/500.html +2 -2
- data/lib/rails/generators/rails/authentication/authentication_generator.rb +8 -6
- data/lib/rails/generators/rails/authentication/templates/app/controllers/passwords_controller.rb.tt +6 -0
- data/lib/rails/generators/rails/authentication/templates/app/controllers/sessions_controller.rb.tt +2 -2
- data/lib/rails/generators/rails/authentication/templates/app/views/passwords_mailer/reset.html.erb.tt +3 -1
- data/lib/rails/generators/rails/authentication/templates/app/views/passwords_mailer/reset.text.erb.tt +3 -1
- data/lib/rails/generators/rails/benchmark/USAGE +1 -1
- data/lib/rails/generators/rails/benchmark/templates/benchmark.rb.tt +0 -2
- data/lib/rails/generators/rails/devcontainer/devcontainer_generator.rb +1 -1
- data/lib/rails/generators/rails/devcontainer/templates/devcontainer/Dockerfile.tt +4 -0
- data/lib/rails/generators/rails/devcontainer/templates/devcontainer/compose.yaml.tt +2 -2
- data/lib/rails/generators/rails/devcontainer/templates/devcontainer/devcontainer.json.tt +1 -1
- data/lib/rails/generators/rails/encryption_key_file/encryption_key_file_generator.rb +17 -5
- data/lib/rails/generators/rails/master_key/master_key_generator.rb +0 -12
- data/lib/rails/generators/rails/plugin/plugin_generator.rb +1 -0
- data/lib/rails/generators/rails/plugin/templates/Rakefile.tt +0 -4
- data/lib/rails/generators/rails/plugin/templates/github/ci.yml.tt +20 -9
- data/lib/rails/generators/rails/plugin/templates/github/dependabot.yml +2 -2
- data/lib/rails/generators/rails/script/USAGE +1 -1
- data/lib/rails/generators/test_unit/authentication/authentication_generator.rb +13 -0
- data/lib/rails/generators/test_unit/authentication/templates/test/controllers/passwords_controller_test.rb.tt +67 -0
- data/lib/rails/generators/test_unit/authentication/templates/test/controllers/sessions_controller_test.rb +33 -0
- data/lib/rails/generators/test_unit/authentication/templates/test/models/user_test.rb.tt +4 -3
- data/lib/rails/generators/test_unit/authentication/templates/test/test_helpers/session_test_helper.rb.tt +19 -0
- data/lib/rails/generators/test_unit/model/templates/fixtures.yml.tt +1 -1
- data/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb +4 -2
- data/lib/rails/generators/testing/behavior.rb +0 -3
- data/lib/rails/generators.rb +3 -1
- data/lib/rails/health_controller.rb +8 -2
- data/lib/rails/info.rb +4 -5
- data/lib/rails/info_controller.rb +4 -5
- data/lib/rails/initializable.rb +63 -19
- data/lib/rails/rack/silence_request.rb +5 -2
- data/lib/rails/railtie/configurable.rb +0 -1
- data/lib/rails/railtie.rb +0 -1
- data/lib/rails/tasks/statistics.rake +3 -21
- data/lib/rails/tasks.rb +1 -3
- data/lib/rails/templates/rails/info/notes.html.erb +23 -0
- data/lib/rails/templates/rails/mailers/email.html.erb +2 -1
- data/lib/rails/templates/rails/welcome/index.html.erb +19 -3
- data/lib/rails/test_unit/reporter.rb +5 -4
- data/lib/rails/test_unit/runner.rb +8 -5
- data/lib/rails.rb +9 -2
- metadata +18 -15
- data/lib/rails/console/methods.rb +0 -7
- data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_8_0.rb.tt +0 -30
- data/lib/rails/generators/test_unit/plugin/plugin_generator.rb +0 -15
- data/lib/rails/generators/test_unit/plugin/templates/%file_name%_test.rb.tt +0 -7
- data/lib/rails/generators/test_unit/plugin/templates/test_helper.rb +0 -2
data/lib/rails/command/base.rb
CHANGED
data/lib/rails/command.rb
CHANGED
|
@@ -73,6 +73,7 @@ module Rails
|
|
|
73
73
|
skip_action_text: !defined?(ActionText::Engine),
|
|
74
74
|
skip_action_cable: !defined?(ActionCable::Engine),
|
|
75
75
|
skip_brakeman: skip_gem?("brakeman"),
|
|
76
|
+
skip_bundler_audit: skip_gem?("bundler-audit"),
|
|
76
77
|
skip_rubocop: skip_gem?("rubocop"),
|
|
77
78
|
skip_thruster: skip_gem?("thruster"),
|
|
78
79
|
skip_test: !defined?(Rails::TestUnitRailtie),
|
|
@@ -91,9 +91,9 @@ module Rails
|
|
|
91
91
|
IRB.conf[:IRB_NAME] = @app.name if IRB.conf[:IRB_NAME] == "irb"
|
|
92
92
|
|
|
93
93
|
IRB.conf[:PROMPT][:RAILS_PROMPT] = {
|
|
94
|
-
PROMPT_I: "#{prompt_prefix}> ",
|
|
95
|
-
PROMPT_S: "#{prompt_prefix}%l ",
|
|
96
|
-
PROMPT_C: "#{prompt_prefix}* ",
|
|
94
|
+
PROMPT_I: "#{prompt_prefix}:%03n> ",
|
|
95
|
+
PROMPT_S: "#{prompt_prefix}:%03n%l ",
|
|
96
|
+
PROMPT_C: "#{prompt_prefix}:%03n* ",
|
|
97
97
|
RETURN: "=> %s\n"
|
|
98
98
|
}
|
|
99
99
|
|
|
@@ -122,7 +122,7 @@ module Rails
|
|
|
122
122
|
when "production"
|
|
123
123
|
IRB::Color.colorize("prod", [:RED])
|
|
124
124
|
else
|
|
125
|
-
Rails.env
|
|
125
|
+
IRB::Color.colorize(Rails.env, [:MAGENTA])
|
|
126
126
|
end
|
|
127
127
|
end
|
|
128
128
|
end
|
|
@@ -35,7 +35,7 @@ module Rails
|
|
|
35
35
|
def show
|
|
36
36
|
load_environment_config!
|
|
37
37
|
|
|
38
|
-
say credentials.read.presence ||
|
|
38
|
+
say credentials.read.presence || missing_credentials!
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
desc "diff", "Enroll/disenroll in decrypted diffs of credentials using git"
|
|
@@ -57,6 +57,26 @@ module Rails
|
|
|
57
57
|
say credentials.content_path.read
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
+
desc "fetch PATH", "Fetch a value in the decrypted credentials"
|
|
61
|
+
def fetch(path)
|
|
62
|
+
load_environment_config!
|
|
63
|
+
|
|
64
|
+
if (yaml = credentials.read)
|
|
65
|
+
begin
|
|
66
|
+
value = YAML.load(yaml)
|
|
67
|
+
value = path.split(".").inject(value) do |doc, key|
|
|
68
|
+
doc.fetch(key)
|
|
69
|
+
end
|
|
70
|
+
say value.to_s
|
|
71
|
+
rescue KeyError, NoMethodError
|
|
72
|
+
say_error "Invalid or missing credential path: #{path}"
|
|
73
|
+
exit 1
|
|
74
|
+
end
|
|
75
|
+
else
|
|
76
|
+
missing_credentials!
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
60
80
|
private
|
|
61
81
|
def config
|
|
62
82
|
Rails.application.config.credentials
|
|
@@ -81,7 +101,6 @@ module Rails
|
|
|
81
101
|
|
|
82
102
|
encryption_key_file_generator = Rails::Generators::EncryptionKeyFileGenerator.new
|
|
83
103
|
encryption_key_file_generator.add_key_file(key_path)
|
|
84
|
-
encryption_key_file_generator.ignore_key_file(key_path)
|
|
85
104
|
end
|
|
86
105
|
|
|
87
106
|
def ensure_credentials_have_been_added
|
|
@@ -115,12 +134,13 @@ module Rails
|
|
|
115
134
|
say "Your application will not be able to load '#{content_path}' until the error has been fixed.", :red
|
|
116
135
|
end
|
|
117
136
|
|
|
118
|
-
def
|
|
137
|
+
def missing_credentials!
|
|
119
138
|
if !credentials.key?
|
|
120
|
-
"Missing '#{key_path}' to decrypt credentials. See `#{executable(:help)}`."
|
|
139
|
+
say_error "Missing '#{key_path}' to decrypt credentials. See `#{executable(:help)}`."
|
|
121
140
|
else
|
|
122
|
-
"File '#{content_path}' does not exist. Use `#{executable(:edit)}` to change that."
|
|
141
|
+
say_error "File '#{content_path}' does not exist. Use `#{executable(:edit)}` to change that."
|
|
123
142
|
end
|
|
143
|
+
exit 1
|
|
124
144
|
end
|
|
125
145
|
|
|
126
146
|
def relative_path(path)
|
|
@@ -45,7 +45,6 @@ module Rails
|
|
|
45
45
|
def ensure_encryption_key_has_been_added
|
|
46
46
|
return if encrypted_configuration.key?
|
|
47
47
|
encryption_key_file_generator.add_key_file(key_path)
|
|
48
|
-
encryption_key_file_generator.ignore_key_file(key_path)
|
|
49
48
|
end
|
|
50
49
|
|
|
51
50
|
def ensure_encrypted_configuration_has_been_added
|
data/lib/rails/engine.rb
CHANGED
data/lib/rails/gem_version.rb
CHANGED
|
@@ -445,11 +445,10 @@ module Rails
|
|
|
445
445
|
|
|
446
446
|
private
|
|
447
447
|
# Define log for backwards compatibility. If just one argument is sent,
|
|
448
|
-
# invoke +say+, otherwise invoke +say_status+.
|
|
449
|
-
# similarly to +say_status+, this method respects the +quiet?+ option given.
|
|
448
|
+
# invoke +say+, otherwise invoke +say_status+.
|
|
450
449
|
def log(*args) # :doc:
|
|
451
450
|
if args.size == 1
|
|
452
|
-
say args.first.to_s
|
|
451
|
+
say args.first.to_s
|
|
453
452
|
else
|
|
454
453
|
args << (behavior == :invoke ? :green : :red)
|
|
455
454
|
say_status(*args)
|
|
@@ -73,7 +73,8 @@ module Rails
|
|
|
73
73
|
class_option :skip_action_cable, type: :boolean, aliases: "-C", default: nil,
|
|
74
74
|
desc: "Skip Action Cable files"
|
|
75
75
|
|
|
76
|
-
class_option :skip_asset_pipeline, type: :boolean, aliases: "-A", default: nil
|
|
76
|
+
class_option :skip_asset_pipeline, type: :boolean, aliases: "-A", default: nil,
|
|
77
|
+
desc: "Skip the asset pipeline setup"
|
|
77
78
|
|
|
78
79
|
class_option :skip_javascript, type: :boolean, aliases: ["-J", "--skip-js"], default: (true if name == "plugin"),
|
|
79
80
|
desc: "Skip JavaScript files"
|
|
@@ -105,6 +106,9 @@ module Rails
|
|
|
105
106
|
class_option :skip_brakeman, type: :boolean, default: nil,
|
|
106
107
|
desc: "Skip brakeman setup"
|
|
107
108
|
|
|
109
|
+
class_option :skip_bundler_audit, type: :boolean, default: nil,
|
|
110
|
+
desc: "Skip bundler-audit setup"
|
|
111
|
+
|
|
108
112
|
class_option :skip_ci, type: :boolean, default: nil,
|
|
109
113
|
desc: "Skip GitHub CI files"
|
|
110
114
|
|
|
@@ -399,6 +403,10 @@ module Rails
|
|
|
399
403
|
options[:skip_brakeman]
|
|
400
404
|
end
|
|
401
405
|
|
|
406
|
+
def skip_bundler_audit?
|
|
407
|
+
options[:skip_bundler_audit]
|
|
408
|
+
end
|
|
409
|
+
|
|
402
410
|
def skip_ci?
|
|
403
411
|
options[:skip_ci]
|
|
404
412
|
end
|
|
@@ -493,7 +501,7 @@ module Rails
|
|
|
493
501
|
def javascript_gemfile_entry
|
|
494
502
|
return if options[:skip_javascript]
|
|
495
503
|
|
|
496
|
-
if
|
|
504
|
+
if using_importmap?
|
|
497
505
|
GemfileEntry.floats "importmap-rails", "Use JavaScript with ESM import maps [https://github.com/rails/importmap-rails]"
|
|
498
506
|
else
|
|
499
507
|
GemfileEntry.floats "jsbundling-rails", "Bundle and transpile JavaScript [https://github.com/rails/jsbundling-rails]"
|
|
@@ -512,9 +520,12 @@ module Rails
|
|
|
512
520
|
[ turbo_rails_entry, stimulus_rails_entry ]
|
|
513
521
|
end
|
|
514
522
|
|
|
523
|
+
def using_importmap?
|
|
524
|
+
!options.skip_javascript? && options[:javascript] == "importmap"
|
|
525
|
+
end
|
|
526
|
+
|
|
515
527
|
def using_js_runtime?
|
|
516
|
-
(options[:
|
|
517
|
-
(options[:css] && !%w[tailwind sass].include?(options[:css]))
|
|
528
|
+
!options.skip_javascript? && (!using_importmap? || (options[:css] && !%w[tailwind sass].include?(options[:css])))
|
|
518
529
|
end
|
|
519
530
|
|
|
520
531
|
def using_node?
|
|
@@ -525,31 +536,35 @@ module Rails
|
|
|
525
536
|
using_js_runtime? && %w[bun].include?(options[:javascript])
|
|
526
537
|
end
|
|
527
538
|
|
|
539
|
+
def capture_command(command, pattern = nil)
|
|
540
|
+
output = `#{command}`
|
|
541
|
+
if pattern
|
|
542
|
+
output[pattern]
|
|
543
|
+
else
|
|
544
|
+
output
|
|
545
|
+
end
|
|
546
|
+
rescue SystemCallError
|
|
547
|
+
nil
|
|
548
|
+
end
|
|
549
|
+
|
|
528
550
|
def node_version
|
|
529
551
|
if using_node?
|
|
530
552
|
ENV.fetch("NODE_VERSION") do
|
|
531
|
-
|
|
532
|
-
rescue
|
|
533
|
-
NODE_LTS_VERSION
|
|
553
|
+
capture_command("node --version", /\d+\.\d+\.\d+/) || NODE_LTS_VERSION
|
|
534
554
|
end
|
|
535
555
|
end
|
|
536
556
|
end
|
|
537
557
|
|
|
538
558
|
def dockerfile_yarn_version
|
|
539
|
-
|
|
540
|
-
rescue
|
|
541
|
-
"latest"
|
|
559
|
+
capture_command("yarn --version", /\d+\.\d+\.\d+/) || "latest"
|
|
542
560
|
end
|
|
543
561
|
|
|
544
562
|
def yarn_through_corepack?
|
|
545
|
-
|
|
546
|
-
dockerfile_yarn_version >= "2"
|
|
563
|
+
using_node? and "#{dockerfile_yarn_version}" >= "2"
|
|
547
564
|
end
|
|
548
565
|
|
|
549
566
|
def dockerfile_bun_version
|
|
550
|
-
|
|
551
|
-
rescue
|
|
552
|
-
BUN_VERSION
|
|
567
|
+
capture_command("bun --version", /\d+\.\d+\.\d+/) || BUN_VERSION
|
|
553
568
|
end
|
|
554
569
|
|
|
555
570
|
def dockerfile_binfile_fixups
|
|
@@ -617,11 +632,16 @@ module Rails
|
|
|
617
632
|
end
|
|
618
633
|
|
|
619
634
|
def ci_packages
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
635
|
+
dockerfile_build_packages - [
|
|
636
|
+
# GitHub Actions doesn't have build-essential,
|
|
637
|
+
# but it's a meta-packages and all its dependencies are already installed.
|
|
638
|
+
"build-essential",
|
|
639
|
+
"git",
|
|
640
|
+
"pkg-config",
|
|
641
|
+
"libyaml-dev",
|
|
642
|
+
"unzip",
|
|
643
|
+
"python-is-python3",
|
|
644
|
+
]
|
|
625
645
|
end
|
|
626
646
|
|
|
627
647
|
def css_gemfile_entry
|
|
@@ -644,6 +664,11 @@ module Rails
|
|
|
644
664
|
end
|
|
645
665
|
end
|
|
646
666
|
|
|
667
|
+
def rails_command(command, command_options = {})
|
|
668
|
+
command_options[:capture] = true if options[:quiet]
|
|
669
|
+
super
|
|
670
|
+
end
|
|
671
|
+
|
|
647
672
|
def bundle_install?
|
|
648
673
|
!(options[:skip_bundle] || options[:pretend])
|
|
649
674
|
end
|
|
@@ -738,12 +763,6 @@ module Rails
|
|
|
738
763
|
end
|
|
739
764
|
end
|
|
740
765
|
|
|
741
|
-
def generate_bundler_binstub
|
|
742
|
-
if bundle_install?
|
|
743
|
-
bundle_command("binstubs bundler")
|
|
744
|
-
end
|
|
745
|
-
end
|
|
746
|
-
|
|
747
766
|
def jruby?
|
|
748
767
|
defined?(JRUBY_VERSION)
|
|
749
768
|
end
|
|
@@ -758,11 +777,13 @@ module Rails
|
|
|
758
777
|
end
|
|
759
778
|
|
|
760
779
|
def user_default_branch
|
|
761
|
-
@user_default_branch ||=
|
|
780
|
+
@user_default_branch ||= capture_command("git config init.defaultbranch").strip.presence || "main"
|
|
762
781
|
end
|
|
763
782
|
|
|
764
783
|
def git_init_command
|
|
765
|
-
|
|
784
|
+
if capture_command("git config init.defaultbranch").present?
|
|
785
|
+
return "git init"
|
|
786
|
+
end
|
|
766
787
|
|
|
767
788
|
git_version = `git --version`[/\d+\.\d+\.\d+/]
|
|
768
789
|
|
|
@@ -5,6 +5,8 @@ require "rails/generators/erb"
|
|
|
5
5
|
module Erb # :nodoc:
|
|
6
6
|
module Generators # :nodoc:
|
|
7
7
|
class AuthenticationGenerator < Rails::Generators::Base # :nodoc:
|
|
8
|
+
hide!
|
|
9
|
+
|
|
8
10
|
def create_files
|
|
9
11
|
template "app/views/passwords/new.html.erb"
|
|
10
12
|
template "app/views/passwords/edit.html.erb"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<div id="<%%= dom_id <%= singular_name %> %>">
|
|
2
2
|
<% attributes.reject(&:password_digest?).each do |attribute| -%>
|
|
3
|
-
<
|
|
3
|
+
<div>
|
|
4
4
|
<strong><%= attribute.human_name %>:</strong>
|
|
5
5
|
<% if attribute.attachment? -%>
|
|
6
6
|
<%%= link_to <%= singular_name %>.<%= attribute.column_name %>.filename, <%= singular_name %>.<%= attribute.column_name %> if <%= singular_name %>.<%= attribute.column_name %>.attached? %>
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
<% else -%>
|
|
12
12
|
<%%= <%= singular_name %>.<%= attribute.column_name %> %>
|
|
13
13
|
<% end -%>
|
|
14
|
-
</
|
|
14
|
+
</div>
|
|
15
15
|
|
|
16
16
|
<% end -%>
|
|
17
17
|
</div>
|
|
@@ -73,7 +73,7 @@ module Rails
|
|
|
73
73
|
def valid_type?(type)
|
|
74
74
|
DEFAULT_TYPES.include?(type.to_s) ||
|
|
75
75
|
!defined?(ActiveRecord::Base) ||
|
|
76
|
-
ActiveRecord::Base.
|
|
76
|
+
ActiveRecord::Base.connection_db_config.adapter_class.valid_type?(type)
|
|
77
77
|
end
|
|
78
78
|
|
|
79
79
|
def valid_index_type?(index_type)
|
|
@@ -109,7 +109,7 @@ module Rails
|
|
|
109
109
|
end
|
|
110
110
|
|
|
111
111
|
def bin
|
|
112
|
-
exclude_pattern = Regexp.union([(/thrust/ if skip_thruster?), (/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?), (/bundler-audit/ if skip_bundler_audit?)].compact)
|
|
113
113
|
directory "bin", { exclude_pattern: exclude_pattern } do |content|
|
|
114
114
|
"#{shebang}\n" + content
|
|
115
115
|
end
|
|
@@ -127,7 +127,9 @@ module Rails
|
|
|
127
127
|
template "routes.rb" unless options[:update]
|
|
128
128
|
template "application.rb"
|
|
129
129
|
template "environment.rb"
|
|
130
|
-
template "
|
|
130
|
+
template "bundler-audit.yml" unless skip_bundler_audit?
|
|
131
|
+
template "cable.yml" unless options[:update] || skip_action_cable?
|
|
132
|
+
template "ci.rb"
|
|
131
133
|
template "puma.rb"
|
|
132
134
|
template "storage.yml" unless options[:update] || skip_active_storage?
|
|
133
135
|
|
|
@@ -140,6 +142,8 @@ module Rails
|
|
|
140
142
|
def config_when_updating
|
|
141
143
|
action_cable_config_exist = File.exist?("config/cable.yml")
|
|
142
144
|
active_storage_config_exist = File.exist?("config/storage.yml")
|
|
145
|
+
ci_config_exist = File.exist?("config/ci.rb")
|
|
146
|
+
bundle_audit_config_exist = File.exist?("config/bundler-audit.yml")
|
|
143
147
|
rack_cors_config_exist = File.exist?("config/initializers/cors.rb")
|
|
144
148
|
assets_config_exist = File.exist?("config/initializers/assets.rb")
|
|
145
149
|
asset_app_stylesheet_exist = File.exist?("app/assets/stylesheets/application.css")
|
|
@@ -149,7 +153,7 @@ module Rails
|
|
|
149
153
|
|
|
150
154
|
config
|
|
151
155
|
|
|
152
|
-
if !
|
|
156
|
+
if !skip_action_cable? && !action_cable_config_exist
|
|
153
157
|
template "config/cable.yml"
|
|
154
158
|
end
|
|
155
159
|
|
|
@@ -157,6 +161,10 @@ module Rails
|
|
|
157
161
|
template "config/storage.yml"
|
|
158
162
|
end
|
|
159
163
|
|
|
164
|
+
if !ci_config_exist
|
|
165
|
+
template "config/ci.rb"
|
|
166
|
+
end
|
|
167
|
+
|
|
160
168
|
if skip_asset_pipeline? && !assets_config_exist
|
|
161
169
|
remove_file "config/initializers/assets.rb"
|
|
162
170
|
end
|
|
@@ -169,6 +177,10 @@ module Rails
|
|
|
169
177
|
remove_file "config/initializers/cors.rb"
|
|
170
178
|
end
|
|
171
179
|
|
|
180
|
+
if !skip_bundler_audit? && !bundle_audit_config_exist
|
|
181
|
+
template "config/bundler-audit.yml"
|
|
182
|
+
end
|
|
183
|
+
|
|
172
184
|
if options[:api]
|
|
173
185
|
unless csp_config_exist
|
|
174
186
|
remove_file "config/initializers/content_security_policy.rb"
|
|
@@ -182,7 +194,6 @@ module Rails
|
|
|
182
194
|
require "rails/generators/rails/master_key/master_key_generator"
|
|
183
195
|
master_key_generator = Rails::Generators::MasterKeyGenerator.new([], quiet: options[:quiet], force: options[:force])
|
|
184
196
|
master_key_generator.add_master_key_file_silently
|
|
185
|
-
master_key_generator.ignore_master_key_file_silently
|
|
186
197
|
end
|
|
187
198
|
|
|
188
199
|
def credentials
|
|
@@ -306,6 +317,7 @@ module Rails
|
|
|
306
317
|
:skip_active_storage,
|
|
307
318
|
:skip_bootsnap,
|
|
308
319
|
:skip_brakeman,
|
|
320
|
+
:skip_bundler_audit,
|
|
309
321
|
:skip_ci,
|
|
310
322
|
:skip_dev_gems,
|
|
311
323
|
:skip_docker,
|
|
@@ -570,7 +582,6 @@ module Rails
|
|
|
570
582
|
public_task :apply_rails_template
|
|
571
583
|
public_task :run_bundle
|
|
572
584
|
public_task :add_bundler_platforms
|
|
573
|
-
public_task :generate_bundler_binstub
|
|
574
585
|
public_task :run_javascript
|
|
575
586
|
public_task :run_hotwire
|
|
576
587
|
public_task :run_css
|
|
@@ -17,18 +17,20 @@ WORKDIR /rails
|
|
|
17
17
|
# Install base packages
|
|
18
18
|
RUN apt-get update -qq && \
|
|
19
19
|
apt-get install --no-install-recommends -y <%= dockerfile_base_packages.join(" ") %> && \
|
|
20
|
+
ln -s /usr/lib/$(uname -m)-linux-gnu/libjemalloc.so.2 /usr/local/lib/libjemalloc.so && \
|
|
20
21
|
rm -rf /var/lib/apt/lists /var/cache/apt/archives
|
|
21
22
|
|
|
22
|
-
# Set production environment
|
|
23
|
+
# Set production environment variables and enable jemalloc for reduced memory usage and latency.
|
|
23
24
|
ENV RAILS_ENV="production" \
|
|
24
25
|
BUNDLE_DEPLOYMENT="1" \
|
|
25
26
|
BUNDLE_PATH="/usr/local/bundle" \
|
|
26
|
-
BUNDLE_WITHOUT="development"
|
|
27
|
+
BUNDLE_WITHOUT="development" \
|
|
28
|
+
LD_PRELOAD="/usr/local/lib/libjemalloc.so"
|
|
27
29
|
|
|
28
30
|
# Throw-away build stage to reduce size of final image
|
|
29
31
|
FROM base AS build
|
|
30
32
|
|
|
31
|
-
# Install packages needed to build gems<%= using_node? ? " and node modules" : "" %>
|
|
33
|
+
# Install packages needed to build gems<%= (using_node? || using_bun?) ? " and node modules" : "" %>
|
|
32
34
|
RUN apt-get update -qq && \
|
|
33
35
|
apt-get install --no-install-recommends -y <%= dockerfile_build_packages.join(" ") %> && \
|
|
34
36
|
rm -rf /var/lib/apt/lists /var/cache/apt/archives
|
|
@@ -59,10 +61,12 @@ RUN curl -fsSL https://bun.sh/install | bash -s -- "bun-v${BUN_VERSION}"
|
|
|
59
61
|
|
|
60
62
|
<% end -%>
|
|
61
63
|
# Install application gems
|
|
62
|
-
COPY Gemfile Gemfile.lock ./
|
|
64
|
+
COPY Gemfile Gemfile.lock vendor ./
|
|
65
|
+
|
|
63
66
|
RUN bundle install && \
|
|
64
67
|
rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git<% if depend_on_bootsnap? -%> && \
|
|
65
|
-
|
|
68
|
+
# -j 1 disable parallel compilation to avoid a QEMU bug: https://github.com/rails/bootsnap/issues/495
|
|
69
|
+
bundle exec bootsnap precompile -j 1 --gemfile<% end %>
|
|
66
70
|
|
|
67
71
|
<% if using_node? -%>
|
|
68
72
|
# Install node modules
|
|
@@ -80,8 +84,9 @@ RUN bun install --frozen-lockfile
|
|
|
80
84
|
COPY . .
|
|
81
85
|
|
|
82
86
|
<% if depend_on_bootsnap? -%>
|
|
83
|
-
# Precompile bootsnap code for faster boot times
|
|
84
|
-
|
|
87
|
+
# Precompile bootsnap code for faster boot times.
|
|
88
|
+
# -j 1 disable parallel compilation to avoid a QEMU bug: https://github.com/rails/bootsnap/issues/495
|
|
89
|
+
RUN bundle exec bootsnap precompile -j 1 app/ lib/
|
|
85
90
|
|
|
86
91
|
<% end -%>
|
|
87
92
|
<% unless dockerfile_binfile_fixups.empty? -%>
|
|
@@ -95,23 +100,22 @@ RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile
|
|
|
95
100
|
|
|
96
101
|
<% end -%>
|
|
97
102
|
|
|
98
|
-
<% if using_node? -%>
|
|
103
|
+
<% if using_node? || using_bun? -%>
|
|
99
104
|
RUN rm -rf node_modules
|
|
100
105
|
<% end %>
|
|
101
106
|
|
|
102
107
|
# Final stage for app image
|
|
103
108
|
FROM base
|
|
104
109
|
|
|
105
|
-
# Copy built artifacts: gems, application
|
|
106
|
-
COPY --from=build "${BUNDLE_PATH}" "${BUNDLE_PATH}"
|
|
107
|
-
COPY --from=build /rails /rails
|
|
108
|
-
|
|
109
110
|
# Run and own only the runtime files as a non-root user for security
|
|
110
111
|
RUN groupadd --system --gid 1000 rails && \
|
|
111
|
-
useradd rails --uid 1000 --gid 1000 --create-home --shell /bin/bash
|
|
112
|
-
chown -R rails:rails <%= dockerfile_chown_directories.join(" ") %>
|
|
112
|
+
useradd rails --uid 1000 --gid 1000 --create-home --shell /bin/bash
|
|
113
113
|
USER 1000:1000
|
|
114
114
|
|
|
115
|
+
# Copy built artifacts: gems, application
|
|
116
|
+
COPY --chown=rails:rails --from=build "${BUNDLE_PATH}" "${BUNDLE_PATH}"
|
|
117
|
+
COPY --chown=rails:rails --from=build /rails /rails
|
|
118
|
+
|
|
115
119
|
# Entrypoint prepares the database.
|
|
116
120
|
ENTRYPOINT ["/rails/bin/docker-entrypoint"]
|
|
117
121
|
|
|
@@ -123,4 +127,4 @@ CMD ["./bin/rails", "server"]
|
|
|
123
127
|
# Start server via Thruster by default, this can be overwritten at runtime
|
|
124
128
|
EXPOSE 80
|
|
125
129
|
CMD ["./bin/thrust", "./bin/rails", "server"]
|
|
126
|
-
<% end -%>
|
|
130
|
+
<% end -%>
|
|
@@ -42,7 +42,7 @@ gem "thruster", require: false
|
|
|
42
42
|
<% unless skip_active_storage? -%>
|
|
43
43
|
|
|
44
44
|
# Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images]
|
|
45
|
-
|
|
45
|
+
gem "image_processing", "~> 1.2"
|
|
46
46
|
<% end -%>
|
|
47
47
|
<%- if options.api? -%>
|
|
48
48
|
|
|
@@ -54,6 +54,11 @@ gem "thruster", require: false
|
|
|
54
54
|
group :development, :test do
|
|
55
55
|
# See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
|
|
56
56
|
gem "debug", platforms: %i[ mri windows ], require: "debug/prelude"
|
|
57
|
+
<%- unless options.skip_bundler_audit? -%>
|
|
58
|
+
|
|
59
|
+
# Audits gems for known security defects (use config/bundler-audit.yml to ignore issues)
|
|
60
|
+
gem "bundler-audit", require: false
|
|
61
|
+
<%- end -%>
|
|
57
62
|
<%- unless options.skip_brakeman? -%>
|
|
58
63
|
|
|
59
64
|
# Static analysis for security vulnerabilities [https://brakemanscanner.org/]
|
|
@@ -2,5 +2,10 @@ class ApplicationController < ActionController::<%= options.api? ? "API" : "Base
|
|
|
2
2
|
<%- unless options.api? -%>
|
|
3
3
|
# Only allow modern browsers supporting webp images, web push, badges, import maps, CSS nesting, and CSS :has.
|
|
4
4
|
allow_browser versions: :modern
|
|
5
|
+
<%- if using_importmap? -%>
|
|
6
|
+
|
|
7
|
+
# Changes to the importmap will invalidate the etag for HTML responses
|
|
8
|
+
stale_when_importmap_changes
|
|
9
|
+
<% end -%>
|
|
5
10
|
<% end -%>
|
|
6
11
|
end
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
<title><%%= content_for(:title) || "<%= app_name.titleize %>" %></title>
|
|
5
5
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
6
6
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
7
|
+
<meta name="application-name" content="<%= app_name.titleize %>">
|
|
7
8
|
<meta name="mobile-web-app-capable" content="yes">
|
|
8
9
|
<%%= csrf_meta_tags %>
|
|
9
10
|
<%%= csp_meta_tag %>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
require "rubygems"
|
|
2
2
|
require "bundler/setup"
|
|
3
3
|
|
|
4
|
-
#
|
|
4
|
+
# Explicit RuboCop config increases performance slightly while avoiding config confusion.
|
|
5
5
|
ARGV.unshift("--config", File.expand_path("../.rubocop.yml", __dir__))
|
|
6
6
|
|
|
7
7
|
load Gem.bin_path("rubocop", "rubocop")
|