bug_reports_client 0.1.1 → 0.1.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2328f7788a059ba5cedf89c2b43e0aaf56cdac6f5a575b663e2f710ad3a0ef02
4
- data.tar.gz: 22357aae7c221c4b41d20cfd56202b0b57679f96a53f11a8a4f9af04d1c81669
3
+ metadata.gz: cc0b9ca39db5bc33d5bf9fda72ded756fe16e42e877ef5eb93dbd2b833cc6aab
4
+ data.tar.gz: 71195c18c23223ffa3dd5c3669b47549b50ff36756deb3fc46c90fba039f3f6f
5
5
  SHA512:
6
- metadata.gz: d60b7fabf51873954b67dd8326a6904b6aa762d72c39c86e18068cdc9c1a83cdf72818c22e866215d57b4241184dde9cb201a39ad62d2e6dfa9d3c91c07f07c4
7
- data.tar.gz: 222a8df13cb624d9c674b482fc2b6a5d63ec16d02937f927931cbb78dcd4beb173aa708a34fadca413c744f4d089d68000656ded24d1ebd7628ae6d597ec0df7
6
+ metadata.gz: 6e125d9c99cfaf74d273509899f1c7e4ec4552b5ebc425552e436b943f47a2ce2d4bd3719aed7fee372fe1fdd98347a3c1c4a5ea76f36ca80c79fe8080d49229
7
+ data.tar.gz: 91125e1ec8de2e57059605f14ab4a2cc4cf705e2ae5ddc7b596381028c841fce299cc928bd828730b3c8be46f88265e04ad5ced9f6001c586a8ec4d57959600a
data/CHANGELOG.md CHANGED
@@ -1,6 +1,23 @@
1
1
  # Changelog
2
2
 
3
- ## 0.1.1 (unreleased)
3
+ ## 0.1.3 (7 October 2026)
4
+
5
+ - Unhandled errors raised by `bin/rails runner` scripts (Rails.error source
6
+ `"application.runner.railties"`) are no longer reported. They have no
7
+ application frame, so they all shared one fingerprint and merged into one
8
+ misleading issue. Requests and jobs are still captured. The skipped sources
9
+ are configurable via the new `config.ignored_error_sources` setting.
10
+
11
+ ## 0.1.2 (16 August 2026)
12
+
13
+ - Resolved-report alerts no longer stack. When a user has two or more
14
+ resolved, undismissed reports, the host layout shows a single collapsed
15
+ banner listing every title with one "Dismiss all" button (new
16
+ `PATCH /dismiss_all` route). A single resolved report keeps its own banner
17
+ and per-report Dismiss as before. Hosts that copied `_alerts.html.erb` via
18
+ the views generator will need to re-copy it to pick this up.
19
+
20
+ ## 0.1.1 (24 July 2026)
4
21
 
5
22
  - The screenshot dropzone's drag-over highlight classes are configurable via
6
23
  the `highlight-classes` Stimulus value, so dark-themed hosts can supply
data/README.md CHANGED
@@ -224,6 +224,7 @@ Opt in per host and unhandled 500s become GitHub issues, deduplicated:
224
224
  config.error_reporting_enabled = true
225
225
  config.error_ignore = [] # extra exception class names to skip
226
226
  config.error_throttle_period = 300 # seconds between posts per fingerprint
227
+ config.ignored_error_sources = [ "application.runner.railties" ] # the default
227
228
  ```
228
229
 
229
230
  The engine subscribes to the Rails error reporter, so anything that would
@@ -236,6 +237,15 @@ slowed down. The API keeps one open issue per fingerprint, counting repeat
236
237
  occurrences; when a closed error recurs, a fresh issue is filed (a
237
238
  regression deserves new attention).
238
239
 
240
+ Errors are also skipped when the `source:` Rails passes to the error
241
+ reporter is in `config.ignored_error_sources`. By default that list holds
242
+ `"application.runner.railties"`, the source Rails uses for unhandled errors
243
+ in `bin/rails runner` scripts: the person running the script already sees the
244
+ error in their terminal, and with no application frame in the backtrace
245
+ every such error would share one fingerprint and merge into one misleading
246
+ issue. Requests and jobs are still captured. Add other sources to skip them
247
+ too, or set the list to `[]` to capture runner errors as well.
248
+
239
249
  Captured errors are also attributed to the signed-in user who hit them
240
250
  (stored locally in `bug_report_error_events`, pruned after 30 days). When
241
251
  that user opens the report form within 24 hours, it asks "did this happen
@@ -90,6 +90,26 @@ module BugReportsClient
90
90
  render :new, status: :unprocessable_entity
91
91
  end
92
92
 
93
+ # PATCH /dismiss_all
94
+ # Dismisses every resolved-and-undismissed alert for the current user in
95
+ # one go - the action behind the collapsed multi-report banner.
96
+ def dismiss_all
97
+ scope = BugReport.where(user: bug_reports_current_user).resolved_and_undismissed
98
+ # Column write, not update!: see dismiss_bug_report
99
+ scope.update_all(dismissed_at: Time.current, updated_at: Time.current)
100
+
101
+ respond_to do |format|
102
+ format.turbo_stream do
103
+ streams = [ turbo_stream.remove("bug_report_alerts") ]
104
+ streams << render_to_string(partial: "bug_reports_client/shared/after_dismiss", formats: [ :turbo_stream ])
105
+ render turbo_stream: streams
106
+ end
107
+ format.html do
108
+ redirect_to fallback_root_path, notice: t("bug_reports_client.flashes.dismissed_all")
109
+ end
110
+ end
111
+ end
112
+
93
113
  # PATCH /:id
94
114
  # Two cases: dismissing a resolved alert (no bug_report params), or
95
115
  # editing an open report (re-syncs the remote issue).
@@ -1,7 +1,12 @@
1
1
  <%# Dismissable alerts for resolved reports. Rendered in HOST layouts via the
2
- bug_report_alerts helper, so routes go through the mount proxy. %>
2
+ bug_report_alerts helper, so routes go through the mount proxy.
3
+
4
+ One resolved report renders as its own banner. Two or more collapse into a
5
+ single banner listing every title with one "Dismiss all" button, so a
6
+ batch of fixes does not stack a wall of green boxes on every page. %>
3
7
  <div id="bug_report_alerts" class="mb-6">
4
- <% resolved_bug_reports.each do |report| %>
8
+ <% if resolved_bug_reports.size == 1 %>
9
+ <% report = resolved_bug_reports.first %>
5
10
  <div id="bug_report_<%= report.id %>" class="flex items-center justify-between p-3 mb-2 border border-green-200 rounded-lg bg-green-50">
6
11
  <div class="flex items-center gap-2">
7
12
  <svg class="flex-shrink-0 w-4 h-4 text-green-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -18,5 +23,32 @@
18
23
  <%= t("bug_reports_client.alerts.dismiss") %>
19
24
  <% end %>
20
25
  </div>
26
+ <% else %>
27
+ <div id="bug_report_alerts_collapsed" class="flex items-start justify-between gap-4 p-3 mb-2 border border-green-200 rounded-lg bg-green-50">
28
+ <div class="flex items-start gap-2 min-w-0">
29
+ <svg class="flex-shrink-0 w-4 h-4 mt-0.5 text-green-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
30
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>
31
+ </svg>
32
+ <div class="text-sm text-green-800 min-w-0">
33
+ <p class="font-medium">
34
+ <%= t("bug_reports_client.alerts.resolved_many", count: resolved_bug_reports.size) %>
35
+ </p>
36
+ <ul class="mt-1 space-y-0.5 list-disc list-inside text-green-700">
37
+ <% resolved_bug_reports.each do |report| %>
38
+ <li id="bug_report_<%= report.id %>" class="truncate">
39
+ <span class="text-green-600"><%= report.type_noun.capitalize %>:</span>
40
+ <span class="font-medium"><%= report.title %></span>
41
+ </li>
42
+ <% end %>
43
+ </ul>
44
+ </div>
45
+ </div>
46
+ <%= button_to bug_reports_client.dismiss_all_bug_reports_path,
47
+ method: :patch,
48
+ class: "text-xs text-green-600 hover:text-green-800 font-medium flex-shrink-0 cursor-pointer whitespace-nowrap",
49
+ data: { turbo_stream: true } do %>
50
+ <%= t("bug_reports_client.alerts.dismiss_all") %>
51
+ <% end %>
52
+ </div>
21
53
  <% end %>
22
54
  </div>
@@ -163,11 +163,14 @@ en:
163
163
  submit_failed: "Unable to submit your report. Please try again later."
164
164
  only_open_editable: "Only open %{type_noun}s can be updated."
165
165
  dismissed: "%{type_noun} notification dismissed."
166
+ dismissed_all: "All resolved alerts dismissed."
166
167
  not_permitted: "You do not have permission for this action."
167
168
 
168
169
  alerts:
169
170
  resolved_html: "Your %{type_noun} <span class=\"font-medium\">\"%{title}\"</span> has been resolved."
171
+ resolved_many: "%{count} of your reports have been resolved:"
170
172
  dismiss: "Dismiss"
173
+ dismiss_all: "Dismiss all"
171
174
 
172
175
  filters:
173
176
  type_label: "Type"
data/config/routes.rb CHANGED
@@ -2,11 +2,14 @@
2
2
  # GET /bug_reports - my reports
3
3
  # GET /bug_reports/new - the report form
4
4
  # GET /bug_reports/all - every report (admins, via config.admin_check)
5
+ # PATCH /bug_reports/dismiss_all - dismiss every resolved alert at once
5
6
  # POST /bug_reports/webhook - signed closure callbacks from the API
6
7
  BugReportsClient::Engine.routes.draw do
7
8
  resources :bug_reports, path: "", only: %i[index new create edit update] do
8
9
  collection do
9
10
  get :all
11
+ # Dismiss every resolved alert at once (the collapsed multi-report banner)
12
+ patch :dismiss_all
10
13
  end
11
14
  end
12
15
 
@@ -44,6 +44,10 @@ module BugReportsClient
44
44
  # limits how often one fingerprint is posted from this app.
45
45
  attr_accessor :error_reporting_enabled, :error_ignore, :error_throttle_period
46
46
 
47
+ # Rails.error `source:` values never reported. Defaults to `bin/rails runner`
48
+ # script errors, which the operator sees in the terminal and which lack an app frame.
49
+ attr_accessor :ignored_error_sources
50
+
47
51
  # Optional overrides for the form definition and GitHub issue template.
48
52
  # When nil, the engine looks for config/bug_report_form.yml and
49
53
  # config/bug_report_issue.md in the host app, then falls back to its own
@@ -82,6 +86,7 @@ module BugReportsClient
82
86
  @error_reporting_enabled = false
83
87
  @error_ignore = []
84
88
  @error_throttle_period = 300
89
+ @ignored_error_sources = [ "application.runner.railties" ]
85
90
  end
86
91
 
87
92
  # The URL the API calls back when a report's GitHub issue is closed.
@@ -7,6 +7,8 @@ module BugReportsClient
7
7
  #
8
8
  # - Only unhandled errors are captured, and only ones Rails would answer
9
9
  # with a 5xx (RecordNotFound and friends map to 4xx and are skipped).
10
+ # - Errors from sources in config.ignored_error_sources are skipped; by
11
+ # default that is `bin/rails runner` scripts.
10
12
  # - Errors are fingerprinted by exception class + the top application
11
13
  # backtrace frame (line numbers stripped, so deploys that shift code
12
14
  # around keep the same fingerprint).
@@ -23,6 +25,7 @@ module BugReportsClient
23
25
  def report(error, handled:, severity: nil, context: {}, source: nil)
24
26
  return if handled
25
27
  return unless BugReportsClient.config.error_reporting_enabled
28
+ return if BugReportsClient.config.ignored_error_sources.include?(source)
26
29
  return if ignored?(error)
27
30
 
28
31
  fingerprint = self.class.fingerprint_for(error)
@@ -1,3 +1,3 @@
1
1
  module BugReportsClient
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.3"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bug_reports_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - PSA Squash Tour
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-07-24 00:00:00.000000000 Z
11
+ date: 2026-10-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails