Skip to content

Commit 673c85a

Browse files
alexeyr-ci2alexeyr
andauthored
Fix invalid version checker warnings and add pre-release comparison (#1742)
* Fix invalid version checker warnings and add pre-release comparison * Additional fixes * Remove semver_to_string * Fix shakapacker_version_as_array caching --------- Co-authored-by: Alexey Romanov <[email protected]>
1 parent b5b30c0 commit 673c85a

File tree

8 files changed

+58
-63
lines changed

8 files changed

+58
-63
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ After a release, please make sure to run `bundle exec rake update_changelog`. Th
2323

2424
Changes since the last non-beta release.
2525

26+
#### Fixed
27+
28+
- Fixed invalid warnings about non-exact versions when using a pre-release version of React on Rails, as well as missing warnings when using different pre-release versions of the gem and the Node package. [PR 1742](https://github.com/shakacode/react_on_rails/pull/1742) by [alexeyr-ci2](https://github.com/alexeyr-ci2).
29+
2630
### [15.0.0-rc.1] - 2025-06-18
2731

2832
#### Improved

lib/react_on_rails/configuration.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ def validate_generated_component_packs_loading_strategy
180180
1. Use :sync or :defer loading strategy instead of :async
181181
2. Upgrade to Shakapacker v8.2.0 or above to enable async script loading
182182
MSG
183-
if PackerUtils.shakapacker_version_requirement_met?([8, 2, 0])
183+
if PackerUtils.shakapacker_version_requirement_met?("8.2.0")
184184
self.generated_component_packs_loading_strategy ||= :async
185185
elsif generated_component_packs_loading_strategy.nil?
186186
Rails.logger.warn("**WARNING** #{msg}")

lib/react_on_rails/packer_utils.rb

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ def self.using_shakapacker_const?
1010
return @using_shakapacker_const if defined?(@using_shakapacker_const)
1111

1212
@using_shakapacker_const = ReactOnRails::Utils.gem_available?("shakapacker") &&
13-
shakapacker_version_requirement_met?([7, 0, 0])
13+
shakapacker_version_requirement_met?("7.0.0")
1414
end
1515

1616
def self.using_webpacker_const?
@@ -57,15 +57,16 @@ def self.shakapacker_version
5757
end
5858

5959
def self.shakapacker_version_as_array
60-
match = shakapacker_version.match(ReactOnRails::VersionChecker::MAJOR_MINOR_PATCH_VERSION_REGEX)
60+
return @shakapacker_version_as_array if defined?(@shakapacker_version_as_array)
6161

62-
@shakapacker_version_as_array = [match[1].to_i, match[2].to_i, match[3].to_i]
62+
match = shakapacker_version.match(ReactOnRails::VersionChecker::VERSION_PARTS_REGEX)
63+
64+
# match[4] is the pre-release version, not normally a number but something like "beta.1" or `nil`
65+
@shakapacker_version_as_array = [match[1].to_i, match[2].to_i, match[3].to_i, match[4]].compact
6366
end
6467

6568
def self.shakapacker_version_requirement_met?(required_version)
66-
req_ver = semver_to_string(required_version)
67-
68-
Gem::Version.new(shakapacker_version) >= Gem::Version.new(req_ver)
69+
Gem::Version.new(shakapacker_version) >= Gem::Version.new(required_version)
6970
end
7071

7172
# This returns either a URL for the webpack-dev-server, non-server bundle or
@@ -171,9 +172,9 @@ def self.raise_nested_entries_disabled
171172

172173
def self.raise_shakapacker_version_incompatible_for_autobundling
173174
msg = <<~MSG
174-
**ERROR** ReactOnRails: Please upgrade Shakapacker to version #{semver_to_string(ReactOnRails::PacksGenerator::MINIMUM_SHAKAPACKER_VERSION)} or \
175+
**ERROR** ReactOnRails: Please upgrade Shakapacker to version #{ReactOnRails::PacksGenerator::MINIMUM_SHAKAPACKER_VERSION} or \
175176
above to use the automated bundle generation feature. The currently installed version is \
176-
#{semver_to_string(ReactOnRails::PackerUtils.shakapacker_version_as_array)}.
177+
#{ReactOnRails::PackerUtils.shakapacker_version}.
177178
MSG
178179

179180
raise ReactOnRails::Error, msg
@@ -182,15 +183,11 @@ def self.raise_shakapacker_version_incompatible_for_autobundling
182183
def self.raise_shakapacker_not_installed
183184
msg = <<~MSG
184185
**ERROR** ReactOnRails: Missing Shakapacker gem. Please upgrade to use Shakapacker \
185-
#{semver_to_string(ReactOnRails::PacksGenerator::MINIMUM_SHAKAPACKER_VERSION)} or above to use the \
186+
#{ReactOnRails::PacksGenerator::MINIMUM_SHAKAPACKER_VERSION} or above to use the \
186187
automated bundle generation feature.
187188
MSG
188189

189190
raise ReactOnRails::Error, msg
190191
end
191-
192-
def self.semver_to_string(ary)
193-
"#{ary[0]}.#{ary[1]}.#{ary[2]}"
194-
end
195192
end
196193
end

lib/react_on_rails/packs_generator.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ module ReactOnRails
66
# rubocop:disable Metrics/ClassLength
77
class PacksGenerator
88
CONTAINS_CLIENT_OR_SERVER_REGEX = /\.(server|client)($|\.)/
9-
MINIMUM_SHAKAPACKER_VERSION = [6, 5, 1].freeze
9+
MINIMUM_SHAKAPACKER_VERSION = "6.5.1"
1010

1111
def self.instance
1212
@instance ||= PacksGenerator.new

lib/react_on_rails/version_checker.rb

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ module ReactOnRails
66
class VersionChecker
77
attr_reader :node_package_version
88

9-
MAJOR_MINOR_PATCH_VERSION_REGEX = /(\d+)\.(\d+)\.(\d+)/
9+
# Semver uses - to separate pre-release, but RubyGems use .
10+
VERSION_PARTS_REGEX = /(\d+)\.(\d+)\.(\d+)(?:[-.]([0-9A-Za-z.-]+))?/
1011

1112
def self.build
1213
new(NodePackageVersion.build)
@@ -23,13 +24,7 @@ def log_if_gem_and_node_package_versions_differ
2324
return if node_package_version.raw.nil? || node_package_version.local_path_or_url?
2425
return log_node_semver_version_warning if node_package_version.semver_wildcard?
2526

26-
node_major_minor_patch = node_package_version.major_minor_patch
27-
gem_major_minor_patch = gem_major_minor_patch_version
28-
versions_match = node_major_minor_patch[0] == gem_major_minor_patch[0] &&
29-
node_major_minor_patch[1] == gem_major_minor_patch[1] &&
30-
node_major_minor_patch[2] == gem_major_minor_patch[2]
31-
32-
log_differing_versions_warning unless versions_match
27+
log_differing_versions_warning unless node_package_version.parts == gem_version_parts
3328
end
3429

3530
private
@@ -39,30 +34,29 @@ def common_error_msg
3934
Detected: #{node_package_version.raw}
4035
gem: #{gem_version}
4136
Ensure the installed version of the gem is the same as the version of
42-
your installed node package. Do not use >= or ~> in your Gemfile for react_on_rails.
43-
Do not use ^ or ~ in your package.json for react-on-rails.
37+
your installed Node package. Do not use >= or ~> in your Gemfile for react_on_rails.
38+
Do not use ^, ~, or other non-exact versions in your package.json for react-on-rails.
4439
Run `yarn add react-on-rails --exact` in the directory containing folder node_modules.
4540
MSG
4641
end
4742

4843
def log_differing_versions_warning
49-
msg = "**WARNING** ReactOnRails: ReactOnRails gem and node package versions do not match\n#{common_error_msg}"
44+
msg = "**WARNING** ReactOnRails: ReactOnRails gem and Node package versions do not match\n#{common_error_msg}"
5045
Rails.logger.warn(msg)
5146
end
5247

5348
def log_node_semver_version_warning
54-
msg = "**WARNING** ReactOnRails: Your node package version for react-on-rails contains a " \
55-
"^ or ~\n#{common_error_msg}"
49+
msg = "**WARNING** ReactOnRails: Your Node package version for react-on-rails is not an exact version\n" \
50+
"#{common_error_msg}"
5651
Rails.logger.warn(msg)
5752
end
5853

5954
def gem_version
6055
ReactOnRails::VERSION
6156
end
6257

63-
def gem_major_minor_patch_version
64-
match = gem_version.match(MAJOR_MINOR_PATCH_VERSION_REGEX)
65-
[match[1], match[2], match[3]]
58+
def gem_version_parts
59+
gem_version.match(VERSION_PARTS_REGEX)&.captures&.compact
6660
end
6761

6862
class NodePackageVersion
@@ -100,7 +94,7 @@ def semver_wildcard?
10094
# See https://docs.npmjs.com/cli/v10/configuring-npm/package-json#dependencies
10195
# We want to disallow all expressions other than exact versions
10296
# and the ones allowed by local_path_or_url?
103-
raw.blank? || raw.match(/[~^><|*-]/).present?
97+
raw.blank? || raw.start_with?(/[~^><*]/) || raw.include?(" - ") || raw.include?(" || ")
10498
end
10599

106100
def local_path_or_url?
@@ -110,15 +104,15 @@ def local_path_or_url?
110104
!raw.nil? && raw.include?("/") && !raw.start_with?("npm:")
111105
end
112106

113-
def major_minor_patch
107+
def parts
114108
return if local_path_or_url?
115109

116-
match = raw.match(MAJOR_MINOR_PATCH_VERSION_REGEX)
110+
match = raw.match(VERSION_PARTS_REGEX)
117111
unless match
118112
raise ReactOnRails::Error, "Cannot parse version number '#{raw}' (only exact versions are supported)"
119113
end
120114

121-
[match[1], match[2], match[3]]
115+
match.captures.compact
122116
end
123117

124118
private

spec/react_on_rails/configuration_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ module ReactOnRails
379379
context "when using Shakapacker >= 8.2.0" do
380380
before do
381381
allow(ReactOnRails::PackerUtils).to receive(:shakapacker_version_requirement_met?)
382-
.with([8, 2, 0]).and_return(true)
382+
.with("8.2.0").and_return(true)
383383
end
384384

385385
it "defaults to :async" do
@@ -426,7 +426,7 @@ module ReactOnRails
426426
context "when using Shakapacker < 8.2.0" do
427427
before do
428428
allow(ReactOnRails::PackerUtils).to receive(:shakapacker_version_requirement_met?)
429-
.with([8, 2, 0]).and_return(false)
429+
.with("8.2.0").and_return(false)
430430
allow(Rails.logger).to receive(:warn)
431431
end
432432

spec/react_on_rails/packer_utils_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
module ReactOnRails
66
describe PackerUtils do
77
describe ".shakapacker_version_requirement_met?" do
8-
minimum_version = [6, 5, 3]
8+
minimum_version = "6.5.3"
99

1010
it "returns false when version is lower than minimum_version" do
1111
allow(described_class).to receive(:shakapacker_version).and_return("6.5.0")
@@ -31,7 +31,7 @@ module ReactOnRails
3131
allow(described_class).to receive(:shakapacker_version).and_return("6.5.4")
3232
expect(described_class.shakapacker_version_requirement_met?(minimum_version)).to be(true)
3333

34-
allow(described_class).to receive(:shakapacker_version).and_return("7.7.7")
34+
allow(described_class).to receive(:shakapacker_version).and_return("7.0.0")
3535
expect(described_class.shakapacker_version_requirement_met?(minimum_version)).to be(true)
3636
end
3737
end

spec/react_on_rails/version_checker_spec.rb

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ module ReactOnRails # rubocop:disable Metrics/ModuleLength
1818

1919
context "when gem and node package major and minor versions are equal" do
2020
let(:node_package_version) do
21-
double_package_version(raw: "2.2.5-beta.2", major_minor_patch: %w[2 2 5])
21+
double_package_version(raw: "2.2.5-beta.2", parts: %w[2 2 5 beta.2])
2222
end
2323

2424
before { stub_gem_version("2.2.5.beta.2") }
@@ -32,67 +32,67 @@ module ReactOnRails # rubocop:disable Metrics/ModuleLength
3232

3333
context "when major and minor versions are equal BUT node uses semver wildcard" do
3434
let(:node_package_version) do
35-
double_package_version(raw: "^2.2.5", semver_wildcard: true, major_minor_patch: %w[2 2 5])
35+
double_package_version(raw: "^2.2.5", semver_wildcard: true, parts: %w[2 2 5])
3636
end
3737

3838
before { stub_gem_version("2.2.5") }
3939

4040
it "logs" do
4141
allow(Rails.logger).to receive(:warn)
42-
message = /ReactOnRails: Your node package version for react-on-rails contains a \^ or ~/
42+
message = /ReactOnRails: Your Node package version for react-on-rails is not an exact version/
4343
check_version_and_log(node_package_version)
4444
expect(Rails.logger).to have_received(:warn).with(message)
4545
end
4646
end
4747

4848
context "when gem and node package major versions differ" do
4949
let(:node_package_version) do
50-
double_package_version(raw: "13.0.0.beta-2", major_minor_patch: %w[13 0 0])
50+
double_package_version(raw: "13.0.0.beta-2", parts: %w[13 0 0 beta-2])
5151
end
5252

5353
before { stub_gem_version("12.0.0.beta.1") }
5454

5555
it "logs" do
5656
allow(Rails.logger).to receive(:warn)
57-
message = /ReactOnRails: ReactOnRails gem and node package versions do not match/
57+
message = /ReactOnRails: ReactOnRails gem and Node package versions do not match/
5858
check_version_and_log(node_package_version)
5959
expect(Rails.logger).to have_received(:warn).with(message)
6060
end
6161
end
6262

6363
context "when gem and node package major versions match and minor differs" do
6464
let(:node_package_version) do
65-
double_package_version(raw: "13.0.0.beta-2", major_minor_patch: %w[13 0 0])
65+
double_package_version(raw: "13.0.0.beta-2", parts: %w[13 0 0 beta-2])
6666
end
6767

6868
before { stub_gem_version("13.1.0") }
6969

7070
it "logs" do
7171
allow(Rails.logger).to receive(:warn)
72-
message = /ReactOnRails: ReactOnRails gem and node package versions do not match/
72+
message = /ReactOnRails: ReactOnRails gem and Node package versions do not match/
7373
check_version_and_log(node_package_version)
7474
expect(Rails.logger).to have_received(:warn).with(message)
7575
end
7676
end
7777

7878
context "when gem and node package major, minor versions match and patch differs" do
7979
let(:node_package_version) do
80-
double_package_version(raw: "13.0.1", major_minor_patch: %w[13 0 1])
80+
double_package_version(raw: "13.0.1", parts: %w[13 0 1])
8181
end
8282

8383
before { stub_gem_version("13.0.0") }
8484

8585
it "logs" do
8686
allow(Rails.logger).to receive(:warn)
87-
message = /ReactOnRails: ReactOnRails gem and node package versions do not match/
87+
message = /ReactOnRails: ReactOnRails gem and Node package versions do not match/
8888
check_version_and_log(node_package_version)
8989
expect(Rails.logger).to have_received(:warn).with(message)
9090
end
9191
end
9292

9393
context "when package json uses a relative path with dots" do
9494
let(:node_package_version) do
95-
double_package_version(raw: "../../..", major_minor_patch: "", local_path_or_url: true)
95+
double_package_version(raw: "../../..", parts: nil, local_path_or_url: true)
9696
end
9797

9898
before { stub_gem_version("2.0.0.beta.1") }
@@ -116,11 +116,11 @@ module ReactOnRails # rubocop:disable Metrics/ModuleLength
116116
end
117117

118118
def double_package_version(raw: nil, semver_wildcard: false,
119-
major_minor_patch: nil, local_path_or_url: false)
119+
parts: nil, local_path_or_url: false)
120120
instance_double(VersionChecker::NodePackageVersion,
121121
raw: raw,
122122
semver_wildcard?: semver_wildcard,
123-
major_minor_patch: major_minor_patch,
123+
parts: parts,
124124
local_path_or_url?: local_path_or_url)
125125
end
126126

@@ -187,8 +187,8 @@ def check_version_and_log(node_package_version)
187187
specify { expect(node_package_version.local_path_or_url?).to be false }
188188
end
189189

190-
describe "#major" do
191-
specify { expect(node_package_version.major_minor_patch).to eq(%w[0 0 2]) }
190+
describe "#parts" do
191+
specify { expect(node_package_version.parts).to eq(%w[0 0 2]) }
192192
end
193193
end
194194

@@ -203,8 +203,8 @@ def check_version_and_log(node_package_version)
203203
specify { expect(node_package_version.local_path_or_url?).to be false }
204204
end
205205

206-
describe "#major_minor_patch" do
207-
specify { expect(node_package_version.major_minor_patch).to eq(%w[14 0 0]) }
206+
describe "#parts" do
207+
specify { expect(node_package_version.parts).to eq(%w[14 0 0 beta-2]) }
208208
end
209209
end
210210

@@ -219,8 +219,8 @@ def check_version_and_log(node_package_version)
219219
specify { expect(node_package_version.local_path_or_url?).to be true }
220220
end
221221

222-
describe "#major" do
223-
specify { expect(node_package_version.major_minor_patch).to be_nil }
222+
describe "#parts" do
223+
specify { expect(node_package_version.parts).to be_nil }
224224
end
225225
end
226226

@@ -235,8 +235,8 @@ def check_version_and_log(node_package_version)
235235
specify { expect(node_package_version.local_path_or_url?).to be true }
236236
end
237237

238-
describe "#major" do
239-
specify { expect(node_package_version.major_minor_patch).to be_nil }
238+
describe "#parts" do
239+
specify { expect(node_package_version.parts).to be_nil }
240240
end
241241
end
242242

@@ -251,8 +251,8 @@ def check_version_and_log(node_package_version)
251251
specify { expect(node_package_version.local_path_or_url?).to be true }
252252
end
253253

254-
describe "#major" do
255-
specify { expect(node_package_version.major_minor_patch).to be_nil }
254+
describe "#parts" do
255+
specify { expect(node_package_version.parts).to be_nil }
256256
end
257257
end
258258

@@ -267,8 +267,8 @@ def check_version_and_log(node_package_version)
267267
specify { expect(node_package_version.local_path_or_url?).to be true }
268268
end
269269

270-
describe "#major" do
271-
specify { expect(node_package_version.major_minor_patch).to be_nil }
270+
describe "#parts" do
271+
specify { expect(node_package_version.parts).to be_nil }
272272
end
273273
end
274274

0 commit comments

Comments
 (0)