plutonium 0.10.2 → 0.10.3

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.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -0
  3. data/app/views/application/_flash_alerts.html.erb +3 -0
  4. data/app/views/application/_flash_toasts.html.erb +2 -0
  5. data/app/views/components/base.rb +1 -1
  6. data/app/views/layouts/resource.html copy.erb +2 -2
  7. data/app/views/layouts/resource.html.erb +3 -3
  8. data/app/views/layouts/rodauth.html.erb +9 -4
  9. data/app/views/rodauth/add_recovery_codes.html.erb +8 -7
  10. data/app/views/rodauth/otp_auth.html.erb +1 -1
  11. data/app/views/rodauth/otp_setup.html.erb +10 -8
  12. data/css.manifest +1 -1
  13. data/lib/generators/pu/core/ruby/ruby_generator.rb +30 -0
  14. data/lib/generators/pu/core/ruby/templates/.keep +0 -0
  15. data/lib/generators/pu/docker/install/install_generator.rb +35 -0
  16. data/lib/generators/pu/docker/install/templates/.keep +0 -0
  17. data/lib/generators/pu/docker/install/templates/Dockerfile.dev.tt +30 -0
  18. data/lib/generators/pu/docker/install/templates/Dockerfile.tt +75 -0
  19. data/lib/generators/pu/docker/install/templates/bin/console +3 -0
  20. data/lib/generators/pu/docker/install/templates/bin/restart +3 -0
  21. data/lib/generators/pu/docker/install/templates/bin/shell +3 -0
  22. data/lib/generators/pu/docker/install/templates/docker-compose.yml +29 -0
  23. data/lib/generators/pu/gem/dotenv/dotenv_generator.rb +32 -0
  24. data/lib/generators/pu/gem/dotenv/templates/.env +6 -0
  25. data/lib/generators/pu/gem/dotenv/templates/.env.local +5 -0
  26. data/lib/generators/pu/gem/dotenv/templates/.env.local.template +5 -0
  27. data/lib/generators/pu/gem/dotenv/templates/.env.template +6 -0
  28. data/lib/generators/pu/gem/dotenv/templates/.keep +0 -0
  29. data/lib/generators/pu/gem/dotenv/templates/config/initializers/001_ensure_required_env.rb +15 -0
  30. data/lib/generators/pu/gem/redis/redis_generator.rb +22 -0
  31. data/lib/generators/pu/gem/redis/templates/.keep +0 -0
  32. data/lib/generators/pu/lib/plutonium_generators/concerns/actions.rb +154 -32
  33. data/lib/generators/pu/lib/plutonium_generators/generator.rb +6 -6
  34. data/lib/generators/pu/lib/plutonium_generators/installer.rb +1 -1
  35. data/lib/generators/pu/rodauth/account_generator.rb +10 -10
  36. data/lib/generators/pu/rodauth/install_generator.rb +9 -2
  37. data/lib/generators/pu/rodauth/migration/sequel/audit_logging.erb +2 -2
  38. data/lib/generators/pu/rodauth/migration_generator.rb +1 -1
  39. data/lib/generators/pu/rodauth/templates/app/{misc → rodauth}/account_rodauth_plugin.rb.tt +2 -2
  40. data/lib/generators/pu/rodauth/templates/app/{misc → rodauth}/rodauth_plugin.rb.tt +0 -3
  41. data/lib/generators/pu/rodauth/templates/db/migrate/install_rodauth.rb.tt +5 -0
  42. data/lib/generators/pu/service/postgres/postgres_generator.rb +61 -0
  43. data/lib/generators/pu/service/postgres/templates/.keep +0 -0
  44. data/lib/generators/pu/service/postgres/templates/bin/initdb.d/create-multiple-postgresql-databases.sh +22 -0
  45. data/lib/generators/pu/service/postgres/templates/database.yml.tt +93 -0
  46. data/lib/generators/pu/service/sidekiq/sidekiq_generator.rb +62 -0
  47. data/lib/generators/pu/service/sidekiq/templates/.keep +0 -0
  48. data/lib/generators/pu/service/sidekiq/templates/app/sidekiq/sidekiq_job.rb +5 -0
  49. data/lib/generators/pu/service/sidekiq/templates/config/initializers/sidekiq.rb +53 -0
  50. data/lib/generators/pu/service/sidekiq/templates/config/sidekiq.yml +6 -0
  51. data/lib/plutonium/config.rb +7 -2
  52. data/lib/plutonium/core/controllers/base.rb +1 -1
  53. data/lib/plutonium/core/controllers/entity_scoping.rb +3 -3
  54. data/lib/plutonium/icons.rb +1 -1
  55. data/lib/plutonium/railtie.rb +4 -0
  56. data/lib/plutonium/resource/controller.rb +1 -0
  57. data/lib/plutonium/rodauth/controller_methods.rb +1 -1
  58. data/lib/plutonium/version.rb +1 -1
  59. data/lib/plutonium.rb +4 -0
  60. data/lib/tasks/create_rodauth_admin.rake +16 -0
  61. data/public/plutonium-assets/plutonium.8bee7a8482988b0360e3.css +3420 -0
  62. metadata +36 -5
  63. /data/lib/generators/pu/rodauth/templates/app/{misc → rodauth}/rodauth_app.rb.tt +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6d56979564e5b0903e39197ae70e304de7848c38c02edcc039a74f9e76093931
4
- data.tar.gz: 19a28e7518edcce1ee883b65bb13d5f4ad97b3eb4820dd00a5ebdb4eeeb1ebf6
3
+ metadata.gz: b388378444b597bf548ce883ad18b8cc939fec40bc15e6096ddbef26c996306a
4
+ data.tar.gz: dfc4cfdcd18770e44a9199da71a54c034bc4adcc786cfc0460ba011557f65e5f
5
5
  SHA512:
6
- metadata.gz: b4177cf2f8f722f19d843961f155286bee3f0bdbf5536233f1850aa8917cb8fd18aae685584747779101024bc761bc3fdfb14a396f537fcee2ec080fcf02acff
7
- data.tar.gz: 6ae52cb87299fb2050416fbcb6dce8fe56412b16ca8c570b77a856bfd08fd8eda1ce5c1b4517fbb56583b4d2312f86adbe3c7837fcca77cc1a29765407dd1ff5
6
+ metadata.gz: '09aab730fac6b3ff2e9207f2ba4ad463c831b2c44864acc32d45c3774624af1e2fa3c25439eb07de33d91712092ccf3b475b121a4e45a97ecd6162f669ed1b7c'
7
+ data.tar.gz: 798e6181fd2b8bc520fe08ad7c7f10deecc3301f83f946b384b9762791efd6cd0b3bde541caec0d2b486b2d35ebd87c5ec03f55672ed4f5d540f1712f8c447c0
data/README.md CHANGED
@@ -87,4 +87,5 @@ rails new pluton8_starter --name="Pluton8 Starter" --database=sqlite3 --skip-act
87
87
  bin/rails app:template LOCATION=/Users/stefan/code/plutonium/starters/vulcan/gems/plutonium/templates/base.rb
88
88
  ```
89
89
 
90
+ rails g pu:rodauth:account admin --no-defaults --login --logout --remember --change-password --internal-request --create-account --lockout --verify-account --audit-logging --close-account --otp --reset-password --reset-password-notify --active-sessions --recovery-codes --password-grace-period
90
91
  -->
@@ -1,5 +1,8 @@
1
+
1
2
  <% flash.each do |type, msg| %>
2
3
  <%
4
+ next unless msg.present?
5
+
3
6
  color = case type.to_sym
4
7
  when :success
5
8
  # bg-green-50 text-green-800 text-green-500 text-green-400 ring-green-400
@@ -1,5 +1,7 @@
1
1
  <% flash.each do |type, msg| %>
2
2
  <%
3
+ next unless msg.present?
4
+
3
5
  color = case type.to_sym
4
6
  when :success
5
7
  # text-green-500 bg-green-100 bg-green-800 text-green-200 bg-green-50 text-green-400 ring-green-400
@@ -31,7 +31,7 @@ module Plutonium::Ui
31
31
  end
32
32
 
33
33
  def render_icon(icon)
34
- Plutonium::Icons.render(icon).html_safe
34
+ Plutonium::Icons.render(icon)
35
35
  end
36
36
 
37
37
  def attributes_to_string(attributes, prefix = nil)
@@ -15,8 +15,8 @@
15
15
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/slim-select/2.6.0/slimselect.min.css" integrity="sha512-GvqWM4KWH8mbgWIyvwdH8HgjUbyZTXrCq0sjGij9fDNiXz3vJoy3jCcAaWNekH2rJe4hXVWCJKN+bEW8V7AAEQ==" crossorigin="anonymous" referrerpolicy="no-referrer" />
16
16
  <script src="https://cdnjs.cloudflare.com/ajax/libs/slim-select/2.6.0/slimselect.min.js" integrity="sha512-0E8oaoA2v32h26IycsmRDShtQ8kMgD91zWVBxdIvUCjU3xBw81PV61QBsBqNQpWkp/zYJZip8Ag3ifmzz1wCKQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
17
17
 
18
- <%== Plutonium::Config.stylesheet_tag.call self %>
19
- <%== Plutonium::Config.script_tag.call self %>
18
+ <%= Plutonium::Config.stylesheet_tag.call self %>
19
+ <%= Plutonium::Config.script_tag.call self %>
20
20
  <%= yield(:head) %>
21
21
  </head>
22
22
  <body class="bg-body-tertiary">
@@ -7,7 +7,7 @@
7
7
  <meta name="turbo-cache-control" content="no-cache">
8
8
  <meta name="turbo-refresh-method" content="morph">
9
9
  <meta name="turbo-refresh-scroll" content="preserve">
10
- <link rel="icon" type="image/x-icon" href="<%= Plutonium.favicon_link %>">
10
+ <%= Plutonium::Config.favicon_tag.call self %>
11
11
  <%= csrf_meta_tags %>
12
12
  <%= csp_meta_tag %>
13
13
  <%= yield(:meta) %>
@@ -24,8 +24,8 @@
24
24
 
25
25
  <%= yield(:assets) %>
26
26
 
27
- <%== Plutonium::Config.stylesheet_tag.call self %>
28
- <%== Plutonium::Config.script_tag.call self %>
27
+ <%= Plutonium::Config.stylesheet_tag.call self %>
28
+ <%= Plutonium::Config.script_tag.call self %>
29
29
 
30
30
  <%= yield(:head) %>
31
31
  </head>
@@ -12,20 +12,25 @@
12
12
  <link rel="preconnect" href="https://fonts.googleapis.com">
13
13
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
14
14
  <link href="https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,100;0,300;0,400;0,700;0,900;1,100;1,300;1,400;1,700;1,900&display=swap" rel="stylesheet">
15
- <%== Plutonium::Config.stylesheet_tag.call self %>
16
- <%== Plutonium::Config.script_tag.call self %>
15
+ <%= Plutonium::Config.stylesheet_tag.call self %>
16
+ <%= Plutonium::Config.script_tag.call self %>
17
17
  </head>
18
18
  <body class="antialiased bg-gray-50 dark:bg-gray-900">
19
19
  <main div class="flex flex-col items-center justify-center px-6 py-8 mx-auto md:h-screen lg:py-0">
20
+ <%= render "flash" %>
20
21
  <p class="flex items-center mb-6 text-2xl font-semibold text-gray-900 dark:text-white">
21
22
  <img class="w-16 h-16 mr-2" src="<%= Plutonium.logo_link %>" alt="logo">
22
23
  <%= application_name %>
23
24
  </p>
24
- <div class="w-full bg-white rounded-lg shadow dark:border md:mt-0 sm:max-w-md xl:p-0 dark:bg-gray-800 dark:border-gray-700">
25
- <div class="p-6 space-y-4 md:space-y-6 sm:p-8">
25
+ <div class="w-full max-w-md bg-white rounded-lg shadow dark:border md:mt-0 xl:p-0 dark:bg-gray-800 dark:border-gray-700">
26
+ <div class="w-full p-6 space-y-4 md:space-y-6 sm:p-8">
26
27
  <%= yield %>
27
28
  </div>
28
29
  </div>
30
+ <div class="mt-4 flex items-center font-medium text-blue-600 dark:text-blue-500 hover:underline">
31
+ <%= Plutonium::Icons.render "outline/home" %>
32
+ <%= link_to "Home", root_path, class: "font-medium text-blue-600 dark:text-blue-500" %>
33
+ </div>
29
34
  </main>
30
35
  </body>
31
36
  </html>
@@ -1,16 +1,17 @@
1
1
  <div>
2
- <% if rodauth.recovery_codes.any? %>
3
- <div class="text-sm px-4 py-3 bg-white rounded-lg border shadow-lg grid grid-cols-2 gap-y-2 gap-x-4 dark:bg-gray-900 dark:text-gray-200">
2
+ <h4 class="text-2xl font-bold dark:text-white mb-4">Recovery Codes</h4>
3
+
4
+ <div class="mb-4 text-sm grid grid-cols-1 gap-y-2 gap-x-4 dark:bg-gray-900 dark:text-gray-200">
5
+ <% if rodauth.recovery_codes.any? %>
4
6
  <% rodauth.recovery_codes.each do |code| %>
5
7
  <div class="font-mono"><%= code %></div>
6
8
  <% end %>
7
- </div>
8
- <% end %>
9
+ <% else %>
10
+ <div class="font-mono">You have no recovery codes</div>
11
+ <% end %>
12
+ </div>
9
13
 
10
14
  <% if rodauth.can_add_recovery_codes? %>
11
- <div class="text-2xl font-medium mt-6 mb-4">
12
- <%== rodauth.add_recovery_codes_heading %>
13
- </div>
14
15
  <%= render template: "rodauth/recovery_codes", layout: false %>
15
16
  <% end %>
16
17
  </div>
@@ -1,7 +1,7 @@
1
1
  <%= form_with url: rodauth.otp_auth_path, method: :post, data: { turbo: false }, class: "w-full max-w-sm" do |form| %>
2
2
  <div class="mb-6">
3
3
  <%= form.label "otp-auth-code", rodauth.otp_auth_label, class: "block text-sm font-semibold" %>
4
- <%= form.text_field rodauth.otp_auth_param, value: "", id: "otp-auth-code", autocomplete: "off", inputmode: "numeric", required: true, class: "mt-2 text-sm w-1/2 px-3 py-2 border rounded-md dark:bg-gray-900 dark:text-gray-100 dark:focus:bg-gray-800 #{rodauth.field_error(rodauth.otp_auth_param) ? "border-red-600 focus:ring-red-600 focus:border-red-600 dark:border-red-400 dark:focus:ring-red-400" : "border-gray-300 dark:border-gray-700 dark:focus:border-emerald-400 dark:focus:ring-emerald-400" }", aria: ({ invalid: true, describedby: "otp-auth-code_error_message" } if rodauth.field_error(rodauth.otp_auth_param)) %>
4
+ <%= form.text_field rodauth.otp_auth_param, value: "", id: "otp-auth-code", autocomplete: "off", inputmode: "numeric", required: true, class: "mt-2 text-sm w-full px-3 py-2 border rounded-md dark:bg-gray-900 dark:text-gray-100 dark:focus:bg-gray-800 #{rodauth.field_error(rodauth.otp_auth_param) ? "border-red-600 focus:ring-red-600 focus:border-red-600 dark:border-red-400 dark:focus:ring-red-400" : "border-gray-300 dark:border-gray-700 dark:focus:border-emerald-400 dark:focus:ring-emerald-400" }", aria: ({ invalid: true, describedby: "otp-auth-code_error_message" } if rodauth.field_error(rodauth.otp_auth_param)) %>
5
5
  <%= content_tag(:span, rodauth.field_error(rodauth.otp_auth_param), class: "block mt-1 text-red-600 text-xs dark:text-red-400", id: "otp-auth-code_error_message") if rodauth.field_error(rodauth.otp_auth_param) %>
6
6
  </div>
7
7
 
@@ -2,8 +2,10 @@
2
2
  <%= form.hidden_field rodauth.otp_setup_param, value: rodauth.otp_user_key, id: "otp-key" %>
3
3
  <%= form.hidden_field rodauth.otp_setup_raw_param, value: rodauth.otp_key, id: "otp-hmac-secret" if rodauth.otp_keys_use_hmac? %>
4
4
 
5
- <div class="mb-6 w-48">
6
- <%== rodauth.otp_qr_code %>
5
+ <div class="mb-6 flex items-center justify-center">
6
+ <div class="w-48">
7
+ <%== rodauth.otp_qr_code %>
8
+ </div>
7
9
  </div>
8
10
 
9
11
  <dl class="mb-6 text-sm">
@@ -14,6 +16,12 @@
14
16
  <dd><%= rodauth.otp_provisioning_uri %></dd>
15
17
  </dl>
16
18
 
19
+ <div class="mb-6">
20
+ <%= form.label "otp-auth-code", rodauth.otp_auth_label, class: "block text-sm font-semibold" %>
21
+ <%= form.text_field rodauth.otp_auth_param, value: "", id: "otp-auth-code", autocomplete: "off", inputmode: "numeric", required: true, class: "mt-2 text-sm w-full px-3 py-2 border rounded-md dark:bg-gray-900 dark:text-gray-100 dark:focus:bg-gray-800 #{rodauth.field_error(rodauth.otp_auth_param) ? "border-red-600 focus:ring-red-600 focus:border-red-600 dark:border-red-400 dark:focus:ring-red-400" : "border-gray-300 dark:border-gray-700 dark:focus:border-emerald-400 dark:focus:ring-emerald-400" }" , aria: ({ invalid: true, describedby: "otp-auth-code_error_message" } if rodauth.field_error(rodauth.otp_auth_param)) %>
22
+ <%= content_tag(:span, rodauth.field_error(rodauth.otp_auth_param), class: "block mt-1 text-red-600 text-xs dark:text-red-400", id: "otp-auth-code_error_message") if rodauth.field_error(rodauth.otp_auth_param) %>
23
+ </div>
24
+
17
25
  <% if rodauth.two_factor_modifications_require_password? %>
18
26
  <div class="mb-6">
19
27
  <%= form.label "password", rodauth.password_label, class: "block text-sm font-semibold" %>
@@ -22,11 +30,5 @@
22
30
  </div>
23
31
  <% end %>
24
32
 
25
- <div class="mb-6">
26
- <%= form.label "otp-auth-code", rodauth.otp_auth_label, class: "block text-sm font-semibold" %>
27
- <%= form.text_field rodauth.otp_auth_param, value: "", id: "otp-auth-code", autocomplete: "off", inputmode: "numeric", required: true, class: "mt-2 text-sm w-1/2 px-3 py-2 border rounded-md dark:bg-gray-900 dark:text-gray-100 dark:focus:bg-gray-800 #{rodauth.field_error(rodauth.otp_auth_param) ? "border-red-600 focus:ring-red-600 focus:border-red-600 dark:border-red-400 dark:focus:ring-red-400" : "border-gray-300 dark:border-gray-700 dark:focus:border-emerald-400 dark:focus:ring-emerald-400" }", aria: ({ invalid: true, describedby: "otp-auth-code_error_message" } if rodauth.field_error(rodauth.otp_auth_param)) %>
28
- <%= content_tag(:span, rodauth.field_error(rodauth.otp_auth_param), class: "block mt-1 text-red-600 text-xs dark:text-red-400", id: "otp-auth-code_error_message") if rodauth.field_error(rodauth.otp_auth_param) %>
29
- </div>
30
-
31
33
  <%= form.submit rodauth.otp_setup_button, class: "w-full px-8 py-3 cursor-pointer font-semibold text-sm rounded-md text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-600 dark:bg-emerald-400 dark:hover:bg-emerald-500 dark:text-gray-900 dark:focus:ring-emerald-400 dark:focus:ring-offset-current" %>
32
34
  <% end %>
data/css.manifest CHANGED
@@ -1,3 +1,3 @@
1
1
  {
2
- "plutonium.css": "plutonium.2d4f0c333cd000051d3b.css"
2
+ "plutonium.css": "plutonium.8bee7a8482988b0360e3.css"
3
3
  }
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../lib/plutonium_generators"
4
+
5
+ module Pu
6
+ module Core
7
+ class RubyGenerator < Rails::Generators::Base
8
+ include PlutoniumGenerators::Generator
9
+
10
+ source_root File.expand_path("templates", __dir__)
11
+
12
+ desc "Set ruby version for project"
13
+ class_option :version, type: :string, desc: "Ruby version", default: "3.3.0"
14
+
15
+ def start
16
+ set_ruby_version! version
17
+ say "Ruby version set to #{version}"
18
+ say "Run `bundle install` to update your dependencies"
19
+ rescue => e
20
+ exception "#{self.class} failed:", e
21
+ end
22
+
23
+ private
24
+
25
+ def version
26
+ options[:version]
27
+ end
28
+ end
29
+ end
30
+ end
File without changes
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../lib/plutonium_generators"
4
+
5
+ module Pu
6
+ module Docker
7
+ class InstallGenerator < Rails::Generators::Base
8
+ include PlutoniumGenerators::Generator
9
+
10
+ source_root File.expand_path("templates", __dir__)
11
+
12
+ desc "Set up docker for project"
13
+
14
+ def start
15
+ in_root do
16
+ template "Dockerfile", force: true
17
+ template "Dockerfile.dev", force: true
18
+ template "docker-compose.yml", force: true
19
+ proc_file :web, "env RUBY_DEBUG_OPEN=true bin/rails server -b '0.0.0.0'", env: :dev
20
+ bin_directory
21
+ gitignore ".volumes"
22
+ dockerignore ".volumes"
23
+ end
24
+ rescue => e
25
+ exception "#{self.class} failed:", e
26
+ end
27
+
28
+ private
29
+
30
+ def ruby_version
31
+ @ruby_version ||= File.read(".ruby-version").strip
32
+ end
33
+ end
34
+ end
35
+ end
File without changes
@@ -0,0 +1,30 @@
1
+ # syntax = docker/dockerfile:1
2
+
3
+ # Make sure RUBY_VERSION matches the Ruby version in .ruby-version and Gemfile
4
+ ARG RUBY_VERSION=<%= ruby_version %>
5
+ FROM registry.docker.com/library/ruby:$RUBY_VERSION
6
+
7
+ WORKDIR /rails
8
+
9
+ # Install packages needed to build gems and node modules
10
+ RUN apt-get update -qq && \
11
+ apt-get install --no-install-recommends -y build-essential curl git libpq-dev node-gyp pkg-config python-is-python3
12
+
13
+ # Install JavaScript dependencies
14
+ ARG NODE_VERSION=22.2.0
15
+ ARG YARN_VERSION=1.22.22
16
+ ENV PATH=/usr/local/node/bin:$PATH
17
+ RUN curl -sL https://github.com/nodenv/node-build/archive/master.tar.gz | tar xz -C /tmp/ && \
18
+ /tmp/node-build-master/bin/node-build "${NODE_VERSION}" /usr/local/node && \
19
+ npm install -g yarn@$YARN_VERSION && \
20
+ rm -rf /tmp/node-build-master
21
+
22
+ # Additional dependencies go here
23
+
24
+ # Upgrade RubyGems and install the latest Bundler version
25
+ RUN gem update --system && gem install bundler
26
+
27
+ # Document that we're going to expose port 3000
28
+ EXPOSE 3000
29
+ # Use Bash as the default command
30
+ CMD ["/bin/bash"]
@@ -0,0 +1,75 @@
1
+ # syntax = docker/dockerfile:1
2
+
3
+ # Make sure RUBY_VERSION matches the Ruby version in .ruby-version and Gemfile
4
+ ARG RUBY_VERSION=<%= ruby_version %>
5
+ FROM registry.docker.com/library/ruby:$RUBY_VERSION-slim as base
6
+
7
+ # Rails app lives here
8
+ WORKDIR /rails
9
+
10
+ # Set production environment
11
+ ENV RAILS_ENV="production" \
12
+ BUNDLE_DEPLOYMENT="1" \
13
+ BUNDLE_PATH="/usr/local/bundle" \
14
+ BUNDLE_WITHOUT="development"
15
+
16
+
17
+ # Throw-away build stage to reduce size of final image
18
+ FROM base as build
19
+
20
+ # Install packages needed to build gems and node modules
21
+ RUN apt-get update -qq && \
22
+ apt-get install --no-install-recommends -y build-essential curl git libpq-dev node-gyp pkg-config python-is-python3
23
+
24
+ # Install JavaScript dependencies
25
+ ARG NODE_VERSION=22.2.0
26
+ ARG YARN_VERSION=1.22.22
27
+ ENV PATH=/usr/local/node/bin:$PATH
28
+ RUN curl -sL https://github.com/nodenv/node-build/archive/master.tar.gz | tar xz -C /tmp/ && \
29
+ /tmp/node-build-master/bin/node-build "${NODE_VERSION}" /usr/local/node && \
30
+ npm install -g yarn@$YARN_VERSION && \
31
+ rm -rf /tmp/node-build-master
32
+
33
+ # Install application gems
34
+ COPY .ruby-version Gemfile Gemfile.lock ./
35
+ RUN bundle install && \
36
+ rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git && \
37
+ bundle exec bootsnap precompile --gemfile
38
+
39
+ # Install node modules
40
+ COPY package.json yarn.lock ./
41
+ RUN yarn install --frozen-lockfile
42
+
43
+ # Copy application code
44
+ COPY . .
45
+
46
+ # Precompile bootsnap code for faster boot times
47
+ RUN bundle exec bootsnap precompile app/ lib/
48
+
49
+ # Precompiling assets for production without requiring secret RAILS_MASTER_KEY
50
+ RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile
51
+
52
+
53
+ # Final stage for app image
54
+ FROM base
55
+
56
+ # Install packages needed for deployment
57
+ RUN apt-get update -qq && \
58
+ apt-get install --no-install-recommends -y curl postgresql-client && \
59
+ rm -rf /var/lib/apt/lists /var/cache/apt/archives
60
+
61
+ # Copy built artifacts: gems, application
62
+ COPY --from=build /usr/local/bundle /usr/local/bundle
63
+ COPY --from=build /rails /rails
64
+
65
+ # Run and own only the runtime files as a non-root user for security
66
+ RUN useradd rails --create-home --shell /bin/bash && \
67
+ chown -R rails:rails db log tmp
68
+ USER rails:rails
69
+
70
+ # Entrypoint prepares the database.
71
+ ENTRYPOINT ["/rails/bin/docker-entrypoint"]
72
+
73
+ # Start the server by default, this can be overwritten at runtime
74
+ EXPOSE 3000
75
+ CMD ["./bin/rails", "server"]
@@ -0,0 +1,3 @@
1
+ #!/bin/bash -e
2
+
3
+ docker compose run --rm web bash -c "bundle && rails c"
@@ -0,0 +1,3 @@
1
+ #!/bin/bash -e
2
+
3
+ touch tmp/restart.txt
@@ -0,0 +1,3 @@
1
+ #!/bin/bash -e
2
+
3
+ docker compose run --rm web bash
@@ -0,0 +1,29 @@
1
+ ---
2
+ x-managed-by: plutonium
3
+
4
+ x-app: &app
5
+ build: # x-app
6
+ context: . # x-app
7
+ dockerfile: Dockerfile.dev # x-app
8
+ # x-app properties
9
+ volumes: # x-app
10
+ - ".:/rails" # x-app
11
+ - "./.volumes/bundle:/usr/local/bundle" # x-app
12
+ - "./.volumes/node_modules:/rails/node_modules" # x-app
13
+ - "./.volumes/shell_history:/root/shell_history" # x-app
14
+ depends_on: [] # x-app
15
+ environment: # x-app
16
+ RUBY_DEBUG_OPEN: true # x-app
17
+ PORT: 3000 # x-app
18
+ HISTFILE: /root/shell_history/.bash_history # x-app
19
+ tty: true # for binding.pry # x-app
20
+ stdin_open: true # for binding.pry # x-app
21
+
22
+ services:
23
+ web:
24
+ <<: *app
25
+ command: /bin/sh -c "rm -f tmp/pids/server.pid && bundle && yarn && bin/dev" # web
26
+ # web properties
27
+ ports: # web
28
+ - "3000:3000" # app
29
+ # additional services go here
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../lib/plutonium_generators"
4
+
5
+ module Pu
6
+ module Gem
7
+ class DotenvGenerator < Rails::Generators::Base
8
+ include PlutoniumGenerators::Generator
9
+
10
+ source_root File.expand_path("templates", __dir__)
11
+
12
+ desc "Set up dotenv"
13
+
14
+ def start
15
+ in_root do
16
+ [".env", ".env.local", ".env.template", ".env.local.template"].each do |file|
17
+ copy_file file
18
+ end
19
+
20
+ copy_file "config/initializers/001_ensure_required_env.rb"
21
+
22
+ gitignore "!/.env.template", "!/.env.local.template", "!/.env"
23
+
24
+ insert_into_file "Gemfile", "\ngem \"dotenv\", :groups => [:development, :test]\n", after: /^gem ["']rails["'].*\n/
25
+ bundle!
26
+ end
27
+ rescue => e
28
+ exception "#{self.class} failed:", e
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,6 @@
1
+ # Secrets should NOT be added here.
2
+ # Set them in `.env.local`
3
+
4
+ # # == S3
5
+ # S3_REGION=S3_REGION
6
+ # S3_BUCKET=S3_BUCKET
@@ -0,0 +1,5 @@
1
+ # Secrets for local testing should be added here.
2
+
3
+ # # == S3
4
+ # S3_ACCESS_KEY_ID=S3_ACCESS_KEY_ID
5
+ # S3_SECRET_ACCESS_KEY=S3_SECRET_ACCESS_KEY
@@ -0,0 +1,5 @@
1
+ # Secrets for local testing should be added here.
2
+
3
+ # # == S3
4
+ # S3_ACCESS_KEY_ID=S3_ACCESS_KEY_ID
5
+ # S3_SECRET_ACCESS_KEY=S3_SECRET_ACCESS_KEY
@@ -0,0 +1,6 @@
1
+ # Secrets should NOT be added here.
2
+ # Set them in `.env.local`
3
+
4
+ # # == S3
5
+ # S3_REGION=S3_REGION
6
+ # S3_BUCKET=S3_BUCKET
File without changes
@@ -0,0 +1,15 @@
1
+ # Add required env vars to this list
2
+ required_env_vars = %w[]
3
+
4
+ # Add additional env vars here
5
+
6
+ # Check required env vars
7
+ required_env_vars.each do |env_var|
8
+ if !ENV.has_key?(env_var) || ENV[env_var].blank?
9
+ raise <<~EOL
10
+ Missing required environment variable: #{env_var}
11
+
12
+ Ask a teammate for the appropriate value.
13
+ EOL
14
+ end
15
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../lib/plutonium_generators"
4
+
5
+ module Pu
6
+ module Gem
7
+ class RedisGenerator < Rails::Generators::Base
8
+ include PlutoniumGenerators::Generator
9
+
10
+ source_root File.expand_path("templates", __dir__)
11
+
12
+ desc "Set up redis"
13
+
14
+ def start
15
+ bundle "redis"
16
+ bundle "hiredis"
17
+ rescue => e
18
+ exception "#{self.class} failed:", e
19
+ end
20
+ end
21
+ end
22
+ end
File without changes