Skip to content

Commit 04e825e

Browse files
committed
Improve build failure detection from XCLogParser
1 parent 4c53bc9 commit 04e825e

File tree

10 files changed

+358
-60
lines changed

10 files changed

+358
-60
lines changed
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import { describe, it, expect, beforeEach, vi } from 'vitest';
2+
import { EventEmitter } from 'events';
3+
4+
const spawnMock = vi.hoisted(() => vi.fn()) as ReturnType<typeof vi.fn>;
5+
6+
vi.mock('child_process', () => ({
7+
spawn: spawnMock
8+
}));
9+
10+
import { BuildLogParser } from '../../src/utils/BuildLogParser.js';
11+
12+
class MockChildProcess extends EventEmitter {
13+
public stdout: EventEmitter;
14+
public stderr: EventEmitter;
15+
public killed = false;
16+
17+
constructor(private readonly stdoutData: string, private readonly stderrData = '', private readonly exitCode = 0) {
18+
super();
19+
this.stdout = new EventEmitter();
20+
this.stderr = new EventEmitter();
21+
this.scheduleEmit();
22+
}
23+
24+
kill(): boolean {
25+
this.killed = true;
26+
return true;
27+
}
28+
29+
private scheduleEmit(): void {
30+
setImmediate(() => {
31+
if (this.stdoutData) {
32+
this.stdout.emit('data', Buffer.from(this.stdoutData));
33+
}
34+
if (this.stderrData) {
35+
this.stderr.emit('data', Buffer.from(this.stderrData));
36+
}
37+
this.emit('close', this.exitCode);
38+
});
39+
}
40+
}
41+
42+
describe('BuildLogParser.parseBuildLog', () => {
43+
beforeEach(() => {
44+
spawnMock.mockReset();
45+
});
46+
47+
it('falls back to summary data when issues reporter returns no errors but build failed', async () => {
48+
spawnMock.mockImplementation((_command: string, args: string[]) => {
49+
const reporterIndex = args.indexOf('--reporter');
50+
const reporter = reporterIndex >= 0 ? args[reporterIndex + 1] : 'issues';
51+
52+
if (reporter === 'summaryJson') {
53+
return new MockChildProcess(JSON.stringify({
54+
buildStatus: 'failed',
55+
errorCount: 1,
56+
warnings: [],
57+
errors: [],
58+
notes: [
59+
{
60+
title: 'Command PhaseScriptExecution failed with a nonzero exit code',
61+
documentURL: 'file:///mock/script.sh'
62+
}
63+
]
64+
}));
65+
}
66+
67+
return new MockChildProcess(JSON.stringify({
68+
errors: [],
69+
warnings: []
70+
}));
71+
});
72+
73+
const result = await BuildLogParser.parseBuildLog('/mock/path/to/log.xcactivitylog');
74+
75+
expect(spawnMock).toHaveBeenCalledTimes(2);
76+
expect(result.buildStatus).toBe('failed');
77+
expect(result.errorCount).toBe(1);
78+
expect(result.errors).not.toHaveLength(0);
79+
expect(result.errors[0]).toContain("Xcode reported build status 'failed'");
80+
});
81+
});

dist/types/index.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ export interface ParsedBuildResults {
1414
errors: string[];
1515
warnings: string[];
1616
buildStatus?: string;
17+
errorCount?: number;
18+
warningCount?: number;
1719
}
1820
export interface EnvironmentValidationResult {
1921
valid: boolean;

dist/types/index.d.ts.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/utils/BuildLogParser.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export declare class BuildLogParser {
66
static getRecentBuildLogs(projectPath: string, sinceTime: number): Promise<BuildLogInfo[]>;
77
static getLatestTestLog(projectPath: string): Promise<BuildLogInfo | null>;
88
static parseBuildLog(logPath: string, retryCount?: number, maxRetries?: number): Promise<ParsedBuildResults>;
9+
private static parseBuildSummary;
910
static canParseLog(logPath: string): Promise<boolean>;
1011
static parseTestResults(_xcresultPath: string): Promise<ParsedBuildResults>;
1112
}

dist/utils/BuildLogParser.d.ts.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)