@@ -73,32 +73,37 @@ async function waitFor<T>(
7373 fn : ( ...args : unknown [ ] ) => Promise < T > ,
7474 timeout = 60_000 ,
7575 interval = 100 ,
76- message : string | ( ( err : any ) => string ) = 'Timeout exceeded for task' ,
76+ message :
77+ | string
78+ | ( ( err : any , attempts : number ) => string ) = 'Timeout exceeded for task' ,
7779 signal ?: AbortSignal
7880) : Promise < T > {
7981 let lastError : any ;
82+ let attempts = 0 ;
8083 const controller = new AbortController ( ) ;
8184 // eslint-disable-next-line chai-friendly/no-unused-expressions
8285 signal ?. addEventListener ( 'abort' , ( ) => {
8386 controller . abort ( signal . reason ) ;
8487 } ) ;
8588 const tid = setTimeout ( ( ) => {
8689 controller . abort (
87- signal ?. reason ??
88- new Error ( typeof message === 'function' ? message ( lastError ) : message )
90+ new Error (
91+ typeof message === 'function' ? message ( lastError , attempts ) : message
92+ )
8993 ) ;
9094 } , timeout ) ;
9195 try {
9296 while ( ! controller . signal . aborted ) {
9397 try {
98+ attempts ++ ;
9499 return await fn ( ) ;
95100 } catch ( err ) {
96101 lastError = err ;
97102 await setTimeoutAsync ( interval ) ;
98103 }
99104 }
100105 // If we ended up here either timeout expired or passed signal was aborted,
101- // either way this inter
106+ // either way this internal controller was aborted with a correct reason
102107 throw controller . signal . reason ;
103108 } finally {
104109 clearTimeout ( tid ) ;
@@ -285,13 +290,16 @@ export class GithubRepo {
285290 } ,
286291 process . env . TEST_UPLOAD_RELEASE_ASSET_TIMEOUT
287292 ? Number ( process . env . TEST_UPLOAD_RELEASE_ASSET_TIMEOUT )
288- // File upload is slow, we allow 5 minutes per file to allow for additional retries
289- : 60_000 * 5 ,
293+ // File upload is slow, we allow 10 minutes per file to allow for additional retries
294+ : 60_000 * 10 ,
290295 100 ,
291- ( lastError ) => {
292- return `Failed to upload asset ${ asset . name } ` + lastError
293- ? `\n\nLast encountered error:\n\n${ lastError ?. stack } `
294- : '' ;
296+ ( lastError , attempts ) => {
297+ return (
298+ `Failed to upload asset ${ path . basename ( asset . path ) } after ${ attempts } attempts` +
299+ ( lastError
300+ ? `\n\nLast encountered error:\n\n${ this . _getErrorMessage ( lastError ) } `
301+ : '' )
302+ ) ;
295303 } ,
296304 controller . signal
297305 ) ;
@@ -325,10 +333,13 @@ export class GithubRepo {
325333 ? Number ( process . env . TEST_GET_RELEASE_TIMEOUT )
326334 : 60_000 ,
327335 100 ,
328- ( lastError ) => {
329- return "Can't fetch releases from GitHub" + lastError
330- ? `\n\nLast encountered error:\n\n${ lastError ?. stack } `
331- : '' ;
336+ ( lastError , attempts ) => {
337+ return (
338+ `Failed to fetch releases from GitHub after ${ attempts } attempts` +
339+ ( lastError
340+ ? `\n\nLast encountered error:\n\n${ this . _getErrorMessage ( lastError ) } `
341+ : '' )
342+ ) ;
332343 } ,
333344 controller . signal
334345 ) ;
@@ -502,4 +513,17 @@ export class GithubRepo {
502513 error . errors [ 0 ] . code === 'already_exists'
503514 ) ;
504515 }
516+
517+ private _getErrorMessage ( _err : any ) : string {
518+ if ( _err . status ) {
519+ return (
520+ ( _err as OctokitRequestError ) . errors
521+ ?. map ( ( err ) => err . message ?? null )
522+ . filter ( ( msg ) : msg is string => ! ! msg )
523+ . join ( '\n\n' )
524+ . trim ( ) || `Octokit request failed with ${ _err . name } (${ _err . status } )`
525+ ) ;
526+ }
527+ return _err . stack ?? _err . message ;
528+ }
505529}
0 commit comments