stackharbinger 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "date"
4
+ require "harbinger/eol_fetcher"
5
+
6
+ module Harbinger
7
+ module Exporters
8
+ # Base class for exporters that transform project data into various formats
9
+ class BaseExporter
10
+ COMPONENTS = %w[ruby rails postgres mysql redis mongo].freeze
11
+ PRODUCT_NAMES = {
12
+ "ruby" => "ruby",
13
+ "rails" => "rails",
14
+ "postgres" => "postgresql",
15
+ "mysql" => "mysql",
16
+ "redis" => "redis",
17
+ "mongo" => "mongodb"
18
+ }.freeze
19
+
20
+ def initialize(projects, fetcher: nil)
21
+ @projects = projects
22
+ @fetcher = fetcher || EolFetcher.new
23
+ end
24
+
25
+ def export
26
+ raise NotImplementedError, "Subclasses must implement #export"
27
+ end
28
+
29
+ protected
30
+
31
+ def build_export_data
32
+ @projects.filter_map do |name, data|
33
+ components = build_components(data)
34
+ next if components.empty?
35
+
36
+ {
37
+ name: name,
38
+ path: data["path"],
39
+ components: components,
40
+ overall_status: determine_overall_status(components)
41
+ }
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def build_components(data)
48
+ COMPONENTS.filter_map do |component|
49
+ version = data[component]
50
+ next if version.nil? || version.empty?
51
+ next if version.include?("gem")
52
+
53
+ product = PRODUCT_NAMES[component]
54
+ eol_date = @fetcher.eol_date_for(product, version)
55
+ days = eol_date ? days_until(eol_date) : nil
56
+ status = days ? calculate_status(days) : "unknown"
57
+
58
+ {
59
+ name: component,
60
+ version: version,
61
+ eol_date: eol_date,
62
+ days_remaining: days,
63
+ status: status
64
+ }
65
+ end
66
+ end
67
+
68
+ def calculate_status(days)
69
+ if days.negative?
70
+ "eol"
71
+ elsif days < 180
72
+ "warning"
73
+ else
74
+ "safe"
75
+ end
76
+ end
77
+
78
+ def determine_overall_status(components)
79
+ statuses = components.map { |c| c[:status] }
80
+ return "unknown" if statuses.empty? || statuses.all? { |s| s == "unknown" }
81
+
82
+ if statuses.include?("eol")
83
+ "eol"
84
+ elsif statuses.include?("warning")
85
+ "warning"
86
+ else
87
+ "safe"
88
+ end
89
+ end
90
+
91
+ def days_until(date_string)
92
+ eol_date = Date.parse(date_string)
93
+ (eol_date - Date.today).to_i
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "csv"
4
+ require_relative "base_exporter"
5
+
6
+ module Harbinger
7
+ module Exporters
8
+ # Exports project EOL data to CSV format
9
+ class CsvExporter < BaseExporter
10
+ HEADERS = %w[project path component version eol_date days_remaining status overall_status].freeze
11
+
12
+ def export
13
+ projects = build_export_data
14
+
15
+ CSV.generate do |csv|
16
+ csv << HEADERS
17
+
18
+ projects.each do |project|
19
+ project[:components].each do |component|
20
+ csv << [
21
+ project[:name],
22
+ project[:path],
23
+ component[:name],
24
+ component[:version],
25
+ component[:eol_date],
26
+ component[:days_remaining],
27
+ component[:status],
28
+ project[:overall_status]
29
+ ]
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+ require_relative "base_exporter"
5
+
6
+ module Harbinger
7
+ module Exporters
8
+ # Exports project EOL data to JSON format
9
+ class JsonExporter < BaseExporter
10
+ def export
11
+ projects = build_export_data
12
+
13
+ {
14
+ generated_at: Time.now.iso8601,
15
+ project_count: projects.size,
16
+ projects: projects
17
+ }.to_json
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Harbinger
4
- VERSION = "0.2.0"
4
+ VERSION = "0.4.0"
5
5
  end
data/lib/harbinger.rb CHANGED
@@ -4,6 +4,9 @@ require_relative "harbinger/version"
4
4
  require_relative "harbinger/cli"
5
5
  require_relative "harbinger/analyzers/ruby_detector"
6
6
  require_relative "harbinger/analyzers/rails_analyzer"
7
+ require_relative "harbinger/analyzers/database_detector"
8
+ require_relative "harbinger/analyzers/postgres_detector"
9
+ require_relative "harbinger/analyzers/mysql_detector"
7
10
  require_relative "harbinger/eol_fetcher"
8
11
 
9
12
  module Harbinger
metadata CHANGED
@@ -1,13 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stackharbinger
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rich Dabrowski
8
+ autorequire:
8
9
  bindir: exe
9
10
  cert_chain: []
10
- date: 1980-01-02 00:00:00.000000000 Z
11
+ date: 2026-01-19 00:00:00.000000000 Z
11
12
  dependencies:
12
13
  - !ruby/object:Gem::Dependency
13
14
  name: thor
@@ -95,11 +96,20 @@ files:
95
96
  - docs/index.html
96
97
  - exe/harbinger
97
98
  - lib/harbinger.rb
99
+ - lib/harbinger/analyzers/database_detector.rb
100
+ - lib/harbinger/analyzers/docker_compose_detector.rb
101
+ - lib/harbinger/analyzers/mongo_detector.rb
102
+ - lib/harbinger/analyzers/mysql_detector.rb
103
+ - lib/harbinger/analyzers/postgres_detector.rb
98
104
  - lib/harbinger/analyzers/rails_analyzer.rb
105
+ - lib/harbinger/analyzers/redis_detector.rb
99
106
  - lib/harbinger/analyzers/ruby_detector.rb
100
107
  - lib/harbinger/cli.rb
101
108
  - lib/harbinger/config_manager.rb
102
109
  - lib/harbinger/eol_fetcher.rb
110
+ - lib/harbinger/exporters/base_exporter.rb
111
+ - lib/harbinger/exporters/csv_exporter.rb
112
+ - lib/harbinger/exporters/json_exporter.rb
103
113
  - lib/harbinger/version.rb
104
114
  - sig/harbinger.rbs
105
115
  homepage: https://stackharbinger.com
@@ -110,6 +120,7 @@ metadata:
110
120
  homepage_uri: https://stackharbinger.com
111
121
  source_code_uri: https://github.com/RichD/harbinger
112
122
  changelog_uri: https://github.com/RichD/harbinger/blob/main/CHANGELOG.md
123
+ post_install_message:
113
124
  rdoc_options: []
114
125
  require_paths:
115
126
  - lib
@@ -124,7 +135,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
124
135
  - !ruby/object:Gem::Version
125
136
  version: '0'
126
137
  requirements: []
127
- rubygems_version: 3.7.2
138
+ rubygems_version: 3.5.14
139
+ signing_key:
128
140
  specification_version: 4
129
141
  summary: Track End-of-Life dates for your tech stack and stay ahead of deprecations
130
142
  test_files: []