solidstats 2.0.0 → 3.0.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 +12 -63
- data/README.md +27 -0
- data/Rakefile +3 -3
- data/app/assets/javascripts/solidstats/dashboard.js +0 -46
- data/app/assets/stylesheets/solidstats/dashboard.css +48 -0
- data/app/controllers/solidstats/dashboard_controller.rb +73 -61
- data/app/controllers/solidstats/logs_controller.rb +72 -0
- data/app/controllers/solidstats/performance_controller.rb +25 -0
- data/app/controllers/solidstats/productivity_controller.rb +39 -0
- data/app/controllers/solidstats/quality_controller.rb +152 -0
- data/app/controllers/solidstats/securities_controller.rb +30 -0
- data/app/helpers/solidstats/application_helper.rb +124 -11
- data/app/helpers/solidstats/performance_helper.rb +87 -0
- data/app/helpers/solidstats/productivity_helper.rb +38 -0
- data/app/services/solidstats/bundler_audit_service.rb +206 -0
- data/app/services/solidstats/coverage_compass_service.rb +335 -0
- data/app/services/solidstats/load_lens_service.rb +474 -0
- data/app/services/solidstats/log_size_monitor_service.rb +197 -66
- data/app/services/solidstats/my_todo_service.rb +242 -0
- data/app/services/solidstats/style_patrol_service.rb +319 -0
- data/app/views/layouts/solidstats/application.html.erb +8 -2
- data/app/views/layouts/solidstats/dashboard.html.erb +84 -0
- data/app/views/solidstats/dashboard/dashboard.html.erb +39 -0
- data/app/views/solidstats/logs/logs_size.html.erb +409 -0
- data/app/views/solidstats/performance/load_lens.html.erb +158 -0
- data/app/views/solidstats/productivity/_todo_list.html.erb +49 -0
- data/app/views/solidstats/productivity/my_todos.html.erb +84 -0
- data/app/views/solidstats/quality/coverage_compass.html.erb +420 -0
- data/app/views/solidstats/quality/style_patrol.html.erb +463 -0
- data/app/views/solidstats/securities/bundler_audit.html.erb +345 -0
- data/app/views/solidstats/shared/_dashboard_card.html.erb +160 -0
- data/app/views/solidstats/shared/_quick_actions.html.erb +26 -0
- data/config/routes.rb +31 -6
- data/lib/generators/solidstats/clean/clean_generator.rb +24 -0
- data/lib/generators/solidstats/clean/templates/README +8 -0
- data/lib/generators/solidstats/install/install_generator.rb +51 -10
- data/lib/generators/solidstats/install/templates/README +7 -0
- data/lib/solidstats/engine.rb +6 -71
- data/lib/solidstats/version.rb +1 -1
- data/lib/solidstats.rb +19 -303
- data/lib/tasks/solidstats.rake +67 -0
- data/lib/tasks/solidstats_performance.rake +61 -0
- data/lib/tasks/solidstats_tasks.rake +16 -4
- metadata +33 -95
- data/app/assets/javascripts/solidstats/gem_metadata.js +0 -554
- data/app/assets/stylesheets/solidstats/components/action_button.css +0 -99
- data/app/assets/stylesheets/solidstats/components/dashboard.css +0 -151
- data/app/assets/stylesheets/solidstats/components/dashboard_header.css +0 -93
- data/app/assets/stylesheets/solidstats/components/dashboard_layout.css +0 -97
- data/app/assets/stylesheets/solidstats/components/gem_metadata.css +0 -1403
- data/app/assets/stylesheets/solidstats/components/navigation.css +0 -80
- data/app/assets/stylesheets/solidstats/components/quick_navigation.css +0 -54
- data/app/assets/stylesheets/solidstats/components/security.css +0 -332
- data/app/assets/stylesheets/solidstats/components/status_badge.css +0 -58
- data/app/assets/stylesheets/solidstats/components/summary_card.css +0 -66
- data/app/assets/stylesheets/solidstats/components/tab_navigation.css +0 -95
- data/app/components/solidstats/base_component.rb +0 -88
- data/app/components/solidstats/code_quality/code_quality_section_component.html.erb +0 -0
- data/app/components/solidstats/code_quality/code_quality_section_component.rb +0 -0
- data/app/components/solidstats/code_quality/section_component.html.erb +0 -45
- data/app/components/solidstats/code_quality/section_component.rb +0 -34
- data/app/components/solidstats/dashboard_header_component.html.erb +0 -39
- data/app/components/solidstats/dashboard_header_component.rb +0 -33
- data/app/components/solidstats/previews/action_button_component_preview/button_vs_link.html.erb +0 -6
- data/app/components/solidstats/previews/action_button_component_preview/sizes.html.erb +0 -6
- data/app/components/solidstats/previews/action_button_component_preview/variants.html.erb +0 -6
- data/app/components/solidstats/previews/action_button_component_preview/with_icons.html.erb +0 -6
- data/app/components/solidstats/previews/action_button_component_preview.rb +0 -64
- data/app/components/solidstats/previews/navigation_component_preview.rb +0 -74
- data/app/components/solidstats/previews/stats_overview_component_preview.rb +0 -100
- data/app/components/solidstats/previews/status_badge_component_preview/sizes.html.erb +0 -6
- data/app/components/solidstats/previews/status_badge_component_preview/statuses.html.erb +0 -6
- data/app/components/solidstats/previews/status_badge_component_preview/with_icons.html.erb +0 -6
- data/app/components/solidstats/previews/status_badge_component_preview.rb +0 -49
- data/app/components/solidstats/previews/summary_card_component_preview/clickable.html.erb +0 -9
- data/app/components/solidstats/previews/summary_card_component_preview/dashboard_layout.html.erb +0 -9
- data/app/components/solidstats/previews/summary_card_component_preview/statuses.html.erb +0 -6
- data/app/components/solidstats/previews/summary_card_component_preview/value_formats.html.erb +0 -6
- data/app/components/solidstats/previews/summary_card_component_preview.rb +0 -67
- data/app/components/solidstats/quick_navigation_component.html.erb +0 -8
- data/app/components/solidstats/quick_navigation_component.rb +0 -21
- data/app/components/solidstats/security/gem_impact_analysis_component.html.erb +0 -44
- data/app/components/solidstats/security/gem_impact_analysis_component.rb +0 -45
- data/app/components/solidstats/security/overview_component.html.erb +0 -21
- data/app/components/solidstats/security/overview_component.rb +0 -104
- data/app/components/solidstats/security/section_component.html.erb +0 -26
- data/app/components/solidstats/security/section_component.rb +0 -52
- data/app/components/solidstats/security/timeline_component.html.erb +0 -39
- data/app/components/solidstats/security/timeline_component.rb +0 -43
- data/app/components/solidstats/tasks_section_component.html.erb +0 -17
- data/app/components/solidstats/tasks_section_component.rb +0 -22
- data/app/components/solidstats/ui/action_button_component.html.erb +0 -6
- data/app/components/solidstats/ui/action_button_component.rb +0 -71
- data/app/components/solidstats/ui/dashboard_layout_component.html.erb +0 -19
- data/app/components/solidstats/ui/dashboard_layout_component.rb +0 -85
- data/app/components/solidstats/ui/navigation_component.html.erb +0 -34
- data/app/components/solidstats/ui/navigation_component.rb +0 -72
- data/app/components/solidstats/ui/stats_overview_component.html.erb +0 -14
- data/app/components/solidstats/ui/stats_overview_component.rb +0 -78
- data/app/components/solidstats/ui/status_badge_component.html.erb +0 -6
- data/app/components/solidstats/ui/status_badge_component.rb +0 -42
- data/app/components/solidstats/ui/summary_card_component.html.erb +0 -12
- data/app/components/solidstats/ui/summary_card_component.rb +0 -63
- data/app/components/solidstats/ui/tab_navigation_component.html.erb +0 -22
- data/app/components/solidstats/ui/tab_navigation_component.rb +0 -79
- data/app/services/solidstats/audit_service.rb +0 -56
- data/app/services/solidstats/data_collector_service.rb +0 -83
- data/app/services/solidstats/gem_metadata/fetcher_service.rb +0 -136
- data/app/services/solidstats/todo_service.rb +0 -114
- data/app/views/solidstats/dashboard/_log_monitor.html.erb +0 -759
- data/app/views/solidstats/dashboard/_todos.html.erb +0 -151
- data/app/views/solidstats/dashboard/audit/_additional_styles.css +0 -22
- data/app/views/solidstats/dashboard/audit/_audit_badge.html.erb +0 -5
- data/app/views/solidstats/dashboard/audit/_audit_details.html.erb +0 -495
- data/app/views/solidstats/dashboard/audit/_audit_summary.html.erb +0 -26
- data/app/views/solidstats/dashboard/audit/_no_vulnerabilities.html.erb +0 -3
- data/app/views/solidstats/dashboard/audit/_security_audit.html.erb +0 -14
- data/app/views/solidstats/dashboard/audit/_vulnerabilities_table.html.erb +0 -1120
- data/app/views/solidstats/dashboard/audit/_vulnerability_details.html.erb +0 -63
- data/app/views/solidstats/dashboard/index.html.erb +0 -81
- data/app/views/solidstats/gem_metadata/_panel.html.erb +0 -419
- data/lib/generators/solidstats/feature/feature_generator.rb +0 -170
- data/lib/generators/solidstats/feature/templates/component.html.erb +0 -84
- data/lib/generators/solidstats/feature/templates/component.rb.erb +0 -103
- data/lib/generators/solidstats/feature/templates/component.scss +0 -243
- data/lib/generators/solidstats/feature/templates/component_test.rb.erb +0 -183
- data/lib/generators/solidstats/feature/templates/controller.rb.erb +0 -44
- data/lib/generators/solidstats/feature/templates/controller_test.rb.erb +0 -111
- data/lib/generators/solidstats/feature/templates/detail_view.html.erb +0 -755
- data/lib/generators/solidstats/feature/templates/preview.rb.erb +0 -107
- data/lib/generators/solidstats/feature/templates/service.rb.erb +0 -132
- data/lib/generators/solidstats/feature/templates/service_test.rb.erb +0 -109
- data/lib/generators/solidstats/install_generator.rb +0 -109
- data/lib/tasks/solidstats_install.rake +0 -133
@@ -1,136 +0,0 @@
|
|
1
|
-
require "net/http"
|
2
|
-
|
3
|
-
module Solidstats
|
4
|
-
module GemMetadata
|
5
|
-
class FetcherService
|
6
|
-
GemMeta = Struct.new(:name, :version, :current_version, :released, :info, :runtime, keyword_init: true)
|
7
|
-
|
8
|
-
def self.call(gem_names = nil, force_refresh = false)
|
9
|
-
new.call(gem_names, force_refresh)
|
10
|
-
end
|
11
|
-
|
12
|
-
def call(gem_names = nil, force_refresh = false)
|
13
|
-
gem_names = get_gem_names(gem_names)
|
14
|
-
fetch_metadata(gem_names, force_refresh)
|
15
|
-
end
|
16
|
-
|
17
|
-
private
|
18
|
-
|
19
|
-
def get_gem_names(gem_names)
|
20
|
-
return gem_names if gem_names.present?
|
21
|
-
|
22
|
-
gemfile_lock = Rails.root.join("Gemfile.lock")
|
23
|
-
return [] unless File.exist?(gemfile_lock)
|
24
|
-
|
25
|
-
lockfile = File.read(gemfile_lock)
|
26
|
-
parser = Bundler::LockfileParser.new(lockfile)
|
27
|
-
parser.specs.map(&:name)
|
28
|
-
end
|
29
|
-
|
30
|
-
def get_current_versions
|
31
|
-
gemfile_lock = Rails.root.join("Gemfile.lock")
|
32
|
-
return {} unless File.exist?(gemfile_lock)
|
33
|
-
|
34
|
-
lockfile = File.read(gemfile_lock)
|
35
|
-
parser = Bundler::LockfileParser.new(lockfile)
|
36
|
-
|
37
|
-
parser.specs.each_with_object({}) do |spec, versions|
|
38
|
-
versions[spec.name] = spec.version.to_s
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def fetch_metadata(gem_names, force_refresh)
|
43
|
-
current_versions = get_current_versions
|
44
|
-
|
45
|
-
gem_names.map do |name|
|
46
|
-
fetch_gem_data(name, current_versions[name], force_refresh)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def fetch_gem_data(name, current_version, force_refresh)
|
51
|
-
cached_data = fetch_from_cache(name) unless force_refresh
|
52
|
-
|
53
|
-
if cached_data
|
54
|
-
# Update current version if it changed since caching
|
55
|
-
if current_version && cached_data.current_version != current_version
|
56
|
-
cached_data.current_version = current_version
|
57
|
-
cache_data(name, cached_data)
|
58
|
-
end
|
59
|
-
return cached_data
|
60
|
-
end
|
61
|
-
|
62
|
-
begin
|
63
|
-
data = fetch_from_api(name)
|
64
|
-
meta = GemMeta.new(
|
65
|
-
name: data["name"],
|
66
|
-
version: data["version"],
|
67
|
-
current_version: current_version,
|
68
|
-
released: data["version_created_at"] ? Time.parse(data["version_created_at"]) : nil,
|
69
|
-
info: data["info"],
|
70
|
-
runtime: data["dependencies"] && data["dependencies"]["runtime"] || []
|
71
|
-
)
|
72
|
-
cache_data(name, meta)
|
73
|
-
meta
|
74
|
-
rescue => e
|
75
|
-
Rails.logger.error("Failed to fetch gem metadata for #{name}: #{e.message}")
|
76
|
-
GemMeta.new(name: name, current_version: current_version, info: "(API unavailable)")
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
def fetch_from_api(name)
|
81
|
-
uri = URI.parse("https://rubygems.org/api/v1/gems/#{name}.json")
|
82
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
83
|
-
http.use_ssl = true
|
84
|
-
http.open_timeout = 5
|
85
|
-
http.read_timeout = 5
|
86
|
-
|
87
|
-
response = http.get(uri.request_uri)
|
88
|
-
|
89
|
-
if response.code == "200"
|
90
|
-
JSON.parse(response.body)
|
91
|
-
else
|
92
|
-
raise "API request failed with status #{response.code}"
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
def fetch_from_cache(name)
|
97
|
-
cache_file = cache_path(name)
|
98
|
-
return nil unless File.exist?(cache_file)
|
99
|
-
|
100
|
-
data = JSON.parse(File.read(cache_file))
|
101
|
-
cache_time = File.mtime(cache_file)
|
102
|
-
|
103
|
-
# Return nil if cache is older than 24 hours
|
104
|
-
return nil if Time.now - cache_time > 24.hours
|
105
|
-
|
106
|
-
GemMeta.new(
|
107
|
-
name: data["name"],
|
108
|
-
version: data["version"],
|
109
|
-
current_version: data["current_version"],
|
110
|
-
released: data["released"] ? Time.parse(data["released"]) : nil,
|
111
|
-
info: data["info"],
|
112
|
-
runtime: data["runtime"] || []
|
113
|
-
)
|
114
|
-
end
|
115
|
-
|
116
|
-
def cache_data(name, meta)
|
117
|
-
FileUtils.mkdir_p(File.dirname(cache_path(name)))
|
118
|
-
|
119
|
-
data = {
|
120
|
-
"name" => meta.name,
|
121
|
-
"version" => meta.version,
|
122
|
-
"current_version" => meta.current_version,
|
123
|
-
"released" => meta.released&.iso8601,
|
124
|
-
"info" => meta.info,
|
125
|
-
"runtime" => meta.runtime
|
126
|
-
}
|
127
|
-
|
128
|
-
File.write(cache_path(name), data.to_json)
|
129
|
-
end
|
130
|
-
|
131
|
-
def cache_path(name)
|
132
|
-
Rails.root.join("tmp", "cache", "gem_metadata", "#{name}.json")
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
@@ -1,114 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Solidstats
|
4
|
-
# Service to collect and process TODO items from codebase
|
5
|
-
class TodoService < DataCollectorService
|
6
|
-
# Initialize with default cache settings for TODO items
|
7
|
-
def initialize
|
8
|
-
super(Rails.root.join("tmp", "solidstats_todos.json"))
|
9
|
-
end
|
10
|
-
|
11
|
-
# Generate a summary for the dashboard display
|
12
|
-
# @return [Hash] Summary information with counts and status
|
13
|
-
def summary
|
14
|
-
todos = fetch
|
15
|
-
return { count: 0, status: "success", message: "No TODO items found" } if todos.nil? || todos.empty?
|
16
|
-
|
17
|
-
stats = calculate_stats(todos)
|
18
|
-
|
19
|
-
{
|
20
|
-
count: todos.count,
|
21
|
-
status: determine_status(todos),
|
22
|
-
message: generate_message(todos.count),
|
23
|
-
by_type: stats[:by_type],
|
24
|
-
hotspots: stats[:hotspots]
|
25
|
-
}
|
26
|
-
end
|
27
|
-
|
28
|
-
private
|
29
|
-
|
30
|
-
# Calculate statistics for the TODO items
|
31
|
-
# @param todos [Array] List of TODO items
|
32
|
-
# @return [Hash] Statistics about the TODO items
|
33
|
-
def calculate_stats(todos)
|
34
|
-
stats = {
|
35
|
-
by_type: {
|
36
|
-
"TODO" => todos.count { |t| (t[:type] || t["type"]) == "TODO" },
|
37
|
-
"FIXME" => todos.count { |t| (t[:type] || t["type"]) == "FIXME" },
|
38
|
-
"HACK" => todos.count { |t| (t[:type] || t["type"]) == "HACK" }
|
39
|
-
},
|
40
|
-
by_file: {}
|
41
|
-
}
|
42
|
-
|
43
|
-
# Group by file path
|
44
|
-
todos.each do |todo|
|
45
|
-
file_path = todo[:file] || todo["file"]
|
46
|
-
stats[:by_file][file_path] ||= 0
|
47
|
-
stats[:by_file][file_path] += 1
|
48
|
-
end
|
49
|
-
|
50
|
-
# Find files with most TODOs (top 5)
|
51
|
-
stats[:hotspots] = stats[:by_file].sort_by { |_, count| -count }
|
52
|
-
.first(5)
|
53
|
-
.to_h
|
54
|
-
|
55
|
-
stats
|
56
|
-
end
|
57
|
-
|
58
|
-
# Determine the status indicator based on TODO items
|
59
|
-
# @param todos [Array] List of TODO items
|
60
|
-
# @return [String] Status indicator (success, warning, or danger)
|
61
|
-
def determine_status(todos)
|
62
|
-
fixme_count = todos.count { |t| t[:type] == "FIXME" }
|
63
|
-
hack_count = todos.count { |t| t[:type] == "HACK" }
|
64
|
-
|
65
|
-
if hack_count > 0
|
66
|
-
"danger"
|
67
|
-
elsif fixme_count > 0
|
68
|
-
"warning"
|
69
|
-
elsif todos.count > 10
|
70
|
-
"warning"
|
71
|
-
else
|
72
|
-
"success"
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
# Generate a status message based on TODO count
|
77
|
-
# @param count [Integer] Number of TODOs
|
78
|
-
# @return [String] Human-readable status message
|
79
|
-
def generate_message(count)
|
80
|
-
"#{count} #{count == 1 ? 'item' : 'items'} found"
|
81
|
-
end
|
82
|
-
|
83
|
-
# Collect fresh TODO data by scanning the codebase
|
84
|
-
# @return [Array] List of TODO items found
|
85
|
-
def collect_data
|
86
|
-
todos = []
|
87
|
-
raw_output = `grep -r -n -E "(TODO|FIXME|HACK|todo|fixme|hack)" app lib`.split("\n")
|
88
|
-
|
89
|
-
raw_output.each do |line|
|
90
|
-
if line =~ /^(.+):(\d+):(.+)$/
|
91
|
-
file = $1
|
92
|
-
line_num = $2
|
93
|
-
content = $3
|
94
|
-
|
95
|
-
# Match only exact lowercase or uppercase variants
|
96
|
-
type_match = content.match(/(TODO|FIXME|HACK|todo|fixme|hack)/)
|
97
|
-
if type_match
|
98
|
-
# Convert to uppercase for consistency
|
99
|
-
type = type_match.to_s.upcase
|
100
|
-
|
101
|
-
todos << {
|
102
|
-
file: file,
|
103
|
-
line: line_num.to_i,
|
104
|
-
content: content.strip,
|
105
|
-
type: type
|
106
|
-
}
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
todos
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|