@@ -123,7 +123,13 @@ async function main() {
123
123
console . log ( `Performing cleanup before exit with code ${ code } ...` ) ;
124
124
if ( hugoProc && hugoStarted ) {
125
125
try {
126
- hugoProc . kill ( 'SIGKILL' ) ; // Use SIGKILL to ensure immediate termination
126
+ // Use SIGTERM first, then SIGKILL if needed
127
+ hugoProc . kill ( 'SIGTERM' ) ;
128
+ setTimeout ( ( ) => {
129
+ if ( ! hugoProc . killed ) {
130
+ hugoProc . kill ( 'SIGKILL' ) ;
131
+ }
132
+ } , 1000 ) ;
127
133
} catch ( err ) {
128
134
console . error ( `Error killing Hugo process: ${ err . message } ` ) ;
129
135
}
@@ -138,6 +144,10 @@ async function main() {
138
144
console . error ( `Uncaught exception: ${ err . message } ` ) ;
139
145
cleanupAndExit ( 1 ) ;
140
146
} ) ;
147
+ process . on ( 'unhandledRejection' , ( reason , promise ) => {
148
+ console . error ( 'Unhandled Rejection at:' , promise , 'reason:' , reason ) ;
149
+ cleanupAndExit ( 1 ) ;
150
+ } ) ;
141
151
142
152
const { fileArgs, specArgs } = parseArgs ( process . argv ) ;
143
153
if ( fileArgs . length === 0 ) {
@@ -354,13 +364,24 @@ async function main() {
354
364
initializeReport ( ) ;
355
365
356
366
console . log ( `Running Cypress tests for ${ urlList . length } URLs...` ) ;
367
+
368
+ // Add CI-specific configuration
369
+ const isCI = process . env . CI === 'true' || process . env . GITHUB_ACTIONS === 'true' ;
370
+
357
371
const cypressOptions = {
358
372
reporter : 'junit' ,
359
373
browser : 'chrome' ,
360
374
config : {
361
375
baseUrl : `http://localhost:${ HUGO_PORT } ` ,
362
- video : true ,
363
- trashAssetsBeforeRuns : false , // Prevent trash errors
376
+ video : ! isCI , // Disable video in CI to reduce resource usage
377
+ trashAssetsBeforeRuns : false ,
378
+ // Add CI-specific timeouts
379
+ defaultCommandTimeout : isCI ? 15000 : 10000 ,
380
+ pageLoadTimeout : isCI ? 45000 : 30000 ,
381
+ responseTimeout : isCI ? 45000 : 30000 ,
382
+ // Reduce memory usage in CI
383
+ experimentalMemoryManagement : true ,
384
+ numTestsKeptInMemory : isCI ? 1 : 5 ,
364
385
} ,
365
386
env : {
366
387
// Pass URLs as a comma-separated string for backward compatibility
@@ -377,8 +398,28 @@ async function main() {
377
398
cypressOptions . spec = specArgs . join ( ',' ) ;
378
399
}
379
400
401
+ // Add error handling for Hugo process monitoring during Cypress execution
402
+ let hugoHealthCheckInterval ;
403
+ if ( hugoProc && hugoStarted ) {
404
+ hugoHealthCheckInterval = setInterval ( ( ) => {
405
+ if ( hugoProc . killed || hugoProc . exitCode !== null ) {
406
+ console . error ( '❌ Hugo server died during Cypress execution' ) ;
407
+ if ( hugoHealthCheckInterval ) {
408
+ clearInterval ( hugoHealthCheckInterval ) ;
409
+ }
410
+ cypressFailed = true ;
411
+ // Don't exit immediately, let Cypress finish gracefully
412
+ }
413
+ } , 5000 ) ;
414
+ }
415
+
380
416
const results = await cypress . run ( cypressOptions ) ;
381
417
418
+ // Clear health check interval
419
+ if ( hugoHealthCheckInterval ) {
420
+ clearInterval ( hugoHealthCheckInterval ) ;
421
+ }
422
+
382
423
// Process broken links report
383
424
const brokenLinksCount = displayBrokenLinksReport ( ) ;
384
425
@@ -496,6 +537,22 @@ async function main() {
496
537
} catch ( err ) {
497
538
console . error ( `❌ Cypress execution error: ${ err . message } ` ) ;
498
539
540
+ // Handle EPIPE errors specifically
541
+ if ( err . code === 'EPIPE' || err . message . includes ( 'EPIPE' ) ) {
542
+ console . error ( '🔧 EPIPE Error Detected:' ) ;
543
+ console . error ( ' • This usually indicates the Hugo server process was terminated unexpectedly' ) ;
544
+ console . error ( ' • Common causes in CI:' ) ;
545
+ console . error ( ' - Memory constraints causing process termination' ) ;
546
+ console . error ( ' - CI runner timeout or resource limits' ) ;
547
+ console . error ( ' - Hugo server crash due to build errors' ) ;
548
+ console . error ( ` • Check Hugo logs: ${ HUGO_LOG_FILE } ` ) ;
549
+
550
+ // Try to provide more context about Hugo server state
551
+ if ( hugoProc ) {
552
+ console . error ( ` • Hugo process state: killed=${ hugoProc . killed } , exitCode=${ hugoProc . exitCode } ` ) ;
553
+ }
554
+ }
555
+
499
556
// Provide more detailed error information
500
557
if ( err . stack ) {
501
558
console . error ( '📋 Error Stack Trace:' ) ;
@@ -552,28 +609,44 @@ async function main() {
552
609
if ( hugoProc && hugoStarted && typeof hugoProc . kill === 'function' ) {
553
610
console . log ( `Stopping Hugo server (fast shutdown: ${ cypressFailed } )...` ) ;
554
611
555
- if ( cypressFailed ) {
556
- hugoProc . kill ( 'SIGKILL' ) ;
557
- console . log ( 'Hugo server forcibly terminated' ) ;
558
- } else {
559
- const shutdownTimeout = setTimeout ( ( ) => {
560
- console . error (
561
- 'Hugo server did not shut down gracefully, forcing termination'
562
- ) ;
612
+ try {
613
+ if ( cypressFailed ) {
614
+ // Fast shutdown for failed tests
563
615
hugoProc . kill ( 'SIGKILL' ) ;
564
- process . exit ( exitCode ) ;
565
- } , 2000 ) ;
616
+ console . log ( 'Hugo server forcibly terminated' ) ;
617
+ } else {
618
+ // Graceful shutdown for successful tests
619
+ const shutdownTimeout = setTimeout ( ( ) => {
620
+ console . error (
621
+ 'Hugo server did not shut down gracefully, forcing termination'
622
+ ) ;
623
+ try {
624
+ hugoProc . kill ( 'SIGKILL' ) ;
625
+ } catch ( killErr ) {
626
+ console . error ( `Error force-killing Hugo: ${ killErr . message } ` ) ;
627
+ }
628
+ process . exit ( exitCode ) ;
629
+ } , 3000 ) ; // Increased timeout for CI
566
630
567
- hugoProc . kill ( 'SIGTERM' ) ;
631
+ hugoProc . kill ( 'SIGTERM' ) ;
568
632
569
- hugoProc . on ( 'close' , ( ) => {
570
- clearTimeout ( shutdownTimeout ) ;
571
- console . log ( 'Hugo server shut down successfully' ) ;
572
- process . exit ( exitCode ) ;
573
- } ) ;
633
+ hugoProc . on ( 'close' , ( ) => {
634
+ clearTimeout ( shutdownTimeout ) ;
635
+ console . log ( 'Hugo server shut down successfully' ) ;
636
+ process . exit ( exitCode ) ;
637
+ } ) ;
574
638
575
- // Return to prevent immediate exit
576
- return ;
639
+ hugoProc . on ( 'error' , ( err ) => {
640
+ console . error ( `Error during Hugo shutdown: ${ err . message } ` ) ;
641
+ clearTimeout ( shutdownTimeout ) ;
642
+ process . exit ( exitCode ) ;
643
+ } ) ;
644
+
645
+ // Return to prevent immediate exit
646
+ return ;
647
+ }
648
+ } catch ( shutdownErr ) {
649
+ console . error ( `Error during Hugo server shutdown: ${ shutdownErr . message } ` ) ;
577
650
}
578
651
} else if ( hugoStarted ) {
579
652
console . log ( 'Hugo process was started but is not available for cleanup' ) ;
0 commit comments