module Gems::Configuration

Global configuration for {Gems::Client} instances @api public

Constants

DEFAULT_HOST

The API endpoint used when the RUBYGEMS_HOST environment variable is not set

DEFAULT_USER_AGENT

The default ‘User-Agent’ HTTP header

Attributes

The IO object for debug output @api public @return [IO, nil] the IO object for debug output @example Get or set the debug output

Gems.debug_output = $stderr

The host used for API requests @api public @return [String] the host, including scheme @example Get the host

Gems.host

The OIDC ID token used for trusted publishing @api public @return [String, nil] the OIDC ID token @example Get or set the ID token

Gems.id_token = ENV.fetch("ID_TOKEN")

Set the one-time passcode used for multi-factor authentication

@api public @param value [String, nil] the one-time passcode, or nil to send requests without one @return [void] @example Set the one-time passcode

Gems.otp = "123456"

The password used for HTTP basic authentication @api public @return [String, nil] the password @example Get or set the password

Gems.password = "schwwwwing"

The proxy URL for requests

When nil, proxies are read from the http_proxy, https_proxy, and no_proxy environment variables.

@api public @return [String, nil] the proxy URL for requests @example Get the proxy URL

Gems.proxy_url

The ‘User-Agent’ HTTP header sent with requests @api public @return [String] the user agent @example Get or set the user agent

Gems.user_agent = "Custom User Agent"

The username used for HTTP basic authentication @api public @return [String, nil] the username @example Get or set the username

Gems.username = "nick@gemcutter.org"

Public Class Methods

Reset the extending module to the default configuration

@api private @param base [Module] the module being extended @return [void]

# File lib/gems/configuration.rb, line 266
def self.extended(base)
  base.reset
end

Public Instance Methods

Convenience method to allow configuration options to be set in a block

@api public @yield [self] the configuration @return [self] @example Configure the API key

Gems.configure do |config|
  config.key = "rubygems_701243f217cdf23b1370c7b66b65ca97"
end
# File lib/gems/configuration.rb, line 407
def configure
  yield self
  self
end

The host ‘gem push` would use

This is the ‘RUBYGEMS_HOST` environment variable, else RubyGems.org. The environment is read when this method is called, as it is for {#default_key}, rather than when the library is required.

@api public @return [String] the host, including scheme @example Get the default host

Gems.default_host
# File lib/gems/configuration.rb, line 306
def default_host
  ENV.fetch("RUBYGEMS_HOST", DEFAULT_HOST)
end

The API key ‘gem push` would use for a host

This is the ‘GEM_HOST_API_KEY` environment variable, else the key `gem signin –host` stored for the host in ~/.gem/credentials, else, for RubyGems.org itself, the key `gem signin` stored there. The environment is read each time this method is called, rather than when the library is required, and the credentials file is read the first time it is needed: RubyGems keeps what it read in `Gem.configuration`, which it shares with everything else running in the process, so a key `gem signin` stores afterwards is picked up only by a new process.

A host nothing is stored for is left without a key, where ‘gem push –host` falls back to the RubyGems.org key for it. RubyGems keeps the key of RubyGems.org under `rubygems_api_key` rather than under its URL, and the key of every other host under the URL `gem signin –host` stored it for, so that key is the key of RubyGems.org rather than one for whichever host is asked about: handing it to another host would send a credential RubyGems.org issued to a host it was not issued for. The host is read as a URL, so RubyGems.org named with a trailing slash or a path of its own is still the host the key was stored for, and a host that is not a URL at all is not.

An empty ‘GEM_HOST_API_KEY` counts as no key rather than as an empty one, since a continuous integration service sets a variable to the empty string when the secret it was given is not set, and an empty `Authorization` header answers with a puzzling 401 where a request without one answers with the error the endpoint has for an unauthenticated request.

When the credentials file does not have the permissions RubyGems requires, RubyGems reports the problem on standard error and would exit the process; this method returns nil instead.

@api public @param gem_host [String] the host to resolve the key for, which defaults to {#host} @return [String, nil] the API key, or nil when none is stored or the credentials file cannot be read @example Get the default API key

Gems.default_key

@example Get the default API key for another host

Gems.default_key("https://gems.example.com")
# File lib/gems/configuration.rb, line 342
def default_key(gem_host = host)
  env_key = ENV.fetch("GEM_HOST_API_KEY", "")
  return env_key unless env_key.empty?

  ::Gem.configuration.api_keys.fetch(gem_host) do
    ::Gem.configuration.rubygems_api_key if http_url?(gem_host) && same_origin?(gem_host, DEFAULT_HOST)
  end
rescue ::Gem::SystemExitException
  nil
end

The one-time passcode ‘gem push` would use

This is the ‘GEM_HOST_OTP_CODE` environment variable, which `gem push` falls back to when it is not given a passcode of its own. The environment is read when this method is called, as it is for {#default_key}, rather than when the library is required.

An empty ‘GEM_HOST_OTP_CODE` counts as no passcode rather than as an empty one, as an empty `GEM_HOST_API_KEY` counts as no key, since a continuous integration service sets a variable to the empty string when the secret it was given is not set, and an empty `OTP` header is refused where a request without one is answered with the error the endpoint has for a request that needs a passcode.

@api public @return [String, nil] the one-time passcode, or nil when the environment does not carry one @example Get the default one-time passcode

Gems.default_otp
# File lib/gems/configuration.rb, line 368
def default_otp
  code = ENV.fetch("GEM_HOST_OTP_CODE", "")
  code unless code.empty?
end

Set the host used for API requests

The host is checked here rather than when a request is made with it, as {Client#host=} checks the host of a client, so that the error names the assignment that was wrong.

@api public @param host [String] the host, including scheme @return [void] @raise [ArgumentError] if the host is not an HTTP or HTTPS URL, in which case the host is left as it was @example Set the host

Gems.host = "https://gems.example.com"
# File lib/gems/configuration.rb, line 53
def host=(host)
  @host = validate_host(host)
end

The API key used for authentication

Falls back to {#default_key} until a key is assigned. Assigning nil disables this API-key fallback. Basic authentication and trusted publishing remain available when their credentials are configured.

@api public @return [String, nil] the API key @example Get the API key

Gems.key
# File lib/gems/configuration.rb, line 280
def key
  key_configured? ? @key : default_key
end

Set the API key used for authentication

@api public @param key [String, APIKey, nil] the API key, or an API key object @return [void] @example Set the API key

Gems.key = "rubygems_701243f217cdf23b1370c7b66b65ca97"

@example Set the API key from a newly created API key

Gems.key = Gems.create_api_key("ci-push", scopes: %i[push_rubygem])
# File lib/gems/configuration.rb, line 66
def key=(key)
  @key = key_of(key)
end

Whether an API key has been assigned, rather than falling back to {#default_key}

A client built without a key of its own asks this to tell a configured key, which it sends wherever it sends a request, from the fallback it resolves for the host of each request.

@api public @return [Boolean] whether an API key has been assigned @example Tell a configured key from the one resolved for the host

Gems.key_configured?
# File lib/gems/configuration.rb, line 382
def key_configured?
  instance_variable_defined?(:@key)
end

The one-time passcode used for multi-factor authentication

Falls back to {#default_otp} until a passcode is assigned. Assigning nil disables that fallback, so that requests are sent without a passcode.

@api public @return [String, nil] the one-time passcode @example Get the one-time passcode

Gems.otp
# File lib/gems/configuration.rb, line 293
def otp
  otp_configured? ? @otp : default_otp
end

Whether a one-time passcode has been assigned

When none has been, {#otp} falls back to {#default_otp}.

@api public @return [Boolean] whether a one-time passcode has been assigned @example Tell a configured passcode from the one the environment carries

Gems.otp_configured?
# File lib/gems/configuration.rb, line 394
def otp_configured?
  instance_variable_defined?(:@otp)
end

Set the proxy URL for requests

The proxy URL is checked here rather than when a request is made with it, as {Connection#proxy_url=} checks the proxy URL of a connection, so that the error names the assignment that was wrong.

@api public @param proxy_url [String, nil] the proxy URL, or nil to read proxies from the environment @return [void] @raise [ArgumentError] if the proxy URL is invalid, in which case the proxy is left as it was; the message

leaves out its user and password

@example Set the proxy URL

Gems.proxy_url = "http://proxy.example.com:8080"
# File lib/gems/configuration.rb, line 196
def proxy_url=(proxy_url)
  parse_proxy_uri(proxy_url) unless proxy_url.nil?
  @proxy_url = proxy_url
end

Reset all configuration options to defaults

The default host is the one ‘gem push` would use, which is taken as it is rather than checked the way a host assigned to {#host=} is, so that a `RUBYGEMS_HOST` that is not a URL is reported when a client is built with it rather than when the library is required.

@api public @return [self] @example Reset the configuration

Gems.reset
# File lib/gems/configuration.rb, line 422
def reset
  @host = default_host
  self.user_agent = DEFAULT_USER_AGENT
  reset_credentials
  reset_connection
  reset_certificates
  self
end