@@ -3313,9 +3313,12 @@ const os = __importStar(__webpack_require__(87));
33133313const path = __importStar ( __webpack_require__ ( 622 ) ) ;
33143314const httpm = __importStar ( __webpack_require__ ( 539 ) ) ;
33153315const semver = __importStar ( __webpack_require__ ( 280 ) ) ;
3316+ const stream = __importStar ( __webpack_require__ ( 794 ) ) ;
3317+ const util = __importStar ( __webpack_require__ ( 669 ) ) ;
33163318const v4_1 = __importDefault ( __webpack_require__ ( 826 ) ) ;
33173319const exec_1 = __webpack_require__ ( 986 ) ;
33183320const assert_1 = __webpack_require__ ( 357 ) ;
3321+ const retry_helper_1 = __webpack_require__ ( 979 ) ;
33193322class HTTPError extends Error {
33203323 constructor ( httpStatusCode ) {
33213324 super ( `Unexpected HTTP response: ${ httpStatusCode } ` ) ;
@@ -3326,31 +3329,6 @@ class HTTPError extends Error {
33263329exports . HTTPError = HTTPError ;
33273330const IS_WINDOWS = process . platform === 'win32' ;
33283331const userAgent = 'actions/tool-cache' ;
3329- // On load grab temp directory and cache directory and remove them from env (currently don't want to expose this)
3330- let tempDirectory = process . env [ 'RUNNER_TEMP' ] || '' ;
3331- let cacheRoot = process . env [ 'RUNNER_TOOL_CACHE' ] || '' ;
3332- // If directories not found, place them in common temp locations
3333- if ( ! tempDirectory || ! cacheRoot ) {
3334- let baseLocation ;
3335- if ( IS_WINDOWS ) {
3336- // On windows use the USERPROFILE env variable
3337- baseLocation = process . env [ 'USERPROFILE' ] || 'C:\\' ;
3338- }
3339- else {
3340- if ( process . platform === 'darwin' ) {
3341- baseLocation = '/Users' ;
3342- }
3343- else {
3344- baseLocation = '/home' ;
3345- }
3346- }
3347- if ( ! tempDirectory ) {
3348- tempDirectory = path . join ( baseLocation , 'actions' , 'temp' ) ;
3349- }
3350- if ( ! cacheRoot ) {
3351- cacheRoot = path . join ( baseLocation , 'actions' , 'cache' ) ;
3352- }
3353- }
33543332/**
33553333 * Download a tool from an url and stream it into a file
33563334 *
@@ -3360,52 +3338,71 @@ if (!tempDirectory || !cacheRoot) {
33603338 */
33613339function downloadTool ( url , dest ) {
33623340 return __awaiter ( this , void 0 , void 0 , function * ( ) {
3363- // Wrap in a promise so that we can resolve from within stream callbacks
3364- return new Promise ( ( resolve , reject ) => __awaiter ( this , void 0 , void 0 , function * ( ) {
3365- try {
3366- const http = new httpm . HttpClient ( userAgent , [ ] , {
3367- allowRetries : true ,
3368- maxRetries : 3
3369- } ) ;
3370- dest = dest || path . join ( tempDirectory , v4_1 . default ( ) ) ;
3371- yield io . mkdirP ( path . dirname ( dest ) ) ;
3372- core . debug ( `Downloading ${ url } ` ) ;
3373- core . debug ( `Downloading ${ dest } ` ) ;
3374- if ( fs . existsSync ( dest ) ) {
3375- throw new Error ( `Destination file path ${ dest } already exists` ) ;
3376- }
3377- const response = yield http . get ( url ) ;
3378- if ( response . message . statusCode !== 200 ) {
3379- const err = new HTTPError ( response . message . statusCode ) ;
3380- core . debug ( `Failed to download from "${ url } ". Code(${ response . message . statusCode } ) Message(${ response . message . statusMessage } )` ) ;
3381- throw err ;
3341+ dest = dest || path . join ( _getTempDirectory ( ) , v4_1 . default ( ) ) ;
3342+ yield io . mkdirP ( path . dirname ( dest ) ) ;
3343+ core . debug ( `Downloading ${ url } ` ) ;
3344+ core . debug ( `Destination ${ dest } ` ) ;
3345+ const maxAttempts = 3 ;
3346+ const minSeconds = _getGlobal ( 'TEST_DOWNLOAD_TOOL_RETRY_MIN_SECONDS' , 10 ) ;
3347+ const maxSeconds = _getGlobal ( 'TEST_DOWNLOAD_TOOL_RETRY_MAX_SECONDS' , 20 ) ;
3348+ const retryHelper = new retry_helper_1 . RetryHelper ( maxAttempts , minSeconds , maxSeconds ) ;
3349+ return yield retryHelper . execute ( ( ) => __awaiter ( this , void 0 , void 0 , function * ( ) {
3350+ return yield downloadToolAttempt ( url , dest || '' ) ;
3351+ } ) , ( err ) => {
3352+ if ( err instanceof HTTPError && err . httpStatusCode ) {
3353+ // Don't retry anything less than 500, except 408 Request Timeout and 429 Too Many Requests
3354+ if ( err . httpStatusCode < 500 &&
3355+ err . httpStatusCode !== 408 &&
3356+ err . httpStatusCode !== 429 ) {
3357+ return false ;
33823358 }
3383- const file = fs . createWriteStream ( dest ) ;
3384- file . on ( 'open' , ( ) => __awaiter ( this , void 0 , void 0 , function * ( ) {
3385- try {
3386- const stream = response . message . pipe ( file ) ;
3387- stream . on ( 'close' , ( ) => {
3388- core . debug ( 'download complete' ) ;
3389- resolve ( dest ) ;
3390- } ) ;
3391- }
3392- catch ( err ) {
3393- core . debug ( `Failed to download from "${ url } ". Code(${ response . message . statusCode } ) Message(${ response . message . statusMessage } )` ) ;
3394- reject ( err ) ;
3395- }
3396- } ) ) ;
3397- file . on ( 'error' , err => {
3398- file . end ( ) ;
3399- reject ( err ) ;
3400- } ) ;
3401- }
3402- catch ( err ) {
3403- reject ( err ) ;
34043359 }
3405- } ) ) ;
3360+ // Otherwise retry
3361+ return true ;
3362+ } ) ;
34063363 } ) ;
34073364}
34083365exports . downloadTool = downloadTool ;
3366+ function downloadToolAttempt ( url , dest ) {
3367+ return __awaiter ( this , void 0 , void 0 , function * ( ) {
3368+ if ( fs . existsSync ( dest ) ) {
3369+ throw new Error ( `Destination file path ${ dest } already exists` ) ;
3370+ }
3371+ // Get the response headers
3372+ const http = new httpm . HttpClient ( userAgent , [ ] , {
3373+ allowRetries : false
3374+ } ) ;
3375+ const response = yield http . get ( url ) ;
3376+ if ( response . message . statusCode !== 200 ) {
3377+ const err = new HTTPError ( response . message . statusCode ) ;
3378+ core . debug ( `Failed to download from "${ url } ". Code(${ response . message . statusCode } ) Message(${ response . message . statusMessage } )` ) ;
3379+ throw err ;
3380+ }
3381+ // Download the response body
3382+ const pipeline = util . promisify ( stream . pipeline ) ;
3383+ const responseMessageFactory = _getGlobal ( 'TEST_DOWNLOAD_TOOL_RESPONSE_MESSAGE_FACTORY' , ( ) => response . message ) ;
3384+ const readStream = responseMessageFactory ( ) ;
3385+ let succeeded = false ;
3386+ try {
3387+ yield pipeline ( readStream , fs . createWriteStream ( dest ) ) ;
3388+ core . debug ( 'download complete' ) ;
3389+ succeeded = true ;
3390+ return dest ;
3391+ }
3392+ finally {
3393+ // Error, delete dest before retry
3394+ if ( ! succeeded ) {
3395+ core . debug ( 'download failed' ) ;
3396+ try {
3397+ yield io . rmRF ( dest ) ;
3398+ }
3399+ catch ( err ) {
3400+ core . debug ( `Failed to delete '${ dest } '. ${ err . message } ` ) ;
3401+ }
3402+ }
3403+ }
3404+ } ) ;
3405+ }
34093406/**
34103407 * Extract a .7z file
34113408 *
@@ -3495,14 +3492,17 @@ function extractTar(file, dest, flags = 'xz') {
34953492 // Create dest
34963493 dest = yield _createExtractFolder ( dest ) ;
34973494 // Determine whether GNU tar
3495+ core . debug ( 'Checking tar --version' ) ;
34983496 let versionOutput = '' ;
34993497 yield exec_1 . exec ( 'tar --version' , [ ] , {
35003498 ignoreReturnCode : true ,
3499+ silent : true ,
35013500 listeners : {
35023501 stdout : ( data ) => ( versionOutput += data . toString ( ) ) ,
35033502 stderr : ( data ) => ( versionOutput += data . toString ( ) )
35043503 }
35053504 } ) ;
3505+ core . debug ( versionOutput . trim ( ) ) ;
35063506 const isGnuTar = versionOutput . toUpperCase ( ) . includes ( 'GNU TAR' ) ;
35073507 // Initialize args
35083508 const args = [ flags ] ;
@@ -3663,7 +3663,7 @@ function find(toolName, versionSpec, arch) {
36633663 let toolPath = '' ;
36643664 if ( versionSpec ) {
36653665 versionSpec = semver . clean ( versionSpec ) || '' ;
3666- const cachePath = path . join ( cacheRoot , toolName , versionSpec , arch ) ;
3666+ const cachePath = path . join ( _getCacheDirectory ( ) , toolName , versionSpec , arch ) ;
36673667 core . debug ( `checking cache: ${ cachePath } ` ) ;
36683668 if ( fs . existsSync ( cachePath ) && fs . existsSync ( `${ cachePath } .complete` ) ) {
36693669 core . debug ( `Found tool in cache ${ toolName } ${ versionSpec } ${ arch } ` ) ;
@@ -3685,7 +3685,7 @@ exports.find = find;
36853685function findAllVersions ( toolName , arch ) {
36863686 const versions = [ ] ;
36873687 arch = arch || os . arch ( ) ;
3688- const toolPath = path . join ( cacheRoot , toolName ) ;
3688+ const toolPath = path . join ( _getCacheDirectory ( ) , toolName ) ;
36893689 if ( fs . existsSync ( toolPath ) ) {
36903690 const children = fs . readdirSync ( toolPath ) ;
36913691 for ( const child of children ) {
@@ -3704,15 +3704,15 @@ function _createExtractFolder(dest) {
37043704 return __awaiter ( this , void 0 , void 0 , function * ( ) {
37053705 if ( ! dest ) {
37063706 // create a temp dir
3707- dest = path . join ( tempDirectory , v4_1 . default ( ) ) ;
3707+ dest = path . join ( _getTempDirectory ( ) , v4_1 . default ( ) ) ;
37083708 }
37093709 yield io . mkdirP ( dest ) ;
37103710 return dest ;
37113711 } ) ;
37123712}
37133713function _createToolPath ( tool , version , arch ) {
37143714 return __awaiter ( this , void 0 , void 0 , function * ( ) {
3715- const folderPath = path . join ( cacheRoot , tool , semver . clean ( version ) || version , arch || '' ) ;
3715+ const folderPath = path . join ( _getCacheDirectory ( ) , tool , semver . clean ( version ) || version , arch || '' ) ;
37163716 core . debug ( `destination ${ folderPath } ` ) ;
37173717 const markerPath = `${ folderPath } .complete` ;
37183718 yield io . rmRF ( folderPath ) ;
@@ -3722,7 +3722,7 @@ function _createToolPath(tool, version, arch) {
37223722 } ) ;
37233723}
37243724function _completeToolPath ( tool , version , arch ) {
3725- const folderPath = path . join ( cacheRoot , tool , semver . clean ( version ) || version , arch || '' ) ;
3725+ const folderPath = path . join ( _getCacheDirectory ( ) , tool , semver . clean ( version ) || version , arch || '' ) ;
37263726 const markerPath = `${ folderPath } .complete` ;
37273727 fs . writeFileSync ( markerPath , '' ) ;
37283728 core . debug ( 'finished caching tool' ) ;
@@ -3759,6 +3759,31 @@ function _evaluateVersions(versions, versionSpec) {
37593759 }
37603760 return version ;
37613761}
3762+ /**
3763+ * Gets RUNNER_TOOL_CACHE
3764+ */
3765+ function _getCacheDirectory ( ) {
3766+ const cacheDirectory = process . env [ 'RUNNER_TOOL_CACHE' ] || '' ;
3767+ assert_1 . ok ( cacheDirectory , 'Expected RUNNER_TOOL_CACHE to be defined' ) ;
3768+ return cacheDirectory ;
3769+ }
3770+ /**
3771+ * Gets RUNNER_TEMP
3772+ */
3773+ function _getTempDirectory ( ) {
3774+ const tempDirectory = process . env [ 'RUNNER_TEMP' ] || '' ;
3775+ assert_1 . ok ( tempDirectory , 'Expected RUNNER_TEMP to be defined' ) ;
3776+ return tempDirectory ;
3777+ }
3778+ /**
3779+ * Gets a global variable
3780+ */
3781+ function _getGlobal ( key , defaultValue ) {
3782+ /* eslint-disable @typescript-eslint/no-explicit-any */
3783+ const value = global [ key ] ;
3784+ /* eslint-enable @typescript-eslint/no-explicit-any */
3785+ return value !== undefined ? value : defaultValue ;
3786+ }
37623787//# sourceMappingURL=tool-cache.js.map
37633788
37643789/***/ } ) ,
@@ -4718,6 +4743,13 @@ function makeSemver(version) {
47184743exports . makeSemver = makeSemver ;
47194744
47204745
4746+ /***/ } ) ,
4747+
4748+ /***/ 794 :
4749+ /***/ ( function ( module ) {
4750+
4751+ module . exports = require ( "stream" ) ;
4752+
47214753/***/ } ) ,
47224754
47234755/***/ 826 :
@@ -4826,6 +4858,83 @@ function checkBypass(reqUrl) {
48264858exports . checkBypass = checkBypass ;
48274859
48284860
4861+ /***/ } ) ,
4862+
4863+ /***/ 979 :
4864+ /***/ ( function ( __unusedmodule , exports , __webpack_require__ ) {
4865+
4866+ "use strict" ;
4867+
4868+ var __awaiter = ( this && this . __awaiter ) || function ( thisArg , _arguments , P , generator ) {
4869+ function adopt ( value ) { return value instanceof P ? value : new P ( function ( resolve ) { resolve ( value ) ; } ) ; }
4870+ return new ( P || ( P = Promise ) ) ( function ( resolve , reject ) {
4871+ function fulfilled ( value ) { try { step ( generator . next ( value ) ) ; } catch ( e ) { reject ( e ) ; } }
4872+ function rejected ( value ) { try { step ( generator [ "throw" ] ( value ) ) ; } catch ( e ) { reject ( e ) ; } }
4873+ function step ( result ) { result . done ? resolve ( result . value ) : adopt ( result . value ) . then ( fulfilled , rejected ) ; }
4874+ step ( ( generator = generator . apply ( thisArg , _arguments || [ ] ) ) . next ( ) ) ;
4875+ } ) ;
4876+ } ;
4877+ var __importStar = ( this && this . __importStar ) || function ( mod ) {
4878+ if ( mod && mod . __esModule ) return mod ;
4879+ var result = { } ;
4880+ if ( mod != null ) for ( var k in mod ) if ( Object . hasOwnProperty . call ( mod , k ) ) result [ k ] = mod [ k ] ;
4881+ result [ "default" ] = mod ;
4882+ return result ;
4883+ } ;
4884+ Object . defineProperty ( exports , "__esModule" , { value : true } ) ;
4885+ const core = __importStar ( __webpack_require__ ( 470 ) ) ;
4886+ /**
4887+ * Internal class for retries
4888+ */
4889+ class RetryHelper {
4890+ constructor ( maxAttempts , minSeconds , maxSeconds ) {
4891+ if ( maxAttempts < 1 ) {
4892+ throw new Error ( 'max attempts should be greater than or equal to 1' ) ;
4893+ }
4894+ this . maxAttempts = maxAttempts ;
4895+ this . minSeconds = Math . floor ( minSeconds ) ;
4896+ this . maxSeconds = Math . floor ( maxSeconds ) ;
4897+ if ( this . minSeconds > this . maxSeconds ) {
4898+ throw new Error ( 'min seconds should be less than or equal to max seconds' ) ;
4899+ }
4900+ }
4901+ execute ( action , isRetryable ) {
4902+ return __awaiter ( this , void 0 , void 0 , function * ( ) {
4903+ let attempt = 1 ;
4904+ while ( attempt < this . maxAttempts ) {
4905+ // Try
4906+ try {
4907+ return yield action ( ) ;
4908+ }
4909+ catch ( err ) {
4910+ if ( isRetryable && ! isRetryable ( err ) ) {
4911+ throw err ;
4912+ }
4913+ core . info ( err . message ) ;
4914+ }
4915+ // Sleep
4916+ const seconds = this . getSleepAmount ( ) ;
4917+ core . info ( `Waiting ${ seconds } seconds before trying again` ) ;
4918+ yield this . sleep ( seconds ) ;
4919+ attempt ++ ;
4920+ }
4921+ // Last attempt
4922+ return yield action ( ) ;
4923+ } ) ;
4924+ }
4925+ getSleepAmount ( ) {
4926+ return ( Math . floor ( Math . random ( ) * ( this . maxSeconds - this . minSeconds + 1 ) ) +
4927+ this . minSeconds ) ;
4928+ }
4929+ sleep ( seconds ) {
4930+ return __awaiter ( this , void 0 , void 0 , function * ( ) {
4931+ return new Promise ( resolve => setTimeout ( resolve , seconds * 1000 ) ) ;
4932+ } ) ;
4933+ }
4934+ }
4935+ exports . RetryHelper = RetryHelper ;
4936+ //# sourceMappingURL=retry-helper.js.map
4937+
48294938/***/ } ) ,
48304939
48314940/***/ 986 :
0 commit comments