From 1cd7a8859734d58ca76e88066cd64e2fcfd224ed Mon Sep 17 00:00:00 2001 From: raistlin042 Date: Fri, 12 Jun 2026 16:58:47 +0800 Subject: [PATCH] fix: read release error_logs from data.error_logs in apps +release-get (#1436) --- shortcuts/apps/apps_release_get.go | 3 + shortcuts/apps/apps_release_get_test.go | 83 ++++++++++++++++++++++--- 2 files changed, 78 insertions(+), 8 deletions(-) diff --git a/shortcuts/apps/apps_release_get.go b/shortcuts/apps/apps_release_get.go index 3ed84053..db7d0aa2 100644 --- a/shortcuts/apps/apps_release_get.go +++ b/shortcuts/apps/apps_release_get.go @@ -57,6 +57,9 @@ var AppsReleaseGet = common.Shortcut{ out := data if release, ok := data["release"].(map[string]interface{}); ok { out = release + if el, ok := data["error_logs"]; ok { + out["error_logs"] = el + } } rctx.OutFormat(out, nil, func(w io.Writer) { fmt.Fprintf(w, "release_id: %v\nstatus: %v\ncreated_at: %v\nupdated_at: %v\n", diff --git a/shortcuts/apps/apps_release_get_test.go b/shortcuts/apps/apps_release_get_test.go index 0d7d2d0f..9cd46cb3 100644 --- a/shortcuts/apps/apps_release_get_test.go +++ b/shortcuts/apps/apps_release_get_test.go @@ -134,13 +134,15 @@ func TestAppsReleaseGetPrettyFailedErrorLogs(t *testing.T) { URL: "/open-apis/spark/v1/apps/app_x/releases/6", Body: map[string]interface{}{ "code": 0, "msg": "", - "data": map[string]interface{}{"release": map[string]interface{}{ - "release_id": "6", "status": "failed", - "created_at": "1700000000000", "updated_at": "1700000000050", + "data": map[string]interface{}{ + "release": map[string]interface{}{ + "release_id": "6", "status": "failed", + "created_at": "1700000000000", "updated_at": "1700000000050", + }, "error_logs": []interface{}{ map[string]interface{}{"step": "build", "error_log": "compile error"}, }, - }}, + }, }, }) if err := AppsReleaseGet.Execute(context.Background(), rctx); err != nil { @@ -200,11 +202,13 @@ func TestAppsReleaseGetPrettyFailedEmptyLogs(t *testing.T) { reg.Register(&httpmock.Stub{ Method: "GET", URL: "/open-apis/spark/v1/apps/app_x/releases/9", Body: map[string]interface{}{"code": 0, "msg": "", - "data": map[string]interface{}{"release": map[string]interface{}{ - "release_id": "9", "status": "failed", - "created_at": "1700000000000", "updated_at": "1700000000050", + "data": map[string]interface{}{ + "release": map[string]interface{}{ + "release_id": "9", "status": "failed", + "created_at": "1700000000000", "updated_at": "1700000000050", + }, "error_logs": []interface{}{}, - }}}, + }}, }) if err := AppsReleaseGet.Execute(context.Background(), rctx); err != nil { t.Fatalf("Execute() = %v", err) @@ -214,6 +218,69 @@ func TestAppsReleaseGetPrettyFailedEmptyLogs(t *testing.T) { } } +func TestAppsReleaseGetJSONErrorLogsPassthrough(t *testing.T) { + rctx, stdoutBuf, reg := newStatusRuntimeContext(t, "app_x", "6") + reg.Register(&httpmock.Stub{ + Method: "GET", URL: "/open-apis/spark/v1/apps/app_x/releases/6", + Body: map[string]interface{}{"code": 0, "msg": "", + "data": map[string]interface{}{ + "release": map[string]interface{}{ + "release_id": "6", "status": "failed", + "created_at": "1700000000000", "updated_at": "1700000000050", + }, + "error_logs": []interface{}{ + map[string]interface{}{"step": "build", "error_log": "compile error"}, + }, + }}, + }) + if err := AppsReleaseGet.Execute(context.Background(), rctx); err != nil { + t.Fatalf("Execute() = %v", err) + } + var env struct { + OK bool `json:"ok"` + Data map[string]interface{} `json:"data"` + } + if err := json.Unmarshal(stdoutBuf.Bytes(), &env); err != nil { + t.Fatalf("unmarshal: %v\nraw: %s", err, stdoutBuf.String()) + } + logs, ok := env.Data["error_logs"].([]interface{}) + if !ok || len(logs) != 1 { + t.Fatalf("JSON must passthrough data.error_logs, got: %v", env.Data["error_logs"]) + } + first, _ := logs[0].(map[string]interface{}) + if first["step"] != "build" || first["error_log"] != "compile error" { + t.Errorf("error_logs content mismatch: %v", logs[0]) + } + // flattened release fields must still be present alongside error_logs + if env.Data["release_id"] != "6" || env.Data["status"] != "failed" { + t.Errorf("flattened release fields missing: %v", env.Data) + } +} + +func TestAppsReleaseGetJSONNoErrorLogsKeyWhenAbsent(t *testing.T) { + rctx, stdoutBuf, reg := newStatusRuntimeContext(t, "app_x", "5") + reg.Register(&httpmock.Stub{ + Method: "GET", URL: "/open-apis/spark/v1/apps/app_x/releases/5", + Body: map[string]interface{}{"code": 0, "msg": "", + "data": map[string]interface{}{"release": map[string]interface{}{ + "release_id": "5", "status": "finished", + "created_at": "1700000000000", "updated_at": "1700000000001", + }}}, + }) + if err := AppsReleaseGet.Execute(context.Background(), rctx); err != nil { + t.Fatalf("Execute() = %v", err) + } + var env struct { + Data map[string]interface{} `json:"data"` + } + if err := json.Unmarshal(stdoutBuf.Bytes(), &env); err != nil { + t.Fatalf("unmarshal: %v\nraw: %s", err, stdoutBuf.String()) + } + if _, present := env.Data["error_logs"]; present { + t.Errorf("error_logs key must be absent when API omits it, got: %v", env.Data) + } +} + func TestAppsReleaseGetPrettyCommitID(t *testing.T) { rctx, stdoutBuf, reg := newStatusRuntimeContext(t, "app_x", "10") rctx.Format = "pretty"