[rubygems/rubygems] Diagnose the bundler connection
https://github.com/rubygems/rubygems/commit/0aae094c89
This commit is contained in:
parent
ae308ae523
commit
cba7408017
@ -1,5 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "uri"
|
||||
|
||||
module Bundler
|
||||
class CLI::Doctor::SSL
|
||||
attr_reader :options
|
||||
@ -12,6 +14,7 @@ module Bundler
|
||||
return unless openssl_installed?
|
||||
|
||||
output_ssl_environment
|
||||
bundler_success = bundler_connection_successful?
|
||||
end
|
||||
|
||||
private
|
||||
@ -32,6 +35,10 @@ module Bundler
|
||||
@verify_mode ||= mode.then {|mod| OpenSSL::SSL.const_get("verify_#{mod}".upcase) }
|
||||
end
|
||||
|
||||
def uri
|
||||
@uri ||= URI("https://#{host}")
|
||||
end
|
||||
|
||||
def openssl_installed?
|
||||
require "openssl"
|
||||
|
||||
@ -55,5 +62,38 @@ module Bundler
|
||||
MESSAGE
|
||||
end
|
||||
|
||||
def bundler_connection_successful?
|
||||
Bundler.ui.info("\nTrying connections to #{uri}:\n")
|
||||
|
||||
bundler_uri = Gem::URI(uri.to_s)
|
||||
Bundler::Fetcher.new(
|
||||
Bundler::Source::Rubygems::Remote.new(bundler_uri)
|
||||
).send(:connection).request(bundler_uri)
|
||||
|
||||
Bundler.ui.info("Bundler: success")
|
||||
|
||||
true
|
||||
rescue StandardError => error
|
||||
Bundler.ui.warn("Bundler: failed (#{Explanation.explain_bundler_or_rubygems_error(error)})")
|
||||
|
||||
false
|
||||
end
|
||||
|
||||
module Explanation
|
||||
extend self
|
||||
|
||||
def explain_bundler_or_rubygems_error(error)
|
||||
case error.message
|
||||
when /certificate verify failed/
|
||||
"certificate verification"
|
||||
when /read server hello A/
|
||||
"SSL/TLS protocol version mismatch"
|
||||
when /tlsv1 alert protocol version/
|
||||
"requested TLS version is too old"
|
||||
else
|
||||
error.message
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -15,8 +15,6 @@ begin
|
||||
rescue LoadError
|
||||
end
|
||||
|
||||
uri = URI("https://#{host}")
|
||||
|
||||
if defined?(RUBY_DESCRIPTION)
|
||||
ruby_version = RUBY_DESCRIPTION
|
||||
else
|
||||
@ -45,30 +43,6 @@ def show_ssl_certs
|
||||
puts
|
||||
end
|
||||
|
||||
def error_reason(error)
|
||||
case error.message
|
||||
when /certificate verify failed/
|
||||
"certificate verification"
|
||||
when /read server hello A/
|
||||
"SSL/TLS protocol version mismatch"
|
||||
when /tlsv1 alert protocol version/
|
||||
"requested TLS version is too old"
|
||||
else
|
||||
error.message
|
||||
end
|
||||
end
|
||||
|
||||
puts "Trying connections to #{uri.to_s}:"
|
||||
puts
|
||||
begin
|
||||
b_uri = defined?(Bundler::URI) ? Bundler::URI(uri.to_s) : uri
|
||||
Bundler::Fetcher.new(Bundler::Source::Rubygems::Remote.new(b_uri)).send(:connection).request(b_uri)
|
||||
bundler_status = "✅ success"
|
||||
rescue => error
|
||||
bundler_status = "❌ failed (#{error_reason(error)})"
|
||||
end
|
||||
puts "Bundler: #{bundler_status}"
|
||||
|
||||
begin
|
||||
require 'rubygems/remote_fetcher'
|
||||
Gem::RemoteFetcher.fetcher.fetch_path(uri)
|
||||
|
@ -3,16 +3,28 @@
|
||||
require "bundler/cli"
|
||||
require "bundler/cli/doctor"
|
||||
require "bundler/cli/doctor/ssl"
|
||||
require_relative "../support/artifice/helpers/artifice"
|
||||
require "bundler/vendored_persistent.rb"
|
||||
|
||||
RSpec.describe "bundle doctor ssl" do
|
||||
before(:each) do
|
||||
require_rack
|
||||
require_relative "../support/artifice/helpers/endpoint"
|
||||
|
||||
@dummy_endpoint = Class.new(Endpoint) do
|
||||
get "/" do
|
||||
end
|
||||
end
|
||||
|
||||
@previous_level = Bundler.ui.level
|
||||
Bundler.ui.instance_variable_get(:@warning_history).clear
|
||||
Bundler.ui.level = "info"
|
||||
Artifice.activate_with(@dummy_endpoint)
|
||||
end
|
||||
|
||||
after(:each) do
|
||||
Bundler.ui.level = @previous_level
|
||||
Artifice.deactivate
|
||||
end
|
||||
|
||||
context "when a diagnostic fails" do
|
||||
@ -27,6 +39,63 @@ RSpec.describe "bundle doctor ssl" do
|
||||
|
||||
expect { subject.run }.to output("").to_stdout.and output(expected_err).to_stderr
|
||||
end
|
||||
|
||||
it "fails due to certificate verification" do
|
||||
net_http = Class.new(Artifice::Net::HTTP) do
|
||||
def connect
|
||||
raise OpenSSL::SSL::SSLError, "certificate verify failed"
|
||||
end
|
||||
end
|
||||
|
||||
Artifice.replace_net_http(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:
|
||||
MSG
|
||||
|
||||
expected_err = <<~MSG
|
||||
Bundler: failed (certificate verification)
|
||||
|
||||
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 too old tls version" do
|
||||
subject = Bundler::CLI::Doctor::SSL.new({})
|
||||
|
||||
net_http = Class.new(Artifice::Net::HTTP) do
|
||||
def connect
|
||||
raise OpenSSL::SSL::SSLError, "read server hello A"
|
||||
end
|
||||
end
|
||||
|
||||
Artifice.replace_net_http(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:
|
||||
MSG
|
||||
|
||||
expected_err = <<~MSG
|
||||
Bundler: failed (SSL/TLS protocol version mismatch)
|
||||
|
||||
MSG
|
||||
|
||||
expect { subject.run }.to output(expected_out).to_stdout.and output(expected_err).to_stderr
|
||||
end
|
||||
end
|
||||
|
||||
context "when no diagnostic fails" do
|
||||
@ -37,6 +106,10 @@ RSpec.describe "bundle doctor ssl" do
|
||||
OpenSSL: #{OpenSSL::VERSION}
|
||||
Compiled with: #{OpenSSL::OPENSSL_VERSION}
|
||||
Loaded with: #{OpenSSL::OPENSSL_LIBRARY_VERSION}
|
||||
|
||||
Trying connections to https://rubygems.org:
|
||||
Bundler: success
|
||||
|
||||
MSG
|
||||
|
||||
subject = Bundler::CLI::Doctor::SSL.new({})
|
||||
|
Loading…
x
Reference in New Issue
Block a user