Skip to content

Commit 80b944d

Browse files
committed
style: add .formatter.exs and mix-format the tree
CI's 'Check formatting' step runs mix format --check-formatted, which errors when no .formatter.exs exists — the file had never been created, so the gate could never genuinely pass on a run that reached it. Adds the standard formatter config and applies mix format (semantics-preserving reflow only; mix test 272/272 green before and after). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017LDhR8gtnittEWSafunnrq
1 parent 2466b0a commit 80b944d

38 files changed

Lines changed: 833 additions & 417 deletions

elixir-mcp/.formatter.exs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# SPDX-License-Identifier: MPL-2.0
2+
[
3+
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
4+
]

elixir-mcp/lib/feedback_a_tron/application.ex

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,9 @@ defmodule FeedbackATron.Application do
9494

9595
env_on? =
9696
case env_enabled? do
97-
nil -> false
97+
nil ->
98+
false
99+
98100
value ->
99101
normalized =
100102
value
@@ -147,7 +149,9 @@ defmodule FeedbackATron.Application do
147149

148150
env_on? =
149151
case env_val do
150-
nil -> false
152+
nil ->
153+
false
154+
151155
value ->
152156
normalized = value |> String.trim() |> String.downcase()
153157
Enum.member?(["1", "true", "yes", "on"], normalized)

elixir-mcp/lib/feedback_a_tron/audit_log.ex

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ defmodule FeedbackATron.AuditLog do
2121
require Logger
2222

2323
@log_file "feedback_a_tron_audit.jsonl"
24-
@max_log_size 10_000_000 # 10MB before rotation
24+
# 10MB before rotation
25+
@max_log_size 10_000_000
2526

2627
defstruct [
2728
:log_file,
@@ -64,11 +65,12 @@ defmodule FeedbackATron.AuditLog do
6465
Log a submission attempt.
6566
"""
6667
def log_submission(platform, issue, status, details \\ %{}) do
67-
event_type = case status do
68-
:success -> :submission_success
69-
:failure -> :submission_failure
70-
_ -> :submission_attempt
71-
end
68+
event_type =
69+
case status do
70+
:success -> :submission_success
71+
:failure -> :submission_failure
72+
_ -> :submission_attempt
73+
end
7274

7375
log(event_type, %{
7476
platform: platform,
@@ -95,11 +97,12 @@ defmodule FeedbackATron.AuditLog do
9597
Log deduplication check.
9698
"""
9799
def log_dedup(issue_hash, result, details \\ %{}) do
98-
event_type = case result do
99-
:duplicate -> :dedup_match
100-
:similar -> :dedup_match
101-
_ -> :dedup_check
102-
end
100+
event_type =
101+
case result do
102+
:duplicate -> :dedup_match
103+
:similar -> :dedup_match
104+
_ -> :dedup_check
105+
end
103106

104107
log(event_type, %{
105108
hash: issue_hash,
@@ -186,6 +189,7 @@ defmodule FeedbackATron.AuditLog do
186189
log_file: state.log_file,
187190
uptime_seconds: DateTime.diff(DateTime.utc_now(), state.started_at)
188191
}
192+
189193
{:reply, stats, state}
190194
end
191195

@@ -201,6 +205,7 @@ defmodule FeedbackATron.AuditLog do
201205
session_id: state.session_id,
202206
entry_count: state.entry_count
203207
})
208+
204209
File.close(state.log_handle)
205210
:ok
206211
end
@@ -230,6 +235,7 @@ defmodule FeedbackATron.AuditLog do
230235
case File.stat(state.log_file) do
231236
{:ok, %{size: size}} when size > @max_log_size ->
232237
rotate_log(state)
238+
233239
_ ->
234240
state
235241
end
@@ -266,13 +272,14 @@ defmodule FeedbackATron.AuditLog do
266272

267273
defp sanitize(data) when is_map(data) do
268274
# Remove sensitive fields
269-
sensitive_keys = ~w(password token secret key api_key access_token)a ++
270-
~w(password token secret key api_key access_token)
275+
sensitive_keys =
276+
~w(password token secret key api_key access_token)a ++
277+
~w(password token secret key api_key access_token)
271278

272279
data
273280
|> Enum.reject(fn {k, _v} ->
274281
key_str = to_string(k) |> String.downcase()
275-
Enum.any?(sensitive_keys, &(String.contains?(key_str, to_string(&1))))
282+
Enum.any?(sensitive_keys, &String.contains?(key_str, to_string(&1)))
276283
end)
277284
|> Enum.into(%{})
278285
end

elixir-mcp/lib/feedback_a_tron/channels/bitbucket.ex

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,31 @@ defmodule FeedbackATron.Channels.Bitbucket do
4040
{:ok, %{platform: :bitbucket, url: resp["links"]["html"]["href"]}}
4141

4242
{:ok, %{status: 401, body: _error}} ->
43-
{:error, %FeedbackATron.Error.AuthenticationError{platform: :bitbucket, reason: "token rejected"}}
43+
{:error,
44+
%FeedbackATron.Error.AuthenticationError{platform: :bitbucket, reason: "token rejected"}}
4445

4546
{:ok, %{status: 429, body: _error}} ->
46-
{:error, %FeedbackATron.Error.RateLimitError{platform: :bitbucket, resets_at: nil, remaining: 0}}
47+
{:error,
48+
%FeedbackATron.Error.RateLimitError{platform: :bitbucket, resets_at: nil, remaining: 0}}
4749

4850
{:ok, %{status: status, body: error}} when status >= 400 and status < 500 ->
4951
{:error, %FeedbackATron.Error.ValidationError{field: "issue", reason: inspect(error)}}
5052

5153
{:ok, %{status: status, body: error}} ->
52-
{:error, %FeedbackATron.Error.PlatformError{platform: :bitbucket, status: status, body: inspect(error)}}
54+
{:error,
55+
%FeedbackATron.Error.PlatformError{
56+
platform: :bitbucket,
57+
status: status,
58+
body: inspect(error)
59+
}}
5360

5461
{:error, reason} ->
55-
{:error, %FeedbackATron.Error.NetworkError{platform: :bitbucket, reason: inspect(reason), url: url}}
62+
{:error,
63+
%FeedbackATron.Error.NetworkError{
64+
platform: :bitbucket,
65+
reason: inspect(reason),
66+
url: url
67+
}}
5668
end
5769
end
5870
end

elixir-mcp/lib/feedback_a_tron/channels/bugzilla.ex

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,22 +48,32 @@ defmodule FeedbackATron.Channels.Bugzilla do
4848
case Req.post(url, json: body, headers: headers) do
4949
{:ok, %{status: 200, body: resp}} when is_map(resp) ->
5050
bug_id = resp["id"]
51-
{:ok, %{platform: :bugzilla, url: "#{base_url}/show_bug.cgi?id=#{bug_id}", bug_id: bug_id}}
51+
52+
{:ok,
53+
%{platform: :bugzilla, url: "#{base_url}/show_bug.cgi?id=#{bug_id}", bug_id: bug_id}}
5254

5355
{:ok, %{status: 401, body: _error}} ->
54-
{:error, %FeedbackATron.Error.AuthenticationError{platform: :bugzilla, reason: "API key rejected"}}
56+
{:error,
57+
%FeedbackATron.Error.AuthenticationError{platform: :bugzilla, reason: "API key rejected"}}
5558

5659
{:ok, %{status: 429, body: _error}} ->
57-
{:error, %FeedbackATron.Error.RateLimitError{platform: :bugzilla, resets_at: nil, remaining: 0}}
60+
{:error,
61+
%FeedbackATron.Error.RateLimitError{platform: :bugzilla, resets_at: nil, remaining: 0}}
5862

5963
{:ok, %{status: status, body: error}} when status >= 400 and status < 500 ->
6064
{:error, %FeedbackATron.Error.ValidationError{field: "bug", reason: inspect(error)}}
6165

6266
{:ok, %{status: status, body: error}} ->
63-
{:error, %FeedbackATron.Error.PlatformError{platform: :bugzilla, status: status, body: inspect(error)}}
67+
{:error,
68+
%FeedbackATron.Error.PlatformError{
69+
platform: :bugzilla,
70+
status: status,
71+
body: inspect(error)
72+
}}
6473

6574
{:error, reason} ->
66-
{:error, %FeedbackATron.Error.NetworkError{platform: :bugzilla, reason: inspect(reason), url: url}}
75+
{:error,
76+
%FeedbackATron.Error.NetworkError{platform: :bugzilla, reason: inspect(reason), url: url}}
6777
end
6878
end
6979
end

elixir-mcp/lib/feedback_a_tron/channels/codeberg.ex

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,27 @@ defmodule FeedbackATron.Channels.Codeberg do
3434
{:ok, %{platform: :codeberg, url: resp["html_url"]}}
3535

3636
{:ok, %{status: 401, body: _error}} ->
37-
{:error, %FeedbackATron.Error.AuthenticationError{platform: :codeberg, reason: "token rejected"}}
37+
{:error,
38+
%FeedbackATron.Error.AuthenticationError{platform: :codeberg, reason: "token rejected"}}
3839

3940
{:ok, %{status: 429, body: _error}} ->
40-
{:error, %FeedbackATron.Error.RateLimitError{platform: :codeberg, resets_at: nil, remaining: 0}}
41+
{:error,
42+
%FeedbackATron.Error.RateLimitError{platform: :codeberg, resets_at: nil, remaining: 0}}
4143

4244
{:ok, %{status: status, body: error}} when status >= 400 and status < 500 ->
4345
{:error, %FeedbackATron.Error.ValidationError{field: "issue", reason: inspect(error)}}
4446

4547
{:ok, %{status: status, body: error}} ->
46-
{:error, %FeedbackATron.Error.PlatformError{platform: :codeberg, status: status, body: inspect(error)}}
48+
{:error,
49+
%FeedbackATron.Error.PlatformError{
50+
platform: :codeberg,
51+
status: status,
52+
body: inspect(error)
53+
}}
4754

4855
{:error, reason} ->
49-
{:error, %FeedbackATron.Error.NetworkError{platform: :codeberg, reason: inspect(reason), url: url}}
56+
{:error,
57+
%FeedbackATron.Error.NetworkError{platform: :codeberg, reason: inspect(reason), url: url}}
5058
end
5159
end
5260
end

elixir-mcp/lib/feedback_a_tron/channels/discord.ex

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,10 @@ defmodule FeedbackATron.Channels.Discord do
5353
cond do
5454
not String.starts_with?(cred[:token] || "", "Bot ") ->
5555
{:error, "Discord bot token must start with 'Bot '"}
56+
5657
is_nil(cred[:channel_id]) ->
5758
{:error, "Discord channel_id required for bot mode"}
59+
5860
true ->
5961
:ok
6062
end
@@ -93,7 +95,12 @@ defmodule FeedbackATron.Channels.Discord do
9395
message_id = resp["id"]
9496
guild_id = resp["guild_id"] || "unknown"
9597
msg_channel_id = resp["channel_id"] || channel_id
96-
{:ok, %{platform: :discord, url: "https://discord.com/channels/#{guild_id}/#{msg_channel_id}/#{message_id}"}}
98+
99+
{:ok,
100+
%{
101+
platform: :discord,
102+
url: "https://discord.com/channels/#{guild_id}/#{msg_channel_id}/#{message_id}"
103+
}}
97104

98105
{:ok, %{status: status, body: resp}} ->
99106
error_msg = extract_error(resp)

elixir-mcp/lib/feedback_a_tron/channels/discourse.ex

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,20 @@ defmodule FeedbackATron.Channels.Discourse do
2424
@impl true
2525
def validate_creds(cred) do
2626
cond do
27-
is_nil(cred[:base_url]) -> {:error, "Discourse base URL required (e.g. https://forum.example.com)"}
28-
not String.starts_with?(cred[:base_url] || "", "https://") -> {:error, "Discourse URL must be HTTPS"}
29-
is_nil(cred[:api_key]) -> {:error, "Discourse API key required"}
30-
is_nil(cred[:api_username]) -> {:error, "Discourse API username required"}
31-
true -> :ok
27+
is_nil(cred[:base_url]) ->
28+
{:error, "Discourse base URL required (e.g. https://forum.example.com)"}
29+
30+
not String.starts_with?(cred[:base_url] || "", "https://") ->
31+
{:error, "Discourse URL must be HTTPS"}
32+
33+
is_nil(cred[:api_key]) ->
34+
{:error, "Discourse API key required"}
35+
36+
is_nil(cred[:api_username]) ->
37+
{:error, "Discourse API username required"}
38+
39+
true ->
40+
:ok
3241
end
3342
end
3443

elixir-mcp/lib/feedback_a_tron/channels/email.ex

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ defmodule FeedbackATron.Channels.Email do
3535
# Email submission delegates to Mailman's SMTPS transport.
3636
# Standalone email will be implemented when gen_smtp or swoosh is added.
3737
Logger.warning("Email channel: use Mailman channel for SMTPS email submission")
38-
{:error, %{platform: :email, error: :not_implemented, reason: "Use Mailman channel for SMTPS"}}
38+
39+
{:error,
40+
%{platform: :email, error: :not_implemented, reason: "Use Mailman channel for SMTPS"}}
3941
end
4042
end

elixir-mcp/lib/feedback_a_tron/channels/github.ex

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,11 @@ defmodule FeedbackATron.Channels.GitHub do
5050
%FeedbackATron.Error.ValidationError{field: "issue", reason: String.trim(output)}
5151

5252
true ->
53-
%FeedbackATron.Error.PlatformError{platform: platform, status: nil, body: String.trim(output)}
53+
%FeedbackATron.Error.PlatformError{
54+
platform: platform,
55+
status: nil,
56+
body: String.trim(output)
57+
}
5458
end
5559
end
5660
end

0 commit comments

Comments
 (0)