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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +40 -0
- data/README.md +101 -25
- data/docs/index.html +38 -16
- data/lib/harbinger/analyzers/database_detector.rb +133 -0
- data/lib/harbinger/analyzers/docker_compose_detector.rb +121 -0
- data/lib/harbinger/analyzers/mongo_detector.rb +104 -0
- data/lib/harbinger/analyzers/mysql_detector.rb +90 -0
- data/lib/harbinger/analyzers/postgres_detector.rb +71 -0
- data/lib/harbinger/analyzers/redis_detector.rb +98 -0
- data/lib/harbinger/analyzers/ruby_detector.rb +9 -1
- data/lib/harbinger/cli.rb +362 -48
- data/lib/harbinger/eol_fetcher.rb +22 -8
- data/lib/harbinger/exporters/base_exporter.rb +97 -0
- data/lib/harbinger/exporters/csv_exporter.rb +36 -0
- data/lib/harbinger/exporters/json_exporter.rb +21 -0
- data/lib/harbinger/version.rb +1 -1
- data/lib/harbinger.rb +3 -0
- metadata +15 -3
|
@@ -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
|
data/lib/harbinger/version.rb
CHANGED
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.
|
|
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:
|
|
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.
|
|
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: []
|