@@ -3313,9 +3313,12 @@ const os = __importStar(__webpack_require__(87));
3313
3313
const path = __importStar ( __webpack_require__ ( 622 ) ) ;
3314
3314
const httpm = __importStar ( __webpack_require__ ( 539 ) ) ;
3315
3315
const semver = __importStar ( __webpack_require__ ( 280 ) ) ;
3316
+ const stream = __importStar ( __webpack_require__ ( 794 ) ) ;
3317
+ const util = __importStar ( __webpack_require__ ( 669 ) ) ;
3316
3318
const v4_1 = __importDefault ( __webpack_require__ ( 826 ) ) ;
3317
3319
const exec_1 = __webpack_require__ ( 986 ) ;
3318
3320
const assert_1 = __webpack_require__ ( 357 ) ;
3321
+ const retry_helper_1 = __webpack_require__ ( 979 ) ;
3319
3322
class HTTPError extends Error {
3320
3323
constructor ( httpStatusCode ) {
3321
3324
super ( `Unexpected HTTP response: ${ httpStatusCode } ` ) ;
@@ -3326,31 +3329,6 @@ class HTTPError extends Error {
3326
3329
exports . HTTPError = HTTPError ;
3327
3330
const IS_WINDOWS = process . platform === 'win32' ;
3328
3331
const 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
- }
3354
3332
/**
3355
3333
* Download a tool from an url and stream it into a file
3356
3334
*
@@ -3360,52 +3338,71 @@ if (!tempDirectory || !cacheRoot) {
3360
3338
*/
3361
3339
function downloadTool ( url , dest ) {
3362
3340
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 ;
3382
3358
}
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 ) ;
3404
3359
}
3405
- } ) ) ;
3360
+ // Otherwise retry
3361
+ return true ;
3362
+ } ) ;
3406
3363
} ) ;
3407
3364
}
3408
3365
exports . 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
+ }
3409
3406
/**
3410
3407
* Extract a .7z file
3411
3408
*
@@ -3495,14 +3492,17 @@ function extractTar(file, dest, flags = 'xz') {
3495
3492
// Create dest
3496
3493
dest = yield _createExtractFolder ( dest ) ;
3497
3494
// Determine whether GNU tar
3495
+ core . debug ( 'Checking tar --version' ) ;
3498
3496
let versionOutput = '' ;
3499
3497
yield exec_1 . exec ( 'tar --version' , [ ] , {
3500
3498
ignoreReturnCode : true ,
3499
+ silent : true ,
3501
3500
listeners : {
3502
3501
stdout : ( data ) => ( versionOutput += data . toString ( ) ) ,
3503
3502
stderr : ( data ) => ( versionOutput += data . toString ( ) )
3504
3503
}
3505
3504
} ) ;
3505
+ core . debug ( versionOutput . trim ( ) ) ;
3506
3506
const isGnuTar = versionOutput . toUpperCase ( ) . includes ( 'GNU TAR' ) ;
3507
3507
// Initialize args
3508
3508
const args = [ flags ] ;
@@ -3663,7 +3663,7 @@ function find(toolName, versionSpec, arch) {
3663
3663
let toolPath = '' ;
3664
3664
if ( versionSpec ) {
3665
3665
versionSpec = semver . clean ( versionSpec ) || '' ;
3666
- const cachePath = path . join ( cacheRoot , toolName , versionSpec , arch ) ;
3666
+ const cachePath = path . join ( _getCacheDirectory ( ) , toolName , versionSpec , arch ) ;
3667
3667
core . debug ( `checking cache: ${ cachePath } ` ) ;
3668
3668
if ( fs . existsSync ( cachePath ) && fs . existsSync ( `${ cachePath } .complete` ) ) {
3669
3669
core . debug ( `Found tool in cache ${ toolName } ${ versionSpec } ${ arch } ` ) ;
@@ -3685,7 +3685,7 @@ exports.find = find;
3685
3685
function findAllVersions ( toolName , arch ) {
3686
3686
const versions = [ ] ;
3687
3687
arch = arch || os . arch ( ) ;
3688
- const toolPath = path . join ( cacheRoot , toolName ) ;
3688
+ const toolPath = path . join ( _getCacheDirectory ( ) , toolName ) ;
3689
3689
if ( fs . existsSync ( toolPath ) ) {
3690
3690
const children = fs . readdirSync ( toolPath ) ;
3691
3691
for ( const child of children ) {
@@ -3704,15 +3704,15 @@ function _createExtractFolder(dest) {
3704
3704
return __awaiter ( this , void 0 , void 0 , function * ( ) {
3705
3705
if ( ! dest ) {
3706
3706
// create a temp dir
3707
- dest = path . join ( tempDirectory , v4_1 . default ( ) ) ;
3707
+ dest = path . join ( _getTempDirectory ( ) , v4_1 . default ( ) ) ;
3708
3708
}
3709
3709
yield io . mkdirP ( dest ) ;
3710
3710
return dest ;
3711
3711
} ) ;
3712
3712
}
3713
3713
function _createToolPath ( tool , version , arch ) {
3714
3714
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 || '' ) ;
3716
3716
core . debug ( `destination ${ folderPath } ` ) ;
3717
3717
const markerPath = `${ folderPath } .complete` ;
3718
3718
yield io . rmRF ( folderPath ) ;
@@ -3722,7 +3722,7 @@ function _createToolPath(tool, version, arch) {
3722
3722
} ) ;
3723
3723
}
3724
3724
function _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 || '' ) ;
3726
3726
const markerPath = `${ folderPath } .complete` ;
3727
3727
fs . writeFileSync ( markerPath , '' ) ;
3728
3728
core . debug ( 'finished caching tool' ) ;
@@ -3759,6 +3759,31 @@ function _evaluateVersions(versions, versionSpec) {
3759
3759
}
3760
3760
return version ;
3761
3761
}
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
+ }
3762
3787
//# sourceMappingURL=tool-cache.js.map
3763
3788
3764
3789
/***/ } ) ,
@@ -4718,6 +4743,13 @@ function makeSemver(version) {
4718
4743
exports . makeSemver = makeSemver ;
4719
4744
4720
4745
4746
+ /***/ } ) ,
4747
+
4748
+ /***/ 794 :
4749
+ /***/ ( function ( module ) {
4750
+
4751
+ module . exports = require ( "stream" ) ;
4752
+
4721
4753
/***/ } ) ,
4722
4754
4723
4755
/***/ 826 :
@@ -4826,6 +4858,83 @@ function checkBypass(reqUrl) {
4826
4858
exports . checkBypass = checkBypass ;
4827
4859
4828
4860
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
+
4829
4938
/***/ } ) ,
4830
4939
4831
4940
/***/ 986 :
0 commit comments