Skip to content

Commit 5cfc18b

Browse files
committed
fix: support list detail of failed GitHub CI
1 parent fb309d9 commit 5cfc18b

File tree

5 files changed

+148
-14
lines changed

5 files changed

+148
-14
lines changed

lib/pr_checker.js

Lines changed: 75 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -359,8 +359,13 @@ export default class PRChecker {
359359
return false;
360360
}
361361

362+
let hasFailures = false;
363+
const failedJobs = [];
364+
const cancelledJobs = [];
365+
const pendingJobs = [];
366+
362367
// GitHub new Check API
363-
for (const { status, conclusion, app } of checkSuites.nodes) {
368+
for (const { status, conclusion, app, checkRuns } of checkSuites.nodes) {
364369
if (app.slug !== 'github-actions') {
365370
// Ignore all non-github check suites, such as Dependabot and Codecov.
366371
// They are expected to show up on PRs whose head branch is not on a
@@ -369,16 +374,80 @@ export default class PRChecker {
369374
}
370375

371376
if (status !== 'COMPLETED') {
372-
cli.error('GitHub CI is still running');
373-
return false;
377+
pendingJobs.push({ app: app.slug, status, conclusion });
378+
continue;
374379
}
375380

376381
if (!GITHUB_SUCCESS_CONCLUSIONS.includes(conclusion)) {
377-
cli.error('Last GitHub CI failed');
378-
return false;
382+
hasFailures = true;
383+
384+
// If we have detailed checkRuns, show specific failing jobs
385+
if (checkRuns && checkRuns.nodes && checkRuns.nodes.length > 0) {
386+
for (const checkRun of checkRuns.nodes) {
387+
if (checkRun.status === 'COMPLETED' &&
388+
!GITHUB_SUCCESS_CONCLUSIONS.includes(checkRun.conclusion)) {
389+
if (checkRun.conclusion === 'CANCELLED') {
390+
cancelledJobs.push({
391+
name: checkRun.name,
392+
conclusion: checkRun.conclusion,
393+
url: checkRun.detailsUrl
394+
});
395+
} else {
396+
failedJobs.push({
397+
name: checkRun.name,
398+
conclusion: checkRun.conclusion,
399+
url: checkRun.detailsUrl
400+
});
401+
}
402+
}
403+
}
404+
} else {
405+
// Fallback to check suite level information if no checkRuns
406+
if (conclusion === 'CANCELLED') {
407+
cancelledJobs.push({
408+
name: app.slug,
409+
conclusion,
410+
url: null
411+
});
412+
} else {
413+
failedJobs.push({
414+
name: app.slug,
415+
conclusion,
416+
url: null
417+
});
418+
}
419+
}
420+
}
421+
}
422+
423+
// Report pending jobs
424+
if (pendingJobs.length > 0) {
425+
cli.error('GitHub CI is still running');
426+
return false;
427+
}
428+
429+
// Report failed jobs
430+
if (failedJobs.length > 0) {
431+
cli.error(`${failedJobs.length} GitHub CI job(s) failed:`);
432+
for (const job of failedJobs) {
433+
const urlInfo = job.url ? ` (${job.url})` : '';
434+
cli.error(` - ${job.name}: ${job.conclusion}${urlInfo}`);
379435
}
380436
}
381437

438+
// Report cancelled jobs
439+
if (cancelledJobs.length > 0) {
440+
cli.error(`${cancelledJobs.length} GitHub CI job(s) cancelled:`);
441+
for (const job of cancelledJobs) {
442+
const urlInfo = job.url ? ` (${job.url})` : '';
443+
cli.error(` - ${job.name}: ${job.conclusion}${urlInfo}`);
444+
}
445+
}
446+
447+
if (hasFailures) {
448+
return false;
449+
}
450+
382451
// GitHub old commit status API
383452
if (commit.status) {
384453
const { state } = commit.status;
@@ -388,7 +457,7 @@ export default class PRChecker {
388457
}
389458

390459
if (!['SUCCESS', 'EXPECTED'].includes(state)) {
391-
cli.error('Last GitHub CI failed');
460+
cli.error(`GitHub CI failed with status: ${state}`);
392461
return false;
393462
}
394463
}

lib/queries/PRCommits.gql

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,15 @@ query Commits($prid: Int!, $owner: String!, $repo: String!, $after: String) {
3131
slug
3232
}
3333
conclusion,
34-
status
34+
status,
35+
checkRuns(first: 40) {
36+
nodes {
37+
name
38+
status
39+
conclusion
40+
detailsUrl
41+
}
42+
}
3543
}
3644
}
3745
status {
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
[
2+
{
3+
"commit": {
4+
"committedDate": "2017-10-26T12:10:20Z",
5+
"oid": "9d098ssiskj8dhd39js0sjd0cn2ng4is9n40sj12d",
6+
"messageHeadline": "doc: add api description README",
7+
"author": {
8+
"login": "foo"
9+
},
10+
"checkSuites": {
11+
"nodes": [
12+
{
13+
"app": { "slug": "github-actions" },
14+
"status": "COMPLETED",
15+
"conclusion": "CANCELLED",
16+
"checkRuns": {
17+
"nodes": [
18+
{
19+
"name": "test-linux",
20+
"status": "COMPLETED",
21+
"conclusion": "CANCELLED",
22+
"detailsUrl": "https://github.com/nodejs/node/runs/12345"
23+
},
24+
{
25+
"name": "lint",
26+
"status": "COMPLETED",
27+
"conclusion": "SUCCESS",
28+
"detailsUrl": "https://github.com/nodejs/node/runs/12346"
29+
}
30+
]
31+
}
32+
}
33+
]
34+
}
35+
}
36+
}
37+
]

test/fixtures/github-ci/check-suite-failure.json

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,23 @@
1212
{
1313
"app": { "slug": "github-actions" },
1414
"status": "COMPLETED",
15-
"conclusion": "FAILURE"
15+
"conclusion": "FAILURE",
16+
"checkRuns": {
17+
"nodes": [
18+
{
19+
"name": "test-linux",
20+
"status": "COMPLETED",
21+
"conclusion": "FAILURE",
22+
"detailsUrl": "https://github.com/nodejs/node/runs/12345"
23+
},
24+
{
25+
"name": "test-macos",
26+
"status": "COMPLETED",
27+
"conclusion": "SUCCESS",
28+
"detailsUrl": "https://github.com/nodejs/node/runs/12346"
29+
}
30+
]
31+
}
1632
}
1733
]
1834
}

test/unit/pr_checker.test.js

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1267,7 +1267,8 @@ describe('PRChecker', () => {
12671267
['Last Jenkins CI successful']
12681268
],
12691269
error: [
1270-
['Last GitHub CI failed']
1270+
['1 GitHub CI job(s) failed:'],
1271+
[' - test-linux: FAILURE (https://github.com/nodejs/node/runs/12345)']
12711272
],
12721273
info: [
12731274
[`Last Full PR CI on 2018-10-22T04:16:36.458Z: ${jenkins.url}`]
@@ -1674,7 +1675,8 @@ describe('PRChecker', () => {
16741675

16751676
const expectedLogs = {
16761677
error: [
1677-
['Last GitHub CI failed']
1678+
['1 GitHub CI job(s) failed:'],
1679+
[' - github-actions: FAILURE']
16781680
]
16791681
};
16801682

@@ -1734,7 +1736,8 @@ describe('PRChecker', () => {
17341736

17351737
const expectedLogs = {
17361738
error: [
1737-
['Last GitHub CI failed']
1739+
['1 GitHub CI job(s) failed:'],
1740+
[' - test-linux: FAILURE (https://github.com/nodejs/node/runs/12345)']
17381741
]
17391742
};
17401743

@@ -1791,7 +1794,7 @@ describe('PRChecker', () => {
17911794

17921795
const expectedLogs = {
17931796
error: [
1794-
['Last GitHub CI failed']
1797+
['GitHub CI failed with status: FAILURE']
17951798
]
17961799
};
17971800

@@ -1867,7 +1870,7 @@ describe('PRChecker', () => {
18671870

18681871
const expectedLogs = {
18691872
error: [
1870-
['Last GitHub CI failed']
1873+
['GitHub CI failed with status: FAILURE']
18711874
]
18721875
};
18731876

@@ -1886,7 +1889,8 @@ describe('PRChecker', () => {
18861889

18871890
const expectedLogs = {
18881891
error: [
1889-
['Last GitHub CI failed']
1892+
['1 GitHub CI job(s) failed:'],
1893+
[' - github-actions: FAILURE']
18901894
]
18911895
};
18921896

0 commit comments

Comments
 (0)