brut 0.5.0 → 0.8.0
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/.gitignore +4 -0
- data/CHANGELOG.md +7 -0
- data/Dockerfile.dx +19 -0
- data/Gemfile.lock +1 -1
- data/README.md +19 -0
- data/assets/YouTubeThumb.pxd +0 -0
- data/bin/build +86 -0
- data/bin/ci +36 -0
- data/bin/docs +39 -9
- data/bin/publish +61 -0
- data/bin/setup +6 -0
- data/brut-css/bin/build +19 -0
- data/brut-css/bin/ci +19 -0
- data/brut-css/bin/docs +19 -0
- data/brut-css/bin/publish +21 -0
- data/brut-css/bin/setup +1 -0
- data/brut-css/package-lock.json +2 -2
- data/brut-css/package.json +1 -1
- data/brut-js/bin/build +15 -6
- data/brut-js/bin/docs +25 -0
- data/brut-js/bin/publish +21 -0
- data/brut-js/bin/setup +1 -0
- data/brut-js/dx +1 -0
- data/brut-js/package-lock.json +2 -2
- data/brut-js/package.json +1 -1
- data/brut.gemspec +2 -2
- data/brutrb.com/bin/setup +1 -0
- data/brutrb.com/getting-started.md +3 -0
- data/brutrb.com/overview.md +6 -0
- data/brutrb.com/tutorial.md +7 -3
- data/docs/404.html +2 -2
- data/docs/adrs.html +3 -3
- data/docs/ai.html +3 -3
- data/docs/assets/{app.D6BuVHo9.js → app.DyQLb4Ot.js} +1 -1
- data/docs/assets/chunks/@localSearchIndexroot.CmtZyrFA.js +1 -0
- data/docs/assets/chunks/{VPLocalSearchBox.BpvHMbx6.js → VPLocalSearchBox.T1iA-eJx.js} +1 -1
- data/docs/assets/chunks/{theme.wlAOvi2f.js → theme.ChwsbWjK.js} +2 -2
- data/docs/assets/{components.md.iLiv2E9X.js → components.md.DHh-NwKs.js} +3 -3
- data/docs/assets/{configuration.md.DmuAdsli.js → configuration.md.D8Wz3oJU.js} +1 -1
- data/docs/assets/{forms.md.D8aa_qI-.js → forms.md.BRE85eju.js} +1 -1
- data/docs/assets/{getting-started.md.DLplsDUd.js → getting-started.md.2ioiTe-B.js} +6 -3
- data/docs/assets/{getting-started.md.DLplsDUd.lean.js → getting-started.md.2ioiTe-B.lean.js} +1 -1
- data/docs/assets/overview.md.DlKiRRG_.js +1 -0
- data/docs/assets/overview.md.DlKiRRG_.lean.js +1 -0
- data/docs/assets/tutorial.md.BIb7XT6j.js +1 -0
- data/docs/assets/tutorial.md.BIb7XT6j.lean.js +1 -0
- data/docs/assets.html +3 -3
- data/docs/brut-js.html +3 -3
- data/docs/business-logic.html +3 -3
- data/docs/cli.html +3 -3
- data/docs/components.html +7 -7
- data/docs/configuration.html +5 -5
- data/docs/css.html +3 -3
- data/docs/custom-element-tests.html +3 -3
- data/docs/database-access.html +3 -3
- data/docs/database-schema.html +3 -3
- data/docs/deployment.html +3 -3
- data/docs/dev-environment.html +3 -3
- data/docs/dir-structure.html +3 -3
- data/docs/doc-conventions.html +3 -3
- data/docs/end-to-end-tests.html +3 -3
- data/docs/features.html +3 -3
- data/docs/flash-and-session.html +3 -3
- data/docs/form-constraints.html +3 -3
- data/docs/forms.html +5 -5
- data/docs/getting-started.html +9 -6
- data/docs/handlers.html +3 -3
- data/docs/hashmap.json +1 -1
- data/docs/hooks.html +3 -3
- data/docs/i18n.html +3 -3
- data/docs/index.html +3 -3
- data/docs/instrumentation.html +3 -3
- data/docs/javascript.html +3 -3
- data/docs/jobs.html +3 -3
- data/docs/keyword-injection.html +3 -3
- data/docs/layouts.html +3 -3
- data/docs/lsp.html +3 -3
- data/docs/markdown-examples.html +3 -3
- data/docs/middleware.html +3 -3
- data/docs/overview.html +5 -5
- data/docs/pages.html +3 -3
- data/docs/recipes/alternate-layouts.html +3 -3
- data/docs/recipes/authentication.html +3 -3
- data/docs/recipes/blank-layouts.html +3 -3
- data/docs/recipes/custom-flash.html +3 -3
- data/docs/recipes/indexed-forms.html +3 -3
- data/docs/recipes/migrations.html +3 -3
- data/docs/recipes/text-field-component.html +3 -3
- data/docs/roadmap.html +3 -3
- data/docs/routes.html +3 -3
- data/docs/security.html +3 -3
- data/docs/seed-data.html +3 -3
- data/docs/space-time-continuum.html +3 -3
- data/docs/tutorial.html +5 -5
- data/docs/unit-tests.html +3 -3
- data/docs/why.html +3 -3
- data/lib/brut/framework/mcp.rb +1 -1
- data/lib/brut/front_end/components/form_tag.rb +2 -2
- data/lib/brut/version.rb +1 -1
- data/mkbrut/.gitignore +16 -0
- data/mkbrut/CODE_OF_CONDUCT.txt +100 -0
- data/mkbrut/Gemfile +3 -0
- data/mkbrut/Gemfile.lock +19 -0
- data/mkbrut/LICENSE.txt +370 -0
- data/mkbrut/README.md +145 -0
- data/mkbrut/Rakefile +2 -0
- data/mkbrut/bin/build +36 -0
- data/mkbrut/bin/ci +19 -0
- data/mkbrut/bin/docs +19 -0
- data/mkbrut/bin/publish +129 -0
- data/mkbrut/bin/rake +16 -0
- data/mkbrut/bin/setup +30 -0
- data/mkbrut/brut-welcome.png +0 -0
- data/mkbrut/deploy/.dockerignore +2 -0
- data/mkbrut/deploy/Dockerfile +25 -0
- data/mkbrut/exe/mkbrut +5 -0
- data/mkbrut/lib/mkbrut/app.rb +79 -0
- data/mkbrut/lib/mkbrut/app_id.rb +8 -0
- data/mkbrut/lib/mkbrut/app_name.rb +29 -0
- data/mkbrut/lib/mkbrut/app_options.rb +36 -0
- data/mkbrut/lib/mkbrut/base.rb +57 -0
- data/mkbrut/lib/mkbrut/cli.rb +107 -0
- data/mkbrut/lib/mkbrut/erb_binding_delegate.rb +20 -0
- data/mkbrut/lib/mkbrut/internet_identifier.rb +32 -0
- data/mkbrut/lib/mkbrut/invalid_identifier.rb +4 -0
- data/mkbrut/lib/mkbrut/ops/add_css_import.rb +42 -0
- data/mkbrut/lib/mkbrut/ops/add_i18n_message.rb +74 -0
- data/mkbrut/lib/mkbrut/ops/add_method.rb +48 -0
- data/mkbrut/lib/mkbrut/ops/append_to_file.rb +20 -0
- data/mkbrut/lib/mkbrut/ops/base_op.rb +21 -0
- data/mkbrut/lib/mkbrut/ops/copy_file.rb +12 -0
- data/mkbrut/lib/mkbrut/ops/insert_code_in_method.rb +58 -0
- data/mkbrut/lib/mkbrut/ops/insert_route.rb +52 -0
- data/mkbrut/lib/mkbrut/ops/mkdir.rb +13 -0
- data/mkbrut/lib/mkbrut/ops/prism_parsing_op.rb +70 -0
- data/mkbrut/lib/mkbrut/ops/render_template.rb +26 -0
- data/mkbrut/lib/mkbrut/ops/skip_file.rb +10 -0
- data/mkbrut/lib/mkbrut/ops.rb +16 -0
- data/mkbrut/lib/mkbrut/organization.rb +5 -0
- data/mkbrut/lib/mkbrut/prefix.rb +26 -0
- data/mkbrut/lib/mkbrut/prefixed_io.rb +16 -0
- data/mkbrut/lib/mkbrut/segments/bare_bones.rb +185 -0
- data/mkbrut/lib/mkbrut/segments/demo.rb +121 -0
- data/mkbrut/lib/mkbrut/segments/heroku.rb +30 -0
- data/mkbrut/lib/mkbrut/segments/sidekiq.rb +3 -0
- data/mkbrut/lib/mkbrut/segments.rb +8 -0
- data/mkbrut/lib/mkbrut/version.rb +3 -0
- data/mkbrut/lib/mkbrut/versions.rb +13 -0
- data/mkbrut/lib/mkbrut.rb +18 -0
- data/mkbrut/mkbrut.gemspec +32 -0
- data/mkbrut/templates/Base/.dockerignore +25 -0
- data/mkbrut/templates/Base/.env.development.erb +60 -0
- data/mkbrut/templates/Base/.env.test.erb +8 -0
- data/mkbrut/templates/Base/.gitignore +31 -0
- data/mkbrut/templates/Base/.projections.json +59 -0
- data/mkbrut/templates/Base/Dockerfile.dx +205 -0
- data/mkbrut/templates/Base/Gemfile.erb +53 -0
- data/mkbrut/templates/Base/Procfile.development +5 -0
- data/mkbrut/templates/Base/Procfile.test +1 -0
- data/mkbrut/templates/Base/README.md +4 -0
- data/mkbrut/templates/Base/README.md.erb +40 -0
- data/mkbrut/templates/Base/app/bootstrap.rb +61 -0
- data/mkbrut/templates/Base/app/config/i18n/en/1_defaults.rb +128 -0
- data/mkbrut/templates/Base/app/config/i18n/en/2_app.rb +24 -0
- data/mkbrut/templates/Base/app/public/static/manifest.json.erb +33 -0
- data/mkbrut/templates/Base/app/src/app.rb.erb +37 -0
- data/mkbrut/templates/Base/app/src/back_end/data_models/app_data_model.rb +5 -0
- data/mkbrut/templates/Base/app/src/back_end/data_models/db.rb +19 -0
- data/mkbrut/templates/Base/app/src/back_end/data_models/migrations/20240101130000_citext.rb +6 -0
- data/mkbrut/templates/Base/app/src/back_end/data_models/seed/seed_data.rb +9 -0
- data/mkbrut/templates/Base/app/src/front_end/components/app_component.rb +8 -0
- data/mkbrut/templates/Base/app/src/front_end/components/custom_element_registration.rb.erb +7 -0
- data/mkbrut/templates/Base/app/src/front_end/css/index.css +2 -0
- data/mkbrut/templates/Base/app/src/front_end/css/svgs.css +12 -0
- data/mkbrut/templates/Base/app/src/front_end/forms/app_form.rb +4 -0
- data/mkbrut/templates/Base/app/src/front_end/handlers/app_handler.rb +4 -0
- data/mkbrut/templates/Base/app/src/front_end/images/LogoPylon.png +0 -0
- data/mkbrut/templates/Base/app/src/front_end/images/LogoTransit.png +0 -0
- data/mkbrut/templates/Base/app/src/front_end/images/apple-touch-icon-120x120.png +0 -0
- data/mkbrut/templates/Base/app/src/front_end/images/apple-touch-icon-152x152.png +0 -0
- data/mkbrut/templates/Base/app/src/front_end/images/apple-touch-icon-167x167.png +0 -0
- data/mkbrut/templates/Base/app/src/front_end/images/apple-touch-icon-180x180.png +0 -0
- data/mkbrut/templates/Base/app/src/front_end/images/favicon.ico +0 -0
- data/mkbrut/templates/Base/app/src/front_end/images/icon.png +0 -0
- data/mkbrut/templates/Base/app/src/front_end/images/mkicons.sh +6 -0
- data/mkbrut/templates/Base/app/src/front_end/js/index.js +6 -0
- data/mkbrut/templates/Base/app/src/front_end/layouts/default_layout.rb.erb +73 -0
- data/mkbrut/templates/Base/app/src/front_end/pages/app_page.rb +11 -0
- data/mkbrut/templates/Base/app/src/front_end/pages/home_page.rb +62 -0
- data/mkbrut/templates/Base/app/src/front_end/support/app_session.rb +6 -0
- data/mkbrut/templates/Base/app/src/front_end/svgs/README.md +5 -0
- data/mkbrut/templates/Base/app/src/front_end/svgs/comment-button.svg +59 -0
- data/mkbrut/templates/Base/bin/README.md.erb +5 -0
- data/mkbrut/templates/Base/bin/build-assets +7 -0
- data/mkbrut/templates/Base/bin/ci +39 -0
- data/mkbrut/templates/Base/bin/console +31 -0
- data/mkbrut/templates/Base/bin/db +9 -0
- data/mkbrut/templates/Base/bin/dbconsole +51 -0
- data/mkbrut/templates/Base/bin/dev +25 -0
- data/mkbrut/templates/Base/bin/release +26 -0
- data/mkbrut/templates/Base/bin/run +86 -0
- data/mkbrut/templates/Base/bin/scaffold +9 -0
- data/mkbrut/templates/Base/bin/setup +256 -0
- data/mkbrut/templates/Base/bin/startup-message +65 -0
- data/mkbrut/templates/Base/bin/test +9 -0
- data/mkbrut/templates/Base/bin/test-server +29 -0
- data/mkbrut/templates/Base/bin/watch-and-build-assets +37 -0
- data/mkbrut/templates/Base/config.ru +16 -0
- data/mkbrut/templates/Base/docker-compose.dx.yml +92 -0
- data/mkbrut/templates/Base/dx/README.md +28 -0
- data/mkbrut/templates/Base/dx/bash_customizations +12 -0
- data/mkbrut/templates/Base/dx/bash_customizations.local +8 -0
- data/mkbrut/templates/Base/dx/build +107 -0
- data/mkbrut/templates/Base/dx/docker-compose.env.erb +25 -0
- data/mkbrut/templates/Base/dx/dx.sh.lib +137 -0
- data/mkbrut/templates/Base/dx/exec +68 -0
- data/mkbrut/templates/Base/dx/prune +19 -0
- data/mkbrut/templates/Base/dx/show-help-in-app-container-then-wait.sh +38 -0
- data/mkbrut/templates/Base/dx/start +30 -0
- data/mkbrut/templates/Base/dx/stop +23 -0
- data/mkbrut/templates/Base/package.json.erb +37 -0
- data/mkbrut/templates/Base/puma.config.rb +53 -0
- data/mkbrut/templates/Base/specs/e2e/home_page.spec.rb.erb +23 -0
- data/mkbrut/templates/Base/specs/front_end/js/SpecHelper.js +24 -0
- data/mkbrut/templates/Base/specs/front_end/pages/home_page.spec.rb +22 -0
- data/mkbrut/templates/Base/specs/lint_factories.spec.rb +7 -0
- data/mkbrut/templates/Base/specs/spec_helper.rb +78 -0
- data/mkbrut/templates/Base/specs/support.rb +2 -0
- data/mkbrut/templates/segments/BareBones/app/src/front_end/handlers/trigger_exception_handler.rb +24 -0
- data/mkbrut/templates/segments/BareBones/app/src/front_end/js/Example.js.erb +49 -0
- data/mkbrut/templates/segments/BareBones/specs/front_end/handlers/trigger_exception_handler.spec.rb +41 -0
- data/mkbrut/templates/segments/BareBones/specs/front_end/js/Example.spec.js.erb +38 -0
- data/mkbrut/templates/segments/Demo/app/src/back_end/data_models/db/guestbook_message.rb +3 -0
- data/mkbrut/templates/segments/Demo/app/src/back_end/data_models/migrations/20250628194124_guestbook.rb +14 -0
- data/mkbrut/templates/segments/Demo/app/src/front_end/components/flash_component.rb +36 -0
- data/mkbrut/templates/segments/Demo/app/src/front_end/css/constraint-violations.css +18 -0
- data/mkbrut/templates/segments/Demo/app/src/front_end/css/fonts.css +19 -0
- data/mkbrut/templates/segments/Demo/app/src/front_end/fonts/monaspace-xenon.ttf +0 -0
- data/mkbrut/templates/segments/Demo/app/src/front_end/forms/guestbook_message_form.rb +4 -0
- data/mkbrut/templates/segments/Demo/app/src/front_end/handlers/guestbook_message_handler.rb +64 -0
- data/mkbrut/templates/segments/Demo/app/src/front_end/pages/guestbook_page/message_component.rb +41 -0
- data/mkbrut/templates/segments/Demo/app/src/front_end/pages/guestbook_page.rb +43 -0
- data/mkbrut/templates/segments/Demo/app/src/front_end/pages/new_guestbook_message_page.rb +64 -0
- data/mkbrut/templates/segments/Demo/specs/back_end/data_models/db/guestbook_message.spec.rb +5 -0
- data/mkbrut/templates/segments/Demo/specs/e2e/guest_message.spec.rb +54 -0
- data/mkbrut/templates/segments/Demo/specs/factories/db/guestbook_message.factory.rb +7 -0
- data/mkbrut/templates/segments/Demo/specs/front_end/components/flash_component.spec.rb +5 -0
- data/mkbrut/templates/segments/Demo/specs/front_end/handlers/guestbook_message_handler.spec.rb +122 -0
- data/mkbrut/templates/segments/Demo/specs/front_end/pages/guestbook_page/message_component.spec.rb +5 -0
- data/mkbrut/templates/segments/Demo/specs/front_end/pages/guestbook_page.spec.rb +52 -0
- data/mkbrut/templates/segments/Demo/specs/front_end/pages/new_guestbook_message_page.spec.rb +5 -0
- data/mkbrut/templates/segments/Heroku/bin/deploy +11 -0
- data/mkbrut/templates/segments/Heroku/deploy/Dockerfile +125 -0
- data/mkbrut/templates/segments/Heroku/deploy/docker-entrypoint +15 -0
- data/mkbrut/templates/segments/Heroku/deploy/heroku_config.rb +26 -0
- metadata +185 -21
- data/docs/assets/chunks/@localSearchIndexroot.COP2Bcmp.js +0 -1
- data/docs/assets/overview.md.iMnwLO4x.js +0 -1
- data/docs/assets/overview.md.iMnwLO4x.lean.js +0 -1
- data/docs/assets/tutorial.md.BYXj4cOu.js +0 -1
- data/docs/assets/tutorial.md.BYXj4cOu.lean.js +0 -1
- /data/docs/assets/{components.md.iLiv2E9X.lean.js → components.md.DHh-NwKs.lean.js} +0 -0
- /data/docs/assets/{configuration.md.DmuAdsli.lean.js → configuration.md.D8Wz3oJU.lean.js} +0 -0
- /data/docs/assets/{forms.md.D8aa_qI-.lean.js → forms.md.BRE85eju.lean.js} +0 -0
@@ -0,0 +1,121 @@
|
|
1
|
+
# Additional classes and configuration for a new Brut
|
2
|
+
# app that provides a more demonstration of the features.
|
3
|
+
class MKBrut::Segments::Demo < MKBrut::Base
|
4
|
+
|
5
|
+
def self.friendly_name = "Demo features and files"
|
6
|
+
|
7
|
+
def initialize(app_options:, current_dir:, templates_dir:)
|
8
|
+
@project_root = current_dir / app_options.app_name
|
9
|
+
@templates_dir = templates_dir / "segments" / "Demo"
|
10
|
+
@erb_binding = ErbBindingDelegate.new(app_options)
|
11
|
+
end
|
12
|
+
|
13
|
+
def add!
|
14
|
+
operations = copy_files(@templates_dir, @project_root) +
|
15
|
+
other_operations(@project_root)
|
16
|
+
|
17
|
+
operations.each do |operation|
|
18
|
+
operation.call
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def other_operations(project_root)
|
25
|
+
[
|
26
|
+
MKBrut::Ops::AddI18nMessage.new(
|
27
|
+
project_root: project_root,
|
28
|
+
hash: {
|
29
|
+
en: {
|
30
|
+
cv: {
|
31
|
+
ss: {
|
32
|
+
not_enough_words: "%{field} does not have enough words",
|
33
|
+
already_posted: "You've already posted a message. Thanks for that!",
|
34
|
+
},
|
35
|
+
},
|
36
|
+
pages: {
|
37
|
+
"NewGuestbookMessagePage": {
|
38
|
+
title: "New guestbook message page",
|
39
|
+
},
|
40
|
+
"GuestbookPage": {
|
41
|
+
title: "Guestbook page",
|
42
|
+
},
|
43
|
+
},
|
44
|
+
guestbook_not_saved: "Your guestbook message was not saved",
|
45
|
+
guestbook_saved: "Thanks for writing!",
|
46
|
+
},
|
47
|
+
}
|
48
|
+
),
|
49
|
+
MKBrut::Ops::InsertRoute.new(
|
50
|
+
project_root: project_root,
|
51
|
+
code: %{page "/guestbook"},
|
52
|
+
),
|
53
|
+
MKBrut::Ops::InsertRoute.new(
|
54
|
+
project_root: project_root,
|
55
|
+
code: %{form "/guestbook_message"},
|
56
|
+
),
|
57
|
+
MKBrut::Ops::InsertRoute.new(
|
58
|
+
project_root: project_root,
|
59
|
+
code: %{page "/new_guestbook_message"},
|
60
|
+
),
|
61
|
+
MKBrut::Ops::InsertCodeInMethod.new(
|
62
|
+
file: project_root / "app" / "src" / "back_end" / "data_models" / "seed" / "seed_data.rb",
|
63
|
+
class_name: "SeedData",
|
64
|
+
method_name: "seed!",
|
65
|
+
code: %{
|
66
|
+
10.times do
|
67
|
+
create(:guestbook_message, created_at: Date.today - rand(1..100))
|
68
|
+
end
|
69
|
+
}
|
70
|
+
),
|
71
|
+
MKBrut::Ops::AddCSSImport.new(
|
72
|
+
project_root: project_root,
|
73
|
+
import: "constraint-violations.css"
|
74
|
+
),
|
75
|
+
MKBrut::Ops::AddCSSImport.new(
|
76
|
+
project_root: project_root,
|
77
|
+
import: "fonts.css"
|
78
|
+
),
|
79
|
+
MKBrut::Ops::InsertCodeInMethod.new(
|
80
|
+
file: project_root / "app" / "src" / "front_end" / "pages"/ "home_page.rb",
|
81
|
+
class_name: "HomePage",
|
82
|
+
method_name: "page_template",
|
83
|
+
where: :start,
|
84
|
+
code: %{
|
85
|
+
div(class: "w-50 mh-auto mt-4") do
|
86
|
+
a(href: NewGuestbookMessagePage.routing,
|
87
|
+
class: "db f-3 ff-sans blue-400 fw-bold tc"
|
88
|
+
) do
|
89
|
+
"Sign The Guestbook!"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
}
|
93
|
+
),
|
94
|
+
MKBrut::Ops::AddMethod.new(
|
95
|
+
file: project_root / "app" / "src" / "front_end" / "support" / "app_session.rb",
|
96
|
+
class_name: "AppSession",
|
97
|
+
code: %{def signed_guestbook? = !!self.guestbook_message},
|
98
|
+
),
|
99
|
+
MKBrut::Ops::AddMethod.new(
|
100
|
+
file: project_root / "app" / "src" / "front_end" / "support" / "app_session.rb",
|
101
|
+
class_name: "AppSession",
|
102
|
+
code: %{
|
103
|
+
def guestbook_message
|
104
|
+
DB::GuestbookMessage.find(
|
105
|
+
external_id: self[:guestbook_message_external_id]
|
106
|
+
)
|
107
|
+
end
|
108
|
+
}
|
109
|
+
),
|
110
|
+
MKBrut::Ops::AddMethod.new(
|
111
|
+
file: project_root / "app" / "src" / "front_end" / "support" / "app_session.rb",
|
112
|
+
class_name: "AppSession",
|
113
|
+
code: %{
|
114
|
+
def signed_guestbook(guestbook_message)
|
115
|
+
self[:guestbook_message_external_id] = guestbook_message.external_id
|
116
|
+
end
|
117
|
+
}
|
118
|
+
),
|
119
|
+
]
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class MKBrut::Segments::Heroku < MKBrut::Base
|
2
|
+
def self.friendly_name = "Heroku-based Deployment"
|
3
|
+
|
4
|
+
def initialize(app_options:, current_dir:, templates_dir:)
|
5
|
+
@project_root = current_dir / app_options.app_name
|
6
|
+
@templates_dir = templates_dir / "segments" / "Heroku"
|
7
|
+
@erb_binding = MKBrut::ErbBindingDelegate.new(app_options)
|
8
|
+
end
|
9
|
+
|
10
|
+
def add!
|
11
|
+
operations = copy_files(@templates_dir, @project_root) +
|
12
|
+
other_operations
|
13
|
+
|
14
|
+
operations.each do |operation|
|
15
|
+
operation.call
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def other_operations
|
20
|
+
[
|
21
|
+
MKBrut::Ops::AppendToFile.new(
|
22
|
+
file: @project_root / ".gitignore",
|
23
|
+
content: %{
|
24
|
+
# These are generated by bin/deploy
|
25
|
+
deploy/Dockerfile.*
|
26
|
+
}
|
27
|
+
)
|
28
|
+
]
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require "pathname"
|
2
|
+
require "json"
|
3
|
+
require_relative "version"
|
4
|
+
|
5
|
+
class MKBrut::Versions
|
6
|
+
def initialize
|
7
|
+
@brut_version = MKBrut::VERSION
|
8
|
+
end
|
9
|
+
|
10
|
+
def brut_version_specifier = "~> #{@brut_version}"
|
11
|
+
def brut_css_version_specifier = "~#{@brut_version}"
|
12
|
+
def brut_js_version_specifier = "~#{@brut_version}"
|
13
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module MKBrut
|
2
|
+
autoload :App, "mkbrut/app"
|
3
|
+
autoload :AppId, "mkbrut/app_id"
|
4
|
+
autoload :AppName, "mkbrut/app_name"
|
5
|
+
autoload :AppOptions, "mkbrut/app_options"
|
6
|
+
autoload :Base, "mkbrut/base"
|
7
|
+
autoload :CLI, "mkbrut/cli"
|
8
|
+
autoload :ErbBindingDelegate, "mkbrut/erb_binding_delegate"
|
9
|
+
autoload :InternetIdentifier, "mkbrut/internet_identifier"
|
10
|
+
autoload :InvalidIdentifier, "mkbrut/invalid_identifier"
|
11
|
+
autoload :Ops, "mkbrut/ops"
|
12
|
+
autoload :Organization, "mkbrut/organization"
|
13
|
+
autoload :Prefix, "mkbrut/prefix"
|
14
|
+
autoload :Segments, "mkbrut/segments"
|
15
|
+
autoload :Versions, "mkbrut/versions"
|
16
|
+
autoload :PrefixedIO, "mkbrut/prefixed_io"
|
17
|
+
autoload :VERSION, "mkbrut/version"
|
18
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
lib = File.expand_path("../lib", __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require "mkbrut/version"
|
4
|
+
Gem::Specification.new do |spec|
|
5
|
+
spec.name = "mkbrut"
|
6
|
+
spec.version = MKBrut::VERSION
|
7
|
+
spec.authors = ["Dave Copeland"]
|
8
|
+
spec.email = ["davec@naildrivin5.com"]
|
9
|
+
|
10
|
+
spec.summary = "Create a new Brut App"
|
11
|
+
spec.description = "mkbrut is how you go from zero to having a Brut app where you can start working."
|
12
|
+
spec.homepage = "https://brutrb.com"
|
13
|
+
spec.bindir = "exe"
|
14
|
+
|
15
|
+
spec.files = Dir.glob("lib/**/*.rb") + # Gem source code
|
16
|
+
Dir.glob( # Templates used to create a new Brut app
|
17
|
+
"templates/**/*",
|
18
|
+
flags: File::FNM_DOTMATCH
|
19
|
+
).reject {
|
20
|
+
it =~ /\/\.{1,2}$/ # Pesky dotfile
|
21
|
+
}.reject {
|
22
|
+
it =~ /\.DS_Store$/ # FML
|
23
|
+
} +
|
24
|
+
[
|
25
|
+
"exe/mkbrut", # executable
|
26
|
+
]
|
27
|
+
|
28
|
+
spec.executables = ["mkbrut"]
|
29
|
+
spec.require_paths = ["lib"]
|
30
|
+
|
31
|
+
spec.add_development_dependency "rake"
|
32
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Ignore git directory.
|
2
|
+
/.git/
|
3
|
+
/.gitignore
|
4
|
+
|
5
|
+
# Ignore bundler config.
|
6
|
+
/.bundle
|
7
|
+
|
8
|
+
# Ignore all environment files
|
9
|
+
/.env*
|
10
|
+
|
11
|
+
# Ignore all logfiles and tempfiles.
|
12
|
+
/logs/*
|
13
|
+
/tmp/*
|
14
|
+
|
15
|
+
# The most important thing to ignore of all time
|
16
|
+
/node_modules/
|
17
|
+
|
18
|
+
# Ignore generated assets
|
19
|
+
/app/public/*
|
20
|
+
|
21
|
+
# Ignore Docker-related files
|
22
|
+
/.dockerignore
|
23
|
+
/Dockerfile*
|
24
|
+
/docker-compose.*
|
25
|
+
/deploy/docker-compose.*
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# Environment variables needed for running in development. This file
|
2
|
+
# also serves as the canonical list of ALL environment variables the app
|
3
|
+
# must have in production.
|
4
|
+
#
|
5
|
+
# Each env var should be preceded by a comment explaining its purpose.
|
6
|
+
# The env var itself can be written in one of two ways:
|
7
|
+
#
|
8
|
+
# * Conventionally set a value:
|
9
|
+
#
|
10
|
+
# ```
|
11
|
+
# # the API key to interact with the OCP Widgets Service.
|
12
|
+
# WIDGETS_API_KEY=some-value
|
13
|
+
# ```
|
14
|
+
# Ideally, all values are set this way so that everyone is using the same
|
15
|
+
# value and the app just works without having to go to an external service
|
16
|
+
# to get a real secret for local development.
|
17
|
+
#
|
18
|
+
# * Indicates a local override is required:
|
19
|
+
#
|
20
|
+
# ```
|
21
|
+
# # the API key to interact with the OCP Widgets Service.
|
22
|
+
# LOCAL:WIDGETS_API_KEY
|
23
|
+
# ```
|
24
|
+
#
|
25
|
+
# In this form, bin/setup will ask the developer for the value and place
|
26
|
+
# it in .env.development.local. As your app evolves and adds more
|
27
|
+
# environment variables, you can add them like this and `bin/setup` will
|
28
|
+
# see which ones are present vs missing.
|
29
|
+
|
30
|
+
# Session secret used to encrypt the session
|
31
|
+
SESSION_SECRET=<%= session_secret %>
|
32
|
+
# URL to the database
|
33
|
+
DATABASE_URL=postgres://postgres:postgres@postgres:5432/<%= app_id %>_development
|
34
|
+
|
35
|
+
# Configures the endpoint where OTel traces are sent.
|
36
|
+
# In dev and test, it's the otel-desktop-viewer set up in
|
37
|
+
# docker-compose.dx.yml. For production, consult your
|
38
|
+
# OTel vendor's documentation.
|
39
|
+
OTEL_EXPORTER_OTLP_ENDPOINT="http://otel-desktop-viewer:4318"
|
40
|
+
|
41
|
+
# OTel exporter to use for sending traces to the endpoint. You usually
|
42
|
+
# want otlp, however, in production, consult your vendor's documentation to be sure.
|
43
|
+
OTEL_TRACES_EXPORTER="otlp"
|
44
|
+
|
45
|
+
# OTel exporter protocol. You usually want http/protobuf, however,
|
46
|
+
# in production, consult your vendor's documentation to be sure.
|
47
|
+
OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"
|
48
|
+
|
49
|
+
# This controls the background thread used by the span processor.
|
50
|
+
# I swear I had to set this to false to make stuff work, however
|
51
|
+
# various corporate AI chatbots said it should be true for use with
|
52
|
+
# Puma. I'm going with my hazy memory for now.
|
53
|
+
OTEL_RUBY_BSP_START_THREAD_ON_BOOT=false
|
54
|
+
|
55
|
+
# OTel log level. Set this to "debug" to try to figure out why OTel isn't working.
|
56
|
+
OTEL_LOG_LEVEL=warn
|
57
|
+
|
58
|
+
# If set to true, Puma will log its configuration, which is handy to understand
|
59
|
+
# if what you think you configured actually got configured.
|
60
|
+
PUMA_LOG_CONFIG=true
|
@@ -0,0 +1,8 @@
|
|
1
|
+
SESSION_SECRET=<%= session_secret %>
|
2
|
+
DATABASE_URL=postgres://postgres:postgres@postgres:5432/<%= app_id %>_test
|
3
|
+
OTEL_EXPORTER_OTLP_ENDPOINT="http://otel-desktop-viewer:4318"
|
4
|
+
OTEL_TRACES_EXPORTER="otlp"
|
5
|
+
OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"
|
6
|
+
OTEL_RUBY_BSP_START_THREAD_ON_BOOT=false
|
7
|
+
OTEL_LOG_LEVEL=warn
|
8
|
+
PUMA_LOG_CONFIG=true
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# Never checkin tmp
|
2
|
+
/tmp
|
3
|
+
# This should never be checked in
|
4
|
+
/node_modules
|
5
|
+
# This contains generated code, so should not be checked in
|
6
|
+
/app/public/css
|
7
|
+
# This contains generated code, so should not be checked in
|
8
|
+
/app/public/js
|
9
|
+
# This contains generated code, so should not be checked in
|
10
|
+
/app/public/static/images/
|
11
|
+
# Don't want to check in the generated JSDocs dir
|
12
|
+
/jsdocs
|
13
|
+
# This is generated per environment
|
14
|
+
/app/config/asset_metadata.json
|
15
|
+
# Don't check in logs
|
16
|
+
/logs
|
17
|
+
|
18
|
+
# This could contain actual secrets and should not be checked in
|
19
|
+
/.env.development.local
|
20
|
+
|
21
|
+
# These are generated artifacts
|
22
|
+
/deploy/Dockerfile.*
|
23
|
+
/deploy/docker-compose.yml
|
24
|
+
|
25
|
+
# RSpec configuration should be in one place.
|
26
|
+
# Devs can override as needed, but this is not how
|
27
|
+
# configuration is to be shared
|
28
|
+
/.rspec
|
29
|
+
|
30
|
+
# Gems installed locally should not be checked in
|
31
|
+
/local-gems
|
@@ -0,0 +1,59 @@
|
|
1
|
+
{
|
2
|
+
"app/src/*.rb": {
|
3
|
+
"alternate": "specs/{}.spec.rb",
|
4
|
+
"type": "source"
|
5
|
+
},
|
6
|
+
"app/src/front_end/js/*.js": {
|
7
|
+
"alternate": "specs/front_end/js/{}.spec.js",
|
8
|
+
"type": "js"
|
9
|
+
},
|
10
|
+
"specs/*.spec.rb": {
|
11
|
+
"alternate": "app/src/{}.rb",
|
12
|
+
"type": "spec"
|
13
|
+
},
|
14
|
+
"specs/front_end/js/*.spec.js": {
|
15
|
+
"alternate": "app/src/front_end/js/{}.js",
|
16
|
+
"type": "jsspec"
|
17
|
+
},
|
18
|
+
"app/src/front_end/components/*.rb": {
|
19
|
+
"type": "component"
|
20
|
+
},
|
21
|
+
"app/src/front_end/forms/*.rb": {
|
22
|
+
"type": "form"
|
23
|
+
},
|
24
|
+
"app/src/front_end/handlers/*.rb": {
|
25
|
+
"type": "handler"
|
26
|
+
},
|
27
|
+
"app/src/front_end/pages/*.rb": {
|
28
|
+
"type": "page"
|
29
|
+
},
|
30
|
+
"app/src/front_end/pages/*.html.rb": {
|
31
|
+
"type": "erb"
|
32
|
+
},
|
33
|
+
"app/src/back_end/data_models/db/*.rb": {
|
34
|
+
"type": "db"
|
35
|
+
},
|
36
|
+
"app/src/back_end/data_models/migrations/*.rb": {
|
37
|
+
"type": "migration"
|
38
|
+
},
|
39
|
+
"app/src/back_end/data_models/migrations/*.sql": {
|
40
|
+
"type": "migration"
|
41
|
+
},
|
42
|
+
"app/src/back_end/data_models/seed/*.rb": {
|
43
|
+
"type": "seed"
|
44
|
+
},
|
45
|
+
"app/src/back_end/domain/*.rb": {
|
46
|
+
"type": "domain"
|
47
|
+
},
|
48
|
+
"app/src/back_end/jobs/*.rb": {
|
49
|
+
"type": "job"
|
50
|
+
},
|
51
|
+
"app/src/back_end/service_wrappers/*.rb": {
|
52
|
+
"type": "service_wrapper"
|
53
|
+
},
|
54
|
+
"specs/factories/*.factory.rb": {
|
55
|
+
"type": "factory",
|
56
|
+
"alternate": "app/src/back_end/data_models/{}.rb"
|
57
|
+
}
|
58
|
+
|
59
|
+
}
|
@@ -0,0 +1,205 @@
|
|
1
|
+
# This file is heavily documented to explain what is going on and why.
|
2
|
+
# If you are reading this, however, you now own this file and can
|
3
|
+
# change it how you like. Just be sure you understand how it works in the
|
4
|
+
# context of docker-compose.dx.yml and the files in dx/,
|
5
|
+
# which are referred to as the Workspace
|
6
|
+
#
|
7
|
+
# This file is a set of instructions to build a Docker _image_, which is
|
8
|
+
# then use to _start_ a _container_.
|
9
|
+
|
10
|
+
# This uses a base image where Ruby is already installed. This saves
|
11
|
+
# us from having to install Ruby ourselves. Change this whenever you update
|
12
|
+
# Ruby. Note that by convention, "3.4" will be whatever the latest point
|
13
|
+
# release of Ruby 3.4 is. If you don't want that, specify an exact Ruby version here.
|
14
|
+
# Note that this value is intended to be in sync with the tag of the image
|
15
|
+
# found in dx/docker-compose.env
|
16
|
+
FROM ruby:3.4
|
17
|
+
|
18
|
+
# This attempts to make RUN directives fail when UNIX pipelines are involved
|
19
|
+
SHELL [ "/bin/bash", "-o", "pipefail", "-c" ]
|
20
|
+
|
21
|
+
# This tells apt-get and friends not to ask for interactive input
|
22
|
+
# as this creates massive confusion in the context of building a Docker image.
|
23
|
+
ENV DEBIAN_FRONTEND=noninteractive
|
24
|
+
|
25
|
+
# These packages are needed to set up other repos to install other
|
26
|
+
# packages and/or are useful in installing other software
|
27
|
+
#
|
28
|
+
# - ca-certificates - needed by Postgres client
|
29
|
+
# - curl - needed by various installation instructions
|
30
|
+
# - gnupg - needed to install Docker
|
31
|
+
# - lsb-release - needed by Postgres install instructions
|
32
|
+
# - rsync - needed by Brut's build_assets command
|
33
|
+
# - vim - needed when we want to edit files inside container
|
34
|
+
RUN apt-get -y clean && \
|
35
|
+
apt-get -y update && \
|
36
|
+
apt-get install --quiet --yes \
|
37
|
+
ca-certificates \
|
38
|
+
curl \
|
39
|
+
gnupg \
|
40
|
+
lsb-release \
|
41
|
+
rsync \
|
42
|
+
vim
|
43
|
+
|
44
|
+
# These are dependencies needed to install Chromium via Playright.
|
45
|
+
# You can check this list via
|
46
|
+
#
|
47
|
+
# npx playwright install-deps --dry-run chromium
|
48
|
+
#
|
49
|
+
RUN apt-get install -y --no-install-recommends libasound2 \
|
50
|
+
libatk-bridge2.0-0 \
|
51
|
+
libatk1.0-0 \
|
52
|
+
libatspi2.0-0 \
|
53
|
+
libcairo2 \
|
54
|
+
libcups2 \
|
55
|
+
libdbus-1-3 \
|
56
|
+
libdrm2 \
|
57
|
+
libgbm1 \
|
58
|
+
libglib2.0-0 \
|
59
|
+
libnspr4 \
|
60
|
+
libnss3 \
|
61
|
+
libpango-1.0-0 \
|
62
|
+
libx11-6 \
|
63
|
+
libxcb1 \
|
64
|
+
libxcomposite1 \
|
65
|
+
libxdamage1 \
|
66
|
+
libxext6 \
|
67
|
+
libxfixes3 \
|
68
|
+
libxkbcommon0 \
|
69
|
+
libxrandr2 \
|
70
|
+
xvfb \
|
71
|
+
fonts-noto-color-emoji \
|
72
|
+
fonts-unifont \
|
73
|
+
libfontconfig1 \
|
74
|
+
libfreetype6 \
|
75
|
+
xfonts-scalable \
|
76
|
+
fonts-liberation \
|
77
|
+
fonts-ipafont-gothic \
|
78
|
+
fonts-wqy-zenhei \
|
79
|
+
fonts-tlwg-loma-otf \
|
80
|
+
fonts-freefont-ttf
|
81
|
+
|
82
|
+
|
83
|
+
# Install Docker itself. Note that this is installed only what is needed to run
|
84
|
+
# the Docker CLI - the docker-compose.dx.yml will connect this docker's socket
|
85
|
+
# to the one on the host. This sets up "Docker outside Docker" and
|
86
|
+
# is here only to build the production Docker containers and to push
|
87
|
+
# them to a repository. This is not intended to run containers from
|
88
|
+
# inside this one.
|
89
|
+
RUN install -m 0755 -d /etc/apt/keyrings && \
|
90
|
+
curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg && \
|
91
|
+
chmod a+r /etc/apt/keyrings/docker.gpg && \
|
92
|
+
echo \
|
93
|
+
"deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
|
94
|
+
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
|
95
|
+
tee /etc/apt/sources.list.d/docker.list > /dev/null && \
|
96
|
+
apt-get update --quiet --yes && \
|
97
|
+
apt-get install --quiet --yes docker-ce \
|
98
|
+
docker-ce-cli \
|
99
|
+
containerd.io \
|
100
|
+
docker-buildx-plugin \
|
101
|
+
docker-compose-plugin
|
102
|
+
|
103
|
+
|
104
|
+
# Install Postgres Client, per https://www.postgresql.org/download/linux/debian/
|
105
|
+
# Note that ca-certificates and curl are installed above
|
106
|
+
#
|
107
|
+
# Also note that the version here should match the version set up in
|
108
|
+
# docker-compose.dx.yml
|
109
|
+
RUN sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' && \
|
110
|
+
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - && \
|
111
|
+
apt-get update && \
|
112
|
+
apt-get -y install postgresql-client-16
|
113
|
+
|
114
|
+
# Update RubyGems and Bundler, setting RubyGems not to generate
|
115
|
+
# documentation as that is slow and you likely won't use it.
|
116
|
+
RUN echo "gem: --no-document" >> ~/.gemrc && \
|
117
|
+
gem update --system && \
|
118
|
+
gem install bundler
|
119
|
+
|
120
|
+
# Installs the Heroku CLI, per Heroku docs at
|
121
|
+
# https://devcenter.heroku.com/articles/heroku-cli#install-with-ubuntu-debian-apt-get
|
122
|
+
RUN curl https://cli-assets.heroku.com/install-ubuntu.sh | sh
|
123
|
+
|
124
|
+
# Up to now, RUN directives ran as the root user. When using this container
|
125
|
+
# for development, we do not want to run as the root user. On macOS, this is not
|
126
|
+
# a big deal, but in Linux, the root user inside this container can create files
|
127
|
+
# as the root user on your computer. You don't want that.
|
128
|
+
|
129
|
+
# What is tricky is that we ultimately want the non-root user here
|
130
|
+
# to have the same UID and same groups as your user on your host/computer.
|
131
|
+
# And, we want that user to be able to run Docker commands.
|
132
|
+
|
133
|
+
# First, set up some build args that `dx/build` will override with the actual values.
|
134
|
+
# The reason these all have values is that Docker will not fail if they are omitted,
|
135
|
+
# but it will behave strangely.
|
136
|
+
#
|
137
|
+
# Their user id, which ideally is overridden to match your user id on the host
|
138
|
+
ARG user_uid=10001
|
139
|
+
|
140
|
+
# Their group id, which ideally is overridden to match your group id on the host
|
141
|
+
ARG user_gid=10002
|
142
|
+
|
143
|
+
# The group id that can access /var/run/docker.sock on the host.
|
144
|
+
# If this isn't mapped properly, no docker-out-of-docker commands will work
|
145
|
+
ARG docker_gid=10003
|
146
|
+
|
147
|
+
# This can be blank if the OS is such that the user inside the container can access
|
148
|
+
# /var/run/docker.sock simply from being in docker_gid. If this is not
|
149
|
+
# the case (as on macOS), it is not only sad, but we must add the group
|
150
|
+
# 0 (root) to the groups our new user is in.
|
151
|
+
ARG sadly_user_must_be_added_to_root=
|
152
|
+
|
153
|
+
# Create the user's group ID if it does not exist
|
154
|
+
RUN getent group ${user_gid} || groupadd --gid ${user_gid} appgroup
|
155
|
+
|
156
|
+
# Create the docker group id if it does not exist
|
157
|
+
RUN getent group ${docker_gid} || groupadd --gid ${docker_gid} hostdocker
|
158
|
+
|
159
|
+
# Create the user and set up their shell.
|
160
|
+
# Note that we put bash_customizations in both .profile and .bashrc
|
161
|
+
# to increase the chances they are used when running bash in various configurations
|
162
|
+
RUN useradd --uid ${user_uid} --gid ${user_gid} --groups ${sadly_user_must_be_added_to_root}${docker_gid} --create-home --home-dir /home/appuser appuser && \
|
163
|
+
echo ". ~/.bash_customizations" >> /home/appuser/.profile && \
|
164
|
+
echo ". ~/.bash_customizations.local" >> /home/appuser/.profile && \
|
165
|
+
echo ". ~/.bash_customizations" >> /home/appuser/.bashrc && \
|
166
|
+
echo ". ~/.bash_customizations.local" >> /home/appuser/.bashrc
|
167
|
+
|
168
|
+
# Now we must grant ownership to the new user over various files they will need to
|
169
|
+
# run or use
|
170
|
+
COPY --chown=appuser:${user_gid} dx/show-help-in-app-container-then-wait.sh /home/appuser
|
171
|
+
COPY --chown=appuser:${user_gid} dx/bash_customizations /home/appuser/.bash_customizations
|
172
|
+
COPY --chown=appuser:${user_gid} dx/bash_customizations.local /home/appuser/.bash_customizations.local
|
173
|
+
|
174
|
+
# This switches to the new user, meaniung all subsequent RUN directives will
|
175
|
+
# be run as this user. The USER directive allows changing both the user
|
176
|
+
# and the current group. We are omitting the group part of that because
|
177
|
+
# to include would exclude the user from all other groups we just set them up
|
178
|
+
# as belonging to.
|
179
|
+
USER appuser
|
180
|
+
|
181
|
+
# Install NodeJS, per https://nodejs.org/en/download
|
182
|
+
#
|
183
|
+
# Yes, this is seting up nvm just to install one version of node we will ever user in
|
184
|
+
# here and yes, this sucks. But it's better to use the vendor's official
|
185
|
+
# recommendation.
|
186
|
+
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash && \
|
187
|
+
\. "$HOME/.nvm/nvm.sh" && \
|
188
|
+
nvm install 22 && \
|
189
|
+
node -v && nvm current && npm -v
|
190
|
+
|
191
|
+
|
192
|
+
|
193
|
+
# This arg should have the version of playwright present in the app's Gemfile.lock.
|
194
|
+
# This is because the playright NodeJS library and the Ruby gem must have the same
|
195
|
+
# version or things won't work right. The value is blank because it really has to be
|
196
|
+
# detected during `dx/build`.
|
197
|
+
ARG PLAYWRIGHT_VERSION
|
198
|
+
# Now install the version of Playwright we detected as well as Chromium. NOTE, we
|
199
|
+
# must install Chromium, not chrome, because there is no version of Chrome for an
|
200
|
+
# ARM-based Debian linux, which is what this Dockerfile will build on an Apple
|
201
|
+
# Silicon Mac.
|
202
|
+
RUN \. "$HOME/.nvm/nvm.sh" && \
|
203
|
+
nvm use default && \
|
204
|
+
npm install -g playwright@$PLAYWRIGHT_VERSION && \
|
205
|
+
npx playwright install chromium
|