Skip to content

Commit 69a3558

Browse files
Jez-Aclaude
andcommitted
refactor: Expand handle_error opts to explicit positional arguments
Replaces the trailing keyword opts with 5 named positional args with defaults: stacktrace, user_context, additional_context, fingerprint, custom_description. Bumps FunctionArity max_arity to 9 in .credo.exs to accommodate the intentionally explicit public API. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 3615fd1 commit 69a3558

3 files changed

Lines changed: 81 additions & 38 deletions

File tree

.credo.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@
117117
{Credo.Check.Refactor.Apply, []},
118118
{Credo.Check.Refactor.CondStatements, []},
119119
{Credo.Check.Refactor.CyclomaticComplexity, []},
120-
{Credo.Check.Refactor.FunctionArity, []},
120+
{Credo.Check.Refactor.FunctionArity, [max_arity: 9]},
121121
{Credo.Check.Refactor.LongQuoteBlocks, []},
122122
{Credo.Check.Refactor.MatchInCondition, []},
123123
{Credo.Check.Refactor.MapJoin, []},

lib/zexbox/auto_escalation.ex

Lines changed: 59 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ defmodule Zexbox.AutoEscalation do
2222
"checkout",
2323
"High",
2424
"Purchase Ops",
25-
stacktrace: __STACKTRACE__,
26-
user_context: %{email: user.email},
27-
additional_context: %{basket_id: basket.id}
25+
__STACKTRACE__,
26+
%{email: user.email},
27+
%{basket_id: basket.id}
2828
)
2929
end
3030
```
@@ -54,9 +54,9 @@ defmodule Zexbox.AutoEscalation do
5454
```
5555
"""
5656

57-
require Logger
57+
alias Zexbox.{AutoEscalation.AdfBuilder, JiraClient}
5858

59-
alias Zexbox.{JiraClient, AutoEscalation.AdfBuilder}
59+
require Logger
6060

6161
defmodule Error do
6262
@moduledoc "Raised when Jira ticket creation or transition fails."
@@ -80,18 +80,47 @@ defmodule Zexbox.AutoEscalation do
8080
- `priority` – Jira priority name (e.g. `"High"`).
8181
- `zigl_team` – value for the ZIGL Team custom field.
8282
83-
Optional options:
84-
- `:stacktrace` – pass `__STACKTRACE__` from the rescue block for a full trace.
85-
- `:user_context` – map rendered as a bullet list in the ticket body.
86-
- `:additional_context` – map of extra key/value pairs in the ticket body.
87-
- `:fingerprint` – override deduplication key; defaults to `"action::ErrorClass"`.
88-
- `:custom_description` – string rendered above Error Details (split on `\\n\\n`).
83+
Optional arguments (all default to `nil` or empty):
84+
- `stacktrace` – pass `__STACKTRACE__` from the rescue block for a full trace.
85+
- `user_context` – map rendered as a bullet list in the ticket body.
86+
- `additional_context` – map of extra key/value pairs in the ticket body.
87+
- `fingerprint` – override deduplication key; auto-generated as `"action::ErrorClass"` when `nil`.
88+
- `custom_description` – string rendered above Error Details (split on `\\n\\n`).
8989
"""
90-
@spec handle_error(Exception.t(), String.t(), String.t(), String.t(), keyword()) ::
91-
{:ok, map()} | {:error, term()} | {:disabled, nil}
92-
def handle_error(error, action, priority, zigl_team, opts \\ []) do
90+
@spec handle_error(
91+
Exception.t(),
92+
String.t(),
93+
String.t(),
94+
String.t(),
95+
Exception.stacktrace() | nil,
96+
map(),
97+
map(),
98+
String.t() | nil,
99+
String.t() | nil
100+
) :: {:ok, map()} | {:error, term()} | {:disabled, nil}
101+
def handle_error(
102+
error,
103+
action,
104+
priority,
105+
zigl_team,
106+
stacktrace \\ nil,
107+
user_context \\ %{},
108+
additional_context \\ %{},
109+
fingerprint \\ nil,
110+
custom_description \\ nil
111+
) do
93112
if auto_escalation_enabled?() do
94-
do_handle_error(error, action, priority, zigl_team, opts)
113+
do_handle_error(
114+
error,
115+
action,
116+
priority,
117+
zigl_team,
118+
stacktrace,
119+
user_context,
120+
additional_context,
121+
fingerprint,
122+
custom_description
123+
)
95124
else
96125
{:disabled, nil}
97126
end
@@ -110,21 +139,23 @@ defmodule Zexbox.AutoEscalation do
110139

111140
# --- Private ---
112141

113-
defp do_handle_error(error, action, priority, zigl_team, opts) do
142+
defp do_handle_error(
143+
error,
144+
action,
145+
priority,
146+
zigl_team,
147+
stacktrace,
148+
user_context,
149+
additional_context,
150+
fingerprint_override,
151+
custom_description
152+
) do
114153
unless is_exception(error) do
115154
raise ArgumentError, "Expected an Exception.t() for :error, got: #{inspect(error)}"
116155
end
117156

118-
user_context = Keyword.get(opts, :user_context, %{})
119-
additional_context = Keyword.get(opts, :additional_context, %{})
120-
stacktrace = Keyword.get(opts, :stacktrace)
121-
custom_description = Keyword.get(opts, :custom_description)
122-
123157
error_class = inspect(error.__struct__)
124-
125-
fingerprint =
126-
Keyword.get(opts, :fingerprint) ||
127-
generate_fingerprint(error_class, action)
158+
fingerprint = fingerprint_override || generate_fingerprint(error_class, action)
128159

129160
case find_existing_ticket(fingerprint) do
130161
nil ->
@@ -166,7 +197,7 @@ defmodule Zexbox.AutoEscalation do
166197
{:ok, []} ->
167198
nil
168199

169-
{:ok, [first | _]} ->
200+
{:ok, [first | _rest]} ->
170201
first
171202

172203
{:error, e} ->
@@ -215,7 +246,7 @@ defmodule Zexbox.AutoEscalation do
215246
priority,
216247
custom_fields
217248
),
218-
{:ok, _} <- JiraClient.transition_issue(result["key"], @transition_to) do
249+
{:ok, _resp} <- JiraClient.transition_issue(result["key"], @transition_to) do
219250
{:ok, result}
220251
else
221252
{:error, e} ->
@@ -249,7 +280,7 @@ defmodule Zexbox.AutoEscalation do
249280
)
250281

251282
case JiraClient.add_comment(issue_key, comment) do
252-
{:ok, _} ->
283+
{:ok, _resp} ->
253284
:ok
254285

255286
{:error, e} ->

test/zexbox/auto_escalation_test.exs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ defmodule Zexbox.AutoEscalationTest do
122122
end
123123
end
124124

125-
describe "handle_error/5 — when disabled" do
125+
describe "handle_error/9 — when disabled" do
126126
test "returns {:disabled, nil} without calling Jira" do
127127
Application.put_env(:zexbox, :auto_escalation_enabled, false)
128128

@@ -136,7 +136,7 @@ defmodule Zexbox.AutoEscalationTest do
136136
end
137137
end
138138

139-
describe "handle_error/5 — new ticket path" do
139+
describe "handle_error/9 — new ticket path" do
140140
test "returns {:ok, ticket} and calls create_issue" do
141141
with_mocks(all_mocks()) do
142142
assert {:ok, ticket} =
@@ -217,8 +217,15 @@ defmodule Zexbox.AutoEscalationTest do
217217

218218
test "uses custom fingerprint override when provided" do
219219
with_mocks(all_mocks(capture_create_issue())) do
220-
AutoEscalation.handle_error(error(), "checkout", "High", "Ops",
221-
fingerprint: "custom::fingerprint"
220+
AutoEscalation.handle_error(
221+
error(),
222+
"checkout",
223+
"High",
224+
"Ops",
225+
nil,
226+
%{},
227+
%{},
228+
"custom::fingerprint"
222229
)
223230

224231
assert_received {:create_opts, opts}
@@ -228,9 +235,14 @@ defmodule Zexbox.AutoEscalationTest do
228235

229236
test "description is a valid ADF doc map" do
230237
with_mocks(all_mocks(capture_create_issue())) do
231-
AutoEscalation.handle_error(error(), "pay", "Medium", "Payments",
232-
user_context: %{email: "u@example.com"},
233-
additional_context: %{basket_id: 123}
238+
AutoEscalation.handle_error(
239+
error(),
240+
"pay",
241+
"Medium",
242+
"Payments",
243+
nil,
244+
%{email: "u@example.com"},
245+
%{basket_id: 123}
234246
)
235247

236248
assert_received {:create_opts, opts}
@@ -272,7 +284,7 @@ defmodule Zexbox.AutoEscalationTest do
272284
end
273285
end
274286

275-
describe "handle_error/5 — existing ticket path" do
287+
describe "handle_error/9 — existing ticket path" do
276288
test "returns the existing ticket and adds a comment" do
277289
jira_overrides = [
278290
search_latest_issues: fn _jql, _project_key -> {:ok, [@existing_ticket]} end
@@ -322,7 +334,7 @@ defmodule Zexbox.AutoEscalationTest do
322334
end
323335
end
324336

325-
describe "handle_error/5 — search failure" do
337+
describe "handle_error/9 — search failure" do
326338
test "logs and falls through to create a new ticket when search fails" do
327339
jira_overrides = [
328340
search_latest_issues: fn _jql, _project_key -> {:error, "Search failed"} end

0 commit comments

Comments
 (0)