Skip to content

Commit d779ae4

Browse files
committed
[CRCR] Add failed-tests-detail input to callback action and ingest path
Add support for per-test failure details in the CRCR pipeline. The callback action now accepts a `failed-tests-detail` JSON array input containing test name, classname, message, and duration for each failed test. The ingest path (crcrUtils.ts) extracts and persists it as `failed_tests_json` in DynamoDB/ClickHouse. Size caps applied at both layers: max 50 entries, message truncated to 500 chars. This prevents unbounded growth in DynamoDB items while giving backend maintainers enough detail to identify which tests broke. Addresses #8545 (ingest path portion).
1 parent 61a7757 commit d779ae4

3 files changed

Lines changed: 40 additions & 0 deletions

File tree

.github/actions/cross-repo-ci-relay-callback/action.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,14 @@ inputs:
4747
Full test results should be uploaded as artifacts and referenced via `artifact-url`.
4848
required: false
4949
default: ''
50+
failed-tests-detail:
51+
description: >
52+
Optional JSON array of failed/errored test details. Each element should
53+
have at minimum a "name" field. Supported fields: name, classname,
54+
message, duration. Capped at 50 entries; message truncated to 500 chars.
55+
Example: [{"name":"test_foo","classname":"TestBar","message":"AssertionError"}]
56+
required: false
57+
default: ''
5058
callback-url:
5159
description: >
5260
Base URL of the result callback server.
@@ -96,6 +104,7 @@ runs:
96104
WORKFLOW_NAME: ${{ github.workflow }}
97105
WORKFLOW_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
98106
TEST_RESULTS: ${{ inputs.test-results }}
107+
FAILED_TESTS_DETAIL: ${{ inputs.failed-tests-detail }}
99108
CLIENT_PAYLOAD: ${{ toJson(github.event.client_payload) }}
100109
OIDC_TOKEN: ${{ steps.oidc.outputs.token }}
101110
CALLBACK_URL: ${{ inputs.callback-url }}

.github/actions/cross-repo-ci-relay-callback/report_callback.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,16 @@ def build_payload() -> str:
112112
except json.JSONDecodeError as exc:
113113
sys.exit(f"Error: TEST_RESULTS is not valid JSON: {exc}")
114114

115+
failed_tests_detail = os.environ.get("FAILED_TESTS_DETAIL", "").strip()
116+
if failed_tests_detail:
117+
try:
118+
parsed = json.loads(failed_tests_detail)
119+
if not isinstance(parsed, list):
120+
sys.exit("Error: FAILED_TESTS_DETAIL must be a JSON array")
121+
workflow["failed_tests_detail"] = parsed[:50]
122+
except json.JSONDecodeError as exc:
123+
sys.exit(f"Error: FAILED_TESTS_DETAIL is not valid JSON: {exc}")
124+
115125
artifact_url = os.environ.get("ARTIFACT_URL", "").strip()
116126
if artifact_url:
117127
workflow["artifact_url"] = artifact_url

torchci/lib/crcr/crcrUtils.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ export interface RelayWorkflow {
3232
skipped?: number;
3333
total?: number;
3434
};
35+
failed_tests_detail?: Array<{
36+
name: string;
37+
classname?: string;
38+
message?: string;
39+
duration?: number;
40+
}>;
3541
artifact_url?: string;
3642
}
3743

@@ -81,6 +87,7 @@ export interface CrcrWorkflowJobRecord {
8187
downstream_repo_level?: string;
8288
event_type?: string;
8389
artifact_url?: string;
90+
failed_tests_json?: string;
8491
environment?: string;
8592
}
8693

@@ -175,6 +182,20 @@ export function extractDynamoRecord(
175182
? tr.total
176183
: (tr.passed ?? 0) + (tr.failed ?? 0) + (tr.skipped ?? 0);
177184
}
185+
186+
if (wf.failed_tests_detail && Array.isArray(wf.failed_tests_detail)) {
187+
const MAX_ENTRIES = 50;
188+
const MAX_MESSAGE_LEN = 500;
189+
const capped = wf.failed_tests_detail.slice(0, MAX_ENTRIES).map((t) => ({
190+
name: String(t.name ?? ""),
191+
...(t.classname && { classname: String(t.classname) }),
192+
...(t.message && {
193+
message: String(t.message).slice(0, MAX_MESSAGE_LEN),
194+
}),
195+
...(t.duration != null && { duration: Number(t.duration) }),
196+
}));
197+
record.failed_tests_json = JSON.stringify(capped);
198+
}
178199
}
179200

180201
return record;

0 commit comments

Comments
 (0)