diff --git a/.licenses/npm/@actions/cache.dep.yml b/.licenses/npm/@actions/cache.dep.yml index c3c245ef3..d9a80f6ba 100644 --- a/.licenses/npm/@actions/cache.dep.yml +++ b/.licenses/npm/@actions/cache.dep.yml @@ -1,6 +1,6 @@ --- name: "@actions/cache" -version: 3.0.0 +version: 3.0.4 type: npm summary: Actions cache lib homepage: https://github.com/actions/toolkit/tree/main/packages/cache diff --git a/dist/cache-save/index.js b/dist/cache-save/index.js index a79693b2b..7ab6a4b12 100644 --- a/dist/cache-save/index.js +++ b/dist/cache-save/index.js @@ -525,7 +525,13 @@ function resolvePaths(patterns) { .replace(new RegExp(`\\${path.sep}`, 'g'), '/'); core.debug(`Matched: ${relativeFile}`); // Paths are made relative so the tar entries are all relative to the root of the workspace. - paths.push(`${relativeFile}`); + if (relativeFile === '') { + // path.relative returns empty string if workspace and file are equal + paths.push('.'); + } + else { + paths.push(`${relativeFile}`); + } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -683,6 +689,7 @@ const util = __importStar(__nccwpck_require__(3837)); const utils = __importStar(__nccwpck_require__(1518)); const constants_1 = __nccwpck_require__(8840); const requestUtils_1 = __nccwpck_require__(3981); +const abort_controller_1 = __nccwpck_require__(2557); /** * Pipes the body of a HTTP response to a stream * @@ -866,15 +873,24 @@ function downloadCacheStorageSDK(archiveLocation, archivePath, options) { const fd = fs.openSync(archivePath, 'w'); try { downloadProgress.startDisplayTimer(); + const controller = new abort_controller_1.AbortController(); + const abortSignal = controller.signal; while (!downloadProgress.isDone()) { const segmentStart = downloadProgress.segmentOffset + downloadProgress.segmentSize; const segmentSize = Math.min(maxSegmentSize, contentLength - segmentStart); downloadProgress.nextSegment(segmentSize); - const result = yield client.downloadToBuffer(segmentStart, segmentSize, { + const result = yield promiseWithTimeout(options.segmentTimeoutInMs || 3600000, client.downloadToBuffer(segmentStart, segmentSize, { + abortSignal, concurrency: options.downloadConcurrency, onProgress: downloadProgress.onProgress() - }); - fs.writeFileSync(fd, result); + })); + if (result === 'timeout') { + controller.abort(); + throw new Error('Aborting cache download as the download time exceeded the timeout.'); + } + else if (Buffer.isBuffer(result)) { + fs.writeFileSync(fd, result); + } } } finally { @@ -885,6 +901,16 @@ function downloadCacheStorageSDK(archiveLocation, archivePath, options) { }); } exports.downloadCacheStorageSDK = downloadCacheStorageSDK; +const promiseWithTimeout = (timeoutMs, promise) => __awaiter(void 0, void 0, void 0, function* () { + let timeoutHandle; + const timeoutPromise = new Promise(resolve => { + timeoutHandle = setTimeout(() => resolve('timeout'), timeoutMs); + }); + return Promise.race([promise, timeoutPromise]).then(result => { + clearTimeout(timeoutHandle); + return result; + }); +}); //# sourceMappingURL=downloadUtils.js.map /***/ }), @@ -1044,6 +1070,7 @@ const fs_1 = __nccwpck_require__(7147); const path = __importStar(__nccwpck_require__(1017)); const utils = __importStar(__nccwpck_require__(1518)); const constants_1 = __nccwpck_require__(8840); +const IS_WINDOWS = process.platform === 'win32'; function getTarPath(args, compressionMethod) { return __awaiter(this, void 0, void 0, function* () { switch (process.platform) { @@ -1091,26 +1118,43 @@ function getWorkingDirectory() { var _a; return (_a = process.env['GITHUB_WORKSPACE']) !== null && _a !== void 0 ? _a : process.cwd(); } +// Common function for extractTar and listTar to get the compression method +function getCompressionProgram(compressionMethod) { + // -d: Decompress. + // unzstd is equivalent to 'zstd -d' + // --long=#: Enables long distance matching with # bits. Maximum is 30 (1GB) on 32-bit OS and 31 (2GB) on 64-bit. + // Using 30 here because we also support 32-bit self-hosted runners. + switch (compressionMethod) { + case constants_1.CompressionMethod.Zstd: + return [ + '--use-compress-program', + IS_WINDOWS ? 'zstd -d --long=30' : 'unzstd --long=30' + ]; + case constants_1.CompressionMethod.ZstdWithoutLong: + return ['--use-compress-program', IS_WINDOWS ? 'zstd -d' : 'unzstd']; + default: + return ['-z']; + } +} +function listTar(archivePath, compressionMethod) { + return __awaiter(this, void 0, void 0, function* () { + const args = [ + ...getCompressionProgram(compressionMethod), + '-tf', + archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), + '-P' + ]; + yield execTar(args, compressionMethod); + }); +} +exports.listTar = listTar; function extractTar(archivePath, compressionMethod) { return __awaiter(this, void 0, void 0, function* () { // Create directory to extract tar into const workingDirectory = getWorkingDirectory(); yield io.mkdirP(workingDirectory); - // --d: Decompress. - // --long=#: Enables long distance matching with # bits. Maximum is 30 (1GB) on 32-bit OS and 31 (2GB) on 64-bit. - // Using 30 here because we also support 32-bit self-hosted runners. - function getCompressionProgram() { - switch (compressionMethod) { - case constants_1.CompressionMethod.Zstd: - return ['--use-compress-program', 'zstd -d --long=30']; - case constants_1.CompressionMethod.ZstdWithoutLong: - return ['--use-compress-program', 'zstd -d']; - default: - return ['-z']; - } - } const args = [ - ...getCompressionProgram(), + ...getCompressionProgram(compressionMethod), '-xf', archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), '-P', @@ -1129,15 +1173,19 @@ function createTar(archiveFolder, sourceDirectories, compressionMethod) { fs_1.writeFileSync(path.join(archiveFolder, manifestFilename), sourceDirectories.join('\n')); const workingDirectory = getWorkingDirectory(); // -T#: Compress using # working thread. If # is 0, attempt to detect and use the number of physical CPU cores. + // zstdmt is equivalent to 'zstd -T0' // --long=#: Enables long distance matching with # bits. Maximum is 30 (1GB) on 32-bit OS and 31 (2GB) on 64-bit. // Using 30 here because we also support 32-bit self-hosted runners. // Long range mode is added to zstd in v1.3.2 release, so we will not use --long in older version of zstd. function getCompressionProgram() { switch (compressionMethod) { case constants_1.CompressionMethod.Zstd: - return ['--use-compress-program', 'zstd -T0 --long=30']; + return [ + '--use-compress-program', + IS_WINDOWS ? 'zstd -T0 --long=30' : 'zstdmt --long=30' + ]; case constants_1.CompressionMethod.ZstdWithoutLong: - return ['--use-compress-program', 'zstd -T0']; + return ['--use-compress-program', IS_WINDOWS ? 'zstd -T0' : 'zstdmt']; default: return ['-z']; } @@ -1159,32 +1207,6 @@ function createTar(archiveFolder, sourceDirectories, compressionMethod) { }); } exports.createTar = createTar; -function listTar(archivePath, compressionMethod) { - return __awaiter(this, void 0, void 0, function* () { - // --d: Decompress. - // --long=#: Enables long distance matching with # bits. - // Maximum is 30 (1GB) on 32-bit OS and 31 (2GB) on 64-bit. - // Using 30 here because we also support 32-bit self-hosted runners. - function getCompressionProgram() { - switch (compressionMethod) { - case constants_1.CompressionMethod.Zstd: - return ['--use-compress-program', 'zstd -d --long=30']; - case constants_1.CompressionMethod.ZstdWithoutLong: - return ['--use-compress-program', 'zstd -d']; - default: - return ['-z']; - } - } - const args = [ - ...getCompressionProgram(), - '-tf', - archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), - '-P' - ]; - yield execTar(args, compressionMethod); - }); -} -exports.listTar = listTar; //# sourceMappingURL=tar.js.map /***/ }), @@ -1235,7 +1257,8 @@ function getDownloadOptions(copy) { const result = { useAzureSdk: true, downloadConcurrency: 8, - timeoutInMs: 30000 + timeoutInMs: 30000, + segmentTimeoutInMs: 3600000 }; if (copy) { if (typeof copy.useAzureSdk === 'boolean') { @@ -1247,10 +1270,21 @@ function getDownloadOptions(copy) { if (typeof copy.timeoutInMs === 'number') { result.timeoutInMs = copy.timeoutInMs; } + if (typeof copy.segmentTimeoutInMs === 'number') { + result.segmentTimeoutInMs = copy.segmentTimeoutInMs; + } + } + const segmentDownloadTimeoutMins = process.env['SEGMENT_DOWNLOAD_TIMEOUT_MINS']; + if (segmentDownloadTimeoutMins && + !isNaN(Number(segmentDownloadTimeoutMins)) && + isFinite(Number(segmentDownloadTimeoutMins))) { + result.segmentTimeoutInMs = Number(segmentDownloadTimeoutMins) * 60 * 1000; } core.debug(`Use Azure SDK: ${result.useAzureSdk}`); core.debug(`Download concurrency: ${result.downloadConcurrency}`); core.debug(`Request timeout (ms): ${result.timeoutInMs}`); + core.debug(`Cache segment download timeout mins env var: ${process.env['SEGMENT_DOWNLOAD_TIMEOUT_MINS']}`); + core.debug(`Segment download timeout (ms): ${result.segmentTimeoutInMs}`); return result; } exports.getDownloadOptions = getDownloadOptions; diff --git a/dist/setup/index.js b/dist/setup/index.js index 0407c1ce2..90f833a8a 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -525,7 +525,13 @@ function resolvePaths(patterns) { .replace(new RegExp(`\\${path.sep}`, 'g'), '/'); core.debug(`Matched: ${relativeFile}`); // Paths are made relative so the tar entries are all relative to the root of the workspace. - paths.push(`${relativeFile}`); + if (relativeFile === '') { + // path.relative returns empty string if workspace and file are equal + paths.push('.'); + } + else { + paths.push(`${relativeFile}`); + } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -683,6 +689,7 @@ const util = __importStar(__nccwpck_require__(3837)); const utils = __importStar(__nccwpck_require__(1518)); const constants_1 = __nccwpck_require__(8840); const requestUtils_1 = __nccwpck_require__(3981); +const abort_controller_1 = __nccwpck_require__(2557); /** * Pipes the body of a HTTP response to a stream * @@ -866,15 +873,24 @@ function downloadCacheStorageSDK(archiveLocation, archivePath, options) { const fd = fs.openSync(archivePath, 'w'); try { downloadProgress.startDisplayTimer(); + const controller = new abort_controller_1.AbortController(); + const abortSignal = controller.signal; while (!downloadProgress.isDone()) { const segmentStart = downloadProgress.segmentOffset + downloadProgress.segmentSize; const segmentSize = Math.min(maxSegmentSize, contentLength - segmentStart); downloadProgress.nextSegment(segmentSize); - const result = yield client.downloadToBuffer(segmentStart, segmentSize, { + const result = yield promiseWithTimeout(options.segmentTimeoutInMs || 3600000, client.downloadToBuffer(segmentStart, segmentSize, { + abortSignal, concurrency: options.downloadConcurrency, onProgress: downloadProgress.onProgress() - }); - fs.writeFileSync(fd, result); + })); + if (result === 'timeout') { + controller.abort(); + throw new Error('Aborting cache download as the download time exceeded the timeout.'); + } + else if (Buffer.isBuffer(result)) { + fs.writeFileSync(fd, result); + } } } finally { @@ -885,6 +901,16 @@ function downloadCacheStorageSDK(archiveLocation, archivePath, options) { }); } exports.downloadCacheStorageSDK = downloadCacheStorageSDK; +const promiseWithTimeout = (timeoutMs, promise) => __awaiter(void 0, void 0, void 0, function* () { + let timeoutHandle; + const timeoutPromise = new Promise(resolve => { + timeoutHandle = setTimeout(() => resolve('timeout'), timeoutMs); + }); + return Promise.race([promise, timeoutPromise]).then(result => { + clearTimeout(timeoutHandle); + return result; + }); +}); //# sourceMappingURL=downloadUtils.js.map /***/ }), @@ -1044,6 +1070,7 @@ const fs_1 = __nccwpck_require__(7147); const path = __importStar(__nccwpck_require__(1017)); const utils = __importStar(__nccwpck_require__(1518)); const constants_1 = __nccwpck_require__(8840); +const IS_WINDOWS = process.platform === 'win32'; function getTarPath(args, compressionMethod) { return __awaiter(this, void 0, void 0, function* () { switch (process.platform) { @@ -1091,26 +1118,43 @@ function getWorkingDirectory() { var _a; return (_a = process.env['GITHUB_WORKSPACE']) !== null && _a !== void 0 ? _a : process.cwd(); } +// Common function for extractTar and listTar to get the compression method +function getCompressionProgram(compressionMethod) { + // -d: Decompress. + // unzstd is equivalent to 'zstd -d' + // --long=#: Enables long distance matching with # bits. Maximum is 30 (1GB) on 32-bit OS and 31 (2GB) on 64-bit. + // Using 30 here because we also support 32-bit self-hosted runners. + switch (compressionMethod) { + case constants_1.CompressionMethod.Zstd: + return [ + '--use-compress-program', + IS_WINDOWS ? 'zstd -d --long=30' : 'unzstd --long=30' + ]; + case constants_1.CompressionMethod.ZstdWithoutLong: + return ['--use-compress-program', IS_WINDOWS ? 'zstd -d' : 'unzstd']; + default: + return ['-z']; + } +} +function listTar(archivePath, compressionMethod) { + return __awaiter(this, void 0, void 0, function* () { + const args = [ + ...getCompressionProgram(compressionMethod), + '-tf', + archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), + '-P' + ]; + yield execTar(args, compressionMethod); + }); +} +exports.listTar = listTar; function extractTar(archivePath, compressionMethod) { return __awaiter(this, void 0, void 0, function* () { // Create directory to extract tar into const workingDirectory = getWorkingDirectory(); yield io.mkdirP(workingDirectory); - // --d: Decompress. - // --long=#: Enables long distance matching with # bits. Maximum is 30 (1GB) on 32-bit OS and 31 (2GB) on 64-bit. - // Using 30 here because we also support 32-bit self-hosted runners. - function getCompressionProgram() { - switch (compressionMethod) { - case constants_1.CompressionMethod.Zstd: - return ['--use-compress-program', 'zstd -d --long=30']; - case constants_1.CompressionMethod.ZstdWithoutLong: - return ['--use-compress-program', 'zstd -d']; - default: - return ['-z']; - } - } const args = [ - ...getCompressionProgram(), + ...getCompressionProgram(compressionMethod), '-xf', archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), '-P', @@ -1129,15 +1173,19 @@ function createTar(archiveFolder, sourceDirectories, compressionMethod) { fs_1.writeFileSync(path.join(archiveFolder, manifestFilename), sourceDirectories.join('\n')); const workingDirectory = getWorkingDirectory(); // -T#: Compress using # working thread. If # is 0, attempt to detect and use the number of physical CPU cores. + // zstdmt is equivalent to 'zstd -T0' // --long=#: Enables long distance matching with # bits. Maximum is 30 (1GB) on 32-bit OS and 31 (2GB) on 64-bit. // Using 30 here because we also support 32-bit self-hosted runners. // Long range mode is added to zstd in v1.3.2 release, so we will not use --long in older version of zstd. function getCompressionProgram() { switch (compressionMethod) { case constants_1.CompressionMethod.Zstd: - return ['--use-compress-program', 'zstd -T0 --long=30']; + return [ + '--use-compress-program', + IS_WINDOWS ? 'zstd -T0 --long=30' : 'zstdmt --long=30' + ]; case constants_1.CompressionMethod.ZstdWithoutLong: - return ['--use-compress-program', 'zstd -T0']; + return ['--use-compress-program', IS_WINDOWS ? 'zstd -T0' : 'zstdmt']; default: return ['-z']; } @@ -1159,32 +1207,6 @@ function createTar(archiveFolder, sourceDirectories, compressionMethod) { }); } exports.createTar = createTar; -function listTar(archivePath, compressionMethod) { - return __awaiter(this, void 0, void 0, function* () { - // --d: Decompress. - // --long=#: Enables long distance matching with # bits. - // Maximum is 30 (1GB) on 32-bit OS and 31 (2GB) on 64-bit. - // Using 30 here because we also support 32-bit self-hosted runners. - function getCompressionProgram() { - switch (compressionMethod) { - case constants_1.CompressionMethod.Zstd: - return ['--use-compress-program', 'zstd -d --long=30']; - case constants_1.CompressionMethod.ZstdWithoutLong: - return ['--use-compress-program', 'zstd -d']; - default: - return ['-z']; - } - } - const args = [ - ...getCompressionProgram(), - '-tf', - archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), - '-P' - ]; - yield execTar(args, compressionMethod); - }); -} -exports.listTar = listTar; //# sourceMappingURL=tar.js.map /***/ }), @@ -1235,7 +1257,8 @@ function getDownloadOptions(copy) { const result = { useAzureSdk: true, downloadConcurrency: 8, - timeoutInMs: 30000 + timeoutInMs: 30000, + segmentTimeoutInMs: 3600000 }; if (copy) { if (typeof copy.useAzureSdk === 'boolean') { @@ -1247,10 +1270,21 @@ function getDownloadOptions(copy) { if (typeof copy.timeoutInMs === 'number') { result.timeoutInMs = copy.timeoutInMs; } + if (typeof copy.segmentTimeoutInMs === 'number') { + result.segmentTimeoutInMs = copy.segmentTimeoutInMs; + } + } + const segmentDownloadTimeoutMins = process.env['SEGMENT_DOWNLOAD_TIMEOUT_MINS']; + if (segmentDownloadTimeoutMins && + !isNaN(Number(segmentDownloadTimeoutMins)) && + isFinite(Number(segmentDownloadTimeoutMins))) { + result.segmentTimeoutInMs = Number(segmentDownloadTimeoutMins) * 60 * 1000; } core.debug(`Use Azure SDK: ${result.useAzureSdk}`); core.debug(`Download concurrency: ${result.downloadConcurrency}`); core.debug(`Request timeout (ms): ${result.timeoutInMs}`); + core.debug(`Cache segment download timeout mins env var: ${process.env['SEGMENT_DOWNLOAD_TIMEOUT_MINS']}`); + core.debug(`Segment download timeout (ms): ${result.segmentTimeoutInMs}`); return result; } exports.getDownloadOptions = getDownloadOptions; diff --git a/package-lock.json b/package-lock.json index 5963fa8f5..2409f72e0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "3.4.1", "license": "MIT", "dependencies": { - "@actions/cache": "^3.0.0", + "@actions/cache": "^3.0.4", "@actions/core": "^1.6.0", "@actions/exec": "^1.1.0", "@actions/github": "^1.1.0", @@ -32,9 +32,9 @@ } }, "node_modules/@actions/cache": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@actions/cache/-/cache-3.0.0.tgz", - "integrity": "sha512-GL9CT1Fnu+pqs8TTB621q8Xa8Cilw2n9MwvbgMedetH7L1q2n6jY61gzbwGbKgtVbp3gVJ12aNMi4osSGXx3KQ==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@actions/cache/-/cache-3.0.4.tgz", + "integrity": "sha512-9RwVL8/ISJoYWFNH1wR/C26E+M3HDkGPWmbFJMMCKwTkjbNZJreMT4XaR/EB1bheIvN4PREQxEQQVJ18IPnf/Q==", "dependencies": { "@actions/core": "^1.2.6", "@actions/exec": "^1.0.1", @@ -5087,9 +5087,9 @@ }, "dependencies": { "@actions/cache": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@actions/cache/-/cache-3.0.0.tgz", - "integrity": "sha512-GL9CT1Fnu+pqs8TTB621q8Xa8Cilw2n9MwvbgMedetH7L1q2n6jY61gzbwGbKgtVbp3gVJ12aNMi4osSGXx3KQ==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@actions/cache/-/cache-3.0.4.tgz", + "integrity": "sha512-9RwVL8/ISJoYWFNH1wR/C26E+M3HDkGPWmbFJMMCKwTkjbNZJreMT4XaR/EB1bheIvN4PREQxEQQVJ18IPnf/Q==", "requires": { "@actions/core": "^1.2.6", "@actions/exec": "^1.0.1", diff --git a/package.json b/package.json index ee15cc8c0..38469c304 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "author": "GitHub", "license": "MIT", "dependencies": { - "@actions/cache": "^3.0.0", + "@actions/cache": "^3.0.4", "@actions/core": "^1.6.0", "@actions/exec": "^1.1.0", "@actions/github": "^1.1.0",
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: