@@ -359,8 +359,13 @@ export default class PRChecker {
359
359
return false ;
360
360
}
361
361
362
+ let hasFailures = false ;
363
+ const failedJobs = [ ] ;
364
+ const cancelledJobs = [ ] ;
365
+ const pendingJobs = [ ] ;
366
+
362
367
// GitHub new Check API
363
- for ( const { status, conclusion, app } of checkSuites . nodes ) {
368
+ for ( const { status, conclusion, app, checkRuns } of checkSuites . nodes ) {
364
369
if ( app . slug !== 'github-actions' ) {
365
370
// Ignore all non-github check suites, such as Dependabot and Codecov.
366
371
// They are expected to show up on PRs whose head branch is not on a
@@ -369,16 +374,80 @@ export default class PRChecker {
369
374
}
370
375
371
376
if ( status !== 'COMPLETED' ) {
372
- cli . error ( 'GitHub CI is still running' ) ;
373
- return false ;
377
+ pendingJobs . push ( { app : app . slug , status , conclusion } ) ;
378
+ continue ;
374
379
}
375
380
376
381
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 } ` ) ;
379
435
}
380
436
}
381
437
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
+
382
451
// GitHub old commit status API
383
452
if ( commit . status ) {
384
453
const { state } = commit . status ;
@@ -388,7 +457,7 @@ export default class PRChecker {
388
457
}
389
458
390
459
if ( ! [ 'SUCCESS' , 'EXPECTED' ] . includes ( state ) ) {
391
- cli . error ( 'Last GitHub CI failed' ) ;
460
+ cli . error ( ` GitHub CI failed with status: ${ state } ` ) ;
392
461
return false ;
393
462
}
394
463
}
0 commit comments