From ff2e0e41730f21b29660254d29cf5bb3ceffdbd4 Mon Sep 17 00:00:00 2001 From: Edouard CHIN Date: Thu, 10 Apr 2025 00:31:08 +0200 Subject: [PATCH] [rubygems/rubygems] Summarize the diagnostic https://github.com/rubygems/rubygems/commit/40cf54d256 --- lib/bundler/cli/doctor/ssl.rb | 38 ++++++++++ libexec/ssl_check.rb | 23 ------ spec/bundler/commands/ssl_spec.rb | 115 ++++++++++++++++++++++++++++++ 3 files changed, 153 insertions(+), 23 deletions(-) diff --git a/lib/bundler/cli/doctor/ssl.rb b/lib/bundler/cli/doctor/ssl.rb index 7ddca0c8a4..7d81e516c3 100644 --- a/lib/bundler/cli/doctor/ssl.rb +++ b/lib/bundler/cli/doctor/ssl.rb @@ -19,6 +19,8 @@ module Bundler rubygem_success = rubygem_connection_successful? return unless net_http_connection_successful? + + Explanation.summarize(bundler_success, rubygem_success, host) end private @@ -171,6 +173,42 @@ module Bundler end end + def summarize(bundler_success, rubygems_success, host) + guide_url = "http://ruby.to/ssl-check-failed" + + message = if bundler_success && rubygems_success + <<~MSG + Hooray! This Ruby can connect to #{host}. + You are all set to use Bundler and RubyGems. + + MSG + elsif !bundler_success && !rubygems_success + <<~MSG + For some reason, your Ruby installation can connect to #{host}, but neither RubyGems nor Bundler can. + The most likely fix is to manually upgrade RubyGems by following the instructions at #{guide_url}. + After you've done that, run `gem install bundler` to upgrade Bundler, and then run this script again to make sure everything worked. ❣ + + MSG + elsif !bundler_success + <<~MSG + Although your Ruby installation and RubyGems can both connect to #{host}, Bundler is having trouble. + The most likely way to fix this is to upgrade Bundler by running `gem install bundler`. + Run this script again after doing that to make sure everything is all set. + If you're still having trouble, check out the troubleshooting guide at #{guide_url}. + + MSG + else + <<~MSG + It looks like Ruby and Bundler can connect to #{host}, but RubyGems itself cannot. + You can likely solve this by manually downloading and installing a RubyGems update. + Visit #{guide_url} for instructions on how to manually upgrade RubyGems. + + MSG + end + + Bundler.ui.info("\n#{message}") + end + private def show_ssl_certs diff --git a/libexec/ssl_check.rb b/libexec/ssl_check.rb index c29d3bfb0f..4d7e51ee2b 100644 --- a/libexec/ssl_check.rb +++ b/libexec/ssl_check.rb @@ -30,29 +30,6 @@ puts "Ruby: %s" % ruby_version puts "RubyGems: %s" % Gem::VERSION if defined?(Gem::VERSION) puts "Bundler: %s" % Bundler::VERSION if defined?(Bundler::VERSION) - -guide_url = "http://ruby.to/ssl-check-failed" -if bundler_status =~ /success/ && rubygems_status =~ /success/ - # Whoa, it seems like it's working! - puts "Hooray! This Ruby can connect to #{host}.", - "You are all set to use Bundler and RubyGems. 👌", "" -elsif rubygems_status !~ /success/ - puts "It looks like Ruby and Bundler can connect to #{host}, but RubyGems itself", - "cannot. You can likely solve this by manually downloading and installing a", - "RubyGems update. Visit #{guide_url} for instructions on how to manually upgrade RubyGems. 💎" -elsif bundler_status !~ /success/ - puts "Although your Ruby installation and RubyGems can both connect to #{host},", - "Bundler is having trouble. The most likely way to fix this is to upgrade", - "Bundler by running `gem install bundler`. Run this script again after doing", - "that to make sure everything is all set. If you're still having trouble,", - "check out the troubleshooting guide at #{guide_url} 📦" -else - puts "For some reason, your Ruby installation can connect to #{host}, but neither", - "RubyGems nor Bundler can. The most likely fix is to manually upgrade RubyGems by", - "following the instructions at #{guide_url}. After you've done that, run `gem install", - "bundler` to upgrade Bundler, and then run this script again to make sure everything worked. ❣️" -end - def tls12_supported? ctx = OpenSSL::SSL::SSLContext.new if ctx.methods.include?(:min_version=) diff --git a/spec/bundler/commands/ssl_spec.rb b/spec/bundler/commands/ssl_spec.rb index 4fc9db0016..38bc2445c7 100644 --- a/spec/bundler/commands/ssl_spec.rb +++ b/spec/bundler/commands/ssl_spec.rb @@ -157,6 +157,115 @@ RSpec.describe "bundle doctor ssl" do expect { subject.run }.to output(expected_out).to_stdout.and output(expected_err).to_stderr end + it "fails due to a bundler and rubygems connection error" do + endpoint = Class.new(Endpoint) do + get "/" do + raise OpenSSL::SSL::SSLError, "read server hello A" + end + end + + Artifice.activate_with(endpoint) + Gem::Request::ConnectionPools.client = Gem::Net::HTTP + + expected_out = <<~MSG + Here's your OpenSSL environment: + + OpenSSL: #{OpenSSL::VERSION} + Compiled with: #{OpenSSL::OPENSSL_VERSION} + Loaded with: #{OpenSSL::OPENSSL_LIBRARY_VERSION} + + Trying connections to https://rubygems.org: + Ruby net/http: success + + For some reason, your Ruby installation can connect to rubygems.org, but neither RubyGems nor Bundler can. + The most likely fix is to manually upgrade RubyGems by following the instructions at http://ruby.to/ssl-check-failed. + After you've done that, run `gem install bundler` to upgrade Bundler, and then run this script again to make sure everything worked. ❣ + + MSG + + expected_err = <<~MSG + Bundler: failed (SSL/TLS protocol version mismatch) + RubyGems: failed (SSL/TLS protocol version mismatch) + MSG + + subject = Bundler::CLI::Doctor::SSL.new({}) + expect { subject.run }.to output(expected_out).to_stdout.and output(expected_err).to_stderr + end + + it "fails due to a bundler connection error" do + endpoint = Class.new(Endpoint) do + get "/" do + if request.user_agent.include?("bundler") + raise OpenSSL::SSL::SSLError, "read server hello A" + end + end + end + + Artifice.activate_with(endpoint) + Gem::Request::ConnectionPools.client = Gem::Net::HTTP + + expected_out = <<~MSG + Here's your OpenSSL environment: + + OpenSSL: #{OpenSSL::VERSION} + Compiled with: #{OpenSSL::OPENSSL_VERSION} + Loaded with: #{OpenSSL::OPENSSL_LIBRARY_VERSION} + + Trying connections to https://rubygems.org: + RubyGems: success + Ruby net/http: success + + Although your Ruby installation and RubyGems can both connect to rubygems.org, Bundler is having trouble. + The most likely way to fix this is to upgrade Bundler by running `gem install bundler`. + Run this script again after doing that to make sure everything is all set. + If you're still having trouble, check out the troubleshooting guide at http://ruby.to/ssl-check-failed. + + MSG + + expected_err = <<~MSG + Bundler: failed (SSL/TLS protocol version mismatch) + MSG + + subject = Bundler::CLI::Doctor::SSL.new({}) + expect { subject.run }.to output(expected_out).to_stdout.and output(expected_err).to_stderr + end + + it "fails due to a RubyGems connection error" do + endpoint = Class.new(Endpoint) do + get "/" do + if request.user_agent.include?("Ruby, RubyGems") + raise OpenSSL::SSL::SSLError, "read server hello A" + end + end + end + + Artifice.activate_with(endpoint) + Gem::Request::ConnectionPools.client = Gem::Net::HTTP + + expected_out = <<~MSG + Here's your OpenSSL environment: + + OpenSSL: #{OpenSSL::VERSION} + Compiled with: #{OpenSSL::OPENSSL_VERSION} + Loaded with: #{OpenSSL::OPENSSL_LIBRARY_VERSION} + + Trying connections to https://rubygems.org: + Bundler: success + Ruby net/http: success + + It looks like Ruby and Bundler can connect to rubygems.org, but RubyGems itself cannot. + You can likely solve this by manually downloading and installing a RubyGems update. + Visit http://ruby.to/ssl-check-failed for instructions on how to manually upgrade RubyGems. + + MSG + + expected_err = <<~MSG + RubyGems: failed (SSL/TLS protocol version mismatch) + MSG + + subject = Bundler::CLI::Doctor::SSL.new({}) + expect { subject.run }.to output(expected_out).to_stdout.and output(expected_err).to_stderr + end end context "when no diagnostic fails" do @@ -173,6 +282,9 @@ RSpec.describe "bundle doctor ssl" do RubyGems: success Ruby net/http: success + Hooray! This Ruby can connect to rubygems.org. + You are all set to use Bundler and RubyGems. + MSG subject = Bundler::CLI::Doctor::SSL.new({}) @@ -211,6 +323,9 @@ RSpec.describe "bundle doctor ssl" do RubyGems: success Ruby net/http: success + Hooray! This Ruby can connect to example.org. + You are all set to use Bundler and RubyGems. + MSG subject = Bundler::CLI::Doctor::SSL.new("tls-version": "1.3", "verify-mode": :none, host: "example.org")