rails_preflight 0.1.0 → 0.1.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/CHANGELOG.md +7 -0
- data/lib/rails_preflight/report_generator.rb +4 -1
- data/lib/rails_preflight/upgrade_analyzer.rb +31 -5
- data/lib/rails_preflight/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e083ff064d2ee34d2b8862a68c3ea41ca63c1f39107237adec73647e8755b1ec
|
|
4
|
+
data.tar.gz: 770f2d5ac5a2b6b5a8bd491517c735be6c3874b45fdbafa7b25f5d1035af78ab
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7c3486a813bd9c02965df146309c21966bc0c463905ea89c06760b74714b32e0ab5f75c2eabdaa20211e68c88f13aba0c03ddf368132d6a740ea772ccc34b9ce
|
|
7
|
+
data.tar.gz: 9d31b9cf5a20aedfbac6452d437760d0f509a169a44837ba9d651364b9d05516d770bac23a165b4f1b327d56be8400a414fc3107ec4f14c10f51e84724f52628
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.1 (2026-10-09)
|
|
4
|
+
|
|
5
|
+
- rubygems.org lookups also trust the certificates RubyGems ships for rubygems.org, so they work wherever `gem install` does, even when Ruby's OpenSSL can't find the system certificates
|
|
6
|
+
- Failed lookups are reported once per distinct error, under their own "rubygems.org lookup" entry with the gem names listed once, instead of the same error repeated for every gem under a second "Private Gems" card
|
|
7
|
+
- A certificate failure says what to do: behind a VPN or proxy that inspects HTTPS, point `SSL_CERT_FILE` at a bundle that includes its root certificate, or pass `--offline`
|
|
8
|
+
- The terminal warns when lookups fail
|
|
9
|
+
|
|
3
10
|
## 0.1.0 (2026-10-09)
|
|
4
11
|
|
|
5
12
|
First release. Point it at a Rails 5.0 – 8.1 app and a target version: it writes a report into the app as HTML, Markdown or JSON, plus a short terminal summary. Read-only and static.
|
|
@@ -280,7 +280,7 @@ module RailsPreflight
|
|
|
280
280
|
<div class="limits">
|
|
281
281
|
<% @summary.fetch(:cant_see, []).each do |entry| %>
|
|
282
282
|
<div class="limit">
|
|
283
|
-
<h3><%= h(entry[:section]) %></h3>
|
|
283
|
+
<h3><%= h(entry[:title] || entry[:section]) %></h3>
|
|
284
284
|
<p><%= code_html(entry[:message]) %></p>
|
|
285
285
|
<% names = Array(entry[:names]) %>
|
|
286
286
|
<% if names.any? %><p class="names"><%= h(names.join(" · ")) %></p><% end %>
|
|
@@ -477,7 +477,10 @@ module RailsPreflight
|
|
|
477
477
|
h(text).gsub(/(?<![\w&;])'(.+?)'(?![\w&])/) { "<code>#{$1}</code>" }
|
|
478
478
|
end
|
|
479
479
|
|
|
480
|
+
# A titled entry (the rubygems.org lookup) says what to do in its own message.
|
|
480
481
|
def cant_see_next(entry)
|
|
482
|
+
return if entry[:title]
|
|
483
|
+
|
|
481
484
|
case entry[:section]
|
|
482
485
|
when "Private Gems" then "Check each gemspec's Rails dependency, and bump them in the same step."
|
|
483
486
|
when "Gem Compatibility"
|
|
@@ -246,9 +246,18 @@ module RailsPreflight
|
|
|
246
246
|
if mixed_gems.any?
|
|
247
247
|
result[:checks] << { message: "Looked up #{mixed_gems.size} gems on rubygems.org, since Gemfile.lock lists them under both rubygems.org and #{mixed_remotes.join(', ')}. Pass --offline to skip.", status: :passed, fix_effort: :low }
|
|
248
248
|
end
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
249
|
+
# One entry per distinct error: a missing certificate fails every lookup the same way.
|
|
250
|
+
inconclusive.group_by { |_, error| error }.each do |error, failed|
|
|
251
|
+
gems = failed.map(&:first).sort
|
|
252
|
+
@out.puts "Couldn't reach rubygems.org for #{gems.size} gems (#{error}). See \"Couldn't check\" in the report."
|
|
253
|
+
# A VPN or proxy that inspects HTTPS re-signs certificates with a root the OS trusts but Ruby's OpenSSL doesn't read.
|
|
254
|
+
advice = if error.include?("certificate verify failed")
|
|
255
|
+
"Behind a VPN or proxy that inspects HTTPS, point SSL_CERT_FILE at a certificate bundle that includes its root certificate, or pass --offline."
|
|
256
|
+
else
|
|
257
|
+
"Run it again once rubygems.org is reachable, or pass --offline."
|
|
258
|
+
end
|
|
259
|
+
result[:checks] << { message: "Couldn't reach rubygems.org for #{gems.size} #{gems.size == 1 ? 'gem' : 'gems'} (#{error}), so whether #{gems.size == 1 ? "it's private and when it was" : "they're private and when they were"} last released is unknown. #{advice}",
|
|
260
|
+
title: "rubygems.org lookup", status: :warning, kind: :unknown, names: gems, fix_effort: :unknown }
|
|
252
261
|
result[:status] = :warning
|
|
253
262
|
end
|
|
254
263
|
end
|
|
@@ -272,6 +281,7 @@ module RailsPreflight
|
|
|
272
281
|
found = {}
|
|
273
282
|
inconclusive = {}
|
|
274
283
|
lock = Mutex.new
|
|
284
|
+
store = rubygems_cert_store
|
|
275
285
|
|
|
276
286
|
Array.new([names.size, 8].min) do
|
|
277
287
|
Thread.new do
|
|
@@ -279,14 +289,16 @@ module RailsPreflight
|
|
|
279
289
|
begin
|
|
280
290
|
url = URI("https://rubygems.org/api/v1/gems/#{name}.json")
|
|
281
291
|
# Certificate errors are reported as inconclusive, never silently trusted.
|
|
282
|
-
response = Net::HTTP.start(url.host, url.port, use_ssl: true, open_timeout: 5, read_timeout: 5) do |http|
|
|
292
|
+
response = Net::HTTP.start(url.host, url.port, use_ssl: true, cert_store: store, open_timeout: 5, read_timeout: 5) do |http|
|
|
283
293
|
http.request(Net::HTTP::Get.new(url))
|
|
284
294
|
end
|
|
285
295
|
raise "HTTP #{response.code}" unless %w[200 404].include?(response.code) # e.g. 429 when rate limited
|
|
286
296
|
info = response.code == "200" && (JSON.parse(response.body.to_s) rescue {})
|
|
287
297
|
lock.synchronize { found[name] = info }
|
|
288
298
|
rescue StandardError => e
|
|
289
|
-
|
|
299
|
+
# The peer address changes per connection; without it, the same failure reads the same for every gem.
|
|
300
|
+
# The peer address changes per connection; without it, the same failure reads the same for every gem.
|
|
301
|
+
lock.synchronize { inconclusive[name] = "#{e.class.name}: #{e.message.sub(/ peeraddr=\S+/, '')}" }
|
|
290
302
|
end
|
|
291
303
|
end
|
|
292
304
|
end
|
|
@@ -295,6 +307,20 @@ module RailsPreflight
|
|
|
295
307
|
[found, inconclusive]
|
|
296
308
|
end
|
|
297
309
|
|
|
310
|
+
# The system's certificates plus the ones RubyGems ships for rubygems.org, which is why `gem install` works on a
|
|
311
|
+
# machine whose OpenSSL can't find the system store. Verification stays on.
|
|
312
|
+
def rubygems_cert_store
|
|
313
|
+
require 'rubygems/request'
|
|
314
|
+
OpenSSL::X509::Store.new.tap do |store|
|
|
315
|
+
store.set_default_paths
|
|
316
|
+
Gem::Request.get_cert_files.each do |file|
|
|
317
|
+
store.add_file(file)
|
|
318
|
+
rescue OpenSSL::X509::StoreError
|
|
319
|
+
# already in the system store
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
end
|
|
323
|
+
|
|
298
324
|
# From the lockfile: :public, :private (git, path, or only non-rubygems.org remotes), or, when one GEM
|
|
299
325
|
# section lists rubygems.org next to another remote (Bundler before 2.2), whatever the Gemfile says; :mixed if it doesn't.
|
|
300
326
|
def gem_origin(spec)
|