Skip to content

Commit 69e5fd7

Browse files
Prerequisites: Raise if Node version unsupported (#1202)
Follow-up to #1201 It's not enough to ensure Node is installed. We also need to ensure the consumer has the supported minimum version installed. Otherwise, subsequent generators will raise errors like so: ``` error [email protected]: The engine "node" is incompatible with this module. Expected version ">=18.12.0". Got "18.0.0" error Found incompatible module. ``` We select `v20.0.0` as our minimum supported version because it is slated for Active LTS, but is not bleeding edge at [this time][] We also raise when calling the template to avoid unnecessarily generating a new Rails application. [this time]: https://nodejs.org/en/about/previous-releases
1 parent 7bf6e82 commit 69e5fd7

File tree

10 files changed

+100
-11
lines changed

10 files changed

+100
-11
lines changed

lib/generators/suspenders/install/web_generator.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ class WebGenerator < Rails::Generators::Base
55
include Suspenders::Generators::APIAppUnsupported
66
include Suspenders::Generators::DatabaseUnsupported
77
include Suspenders::Generators::NodeNotInstalled
8+
include Suspenders::Generators::NodeVersionUnsupported
89

910
source_root File.expand_path("../../../templates/install/web", __FILE__)
1011
desc <<~MARKDOWN

lib/generators/suspenders/prerequisites_generator.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module Generators
33
class PrerequisitesGenerator < Rails::Generators::Base
44
include Suspenders::Generators::Helpers
55
include Suspenders::Generators::NodeNotInstalled
6+
include Suspenders::Generators::NodeVersionUnsupported
67

78
source_root File.expand_path("../../templates/prerequisites", __FILE__)
89

lib/install/web.rb

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,27 @@
1+
def node_version
2+
ENV["NODE_VERSION"] || `node --version`[/\d+\.\d+\.\d+/]
3+
end
4+
5+
def node_not_installed?
6+
!node_version.present?
7+
end
8+
9+
def node_version_unsupported?
10+
node_version < "20.0.0"
11+
end
12+
113
def apply_template!
14+
if node_not_installed? || node_version_unsupported?
15+
message = <<~ERROR
16+
17+
18+
=== Node version unsupported ===
19+
20+
Suspenders requires Node >= 20.0.0
21+
ERROR
22+
23+
fail Rails::Generators::Error, message
24+
end
225
if options[:database] == "postgresql" && options[:skip_test]
326
after_bundle do
427
gem_group :development, :test do

lib/suspenders/generators.rb

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@ def rspec_test_helper_present?
2222
def node_version
2323
ENV["NODE_VERSION"] || `node --version`[/\d+\.\d+\.\d+/]
2424
end
25+
26+
def node_not_installed?
27+
!node_version.present?
28+
end
29+
30+
def node_version_unsupported?
31+
node_version < Suspenders::MINIMUM_NODE_VERSION
32+
end
2533
end
2634

2735
module APIAppUnsupported
@@ -81,6 +89,9 @@ def database_unsupported?
8189

8290
module NodeNotInstalled
8391
class Error < StandardError
92+
def message
93+
"This generator requires Node"
94+
end
8495
end
8596

8697
extend ActiveSupport::Concern
@@ -92,11 +103,23 @@ def raise_if_node_not_installed
92103
end
93104
end
94105
end
106+
end
95107

96-
private
108+
module NodeVersionUnsupported
109+
class Error < StandardError
110+
def message
111+
"This generator requires Node >= #{Suspenders::MINIMUM_NODE_VERSION}"
112+
end
113+
end
97114

98-
def node_not_installed?
99-
!node_version.present?
115+
extend ActiveSupport::Concern
116+
117+
included do
118+
def raise_if_node_version_unsupported
119+
if node_version_unsupported?
120+
raise Suspenders::Generators::NodeVersionUnsupported::Error
121+
end
122+
end
100123
end
101124
end
102125
end

lib/suspenders/version.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ module Suspenders
22
VERSION = "3.0.0".freeze
33
RAILS_VERSION = "~> 7.0".freeze
44
MINIMUM_RUBY_VERSION = ">= 3.1".freeze
5+
MINIMUM_NODE_VERSION = "20.0.0".freeze
56
end

test/generators/suspenders/install/web_generator_test.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,16 @@ class WebGeneratorTest < Rails::Generators::TestCase
3838
end
3939
end
4040

41+
test "raises if Node is unsupported" do
42+
Object.any_instance.stubs(:`).returns("v19.9.9\n")
43+
44+
with_database "postgresql" do
45+
assert_raises Suspenders::Generators::NodeVersionUnsupported::Error do
46+
run_generator
47+
end
48+
end
49+
end
50+
4151
private
4252

4353
def prepare_destination

test/generators/suspenders/prerequisites_generator_test.rb

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,22 @@ class PrerequisitesGeneratorTest < Rails::Generators::TestCase
1212
teardown :restore_destination
1313

1414
test "generates .node-version file (from ENV)" do
15-
ClimateControl.modify NODE_VERSION: "1.2.3" do
15+
ClimateControl.modify NODE_VERSION: "20.0.0" do
1616
run_generator
1717

1818
assert_file app_root(".node-version") do |file|
19-
assert_match(/1\.2\.3/, file)
19+
assert_match(/20\.0\.0/, file)
2020
end
2121
end
2222
end
2323

2424
test "generates .node-version file (from system)" do
25-
Object.any_instance.stubs(:`).returns("v1.2.3\n")
25+
Object.any_instance.stubs(:`).returns("v20.0.0\n")
2626

2727
run_generator
2828

2929
assert_file app_root(".node-version") do |file|
30-
assert_match(/1\.2\.3/, file)
30+
assert_match(/20\.0\.0/, file)
3131
end
3232
end
3333

@@ -41,6 +41,16 @@ class PrerequisitesGeneratorTest < Rails::Generators::TestCase
4141
assert_no_file app_root(".node-version")
4242
end
4343

44+
test "raises if Node is unsupported" do
45+
Object.any_instance.stubs(:`).returns("v19.9.9\n")
46+
47+
assert_raises Suspenders::Generators::NodeVersionUnsupported::Error do
48+
run_generator
49+
end
50+
51+
assert_no_file app_root(".node-version")
52+
end
53+
4454
private
4555

4656
def restore_destination

test/suspenders/cleanup/generate_readme_test.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ module Suspenders
66
module Cleanup
77
class GenerateReadmeTest < ActiveSupport::TestCase
88
test "generates README using generator descriptions" do
9-
Object.any_instance.stubs(:`).returns("v1.2.3\n")
9+
Object.any_instance.stubs(:`).returns("v20.0.0\n")
1010

1111
Tempfile.create "README.md" do |readme|
1212
path = readme.path
@@ -20,7 +20,7 @@ class GenerateReadmeTest < ActiveSupport::TestCase
2020

2121
assert_match "## Prerequisites", readme
2222
assert_match Suspenders::MINIMUM_RUBY_VERSION, readme
23-
assert_match "Node: `1.2.3`", readme
23+
assert_match "Node: `20.0.0`", readme
2424

2525
assert_match "## Configuration", readme
2626
assert_match "### Test", readme

test/suspenders/generators_test.rb

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,35 @@
11
require "test_helper"
22

33
class Suspenders::GeneratorsTest < ActiveSupport::TestCase
4-
class APIAppUnsupportedTest < Suspenders::GeneratorsTest
4+
class APIAppUnsupportedTest < ActiveSupport::TestCase
55
test "message returns a custom message" do
66
expected = "This generator cannot be used on API only applications."
77

88
assert_equal expected, Suspenders::Generators::APIAppUnsupported::Error.new.message
99
end
1010
end
1111

12-
class DatabaseUnsupportedTest < Suspenders::GeneratorsTest
12+
class DatabaseUnsupportedTest < ActiveSupport::TestCase
1313
test "message returns a custom message" do
1414
expected = "This generator requires PostgreSQL"
1515

1616
assert_equal expected, Suspenders::Generators::DatabaseUnsupported::Error.new.message
1717
end
1818
end
19+
20+
class NodeNotInstalledTest < ActiveSupport::TestCase
21+
test "message returns a custom message" do
22+
expected = "This generator requires Node"
23+
24+
assert_equal expected, Suspenders::Generators::NodeNotInstalled::Error.new.message
25+
end
26+
end
27+
28+
class NodeVersionUnsupportedTest < ActiveSupport::TestCase
29+
test "message returns a custom message" do
30+
expected = "This generator requires Node >= #{Suspenders::MINIMUM_NODE_VERSION}"
31+
32+
assert_equal expected, Suspenders::Generators::NodeVersionUnsupported::Error.new.message
33+
end
34+
end
1935
end

test/suspenders_test.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,8 @@ class SuspendersTest < ActiveSupport::TestCase
1212
test "it has a Minimum Ruby version number" do
1313
assert Suspenders::MINIMUM_RUBY_VERSION
1414
end
15+
16+
test "it has a Minimum Node version number" do
17+
assert Suspenders::MINIMUM_NODE_VERSION
18+
end
1519
end

0 commit comments

Comments
 (0)