Class: Gem::Cooldown
| Relationships & Source Files | |
| Inherits: | Object |
| Defined in: | lib/rubygems/cooldown.rb |
Overview
Applies a cooldown period to remote gem versions as a supply chain attack mitigation. When a cooldown of N days is configured, gem versions published within the last N days are not considered for installation or update. Versions whose publish time is unknown are never excluded, so sources that do not provide publish times keep working.
The cooldown period comes from the --cooldown DAYS option when given, falling back to the :cooldown: setting in the gemrc file. A value of 0 disables the cooldown.
Class Method Summary
-
.from_options(options)
Creates a
Cooldownfrom the command lineoptions, preferring the --cooldown option over the :cooldown: gemrc setting. - .new(days, now: Time.now) ⇒ Cooldown constructor
-
.output_skipped_summary(entries)
Reports, per gem, the newest version the cooldown kept out of a completed installation or update.
-
.warn_missing_created_at(source)
Warns once per process that
sourcedid not provide publish times, so the cooldown cannot be applied to gems from it. - .reset_warned_missing_created_at Internal use only
Instance Attribute Summary
-
#active? ⇒ Boolean
readonly
True when a cooldown period is configured.
-
#days
readonly
The cooldown period in days.
Instance Method Summary
-
#remaining_days(created_at)
Number of days until a gem version published at
created_atleaves the cooldown period, rounded up and at least 1. -
#skip?(created_at) ⇒ Boolean
True when a gem version published at
created_atmust not be considered.
Constructor Details
.new(days, now: Time.now) ⇒ Cooldown
Class Method Details
.from_options(options)
Creates a Cooldown from the command line options, preferring the
--cooldown option over the :cooldown: gemrc setting.
# File 'lib/rubygems/cooldown.rb', line 26
def self.() new([:cooldown] || Gem.configuration.cooldown) end
.output_skipped_summary(entries)
Reports, per gem, the newest version the cooldown kept out of a
completed installation or update. entries are hashes with :name,
:version, :resolved and :available_in_days keys; when several entries
name the same gem only the newest version is shown.
# File 'lib/rubygems/cooldown.rb', line 69
def self.output_skipped_summary(entries) return if entries.nil? || entries.empty? newest = {} entries.each do |entry| current = newest[entry[:name]] newest[entry[:name]] = entry if current.nil? || entry[:version] > current[:version] end ui = Gem::DefaultUserInteraction.ui ui.say "The following gem versions were skipped by the cooldown setting:" newest.values.sort_by {|entry| entry[:name] }.each do |entry| days = entry[:available_in_days] ui.say " * #{entry[:name]} #{entry[:version]} (available in #{days} #{days == 1 ? "day" : "days"}), resolved #{entry[:resolved]} instead" end end
.reset_warned_missing_created_at
# File 'lib/rubygems/cooldown.rb', line 98
def self.reset_warned_missing_created_at # :nodoc: @warned = nil end
.warn_missing_created_at(source)
Warns once per process that source did not provide publish times, so
the cooldown cannot be applied to gems from it.
# File 'lib/rubygems/cooldown.rb', line 90
def self.warn_missing_created_at(source) return if @warned @warned = true Gem::DefaultUserInteraction.ui.alert_warning \ "#{source.uri} does not provide gem publish times, the cooldown period does not apply to gems from this source" end
Instance Attribute Details
#active? ⇒ Boolean (readonly)
True when a cooldown period is configured.
# File 'lib/rubygems/cooldown.rb', line 38
def active? @days > 0 end
#days (readonly)
The cooldown period in days.
# File 'lib/rubygems/cooldown.rb', line 20
attr_reader :days
Instance Method Details
#remaining_days(created_at)
Number of days until a gem version published at created_at leaves
the cooldown period, rounded up and at least 1.
# File 'lib/rubygems/cooldown.rb', line 57
def remaining_days(created_at) remaining = @days * 86_400 - (@now - created_at) [(remaining / 86_400.0).ceil, 1].max end
#skip?(created_at) ⇒ Boolean
True when a gem version published at created_at must not be
considered. Versions with an unknown publish time (nil) are kept.
# File 'lib/rubygems/cooldown.rb', line 46
def skip?(created_at) return false unless active? return false unless created_at (@now - created_at) < @days * 86_400 end