Skip to content

Commit 99eb9af

Browse files
authored
Merge pull request #1402 from k1LoW/structured-error-output
feat: structure error field in JSON output for programmatic error analysis
2 parents 44408dd + c77811b commit 99eb9af

File tree

7 files changed

+78
-8
lines changed

7 files changed

+78
-8
lines changed

result.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,17 @@ type stepResultSimplified struct {
8686
RunnerType RunnerType `json:"runner_type,omitempty"`
8787
RunnerKey string `json:"runner_key,omitempty"`
8888
Result result `json:"result"`
89-
Error string `json:"error,omitempty"`
89+
Error *stepErrorSimplified `json:"error,omitempty"`
9090
IncludedRunResults []*runResultSimplified `json:"included_run_result,omitempty"`
9191
Elapsed time.Duration `json:"elapsed,omitempty"`
9292
}
9393

94+
type stepErrorSimplified struct {
95+
Message string `json:"message"`
96+
Condition string `json:"condition,omitempty"`
97+
ExprTrace string `json:"expr_trace,omitempty"`
98+
}
99+
94100
func newRunResult(desc string, labels []string, path string, included bool, store *store.Store) *RunResult {
95101
return &RunResult{
96102
Desc: desc,
@@ -315,7 +321,15 @@ func simplifyStepResults(stepResults []*StepResult) []*stepResultSimplified {
315321
Elapsed: sr.Elapsed,
316322
}
317323
if sr.Err != nil {
318-
s.Error = sr.Err.Error()
324+
se := &stepErrorSimplified{
325+
Message: sr.Err.Error(),
326+
}
327+
var cfe *condFalseError
328+
if errors.As(sr.Err, &cfe) {
329+
se.Condition = cfe.cond
330+
se.ExprTrace = cfe.tree
331+
}
332+
s.Error = se
319333
}
320334
simplified = append(simplified, s)
321335
}

result_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,21 @@ func TestResultOutJSON(t *testing.T) {
207207
}}}},
208208
},
209209
})},
210+
{newRunNResult(t, 1, []*RunResult{
211+
{
212+
ID: "ab13ba1e546838ceafa17f91ab3220102f397b2e",
213+
Desc: "cond false runbook",
214+
Path: "testdata/book/runn_cond_false.yml",
215+
Err: newCondFalseError("current.res.status == 200", "current.res.status == 200\n=> 404 == 200\n=> false"),
216+
StepResults: []*StepResult{{
217+
ID: "ab13ba1e546838ceafa17f91ab3220102f397b2e?step=0",
218+
Key: "0",
219+
RunnerType: RunnerTypeTest,
220+
RunnerKey: "test",
221+
Err: newCondFalseError("current.res.status == 200", "current.res.status == 200\n=> 404 == 200\n=> false"),
222+
}},
223+
},
224+
})},
210225
}
211226
for i, tt := range tests {
212227
key := fmt.Sprintf("result_out_json_%d", i)

testdata/result_out_json_0.golden

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@
3434
"runner_type": "http",
3535
"runner_key": "req",
3636
"result": "failure",
37-
"error": "dummy"
37+
"error": {
38+
"message": "dummy"
39+
}
3840
}
3941
]
4042
},

testdata/result_out_json_1.golden

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@
3434
"runner_type": "http",
3535
"runner_key": "req",
3636
"result": "failure",
37-
"error": "dummy"
37+
"error": {
38+
"message": "dummy"
39+
}
3840
}
3941
]
4042
},
@@ -74,7 +76,9 @@
7476
"index": 0,
7577
"key": "0",
7678
"result": "failure",
77-
"error": "dummy"
79+
"error": {
80+
"message": "dummy"
81+
}
7882
}
7983
]
8084
}

testdata/result_out_json_2.golden

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@
2727
"index": 0,
2828
"key": "0",
2929
"result": "failure",
30-
"error": "dummy"
30+
"error": {
31+
"message": "dummy"
32+
}
3133
}
3234
]
3335
}

testdata/result_out_json_3.golden

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@
2727
"index": 0,
2828
"key": "0",
2929
"result": "failure",
30-
"error": "dummy",
30+
"error": {
31+
"message": "dummy"
32+
},
3133
"included_run_result": [
3234
{
3335
"id": "ab13ba1e546838ceafa17f91ab3220102f397b2e?step=0",
@@ -39,7 +41,9 @@
3941
"index": 0,
4042
"key": "0",
4143
"result": "failure",
42-
"error": "dummy"
44+
"error": {
45+
"message": "dummy"
46+
}
4347
}
4448
]
4549
}

testdata/result_out_json_4.golden

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"total": 1,
3+
"success": 0,
4+
"failure": 1,
5+
"skipped": 0,
6+
"results": [
7+
{
8+
"id": "ab13ba1e546838ceafa17f91ab3220102f397b2e",
9+
"desc": "cond false runbook",
10+
"path": "testdata/book/runn_cond_false.yml",
11+
"result": "failure",
12+
"steps": [
13+
{
14+
"id": "ab13ba1e546838ceafa17f91ab3220102f397b2e?step=0",
15+
"index": 0,
16+
"key": "0",
17+
"runner_type": "test",
18+
"runner_key": "test",
19+
"result": "failure",
20+
"error": {
21+
"message": "condition is not true\n\nCondition:\n current.res.status == 200\n =\u003e 404 == 200\n =\u003e false\n",
22+
"condition": "current.res.status == 200",
23+
"expr_trace": "current.res.status == 200\n=\u003e 404 == 200\n=\u003e false"
24+
}
25+
}
26+
]
27+
}
28+
]
29+
}

0 commit comments

Comments
 (0)