solidstats 0.0.4 → 1.1.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 +78 -5
- data/README.md +54 -5
- data/app/controllers/solidstats/dashboard_controller.rb +60 -121
- data/app/services/solidstats/audit_service.rb +56 -0
- data/app/services/solidstats/data_collector_service.rb +83 -0
- data/app/services/solidstats/log_size_monitor_service.rb +94 -0
- data/app/services/solidstats/todo_service.rb +114 -0
- data/app/views/solidstats/dashboard/_log_monitor.html.erb +759 -0
- data/app/views/solidstats/dashboard/_todos.html.erb +6 -27
- data/app/views/solidstats/dashboard/audit/_additional_styles.css +22 -0
- data/app/views/solidstats/dashboard/audit/_audit_details.html.erb +47 -58
- data/app/views/solidstats/dashboard/audit/_audit_summary.html.erb +1 -1
- data/app/views/solidstats/dashboard/audit/_security_audit.html.erb +0 -23
- data/app/views/solidstats/dashboard/audit/_vulnerabilities_table.html.erb +1092 -38
- data/app/views/solidstats/dashboard/audit/_vulnerability_details.html.erb +4 -3
- data/app/views/solidstats/dashboard/index.html.erb +1166 -162
- data/config/routes.rb +5 -0
- data/lib/solidstats/version.rb +1 -1
- data/lib/tasks/solidstats_release.rake +69 -0
- metadata +12 -5
- data/app/views/solidstats/dashboard/audit/_audit_filters.html.erb +0 -5
@@ -0,0 +1,114 @@
|
|
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
|