Module: StillActive::EndoflifeHelper
- Extended by:
- EndoflifeHelper
- Included in:
- EndoflifeHelper
- Defined in:
- lib/helpers/endoflife_helper.rb
Overview
The ecosystem-neutral support-window builder over an endoflife.date feed.
Given a feed path (/api/ruby.json, /api/python.json, ...) it returns the
runtime facts a per-package language ceiling is measured against: the oldest
cycle still receiving security releases, the latest stable release, a
grace-window flag, and the normalized cycle list. RubyHelper and PythonHelper
are thin calibration wrappers that only choose the feed path, exactly as
RuntimeCeilingHelper keeps the ceiling math generic and pushes the runtime
specifics to the edges. RubyHelper#ruby_freshness also reuses the cycle-date
parsing here so there is one home for reading this best-effort feed.
Everything degrades on bad third-party data rather than raising: the window is fetched once outside the per-package rescue, so an unguarded raise would abort the whole audit. A single malformed field must cost at most the finding it feeds, never the whole signal.
Constant Summary collapse
- ENDOFLIFE_URI =
URI("https://endoflife.date/")
- LATEST_STABLE_GRACE_SECONDS =
How long a newly-released runtime gets before packages are held accountable for not yet declaring support for it. Below this, a latest-not-yet ceiling is about the release calendar, not the package, so the note is suppressed.
90 * 24 * 60 * 60
Instance Method Summary collapse
-
#eol_reached?(value) ⇒ Boolean
true / false when the eol date is known, nil when it's absent or malformed (so callers can decide how to treat "unknown").
-
#parse_date(date_string) ⇒ Object
A best-effort date parse over this feed's values: nil for a missing OR malformed date, never a raise.
- #parse_eol(value) ⇒ Object
-
#support_window(feed_path:) ⇒ Object
=> { oldest_supported:, latest_stable:, latest_stable_fresh:, cycles: } of Gem::Versions plus normalized EOL cycles, or nil when the feed is unavailable, empty, or every known cycle is EOL (no supported floor to compare against).
Instance Method Details
#eol_reached?(value) ⇒ Boolean
true / false when the eol date is known, nil when it's absent or malformed (so callers can decide how to treat "unknown"). Routes through parse_date, so a garbled eol string degrades to nil rather than raising.
80 81 82 83 84 85 86 87 88 |
# File 'lib/helpers/endoflife_helper.rb', line 80 def eol_reached?(value) case value when true then true when false then false when String parsed = parse_date(value) parsed.nil? ? nil : parsed <= Time.now end end |
#parse_date(date_string) ⇒ Object
A best-effort date parse over this feed's values: nil for a missing OR malformed date, never a raise. endoflife.date is third-party data; a garbled date on one cycle must degrade that cycle, not abort the run.
63 64 65 66 67 68 69 |
# File 'lib/helpers/endoflife_helper.rb', line 63 def parse_date(date_string) return if date_string.nil? Time.parse(date_string) rescue ArgumentError nil end |
#parse_eol(value) ⇒ Object
71 72 73 74 75 |
# File 'lib/helpers/endoflife_helper.rb', line 71 def parse_eol(value) case value when String then parse_date(value) end end |
#support_window(feed_path:) ⇒ Object
=> { oldest_supported:, latest_stable:, latest_stable_fresh:, cycles: } of
Gem::Versions plus normalized EOL cycles, or nil when the feed is
unavailable, empty, or every known cycle is EOL (no supported floor to
compare against). latest_stable is nil when the newest cycle's latest is
malformed -- see below.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/helpers/endoflife_helper.rb', line 36 def support_window(feed_path:) cycles = fetch_cycles(feed_path) return if cycles.nil? || cycles.empty? normalized = cycles.filter_map { |cycle| normalize_cycle(cycle) } supported = normalized.reject { |cycle| cycle[:eol] } return if supported.empty? # A malformed/preview `latest` on the newest cycle must not sink the whole # window: latest_stable feeds only the latest-not-yet NOTE, whereas the # EOL-forced CRITICAL depends solely on the cycles' eol flags. Degrade it to # nil (the note is then suppressed) rather than returning nil, which would # silently disable criticals too. latest = cycles.first["latest"] latest_stable = latest && Gem::Version.correct?(latest) ? Gem::Version.new(latest) : nil { oldest_supported: supported.map { |cycle| cycle[:version] }.min, latest_stable: latest_stable, latest_stable_fresh: !latest_stable.nil? && latest_stable_fresh?(cycles.first), cycles: normalized, } end |