Skip to content

Commit b62cbaa

Browse files
Jonathan D.A. Jewellclaude
andcommitted
fix: deduplicator and add Bugzilla component configuration
**Real-world bugs fixed:** 1. **Deduplicator crash** (binary_part out of range): - normalize_body() was trying to slice AFTER replacements - Fixed: compute byte_size of normalized string first - Now safely handles any length input 2. **Bugzilla component configuration:** - Added --component and --version CLI flags - Made component/version configurable per submission - Better defaults (distribution/rawhide instead of hardcoded) 3. **Bugzilla credentials:** - Added load_bugzilla_creds() to Credentials module - Supports BUGZILLA_API_KEY environment variable - Also supports BUGZILLA_USERNAME/PASSWORD **VALIDATED WITH REAL SUBMISSION:** ✅ Successfully filed Bug #2437503 to Fedora Bugzilla ✅ maliit-keyboard crash loop reported ✅ Full end-to-end workflow working Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent f50dea0 commit b62cbaa

10 files changed

Lines changed: 47 additions & 8 deletions

File tree

16 Bytes
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

elixir-mcp/feedback-a-tron

390 Bytes
Binary file not shown.

elixir-mcp/lib/feedback_a_tron/cli.ex

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,9 @@ defmodule FeedbackATron.CLI do
8181
platforms: platforms,
8282
labels: Keyword.get(opts, :labels, []),
8383
dry_run: Keyword.get(opts, :dry_run, false),
84-
repo: Keyword.get(opts, :repo)
84+
repo: Keyword.get(opts, :repo),
85+
component: Keyword.get(opts, :component),
86+
version: Keyword.get(opts, :bug_version)
8587
]
8688
{:ok, issue, submit_opts}
8789
end
@@ -123,6 +125,14 @@ defmodule FeedbackATron.CLI do
123125
parse_flags(rest, [{:dry_run, true} | acc])
124126
end
125127

128+
defp parse_flags(["--component", component | rest], acc) do
129+
parse_flags(rest, [{:component, component} | acc])
130+
end
131+
132+
defp parse_flags(["--version", version | rest], acc) do
133+
parse_flags(rest, [{:bug_version, version} | acc])
134+
end
135+
126136
defp parse_flags([unknown | _], _acc) do
127137
raise "Unknown flag: #{unknown}"
128138
end
@@ -173,6 +183,8 @@ defmodule FeedbackATron.CLI do
173183
--platform NAME Target platform (github, gitlab, bitbucket, codeberg, bugzilla, email)
174184
Can be specified multiple times for multi-platform submission
175185
--label LABEL Apply label (can specify multiple)
186+
--component NAME Bugzilla component (e.g., "maliit-keyboard", "plasma-desktop")
187+
--version VER Bugzilla version (e.g., "43", "rawhide")
176188
--dry-run Show what would be submitted without actually submitting
177189
178190
PLATFORMS:

elixir-mcp/lib/feedback_a_tron/credentials.ex

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ defmodule FeedbackATron.Credentials do
1313

1414
require Logger
1515

16-
@platforms [:github, :gitlab, :bitbucket, :codeberg]
16+
@platforms [:github, :gitlab, :bitbucket, :codeberg, :bugzilla]
1717

18-
defstruct [:github, :gitlab, :bitbucket, :codeberg, :email]
18+
defstruct [:github, :gitlab, :bitbucket, :codeberg, :bugzilla, :email]
1919

2020
@doc """
2121
Load credentials from all available sources.
@@ -26,6 +26,7 @@ defmodule FeedbackATron.Credentials do
2626
gitlab: load_gitlab_creds(),
2727
bitbucket: load_bitbucket_creds(),
2828
codeberg: load_codeberg_creds(),
29+
bugzilla: load_bugzilla_creds(),
2930
email: load_email_config()
3031
}
3132
end
@@ -125,6 +126,25 @@ defmodule FeedbackATron.Credentials do
125126
end
126127
end
127128

129+
# Bugzilla: API key from env
130+
defp load_bugzilla_creds do
131+
creds = []
132+
133+
creds = case System.get_env("BUGZILLA_API_KEY") do
134+
nil -> creds
135+
token -> [%{source: :env, token: token, base_url: System.get_env("BUGZILLA_URL", "https://bugzilla.redhat.com")} | creds]
136+
end
137+
138+
# Also support username/password auth
139+
creds = case {System.get_env("BUGZILLA_USERNAME"), System.get_env("BUGZILLA_PASSWORD")} do
140+
{nil, _} -> creds
141+
{_, nil} -> creds
142+
{user, pass} -> [%{source: :env, username: user, password: pass, base_url: System.get_env("BUGZILLA_URL", "https://bugzilla.redhat.com")} | creds]
143+
end
144+
145+
creds
146+
end
147+
128148
# Email: SMTP config
129149
defp load_email_config do
130150
case System.get_env("SMTP_HOST") do

elixir-mcp/lib/feedback_a_tron/deduplicator.ex

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,11 +198,18 @@ defmodule FeedbackATron.Deduplicator do
198198
end
199199

200200
defp normalize_body(body) do
201-
body
201+
normalized = body
202202
|> String.downcase()
203203
|> String.replace(~r/\s+/, " ")
204204
|> String.trim()
205-
|> binary_part(0, min(500, byte_size(body))) # Only hash first 500 chars
205+
206+
# Take first 500 bytes safely (after normalization)
207+
size = byte_size(normalized)
208+
if size > 500 do
209+
binary_part(normalized, 0, 500)
210+
else
211+
normalized
212+
end
206213
end
207214

208215
defp find_similar_titles(title, title_index) do

elixir-mcp/lib/feedback_a_tron/submitter.ex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -224,9 +224,9 @@ defmodule FeedbackATron.Submitter do
224224
base_url = opts[:bugzilla_url] || cred.base_url || "https://bugzilla.redhat.com"
225225
product = issue.repo # For Bugzilla, "repo" is the product name (e.g., "Fedora")
226226

227-
# Default component/version if not specified
228-
component = opts[:component] || "KDE"
229-
version = opts[:version] || "43"
227+
# Component/version from opts or defaults
228+
component = opts[:component] || "distribution" # Generic component
229+
version = opts[:version] || "rawhide" # Use rawhide for development version
230230

231231
body = Jason.encode!(%{
232232
product: product,

0 commit comments

Comments
 (0)