@@ -32,8 +32,14 @@ if (cacheCompressionEnv != null) {
32
32
cacheCompressionOption = false
33
33
}
34
34
}
35
- const cpuCountRaw = os . cpus ( ) ?. length
36
- const cpuCount = Number . isInteger ( cpuCountRaw ) && cpuCountRaw > 0 ? cpuCountRaw : 1
35
+ let cpuCount = 1
36
+ try {
37
+ const cpuInfo = os . cpus && os . cpus ( )
38
+ const len = Array . isArray ( cpuInfo ) ? cpuInfo . length : 0
39
+ cpuCount = Number . isInteger ( len ) && len > 0 ? len : 1
40
+ } catch {
41
+ cpuCount = 1
42
+ }
37
43
const rawWorkers = process . env . BUILD_THREAD_WORKERS
38
44
? parseInt ( process . env . BUILD_THREAD_WORKERS , 10 )
39
45
: undefined
@@ -78,8 +84,16 @@ async function runWebpack(isWithoutKatex, isWithoutTiktoken, minimal, sourceBuil
78
84
]
79
85
if ( isWithoutKatex ) shared . push ( './src/components' )
80
86
81
- // Use the default export from sass-embedded; sass-loader expects the implementation object
82
- const { default : sassImpl } = await import ( 'sass-embedded' )
87
+ // Use the default export from sass-embedded; sass-loader expects the implementation object.
88
+ // Fallback to `sass` if sass-embedded is unavailable.
89
+ let sassImpl
90
+ try {
91
+ const mod = await import ( 'sass-embedded' )
92
+ sassImpl = mod . default || mod
93
+ } catch ( e ) {
94
+ const mod = await import ( 'sass' )
95
+ sassImpl = mod . default || mod
96
+ }
83
97
84
98
const variantId = [
85
99
isWithoutKatex ? 'no-katex' : 'with-katex' ,
@@ -117,6 +131,12 @@ async function runWebpack(isWithoutKatex, isWithoutTiktoken, minimal, sourceBuil
117
131
cache : {
118
132
type : 'filesystem' ,
119
133
name : `webpack-${ variantId } ` ,
134
+ version : JSON . stringify ( {
135
+ THREAD : enableThread ,
136
+ WORKERS : threadWorkers ,
137
+ CACHE_COMP : cacheCompressionOption ?? false ,
138
+ PROD : isProduction ,
139
+ } ) ,
120
140
// default none; override via BUILD_CACHE_COMPRESSION=gzip|brotli
121
141
compression : cacheCompressionOption ?? false ,
122
142
buildDependencies : {
@@ -341,27 +361,57 @@ async function runWebpack(isWithoutKatex, isWithoutTiktoken, minimal, sourceBuil
341
361
] ,
342
362
} ,
343
363
} )
344
- if ( isProduction ) compiler . run ( callback )
345
- else {
364
+ if ( isProduction ) {
365
+ // Ensure compiler is properly closed after production runs
366
+ compiler . run ( ( err , stats ) => {
367
+ const finishClose = ( ) =>
368
+ compiler . close ( ( closeErr ) => {
369
+ if ( closeErr ) console . error ( 'Error closing compiler:' , closeErr )
370
+ } )
371
+ try {
372
+ const ret = callback ( err , stats )
373
+ if ( ret && typeof ret . then === 'function' ) {
374
+ ret . then ( finishClose , finishClose )
375
+ } else {
376
+ finishClose ( )
377
+ }
378
+ } catch ( _ ) {
379
+ finishClose ( )
380
+ }
381
+ } )
382
+ } else {
346
383
const watching = compiler . watch ( { } , ( err , stats ) => {
384
+ const hasErrors = ! ! (
385
+ err ||
386
+ ( stats && typeof stats . hasErrors === 'function' && stats . hasErrors ( ) )
387
+ )
347
388
callback ( err , stats )
348
389
if ( process . env . BUILD_WATCH_ONCE ) {
349
390
watching . close ( ( closeErr ) => {
350
391
if ( closeErr ) console . error ( 'Error closing watcher:' , closeErr )
392
+ // Exit explicitly to prevent hanging processes in CI
393
+ // Use non-zero exit code when errors occurred
394
+ process . exit ( hasErrors || closeErr ? 1 : 0 )
351
395
} )
352
396
}
353
397
} )
354
398
}
355
399
}
356
400
357
401
async function zipFolder ( dir ) {
358
- const output = fs . createWriteStream ( `${ dir } .zip` )
359
- const archive = archiver ( 'zip' , {
360
- zlib : { level : 9 } ,
402
+ const zipPath = `${ dir } .zip`
403
+ await fs . ensureDir ( path . dirname ( zipPath ) )
404
+ await new Promise ( ( resolve , reject ) => {
405
+ const output = fs . createWriteStream ( zipPath )
406
+ const archive = archiver ( 'zip' , { zlib : { level : 9 } } )
407
+ const onError = ( err ) => reject ( err )
408
+ output . on ( 'error' , onError )
409
+ archive . on ( 'error' , onError )
410
+ output . on ( 'close' , resolve )
411
+ archive . pipe ( output )
412
+ archive . directory ( dir , false )
413
+ archive . finalize ( ) . catch ( onError )
361
414
} )
362
- archive . pipe ( output )
363
- archive . directory ( dir , false )
364
- await archive . finalize ( )
365
415
}
366
416
367
417
async function copyFiles ( entryPoints , targetDir ) {
0 commit comments