Class: Kettle::Rb::GemFloors::Generator

Inherits:
Object
  • Object
show all
Defined in:
lib/kettle/rb/gem_floors/generator.rb

Overview

Regenerates lib/kettle/rb/gem_floors/data.rb for tracked gems from the rubygems.org versions API and ruby-advisory-db (through bundler-audit).

This is development tooling. It is loaded by the kettle:rb:gem_floors:generate rake task, never by require "kettle/rb".

For each minor series of a tracked gem the floor is the newest released patch that does not raise the series' original minimum Ruby. When that patch is affected by an advisory but an older compatible patch is not, the newest unaffected patch is used instead. Advisories that still affect the chosen floor are recorded as unpatched.

Constant Summary collapse

TRACKED =

Tracked gems and the oldest minor series to record for each.

[
  ["activemodel", "5.2"],
  ["activerecord", "5.2"],
  ["activesupport", "5.2"],
  ["sqlite3", "1.3"]
].freeze
DATA_PATH =
File.expand_path(File.join(File.dirname(__FILE__), "data.rb"))
VERSIONS_URL =
"https://rubygems.org/api/v1/versions/%s.json"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Generator

Returns a new instance of Generator.

Options Hash (options):

  • :tracked (Array<Array(String, String)>) —

    gem names and oldest series

  • :versions_fetcher (#call) —

    returns rubygems.org version hashes for a gem name

  • :advisories_fetcher (#call) —

    returns advisories (+#id+, #vulnerable?) for a gem name

  • :advisory_db_commit (String, nil) —

    ruby-advisory-db commit to record

  • :generated_on (String) —

    date to record



47
48
49
50
51
52
53
# File 'lib/kettle/rb/gem_floors/generator.rb', line 47

def initialize(options = {})
  @tracked = options[:tracked] || TRACKED
  @versions_fetcher = options[:versions_fetcher] || method(:fetch_versions)
  @advisories_fetcher = options[:advisories_fetcher] || method(:fetch_advisories)
  @advisory_db_commit = options.key?(:advisory_db_commit) ? options[:advisory_db_commit] : database_commit
  @generated_on = options[:generated_on] || Time.now.utc.strftime("%Y-%m-%d")
end

Instance Attribute Details

#advisory_db_commit ⇒ String? (readonly)



36
37
38
# File 'lib/kettle/rb/gem_floors/generator.rb', line 36

def advisory_db_commit
  @advisory_db_commit
end

#generated_on ⇒ String (readonly)



39
40
41
# File 'lib/kettle/rb/gem_floors/generator.rb', line 39

def generated_on
  @generated_on
end

#tracked ⇒ Array<Array(String, String)> (readonly)



33
34
35
# File 'lib/kettle/rb/gem_floors/generator.rb', line 33

def tracked
  @tracked
end

Instance Method Details

#render ⇒ String



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/kettle/rb/gem_floors/generator.rb', line 65

def render
  lines = [
    "# frozen_string_literal: true",
    "",
    "# Generated by `rake kettle:rb:gem_floors:generate`; do not edit by hand.",
    "# Sources: rubygems.org versions API and ruby-advisory-db.",
    "",
    "module Kettle",
    "  module Rb",
    "    module GemFloors",
    "      GENERATED_ON = #{generated_on.inspect}",
    "      ADVISORY_DB_COMMIT = #{advisory_db_commit.inspect}",
    "      TRACKED_GEMS = #{tracked.map { |pair| pair.first }.inspect}.freeze",
    "      ROWS = ["
  ]
  lines << rows.map { |row| "        #{row.inspect}" }.join(",\n")
  lines.concat(["      ].freeze", "    end", "  end", "end", ""])
  lines.join("\n")
end

#rows ⇒ Array<Array>



56
57
58
59
60
61
62
# File 'lib/kettle/rb/gem_floors/generator.rb', line 56

def rows
  result = []
  tracked.each do |gem_name, oldest_series|
    result.concat(rows_for(gem_name, Gem::Version.new(oldest_series)))
  end
  result
end

#write(path = DATA_PATH) ⇒ String

Writes the rendered data file.



89
90
91
92
# File 'lib/kettle/rb/gem_floors/generator.rb', line 89

def write(path = DATA_PATH)
  File.open(path, "w") { |file| file.write(render) }
  path
end