Skip to content

Commit 801c541

Browse files
committed
Merge artifacts for new structure
1 parent 7adb09b commit 801c541

File tree

2 files changed

+100
-1
lines changed

2 files changed

+100
-1
lines changed

lib/test-results-downloader.test.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,72 @@ Deno.test("download multiple artifacts in parallel", async () => {
376376
);
377377
});
378378

379+
Deno.test("merge split artifacts by job", async () => {
380+
const mockClient = new MockGitHubApiClient();
381+
const mockParser = new MockArtifactParser();
382+
const mockStore = new MockTestResultArtifactStore();
383+
384+
const downloader = new RealTestResultsDownloader(
385+
mockParser,
386+
mockClient,
387+
mockStore,
388+
);
389+
390+
// setup artifacts split by suite (new naming convention)
391+
const artifacts = [
392+
createMockArtifact(
393+
1,
394+
"test-results-linux-x86_64-debug-integration.json",
395+
"https://example.com/1.zip",
396+
),
397+
createMockArtifact(
398+
2,
399+
"test-results-linux-x86_64-debug-unit.json",
400+
"https://example.com/2.zip",
401+
),
402+
createMockArtifact(
403+
3,
404+
"test-results-macos-aarch64-debug-specs.json",
405+
"https://example.com/3.zip",
406+
),
407+
];
408+
409+
mockClient.mockArtifacts(444, artifacts);
410+
for (let i = 1; i <= 3; i++) {
411+
mockClient.mockBlob(`https://example.com/${i}.zip`, new Blob([`test${i}`]));
412+
}
413+
414+
mockParser.mockParseResult(
415+
"test-results-linux-x86_64-debug-integration.json",
416+
{
417+
name: "linux-x86_64-debug-integration",
418+
tests: [{ name: "int_test", path: "test/int.ts", duration: 100 }],
419+
},
420+
);
421+
mockParser.mockParseResult("test-results-linux-x86_64-debug-unit.json", {
422+
name: "linux-x86_64-debug-unit",
423+
tests: [{ name: "unit_test", path: "test/unit.ts", duration: 50 }],
424+
});
425+
mockParser.mockParseResult(
426+
"test-results-macos-aarch64-debug-specs.json",
427+
{
428+
name: "macos-aarch64-debug-specs",
429+
tests: [{ name: "spec_test", path: "test/spec.ts", duration: 200 }],
430+
},
431+
);
432+
433+
const results = await downloader.downloadForRunId(444);
434+
435+
// linux-x86_64-debug artifacts should be merged into one
436+
assertEquals(results.length, 2);
437+
assertEquals(results[0].name, "linux-x86_64-debug");
438+
assertEquals(results[0].tests.length, 2);
439+
assertEquals(results[0].tests[0].name, "int_test");
440+
assertEquals(results[0].tests[1].name, "unit_test");
441+
assertEquals(results[1].name, "macos-aarch64-debug");
442+
assertEquals(results[1].tests.length, 1);
443+
});
444+
379445
Deno.test("store is shared across downloads", async () => {
380446
const mockClient = new MockGitHubApiClient();
381447
const mockParser = new MockArtifactParser();

lib/test-results-downloader.ts

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ export class RealTestResultsDownloader {
6868
matchingArtifacts.map((artifact) => this.#downloadArtifact(artifact)),
6969
);
7070

71-
return downloads;
71+
return mergeArtifactsByJob(downloads);
7272
}
7373

7474
#downloadArtifact(
@@ -87,3 +87,36 @@ export class RealTestResultsDownloader {
8787
return value.get();
8888
}
8989
}
90+
91+
/**
92+
* Merges artifacts that belong to the same job. Artifacts follow the naming
93+
* pattern `{os}-{arch}-{build_type}-{suite}` (e.g. `linux-x86_64-debug-integration`).
94+
* This groups by the first three segments (os-arch-build_type) and concatenates
95+
* tests from each suite. Old-style names without suite segments are left as-is.
96+
*/
97+
function mergeArtifactsByJob(
98+
artifacts: ParsedTestResultArtifact[],
99+
): ParsedTestResultArtifact[] {
100+
const groups = new Map<string, RecordedTestResult[]>();
101+
const groupOrder: string[] = [];
102+
103+
for (const artifact of artifacts) {
104+
const parts = artifact.name.split("-");
105+
// new-style: os-arch-build_type-suite (4+ segments)
106+
// old-style: os (1 segment, e.g. "linux")
107+
const key = parts.length >= 4 ? parts.slice(0, 3).join("-") : artifact.name;
108+
109+
const existing = groups.get(key);
110+
if (existing) {
111+
existing.push(...artifact.tests);
112+
} else {
113+
groupOrder.push(key);
114+
groups.set(key, [...artifact.tests]);
115+
}
116+
}
117+
118+
return groupOrder.map((key) => ({
119+
name: key,
120+
tests: groups.get(key)!,
121+
}));
122+
}

0 commit comments

Comments
 (0)