react_on_rails_pro 17.0.0.rc.0 → 17.0.0.rc.1
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/Gemfile.lock +3 -3
- data/app/controllers/react_on_rails_pro/rolling_deploy/bundles_controller.rb +23 -14
- data/lib/react_on_rails_pro/configuration.rb +2 -2
- data/lib/react_on_rails_pro/engine.rb +17 -0
- data/lib/react_on_rails_pro/renderer_cache_helpers.rb +0 -1
- data/lib/react_on_rails_pro/rolling_deploy_adapters/http.rb +95 -21
- data/lib/react_on_rails_pro/version.rb +1 -1
- data/react_on_rails_pro.gemspec +1 -1
- metadata +5 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d82436e63c02deff1774b11e01658f6f06a17bca6c583986aea35ac6f8b865de
|
|
4
|
+
data.tar.gz: e88f6d4495a06792faf61891d8aefe335323dd53461deb612412d5796d8ebe10
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4867d95e20f8e7bb15732ea1d749d34f49e8232a8a16b4d8ce5c2203ada419d2d5815569208b410e3f6f3e01ae7dd842896922e686aae5f49edca13de9dd61f6
|
|
7
|
+
data.tar.gz: 40720afca29e6f6ef1a527d9674adf81bde008edc6b4da86cafc009e2c2ef6e75b6c338e3f4ff4a4ef9dd7d5924aba3d81b5a313eff195bafc0de2750f361752
|
data/Gemfile.lock
CHANGED
|
@@ -9,7 +9,7 @@ GIT
|
|
|
9
9
|
PATH
|
|
10
10
|
remote: ..
|
|
11
11
|
specs:
|
|
12
|
-
react_on_rails (17.0.0.rc.
|
|
12
|
+
react_on_rails (17.0.0.rc.1)
|
|
13
13
|
addressable
|
|
14
14
|
connection_pool
|
|
15
15
|
execjs (~> 2.5)
|
|
@@ -20,7 +20,7 @@ PATH
|
|
|
20
20
|
PATH
|
|
21
21
|
remote: .
|
|
22
22
|
specs:
|
|
23
|
-
react_on_rails_pro (17.0.0.rc.
|
|
23
|
+
react_on_rails_pro (17.0.0.rc.1)
|
|
24
24
|
addressable
|
|
25
25
|
async (>= 2.29)
|
|
26
26
|
async-http (~> 0.95)
|
|
@@ -28,7 +28,7 @@ PATH
|
|
|
28
28
|
io-endpoint (~> 0.17.0)
|
|
29
29
|
jwt (>= 2.5, < 4)
|
|
30
30
|
rainbow
|
|
31
|
-
react_on_rails (= 17.0.0.rc.
|
|
31
|
+
react_on_rails (= 17.0.0.rc.1)
|
|
32
32
|
|
|
33
33
|
GEM
|
|
34
34
|
remote: https://rubygems.org/
|
|
@@ -13,11 +13,12 @@ module ReactOnRailsPro
|
|
|
13
13
|
# ReactOnRailsPro::RollingDeployAdapters::Http adapter on the next
|
|
14
14
|
# deploy's build CI consumes both endpoints.
|
|
15
15
|
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
# `config.
|
|
19
|
-
#
|
|
20
|
-
#
|
|
16
|
+
# When `config.rolling_deploy_adapter` is the built-in Http adapter, the
|
|
17
|
+
# Pro engine auto-mounts this controller at
|
|
18
|
+
# `config.rolling_deploy_mount_path` (default:
|
|
19
|
+
# `/react_on_rails_pro/rolling_deploy`). Set the mount path to nil or blank
|
|
20
|
+
# to opt out of the auto-mount. Use `draw_routes` only when you need a
|
|
21
|
+
# manual mount, such as a secondary path or app-specific routing wrapper:
|
|
21
22
|
#
|
|
22
23
|
# # config/routes.rb
|
|
23
24
|
# ReactOnRailsPro::RollingDeploy::BundlesController.draw_routes(
|
|
@@ -25,10 +26,11 @@ module ReactOnRailsPro
|
|
|
25
26
|
# path: "/internal/rolling-deploy"
|
|
26
27
|
# )
|
|
27
28
|
#
|
|
28
|
-
#
|
|
29
|
-
#
|
|
30
|
-
# distinct `as_prefix:`
|
|
31
|
-
# raise `ArgumentError: Invalid route name,
|
|
29
|
+
# The engine auto-mount uses an internal route-helper prefix so existing
|
|
30
|
+
# manual mounts that use the default prefix keep booting during upgrades.
|
|
31
|
+
# Multiple manual mounts still need distinct `as_prefix:` values so Rails'
|
|
32
|
+
# named-route registry doesn't raise `ArgumentError: Invalid route name,
|
|
33
|
+
# already in use`.
|
|
32
34
|
#
|
|
33
35
|
# Security:
|
|
34
36
|
# * Bearer-token auth via `Authorization: Bearer <token>`, constant-time
|
|
@@ -56,10 +58,19 @@ module ReactOnRailsPro
|
|
|
56
58
|
before_action :set_no_store_headers
|
|
57
59
|
|
|
58
60
|
DEFAULT_ROUTE_PREFIX = "react_on_rails_pro_rolling_deploy"
|
|
61
|
+
SAFE_HASH_PATTERN = ReactOnRailsPro::RollingDeploy::SAFE_HASH_PATTERN
|
|
62
|
+
# Rails route requirements reject anchor characters, while the route
|
|
63
|
+
# matcher applies segment constraints to the full segment. Derived from
|
|
64
|
+
# SAFE_HASH_PATTERN by stripping the \A/\z anchors; the controller still
|
|
65
|
+
# performs the anchored defense-in-depth validation before any filesystem
|
|
66
|
+
# lookup.
|
|
67
|
+
ROUTE_HASH_PATTERN = Regexp.new(SAFE_HASH_PATTERN.source.delete_prefix("\\A").delete_suffix("\\z"))
|
|
59
68
|
|
|
60
69
|
class << self
|
|
61
|
-
# Helper for
|
|
62
|
-
#
|
|
70
|
+
# Helper for manual route mounts. The Pro engine uses these same route
|
|
71
|
+
# definitions for the default auto-mount when the built-in Http adapter
|
|
72
|
+
# is configured, with an internal `as_prefix:` to avoid collisions with
|
|
73
|
+
# existing manual mounts.
|
|
63
74
|
#
|
|
64
75
|
# `as_prefix:` controls the generated named-route helpers
|
|
65
76
|
# (`<prefix>_manifest`, `<prefix>_bundle`). Callers that mount the
|
|
@@ -72,7 +83,7 @@ module ReactOnRailsPro
|
|
|
72
83
|
as: :"#{as_prefix}_manifest")
|
|
73
84
|
mapper.get("#{path}/bundles/:hash",
|
|
74
85
|
to: "react_on_rails_pro/rolling_deploy/bundles#show",
|
|
75
|
-
constraints: { hash:
|
|
86
|
+
constraints: { hash: ROUTE_HASH_PATTERN },
|
|
76
87
|
as: :"#{as_prefix}_bundle")
|
|
77
88
|
end
|
|
78
89
|
end
|
|
@@ -81,8 +92,6 @@ module ReactOnRailsPro
|
|
|
81
92
|
# path-traversal value through, the controller still rejects it
|
|
82
93
|
# before any disk lookup because the hash must be in the
|
|
83
94
|
# (regex-validated) current-hash set.
|
|
84
|
-
SAFE_HASH_PATTERN = ReactOnRailsPro::RollingDeploy::SAFE_HASH_PATTERN
|
|
85
|
-
|
|
86
95
|
# Tarball entry name reserved for the server bundle. Companion assets
|
|
87
96
|
# whose basename collides with this are skipped to keep the receiver
|
|
88
97
|
# from extracting the wrong bytes into the bundle slot.
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "set"
|
|
4
|
-
|
|
5
3
|
module ReactOnRailsPro
|
|
6
4
|
def self.configure
|
|
7
5
|
yield(configuration)
|
|
@@ -182,6 +180,8 @@ module ReactOnRailsPro
|
|
|
182
180
|
self.rolling_deploy_adapter = rolling_deploy_adapter
|
|
183
181
|
self.rolling_deploy_token = rolling_deploy_token
|
|
184
182
|
self.rolling_deploy_previous_url = rolling_deploy_previous_url
|
|
183
|
+
# Constructor nil/blank means "use the default"; configure-block assignment
|
|
184
|
+
# can still set nil/blank later to opt out of the engine auto-mount.
|
|
185
185
|
self.rolling_deploy_mount_path = rolling_deploy_mount_path.presence || DEFAULT_ROLLING_DEPLOY_MOUNT_PATH
|
|
186
186
|
self.ssr_pre_hook_js = ssr_pre_hook_js
|
|
187
187
|
self.assets_to_copy = assets_to_copy
|
|
@@ -7,13 +7,30 @@ module ReactOnRailsPro
|
|
|
7
7
|
LICENSE_URL = "https://pro.reactonrails.com/"
|
|
8
8
|
# TODO: Remove this legacy migration warning path after 16.5.0 stable release (target: 2026-05-31).
|
|
9
9
|
LEGACY_LICENSE_FILE = "config/react_on_rails_pro_license.key"
|
|
10
|
+
ROLLING_DEPLOY_AUTO_ROUTE_PREFIX = "react_on_rails_pro_auto_rolling_deploy"
|
|
10
11
|
private_constant :LICENSE_URL
|
|
11
12
|
private_constant :LEGACY_LICENSE_FILE
|
|
13
|
+
private_constant :ROLLING_DEPLOY_AUTO_ROUTE_PREFIX
|
|
12
14
|
|
|
13
15
|
initializer "react_on_rails_pro.routes" do
|
|
14
16
|
ActionDispatch::Routing::Mapper.include ReactOnRailsPro::Routes
|
|
15
17
|
end
|
|
16
18
|
|
|
19
|
+
initializer "react_on_rails_pro.rolling_deploy_routes" do |app|
|
|
20
|
+
app.routes.prepend do
|
|
21
|
+
pro_config = ReactOnRailsPro.configuration
|
|
22
|
+
mount_path = pro_config.rolling_deploy_mount_path
|
|
23
|
+
|
|
24
|
+
if pro_config.rolling_deploy_http_adapter? && mount_path.present?
|
|
25
|
+
ReactOnRailsPro::RollingDeploy::BundlesController.draw_routes(
|
|
26
|
+
self,
|
|
27
|
+
path: mount_path,
|
|
28
|
+
as_prefix: ROLLING_DEPLOY_AUTO_ROUTE_PREFIX
|
|
29
|
+
)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
17
34
|
# Check license status on Rails startup and log appropriately
|
|
18
35
|
# App continues running regardless of license status
|
|
19
36
|
initializer "react_on_rails_pro.check_license" do
|
|
@@ -4,6 +4,7 @@ require "fileutils"
|
|
|
4
4
|
require "json"
|
|
5
5
|
require "net/http"
|
|
6
6
|
require "openssl"
|
|
7
|
+
require "tempfile"
|
|
7
8
|
require "uri"
|
|
8
9
|
|
|
9
10
|
require "react_on_rails_pro/error"
|
|
@@ -32,6 +33,7 @@ module ReactOnRailsPro
|
|
|
32
33
|
# Error contract matches the rolling_deploy_adapter protocol: every
|
|
33
34
|
# exception is caught and reported as a warning so a failed seed degrades
|
|
34
35
|
# to the runtime 410-retry fallback rather than failing the build.
|
|
36
|
+
# rubocop:disable Metrics/ClassLength
|
|
35
37
|
class Http
|
|
36
38
|
# Per-request HTTP timeouts. The outer Timeout.timeout in
|
|
37
39
|
# RollingDeployCacheStager bounds the total wall-clock budget (10s for
|
|
@@ -49,6 +51,12 @@ module ReactOnRailsPro
|
|
|
49
51
|
# exhaust disk via a zip-bomb-style response.
|
|
50
52
|
DEFAULT_MAX_SIZE = ReactOnRailsPro::RollingDeploy::Tarball::DEFAULT_MAX_SIZE
|
|
51
53
|
|
|
54
|
+
# Maximum compressed bytes accepted from /bundles/:hash before extract
|
|
55
|
+
# enforces DEFAULT_MAX_SIZE on the uncompressed tarball contents.
|
|
56
|
+
# Set near 1/4 of DEFAULT_MAX_SIZE: JS bundles typically decompress 3-5x,
|
|
57
|
+
# so a 50 MB wire payload that decompresses beyond 200 MB is anomalous.
|
|
58
|
+
COMPRESSED_BODY_CAP = 50 * 1024 * 1024
|
|
59
|
+
|
|
52
60
|
LOG_PREFIX = "[ReactOnRailsPro::RollingDeployAdapters::Http]"
|
|
53
61
|
|
|
54
62
|
# Wire-format constant: must stay in sync with
|
|
@@ -101,10 +109,13 @@ module ReactOnRailsPro
|
|
|
101
109
|
|
|
102
110
|
dir = bundle_dir(bundle_hash)
|
|
103
111
|
FileUtils.mkdir_p(dir)
|
|
104
|
-
tarball_body = download_bundle_tarball(base, bundle_hash)
|
|
105
|
-
return cleanup_and_return(dir, nil) if tarball_body.nil?
|
|
106
112
|
|
|
107
|
-
|
|
113
|
+
result = download_bundle_tarball(base, bundle_hash) do |tarball|
|
|
114
|
+
extract_payload(tarball, dir, bundle_hash)
|
|
115
|
+
end
|
|
116
|
+
return cleanup_and_return(dir, nil) if result.nil?
|
|
117
|
+
|
|
118
|
+
result
|
|
108
119
|
rescue StandardError => e
|
|
109
120
|
cleanup_and_return(dir, nil) if dir
|
|
110
121
|
warn_and_return("fetch(#{bundle_hash.inspect}) failed: #{e.class}: #{e.message}", nil)
|
|
@@ -168,26 +179,77 @@ module ReactOnRailsPro
|
|
|
168
179
|
end
|
|
169
180
|
|
|
170
181
|
def download_bundle_tarball(base, bundle_hash)
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
182
|
+
Tempfile.create(["rolling-deploy-download-", ".tar.gz"]) do |tmp|
|
|
183
|
+
tmp.binmode
|
|
184
|
+
response = http_stream(URI("#{base}/bundles/#{bundle_hash}")) do |streaming_response|
|
|
185
|
+
unless streaming_response.is_a?(Net::HTTPSuccess)
|
|
186
|
+
Rails.logger.warn(
|
|
187
|
+
"#{LOG_PREFIX} bundles/#{bundle_hash} returned HTTP #{streaming_response.code}; skipping this hash."
|
|
188
|
+
)
|
|
189
|
+
# Drain the error body (capped) so Net::HTTP can finish the
|
|
190
|
+
# response cleanly. If the body itself exceeds the cap,
|
|
191
|
+
# `drain_response_body` raises and `fetch`'s rescue logs a second
|
|
192
|
+
# "fetch(...) failed" warning alongside the "skipping this hash"
|
|
193
|
+
# line above. Both lines are expected for an oversized error
|
|
194
|
+
# body — the pair signals "non-2xx, and the body was too large
|
|
195
|
+
# to drain," not a separate failure.
|
|
196
|
+
drain_response_body(streaming_response)
|
|
197
|
+
next
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
stream_response_body(streaming_response, tmp)
|
|
201
|
+
end
|
|
202
|
+
# Non-local return: exits `download_bundle_tarball`; Tempfile.create's
|
|
203
|
+
# ensure block still unlinks `tmp` before the method returns.
|
|
204
|
+
return nil unless response.is_a?(Net::HTTPSuccess)
|
|
205
|
+
|
|
206
|
+
tmp.flush
|
|
207
|
+
tmp.rewind
|
|
208
|
+
yield tmp
|
|
177
209
|
end
|
|
178
|
-
# `response.body` buffers the full compressed tarball into a single
|
|
179
|
-
# Ruby String before `Tarball.extract` can enforce DEFAULT_MAX_SIZE on
|
|
180
|
-
# uncompressed bytes. For v1 this is acceptable: build CI fetches are
|
|
181
|
-
# infrequent, the 200 MB uncompressed ceiling fits in heap, and the
|
|
182
|
-
# read timeout bounds slow responses. A future follow-up should stream
|
|
183
|
-
# the body into a Tempfile with its own compressed-byte cap (mirroring
|
|
184
|
-
# the controller's `compose_to_tempfile`) so an oversized wire payload
|
|
185
|
-
# cannot fill build-CI heap before extraction aborts.
|
|
186
|
-
response.body
|
|
187
210
|
end
|
|
188
211
|
|
|
189
|
-
def
|
|
190
|
-
|
|
212
|
+
def stream_response_body(response, io)
|
|
213
|
+
each_capped_body_chunk(response, context: "bundle body") { |chunk| io.write(chunk) }
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
# Reads and discards a non-success body solely to enforce the
|
|
217
|
+
# compressed-byte cap. No block is passed, so `each_capped_body_chunk`
|
|
218
|
+
# counts bytes without writing them anywhere.
|
|
219
|
+
def drain_response_body(response)
|
|
220
|
+
each_capped_body_chunk(response, context: "non-success response body")
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def each_capped_body_chunk(response, context:)
|
|
224
|
+
bytes = 0
|
|
225
|
+
response.read_body do |chunk|
|
|
226
|
+
bytes += chunk.bytesize
|
|
227
|
+
# Strictly greater-than (`>`, not `>=`): exactly COMPRESSED_BODY_CAP
|
|
228
|
+
# bytes are allowed through, so the cap is an exclusive ceiling. The
|
|
229
|
+
# raise fires before `yield chunk`, so the offending chunk is counted
|
|
230
|
+
# but never written/drained — the Tempfile never sees more than
|
|
231
|
+
# COMPRESSED_BODY_CAP bytes.
|
|
232
|
+
if bytes > COMPRESSED_BODY_CAP
|
|
233
|
+
raise ReactOnRailsPro::Error,
|
|
234
|
+
"#{context} exceeded compressed body cap " \
|
|
235
|
+
"(#{compressed_body_cap_label}); aborting download"
|
|
236
|
+
end
|
|
237
|
+
yield chunk if block_given?
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
# Dynamic (not a constant) so specs that `stub_const` the cap to a small
|
|
242
|
+
# value still see the stubbed value reflected in the warning message.
|
|
243
|
+
def compressed_body_cap_label
|
|
244
|
+
megabyte_bytes = 1024 * 1024
|
|
245
|
+
megabytes = COMPRESSED_BODY_CAP / megabyte_bytes
|
|
246
|
+
return "#{megabytes} MB" if megabytes.positive? && megabytes * megabyte_bytes == COMPRESSED_BODY_CAP
|
|
247
|
+
|
|
248
|
+
"#{COMPRESSED_BODY_CAP} bytes"
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
def extract_payload(tarball_source, dir, bundle_hash)
|
|
252
|
+
ReactOnRailsPro::RollingDeploy::Tarball.extract(tarball_source, dir, max_size: DEFAULT_MAX_SIZE)
|
|
191
253
|
bundle_path = File.join(dir, BUNDLE_ENTRY_NAME)
|
|
192
254
|
unless File.file?(bundle_path)
|
|
193
255
|
return cleanup_and_return(
|
|
@@ -225,18 +287,29 @@ module ReactOnRailsPro
|
|
|
225
287
|
# connection pooling would force us to manage lifecycle / cleanup
|
|
226
288
|
# across threads.
|
|
227
289
|
def http_get(uri, read_timeout: DEFAULT_READ_TIMEOUT_SECONDS)
|
|
290
|
+
http_for(uri, read_timeout: read_timeout).request(build_request(uri))
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
def http_stream(uri, read_timeout: DEFAULT_READ_TIMEOUT_SECONDS, &block)
|
|
294
|
+
http_for(uri, read_timeout: read_timeout).request(build_request(uri), &block)
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
def build_request(uri)
|
|
228
298
|
request = Net::HTTP::Get.new(uri.request_uri)
|
|
229
299
|
token = configured_token
|
|
230
300
|
request["Authorization"] = "Bearer #{token}" unless token.empty?
|
|
231
301
|
request["Accept-Encoding"] = "identity" # tarball is already gzipped; don't double-compress
|
|
302
|
+
request
|
|
303
|
+
end
|
|
232
304
|
|
|
305
|
+
def http_for(uri, read_timeout:)
|
|
233
306
|
http = Net::HTTP.new(uri.host, uri.port)
|
|
234
307
|
http.use_ssl = (uri.scheme == "https")
|
|
235
308
|
warn_plain_http_token(uri) unless http.use_ssl?
|
|
236
309
|
http.verify_mode = OpenSSL::SSL::VERIFY_PEER if http.use_ssl?
|
|
237
310
|
http.open_timeout = DEFAULT_OPEN_TIMEOUT_SECONDS
|
|
238
311
|
http.read_timeout = read_timeout
|
|
239
|
-
http
|
|
312
|
+
http
|
|
240
313
|
end
|
|
241
314
|
|
|
242
315
|
# Plain-HTTP guardrail. The full HTTPS-only guard lands in PR 2; until
|
|
@@ -260,5 +333,6 @@ module ReactOnRailsPro
|
|
|
260
333
|
end
|
|
261
334
|
end
|
|
262
335
|
end
|
|
336
|
+
# rubocop:enable Metrics/ClassLength
|
|
263
337
|
end
|
|
264
338
|
end
|
data/react_on_rails_pro.gemspec
CHANGED
|
@@ -34,7 +34,7 @@ Gem::Specification.new do |s|
|
|
|
34
34
|
s.executables = s.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
35
35
|
s.require_paths = ["lib"]
|
|
36
36
|
|
|
37
|
-
s.required_ruby_version = ">= 3.3"
|
|
37
|
+
s.required_ruby_version = ">= 3.3.0"
|
|
38
38
|
|
|
39
39
|
s.add_runtime_dependency "addressable"
|
|
40
40
|
s.add_runtime_dependency "async", ">= 2.29"
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: react_on_rails_pro
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 17.0.0.rc.
|
|
4
|
+
version: 17.0.0.rc.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Justin Gordon
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-06-03 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: addressable
|
|
@@ -120,14 +120,14 @@ dependencies:
|
|
|
120
120
|
requirements:
|
|
121
121
|
- - '='
|
|
122
122
|
- !ruby/object:Gem::Version
|
|
123
|
-
version: 17.0.0.rc.
|
|
123
|
+
version: 17.0.0.rc.1
|
|
124
124
|
type: :runtime
|
|
125
125
|
prerelease: false
|
|
126
126
|
version_requirements: !ruby/object:Gem::Requirement
|
|
127
127
|
requirements:
|
|
128
128
|
- - '='
|
|
129
129
|
- !ruby/object:Gem::Version
|
|
130
|
-
version: 17.0.0.rc.
|
|
130
|
+
version: 17.0.0.rc.1
|
|
131
131
|
- !ruby/object:Gem::Dependency
|
|
132
132
|
name: bundler
|
|
133
133
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -311,7 +311,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
311
311
|
requirements:
|
|
312
312
|
- - ">="
|
|
313
313
|
- !ruby/object:Gem::Version
|
|
314
|
-
version:
|
|
314
|
+
version: 3.3.0
|
|
315
315
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
316
316
|
requirements:
|
|
317
317
|
- - ">="
|