findbug 0.3.4 → 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/README.md +5 -27
- data/app/controllers/findbug/alerts_controller.rb +224 -0
- data/app/models/findbug/alert_channel.rb +167 -0
- data/app/views/findbug/alerts/edit.html.erb +133 -0
- data/app/views/findbug/alerts/index.html.erb +127 -0
- data/app/views/findbug/alerts/new.html.erb +154 -0
- data/app/views/layouts/findbug/application.html.erb +56 -1
- data/docs/index.html +2496 -0
- data/lib/findbug/alerts/dispatcher.rb +18 -32
- data/lib/findbug/configuration.rb +17 -56
- data/lib/findbug/engine.rb +9 -0
- data/lib/findbug/railtie.rb +8 -0
- data/lib/findbug/version.rb +1 -1
- data/lib/generators/findbug/install_generator.rb +6 -0
- data/lib/generators/findbug/templates/POST_INSTALL +5 -8
- data/lib/generators/findbug/templates/create_findbug_alert_channels.rb +24 -0
- data/lib/generators/findbug/templates/initializer.rb +3 -26
- data/lib/generators/findbug/upgrade_generator.rb +79 -0
- metadata +12 -4
|
@@ -12,6 +12,12 @@ module Findbug
|
|
|
12
12
|
# 3. Dispatcher checks throttling (avoid spam)
|
|
13
13
|
# 4. Dispatcher sends to enabled channels (async via AlertJob)
|
|
14
14
|
#
|
|
15
|
+
# CHANNEL SOURCE
|
|
16
|
+
# ==============
|
|
17
|
+
#
|
|
18
|
+
# Alert channels are stored in the database (findbug_alert_channels table)
|
|
19
|
+
# and managed via the dashboard UI at /findbug/alerts.
|
|
20
|
+
#
|
|
15
21
|
# THROTTLING
|
|
16
22
|
# ==========
|
|
17
23
|
#
|
|
@@ -36,7 +42,7 @@ module Findbug
|
|
|
36
42
|
#
|
|
37
43
|
def notify(error_event, async: true)
|
|
38
44
|
return unless Findbug.enabled?
|
|
39
|
-
return unless
|
|
45
|
+
return unless any_enabled?
|
|
40
46
|
return unless should_alert?(error_event)
|
|
41
47
|
return if throttled?(error_event)
|
|
42
48
|
|
|
@@ -54,17 +60,23 @@ module Findbug
|
|
|
54
60
|
# @param error_event [ErrorEvent] the error to alert about
|
|
55
61
|
#
|
|
56
62
|
def send_alerts(error_event)
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
send_to_channel(channel_name, error_event, config)
|
|
63
|
+
Findbug::AlertChannel.enabled.find_each do |channel_record|
|
|
64
|
+
channel_instance = channel_record.channel_class.new(channel_record.config.symbolize_keys)
|
|
65
|
+
channel_instance.send_alert(error_event)
|
|
61
66
|
rescue StandardError => e
|
|
62
67
|
Findbug.logger.error(
|
|
63
|
-
"[Findbug] Failed to send alert to #{
|
|
68
|
+
"[Findbug] Failed to send alert to #{channel_record.name}: #{e.message}"
|
|
64
69
|
)
|
|
65
70
|
end
|
|
66
71
|
end
|
|
67
72
|
|
|
73
|
+
# Check if any alert channels are enabled in the database
|
|
74
|
+
def any_enabled?
|
|
75
|
+
Findbug::AlertChannel.enabled.exists?
|
|
76
|
+
rescue StandardError
|
|
77
|
+
false
|
|
78
|
+
end
|
|
79
|
+
|
|
68
80
|
private
|
|
69
81
|
|
|
70
82
|
# Check if we should alert for this error
|
|
@@ -94,32 +106,6 @@ module Findbug
|
|
|
94
106
|
def record_alert(error_event)
|
|
95
107
|
Throttler.record(error_event.fingerprint)
|
|
96
108
|
end
|
|
97
|
-
|
|
98
|
-
# Send to a specific channel
|
|
99
|
-
def send_to_channel(channel_name, error_event, config)
|
|
100
|
-
channel_class = channel_for(channel_name)
|
|
101
|
-
return unless channel_class
|
|
102
|
-
|
|
103
|
-
channel = channel_class.new(config)
|
|
104
|
-
channel.send_alert(error_event)
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
# Get the channel class for a channel name
|
|
108
|
-
def channel_for(channel_name)
|
|
109
|
-
case channel_name.to_sym
|
|
110
|
-
when :email
|
|
111
|
-
Channels::Email
|
|
112
|
-
when :slack
|
|
113
|
-
Channels::Slack
|
|
114
|
-
when :discord
|
|
115
|
-
Channels::Discord
|
|
116
|
-
when :webhook
|
|
117
|
-
Channels::Webhook
|
|
118
|
-
else
|
|
119
|
-
Findbug.logger.warn("[Findbug] Unknown alert channel: #{channel_name}")
|
|
120
|
-
nil
|
|
121
|
-
end
|
|
122
|
-
end
|
|
123
109
|
end
|
|
124
110
|
end
|
|
125
111
|
end
|
|
@@ -310,70 +310,31 @@ module Findbug
|
|
|
310
310
|
|
|
311
311
|
# Nested class for alert configuration
|
|
312
312
|
#
|
|
313
|
-
#
|
|
314
|
-
#
|
|
315
|
-
#
|
|
313
|
+
# ALERT CHANNELS ARE DB-DRIVEN
|
|
314
|
+
# ============================
|
|
315
|
+
#
|
|
316
|
+
# Alert channels (email, Slack, Discord, webhook) are stored in the database
|
|
317
|
+
# and managed via the dashboard UI at /findbug/alerts.
|
|
318
|
+
#
|
|
319
|
+
# This class only holds global alert settings like throttle_period.
|
|
316
320
|
#
|
|
317
321
|
class AlertConfiguration
|
|
318
322
|
attr_accessor :throttle_period
|
|
319
323
|
|
|
320
324
|
def initialize
|
|
321
|
-
@channels = {}
|
|
322
325
|
@throttle_period = 300 # 5 minutes default
|
|
323
326
|
end
|
|
324
327
|
|
|
325
|
-
#
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
def slack(enabled:, webhook_url: nil, channel: nil, **options)
|
|
336
|
-
@channels[:slack] = {
|
|
337
|
-
enabled: enabled,
|
|
338
|
-
webhook_url: webhook_url,
|
|
339
|
-
channel: channel,
|
|
340
|
-
**options
|
|
341
|
-
}
|
|
342
|
-
end
|
|
343
|
-
|
|
344
|
-
# Configure Discord alerts
|
|
345
|
-
def discord(enabled:, webhook_url: nil, **options)
|
|
346
|
-
@channels[:discord] = {
|
|
347
|
-
enabled: enabled,
|
|
348
|
-
webhook_url: webhook_url,
|
|
349
|
-
**options
|
|
350
|
-
}
|
|
351
|
-
end
|
|
352
|
-
|
|
353
|
-
# Configure generic webhook alerts
|
|
354
|
-
def webhook(enabled:, url: nil, headers: {}, **options)
|
|
355
|
-
@channels[:webhook] = {
|
|
356
|
-
enabled: enabled,
|
|
357
|
-
url: url,
|
|
358
|
-
headers: headers,
|
|
359
|
-
**options
|
|
360
|
-
}
|
|
361
|
-
end
|
|
362
|
-
|
|
363
|
-
# Get configuration for a specific channel
|
|
364
|
-
def channel(name)
|
|
365
|
-
@channels[name.to_sym]
|
|
366
|
-
end
|
|
367
|
-
|
|
368
|
-
# Get all enabled channels
|
|
369
|
-
def enabled_channels
|
|
370
|
-
@channels.select { |_, config| config[:enabled] }
|
|
371
|
-
end
|
|
372
|
-
|
|
373
|
-
# Check if any alerts are configured
|
|
374
|
-
def any_enabled?
|
|
375
|
-
enabled_channels.any?
|
|
376
|
-
end
|
|
328
|
+
# Deprecated DSL methods — kept for backward compatibility so existing
|
|
329
|
+
# initializers don't raise NoMethodError on upgrade. These are no-ops;
|
|
330
|
+
# alert channels are now configured via the dashboard UI.
|
|
331
|
+
def email(**) = nil
|
|
332
|
+
def slack(**) = nil
|
|
333
|
+
def discord(**) = nil
|
|
334
|
+
def webhook(**) = nil
|
|
335
|
+
def channel(_name) = nil
|
|
336
|
+
def enabled_channels = {}
|
|
337
|
+
def any_enabled? = false
|
|
377
338
|
end
|
|
378
339
|
|
|
379
340
|
# Custom error for configuration issues
|
data/lib/findbug/engine.rb
CHANGED
|
@@ -11,6 +11,7 @@ require_relative "../../app/controllers/findbug/application_controller"
|
|
|
11
11
|
require_relative "../../app/controllers/findbug/dashboard_controller"
|
|
12
12
|
require_relative "../../app/controllers/findbug/errors_controller"
|
|
13
13
|
require_relative "../../app/controllers/findbug/performance_controller"
|
|
14
|
+
require_relative "../../app/controllers/findbug/alerts_controller"
|
|
14
15
|
|
|
15
16
|
module Findbug
|
|
16
17
|
# Engine is the main Rails integration point for Findbug.
|
|
@@ -97,6 +98,14 @@ Findbug::Engine.routes.draw do
|
|
|
97
98
|
# Performance
|
|
98
99
|
resources :performance, only: [:index, :show]
|
|
99
100
|
|
|
101
|
+
# Alerts
|
|
102
|
+
resources :alerts, only: [:index, :new, :create, :edit, :update, :destroy] do
|
|
103
|
+
member do
|
|
104
|
+
post :toggle
|
|
105
|
+
post :test
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
100
109
|
# Health check (useful for monitoring)
|
|
101
110
|
get "health", to: "dashboard#health"
|
|
102
111
|
|
data/lib/findbug/railtie.rb
CHANGED
|
@@ -60,6 +60,7 @@ module Findbug
|
|
|
60
60
|
models_path = File.expand_path("../../app/models/findbug", __dir__)
|
|
61
61
|
require "#{models_path}/error_event"
|
|
62
62
|
require "#{models_path}/performance_event"
|
|
63
|
+
require "#{models_path}/alert_channel"
|
|
63
64
|
end
|
|
64
65
|
|
|
65
66
|
# Register our middleware to catch exceptions
|
|
@@ -84,6 +85,13 @@ module Findbug
|
|
|
84
85
|
require_relative "capture/middleware"
|
|
85
86
|
|
|
86
87
|
Rails.application.config.middleware.use(Findbug::Capture::Middleware)
|
|
88
|
+
|
|
89
|
+
# Ensure Rack::MethodOverride is available so the dashboard's HTML
|
|
90
|
+
# forms can use PATCH/DELETE via the _method hidden field.
|
|
91
|
+
# API-only Rails apps don't include this middleware by default.
|
|
92
|
+
if Rails.application.config.api_only
|
|
93
|
+
Rails.application.config.middleware.insert_before 0, Rack::MethodOverride
|
|
94
|
+
end
|
|
87
95
|
end
|
|
88
96
|
|
|
89
97
|
# Set up Rails error reporting integration (Rails 7+)
|
data/lib/findbug/version.rb
CHANGED
|
@@ -49,8 +49,14 @@ module Findbug
|
|
|
49
49
|
"db/migrate/create_findbug_performance_events.rb"
|
|
50
50
|
)
|
|
51
51
|
|
|
52
|
+
migration_template(
|
|
53
|
+
"create_findbug_alert_channels.rb",
|
|
54
|
+
"db/migrate/create_findbug_alert_channels.rb"
|
|
55
|
+
)
|
|
56
|
+
|
|
52
57
|
say_status :create, "db/migrate/create_findbug_error_events.rb", :green
|
|
53
58
|
say_status :create, "db/migrate/create_findbug_performance_events.rb", :green
|
|
59
|
+
say_status :create, "db/migrate/create_findbug_alert_channels.rb", :green
|
|
54
60
|
end
|
|
55
61
|
|
|
56
62
|
def display_post_install
|
|
@@ -29,18 +29,15 @@ Next steps:
|
|
|
29
29
|
FINDBUG_USERNAME=your-username
|
|
30
30
|
FINDBUG_PASSWORD=your-secure-password
|
|
31
31
|
|
|
32
|
-
4. (Optional) Configure alerts
|
|
32
|
+
4. (Optional) Configure alerts via the dashboard:
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
webhook_url: ENV["SLACK_WEBHOOK_URL"]
|
|
38
|
-
)
|
|
39
|
-
end
|
|
34
|
+
http://localhost:3000/findbug/alerts
|
|
35
|
+
|
|
36
|
+
Add Email, Slack, Discord, or Webhook channels directly from the UI.
|
|
40
37
|
|
|
41
38
|
5. (Multi-tenant apps) If using Apartment/ros-apartment, add to apartment.rb:
|
|
42
39
|
|
|
43
|
-
config.excluded_models = %w[Findbug::ErrorEvent Findbug::PerformanceEvent]
|
|
40
|
+
config.excluded_models = %w[Findbug::ErrorEvent Findbug::PerformanceEvent Findbug::AlertChannel]
|
|
44
41
|
|
|
45
42
|
And exclude /findbug from your tenant switching middleware.
|
|
46
43
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class CreateFindbugAlertChannels < ActiveRecord::Migration<%= migration_version %>
|
|
4
|
+
def change
|
|
5
|
+
create_table :findbug_alert_channels do |t|
|
|
6
|
+
# Channel identification
|
|
7
|
+
t.string :channel_type, null: false # email, slack, discord, webhook
|
|
8
|
+
t.string :name, null: false # user-friendly label
|
|
9
|
+
|
|
10
|
+
# Status
|
|
11
|
+
t.boolean :enabled, default: false
|
|
12
|
+
|
|
13
|
+
# Configuration (JSON-serialized, encrypted at rest)
|
|
14
|
+
# Using text instead of jsonb so Rails encryption can work on it
|
|
15
|
+
t.text :config_data
|
|
16
|
+
|
|
17
|
+
t.timestamps
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Indexes for common queries
|
|
21
|
+
add_index :findbug_alert_channels, :channel_type
|
|
22
|
+
add_index :findbug_alert_channels, :enabled
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -113,35 +113,12 @@ Findbug.configure do |config|
|
|
|
113
113
|
# ALERTS
|
|
114
114
|
# ============================================================================
|
|
115
115
|
|
|
116
|
+
# Alert channels (Email, Slack, Discord, Webhook) are configured via the
|
|
117
|
+
# dashboard UI at /findbug/alerts — no code changes needed.
|
|
118
|
+
|
|
116
119
|
config.alerts do |alerts|
|
|
117
120
|
# Throttle period - don't alert for same error more than once in this period
|
|
118
121
|
alerts.throttle_period = 5.minutes
|
|
119
|
-
|
|
120
|
-
# Email alerts
|
|
121
|
-
# alerts.email(
|
|
122
|
-
# enabled: true,
|
|
123
|
-
# recipients: ["dev-team@example.com"]
|
|
124
|
-
# )
|
|
125
|
-
|
|
126
|
-
# Slack alerts
|
|
127
|
-
# alerts.slack(
|
|
128
|
-
# enabled: true,
|
|
129
|
-
# webhook_url: ENV["SLACK_WEBHOOK_URL"],
|
|
130
|
-
# channel: "#errors" # optional
|
|
131
|
-
# )
|
|
132
|
-
|
|
133
|
-
# Discord alerts
|
|
134
|
-
# alerts.discord(
|
|
135
|
-
# enabled: true,
|
|
136
|
-
# webhook_url: ENV["DISCORD_WEBHOOK_URL"]
|
|
137
|
-
# )
|
|
138
|
-
|
|
139
|
-
# Generic webhook
|
|
140
|
-
# alerts.webhook(
|
|
141
|
-
# enabled: true,
|
|
142
|
-
# url: "https://your-service.com/findbug-webhook",
|
|
143
|
-
# headers: { "Authorization" => "Bearer #{ENV['WEBHOOK_TOKEN']}" }
|
|
144
|
-
# )
|
|
145
122
|
end
|
|
146
123
|
|
|
147
124
|
# ============================================================================
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails/generators"
|
|
4
|
+
require "rails/generators/active_record"
|
|
5
|
+
|
|
6
|
+
module Findbug
|
|
7
|
+
module Generators
|
|
8
|
+
# UpgradeGenerator creates any missing migrations for existing Findbug installations.
|
|
9
|
+
#
|
|
10
|
+
# Usage:
|
|
11
|
+
# rails generate findbug:upgrade
|
|
12
|
+
#
|
|
13
|
+
# This is safe to run multiple times — it only creates migrations that don't
|
|
14
|
+
# already exist. Use this when upgrading Findbug to a new version that adds
|
|
15
|
+
# new database tables.
|
|
16
|
+
#
|
|
17
|
+
class UpgradeGenerator < Rails::Generators::Base
|
|
18
|
+
include Rails::Generators::Migration
|
|
19
|
+
|
|
20
|
+
source_root File.expand_path("templates", __dir__)
|
|
21
|
+
|
|
22
|
+
desc "Upgrade Findbug: creates any missing migrations"
|
|
23
|
+
|
|
24
|
+
def self.next_migration_number(dirname)
|
|
25
|
+
ActiveRecord::Generators::Base.next_migration_number(dirname)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def create_missing_migrations
|
|
29
|
+
create_migration_if_missing(
|
|
30
|
+
"create_findbug_alert_channels.rb",
|
|
31
|
+
"db/migrate/create_findbug_alert_channels.rb"
|
|
32
|
+
)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def display_next_steps
|
|
36
|
+
return unless behavior == :invoke
|
|
37
|
+
|
|
38
|
+
say ""
|
|
39
|
+
say "=================================================================", :green
|
|
40
|
+
say " Findbug upgrade complete!", :green
|
|
41
|
+
say "=================================================================", :green
|
|
42
|
+
say ""
|
|
43
|
+
say "Next steps:"
|
|
44
|
+
say ""
|
|
45
|
+
say " 1. Run migrations: rails db:migrate"
|
|
46
|
+
say ""
|
|
47
|
+
say " 2. Configure alerts via the dashboard:"
|
|
48
|
+
say " http://localhost:3000/findbug/alerts"
|
|
49
|
+
say ""
|
|
50
|
+
say " 3. (Multi-tenant apps) Add to apartment.rb excluded_models:"
|
|
51
|
+
say " Findbug::AlertChannel"
|
|
52
|
+
say ""
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
def migration_version
|
|
58
|
+
"[#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}]"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Only create a migration if no migration with the same class name exists
|
|
62
|
+
def create_migration_if_missing(template_name, destination)
|
|
63
|
+
migration_name = template_name.sub(/\.rb$/, "")
|
|
64
|
+
|
|
65
|
+
if migration_exists?(migration_name)
|
|
66
|
+
say_status :skip, destination, :yellow
|
|
67
|
+
else
|
|
68
|
+
migration_template(template_name, destination)
|
|
69
|
+
say_status :create, destination, :green
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Check if a migration file already exists in db/migrate/
|
|
74
|
+
def migration_exists?(migration_name)
|
|
75
|
+
Dir.glob("db/migrate/[0-9]*_#{migration_name}.rb").any?
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: findbug
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Soumit Das
|
|
8
8
|
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-
|
|
10
|
+
date: 2026-02-25 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: railties
|
|
@@ -177,6 +177,7 @@ files:
|
|
|
177
177
|
- LICENSE.txt
|
|
178
178
|
- README.md
|
|
179
179
|
- Rakefile
|
|
180
|
+
- app/controllers/findbug/alerts_controller.rb
|
|
180
181
|
- app/controllers/findbug/application_controller.rb
|
|
181
182
|
- app/controllers/findbug/dashboard_controller.rb
|
|
182
183
|
- app/controllers/findbug/errors_controller.rb
|
|
@@ -184,14 +185,19 @@ files:
|
|
|
184
185
|
- app/jobs/findbug/alert_job.rb
|
|
185
186
|
- app/jobs/findbug/cleanup_job.rb
|
|
186
187
|
- app/jobs/findbug/persist_job.rb
|
|
188
|
+
- app/models/findbug/alert_channel.rb
|
|
187
189
|
- app/models/findbug/error_event.rb
|
|
188
190
|
- app/models/findbug/performance_event.rb
|
|
191
|
+
- app/views/findbug/alerts/edit.html.erb
|
|
192
|
+
- app/views/findbug/alerts/index.html.erb
|
|
193
|
+
- app/views/findbug/alerts/new.html.erb
|
|
189
194
|
- app/views/findbug/dashboard/index.html.erb
|
|
190
195
|
- app/views/findbug/errors/index.html.erb
|
|
191
196
|
- app/views/findbug/errors/show.html.erb
|
|
192
197
|
- app/views/findbug/performance/index.html.erb
|
|
193
198
|
- app/views/findbug/performance/show.html.erb
|
|
194
199
|
- app/views/layouts/findbug/application.html.erb
|
|
200
|
+
- docs/index.html
|
|
195
201
|
- lib/findbug.rb
|
|
196
202
|
- lib/findbug/alerts/channels/base.rb
|
|
197
203
|
- lib/findbug/alerts/channels/discord.rb
|
|
@@ -220,15 +226,17 @@ files:
|
|
|
220
226
|
- lib/findbug/version.rb
|
|
221
227
|
- lib/generators/findbug/install_generator.rb
|
|
222
228
|
- lib/generators/findbug/templates/POST_INSTALL
|
|
229
|
+
- lib/generators/findbug/templates/create_findbug_alert_channels.rb
|
|
223
230
|
- lib/generators/findbug/templates/create_findbug_error_events.rb
|
|
224
231
|
- lib/generators/findbug/templates/create_findbug_performance_events.rb
|
|
225
232
|
- lib/generators/findbug/templates/initializer.rb
|
|
233
|
+
- lib/generators/findbug/upgrade_generator.rb
|
|
226
234
|
- sig/findbug.rbs
|
|
227
|
-
homepage: https://
|
|
235
|
+
homepage: https://findbug.dev
|
|
228
236
|
licenses:
|
|
229
237
|
- MIT
|
|
230
238
|
metadata:
|
|
231
|
-
homepage_uri: https://
|
|
239
|
+
homepage_uri: https://findbug.dev
|
|
232
240
|
source_code_uri: https://github.com/ITSSOUMIT/findbug
|
|
233
241
|
changelog_uri: https://github.com/ITSSOUMIT/findbug/blob/main/CHANGELOG.md
|
|
234
242
|
rdoc_options: []
|