diff --git a/.github/workflows/bump-cache-version.yml b/.github/workflows/bump-cache-version.yml deleted file mode 100644 index a8187833..00000000 --- a/.github/workflows/bump-cache-version.yml +++ /dev/null @@ -1,64 +0,0 @@ -name: Bump Cache Version - -on: - workflow_dispatch: - inputs: - cache_version: - description: "New @useblacksmith/cache version" - required: true - type: string - -jobs: - bump-cache-version: - runs-on: blacksmith - steps: - - uses: actions/checkout@v4 - - - name: Create new branch - id: create-branch - run: | - git config user.name github-actions[bot] - git config user.email github-actions[bot]@users.noreply.github.com - git fetch origin master - git checkout master - git pull origin master - timestamp=$(date +%Y%m%d%H%M%S) - branch_name="bump-cache-version-${{ github.event.inputs.cache_version }}-$timestamp" - git checkout -b $branch_name - echo "branch_name=$branch_name" >> $GITHUB_OUTPUT - cd packages/setup-ocaml - - - name: Update package.json - working-directory: packages/setup-ocaml - run: | - sed -i 's/"@actions\/cache": "npm:@useblacksmith\/cache@[^"]*"/"@actions\/cache": "npm:@useblacksmith\/cache@${{ github.event.inputs.cache_version }}"/' package.json - - - name: Setup Node.js - uses: actions/setup-node@v3 - with: - node-version: '18' - - - name: Install Yarn - run: npm install -g yarn@4.1.0 - - - name: Install dependencies - working-directory: packages/setup-ocaml - run: yarn install - - - name: Build - working-directory: packages/setup-ocaml - run: yarn build - - - name: Check for changes - id: git-check - run: | - git diff --exit-code || echo "changes=true" >> $GITHUB_OUTPUT - - name: Create Pull Request - if: steps.git-check.outputs.changes == 'true' - env: - GH_TOKEN: ${{ github.token }} - run: | - git add . - git commit -m "Bump @actions/cache version to ${{ github.event.inputs.cache_version }}" - git push origin ${{ steps.create-branch.outputs.branch_name }} - gh pr create --title "Bump @actions/cache version to ${{ github.event.inputs.cache_version }}" --body "This PR updates the @actions/cache version to ${{ github.event.inputs.cache_version }}" \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index c2648c72..dd288aff 100644 --- a/dist/index.js +++ b/dist/index.js @@ -95,10 +95,11 @@ const promiseWithTimeout = (timeoutMs, promise) => __awaiter(void 0, void 0, voi }); }); function reportFailure() { + var _a, _b; return __awaiter(this, void 0, void 0, function* () { try { core.info('Reporting failure to api.blacksmith.sh'); - const message = `${process.env.GITHUB_JOB} failed for ${process.env.GITHUB_REPOSITORY} with run ID: ${process.env.GITHUB_RUN_ID}; Sender: ${process.env.GITHUB_TRIGGERING_ACTOR}`; + const message = `${process.env.GITHUB_JOB} failed for ${process.env.GITHUB_REPOSITORY} with run ID: ${process.env.GITHUB_RUN_ID}; Sender: ${process.env.GITHUB_TRIGGERING_ACTOR}; VM ID: ${(_a = process.env.VM_ID) !== null && _a !== void 0 ? _a : 'unknown'}; petname: ${(_b = process.env.PETNAME) !== null && _b !== void 0 ? _b : 'unknown'}`; const httpClient = (0, cacheHttpClient_1.createHttpClient)(); yield promiseWithTimeout(10000, httpClient.postJson((0, cacheHttpClient_1.getCacheApiUrl)('report-failed'), { message @@ -180,9 +181,7 @@ function restoreCache(paths, primaryKey, restoreKeys, options, enableCrossOsArch finally { // Try to delete the archive to save space try { - const before = Date.now(); yield unlinkWithTimeout(archivePath, 5000); - core.info(`cleaning up archive took ${Date.now() - before}ms`); } catch (error) { core.debug(`Failed to delete archive: ${error}`); @@ -334,6 +333,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.saveCache = exports.reserveCache = exports.downloadCache = exports.getCacheEntry = exports.getCacheVersion = exports.createHttpClient = exports.getCacheApiUrl = void 0; const core = __importStar(__nccwpck_require__(37117)); @@ -346,14 +348,20 @@ const utils = __importStar(__nccwpck_require__(44812)); const downloadUtils_1 = __nccwpck_require__(55613); const options_1 = __nccwpck_require__(2269); const requestUtils_1 = __nccwpck_require__(42506); +const axios_1 = __importDefault(__nccwpck_require__(88379)); const versionSalt = '1.0'; function getCacheApiUrl(resource) { - const baseUrl = process.env['BLACKSMITH_CACHE_URL'] || 'https://api.blacksmith.sh/cache'; + var _a, _b; + let baseUrl = process.env.BLACKSMITH_CACHE_URL; if (!baseUrl) { - throw new Error('Cache Service Url not found, unable to restore cache.'); + baseUrl = ((_a = process.env.PETNAME) === null || _a === void 0 ? void 0 : _a.includes('staging')) + ? 'https://stagingapi.blacksmith.sh/cache' + : 'https://api.blacksmith.sh/cache'; } const url = `${baseUrl}/${resource}`; - core.debug(`Blacksmith cache resource URL: ${url}; version: 3.2.40`); + if ((_b = process.env.PETNAME) === null || _b === void 0 ? void 0 : _b.includes('staging')) { + core.info(`Using staging API: ${url}`); + } return url; } exports.getCacheApiUrl = getCacheApiUrl; @@ -394,31 +402,65 @@ function getCacheVersion(paths, compressionMethod, enableCrossOsArchive = false) exports.getCacheVersion = getCacheVersion; function getCacheEntry(keys, paths, options) { return __awaiter(this, void 0, void 0, function* () { - const httpClient = createHttpClient(); const version = getCacheVersion(paths, options === null || options === void 0 ? void 0 : options.compressionMethod, options === null || options === void 0 ? void 0 : options.enableCrossOsArchive); const resource = `?keys=${encodeURIComponent(keys.join(','))}&version=${version}`; - const response = yield (0, requestUtils_1.retryTypedResponse)('getCacheEntry', () => __awaiter(this, void 0, void 0, function* () { return httpClient.getJson(getCacheApiUrl(resource)); })); - // Cache not found - if (response.statusCode === 204) { - // List cache for primary key only if cache miss occurs - if (core.isDebug()) { - yield printCachesListForDiagnostics(keys[0], httpClient, version); + const maxRetries = 2; + let retries = 0; + core.info(`Checking cache for keys ${keys.join(',')} and version ${version}`); + while (retries <= maxRetries) { + try { + const before = Date.now(); + const response = yield axios_1.default.get(getCacheApiUrl(resource), { + headers: { + Accept: createAcceptHeader('application/json', '6.0-preview.1'), + 'X-Github-Repo-Name': process.env['GITHUB_REPO_NAME'], + Authorization: `Bearer ${process.env['BLACKSMITH_CACHE_TOKEN']}` + }, + timeout: 10000 // 10 seconds timeout + }); + core.debug(`Cache lookup took ${Date.now() - before}ms`); + // Cache not found + if (response.status === 204) { + // List cache for primary key only if cache miss occurs + if (core.isDebug()) { + yield printCachesListForDiagnostics(keys[0], createHttpClient(), version); + } + return null; + } + if (response.status < 200 || response.status >= 300) { + throw new Error(`Cache service responded with ${response.status}`); + } + const cacheResult = response.data; + const cacheDownloadUrl = cacheResult === null || cacheResult === void 0 ? void 0 : cacheResult.archiveLocation; + if (!cacheDownloadUrl) { + // Cache archiveLocation not found. This should never happen, and hence bail out. + throw new Error('Cache not found.'); + } + core.setSecret(cacheDownloadUrl); + core.debug(`Cache Result:`); + core.debug(JSON.stringify(cacheResult)); + return cacheResult; + } + catch (error) { + if (error.response && + error.response.status >= 500 && + retries < maxRetries) { + retries++; + core.warning(`Retrying due to server error (attempt ${retries} of ${maxRetries})`); + continue; + } + if (error.response) { + throw new Error(`Cache service responded with ${error.response.status}`); + } + else if (error.code === 'ECONNABORTED') { + throw new Error('Request timed out after 10 seconds'); + } + else { + throw error; + } } - return null; - } - if (!(0, requestUtils_1.isSuccessStatusCode)(response.statusCode)) { - throw new Error(`Cache service responded with ${response.statusCode}`); - } - const cacheResult = response.result; - const cacheDownloadUrl = cacheResult === null || cacheResult === void 0 ? void 0 : cacheResult.archiveLocation; - if (!cacheDownloadUrl) { - // Cache achiveLocation not found. This should never happen, and hence bail out. - throw new Error('Cache not found.'); } - core.setSecret(cacheDownloadUrl); - core.debug(`Cache Result:`); - core.debug(JSON.stringify(cacheResult)); - return cacheResult; + throw new Error(`Failed to get cache entry after ${maxRetries} retries`); }); } exports.getCacheEntry = getCacheEntry; @@ -1059,12 +1101,25 @@ function downloadCacheAxiosMultiPart(archiveLocation, archivePath) { }); try { core.debug(`Downloading from ${archiveLocation} to ${archivePath}`); - const metadataResponse = yield axios_1.default.get(archiveLocation, { - headers: { Range: 'bytes=0-1' } - }); - const contentRangeHeader = metadataResponse.headers['content-range']; + let metadataResponse; + let contentRangeHeader; + let retries = 0; + const maxRetries = 2; + while (retries <= maxRetries) { + metadataResponse = yield axios_1.default.get(archiveLocation, { + headers: { Range: 'bytes=0-1' } + }); + contentRangeHeader = metadataResponse.headers['content-range']; + if (contentRangeHeader) { + break; + } + retries++; + if (retries <= maxRetries) { + core.debug(`Content-Range header not found. Retrying (${retries}/${maxRetries})...`); + } + } if (!contentRangeHeader) { - throw new Error('Content-Range is not defined; unable to determine file size'); + throw new Error('Content-Range is not defined after retries; unable to determine file size'); } // Parse the total file size from the Content-Range header const fileSize = parseInt(contentRangeHeader.split('/')[1]); @@ -1242,7 +1297,6 @@ exports.downloadCacheHttpClient = downloadCacheHttpClient; function downloadCacheHttpClientConcurrent(archiveLocation, archivePath, options) { var _a; return __awaiter(this, void 0, void 0, function* () { - core.info('Downloading from cache using Blacksmith Actions http-client'); const archiveDescriptor = yield fs.promises.open(archivePath, 'w+'); // Set file permissions so that other users can untar the cache yield archiveDescriptor.chmod(0o644); @@ -1257,19 +1311,34 @@ function downloadCacheHttpClientConcurrent(archiveLocation, archivePath, options }, 300000); stallTimeout.unref(); // Don't keep the process alive if the download is stalled. try { - const metadataResponse = yield (0, requestUtils_1.retryHttpClientResponse)('downloadCache', () => __awaiter(this, void 0, void 0, function* () { - return httpClient.get(archiveLocation, { - Range: 'bytes=0-1' + let metadataResponse; + let contentRangeHeader; + let retries = 0; + const maxRetries = 2; + while (retries <= maxRetries) { + metadataResponse = yield (0, requestUtils_1.retryHttpClientResponse)('downloadCache', () => __awaiter(this, void 0, void 0, function* () { + return httpClient.get(archiveLocation, { + Range: 'bytes=0-1' + }); + })); + // Abort download if no traffic received over the socket. + metadataResponse.message.socket.setTimeout(constants_1.SocketTimeout, () => { + metadataResponse.message.destroy(); + core.debug(`Aborting download, socket timed out after ${constants_1.SocketTimeout} ms`); }); - })); - // Abort download if no traffic received over the socket. - metadataResponse.message.socket.setTimeout(constants_1.SocketTimeout, () => { - metadataResponse.message.destroy(); - core.debug(`Aborting download, socket timed out after ${constants_1.SocketTimeout} ms`); - }); - const contentRangeHeader = metadataResponse.message.headers['content-range']; + contentRangeHeader = metadataResponse.message.headers['content-range']; + if (contentRangeHeader) { + break; + } + retries++; + if (retries <= maxRetries) { + core.debug(`Content-Range header not found. Retrying (${retries}/${maxRetries})...`); + } + } if (!contentRangeHeader) { - throw new Error('Content-Range is not defined; unable to determine file size'); + const headers = JSON.stringify(metadataResponse.message.headers); + const statusCode = metadataResponse.message.statusCode; + throw new Error(`Content-Range is not defined; unable to determine file size; Headers: ${headers}; Status Code: ${statusCode}`); } // Parse the total file size from the Content-Range header const length = parseInt(contentRangeHeader.split('/')[1]); @@ -1553,9 +1622,12 @@ function retry(name, method, getStatusCode, maxAttempts = constants_1.DefaultRet isRetryable = isRetryableStatusCode(statusCode); errorMessage = `Cache service responded with ${statusCode}`; } + if (!statusCode) { + isRetryable = true; + } core.debug(`${name} - Attempt ${attempt} of ${maxAttempts} failed with error: ${errorMessage}`); if (!isRetryable) { - core.debug(`${name} - Error is not retryable`); + core.warning(`${name} - Error is not retryable; Status Code: ${statusCode}; Error: ${errorMessage}`); break; } yield sleep(delay); @@ -1683,11 +1755,14 @@ function getTarPath() { } // Return arguments for tar as per tarPath, compressionMethod, method type and os function getTarArgs(tarPath, compressionMethod, type, archivePath = '') { + var _a, _b; return __awaiter(this, void 0, void 0, function* () { const args = [`"${tarPath.path}"`]; const cacheFileName = utils.getCacheFileName(compressionMethod); const tarFile = 'cache.tar'; const workingDirectory = getWorkingDirectory(); + const shouldSkipOldFiles = ((_a = process.env['GITHUB_REPOSITORY']) === null || _a === void 0 ? void 0 : _a.includes('muzzapp')) || + ((_b = process.env['GITHUB_REPOSITORY']) === null || _b === void 0 ? void 0 : _b.includes('FastActions')); // Speficic args for BSD tar on windows for workaround const BSD_TAR_ZSTD = tarPath.type === constants_1.ArchiveToolType.BSD && compressionMethod !== constants_1.CompressionMethod.Gzip && @@ -1702,9 +1777,12 @@ function getTarArgs(tarPath, compressionMethod, type, archivePath = '') { : cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), '-P', '-C', workingDirectory.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), '--files-from', constants_1.ManifestFilename); break; case 'extract': - args.push('--skip-old-files', '-xf', BSD_TAR_ZSTD + args.push('-xf', BSD_TAR_ZSTD ? tarFile : archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), '-P', '-C', workingDirectory.replace(new RegExp(`\\${path.sep}`, 'g'), '/')); + if (shouldSkipOldFiles) { + args.push('--skip-old-files'); + } break; case 'list': args.push('-tf', BSD_TAR_ZSTD diff --git a/dist/post/index.js b/dist/post/index.js index dea12cd7..a98703d4 100644 --- a/dist/post/index.js +++ b/dist/post/index.js @@ -95,10 +95,11 @@ const promiseWithTimeout = (timeoutMs, promise) => __awaiter(void 0, void 0, voi }); }); function reportFailure() { + var _a, _b; return __awaiter(this, void 0, void 0, function* () { try { core.info('Reporting failure to api.blacksmith.sh'); - const message = `${process.env.GITHUB_JOB} failed for ${process.env.GITHUB_REPOSITORY} with run ID: ${process.env.GITHUB_RUN_ID}; Sender: ${process.env.GITHUB_TRIGGERING_ACTOR}`; + const message = `${process.env.GITHUB_JOB} failed for ${process.env.GITHUB_REPOSITORY} with run ID: ${process.env.GITHUB_RUN_ID}; Sender: ${process.env.GITHUB_TRIGGERING_ACTOR}; VM ID: ${(_a = process.env.VM_ID) !== null && _a !== void 0 ? _a : 'unknown'}; petname: ${(_b = process.env.PETNAME) !== null && _b !== void 0 ? _b : 'unknown'}`; const httpClient = (0, cacheHttpClient_1.createHttpClient)(); yield promiseWithTimeout(10000, httpClient.postJson((0, cacheHttpClient_1.getCacheApiUrl)('report-failed'), { message @@ -180,9 +181,7 @@ function restoreCache(paths, primaryKey, restoreKeys, options, enableCrossOsArch finally { // Try to delete the archive to save space try { - const before = Date.now(); yield unlinkWithTimeout(archivePath, 5000); - core.info(`cleaning up archive took ${Date.now() - before}ms`); } catch (error) { core.debug(`Failed to delete archive: ${error}`); @@ -334,6 +333,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.saveCache = exports.reserveCache = exports.downloadCache = exports.getCacheEntry = exports.getCacheVersion = exports.createHttpClient = exports.getCacheApiUrl = void 0; const core = __importStar(__nccwpck_require__(7117)); @@ -346,14 +348,20 @@ const utils = __importStar(__nccwpck_require__(4812)); const downloadUtils_1 = __nccwpck_require__(5613); const options_1 = __nccwpck_require__(2269); const requestUtils_1 = __nccwpck_require__(2506); +const axios_1 = __importDefault(__nccwpck_require__(8379)); const versionSalt = '1.0'; function getCacheApiUrl(resource) { - const baseUrl = process.env['BLACKSMITH_CACHE_URL'] || 'https://api.blacksmith.sh/cache'; + var _a, _b; + let baseUrl = process.env.BLACKSMITH_CACHE_URL; if (!baseUrl) { - throw new Error('Cache Service Url not found, unable to restore cache.'); + baseUrl = ((_a = process.env.PETNAME) === null || _a === void 0 ? void 0 : _a.includes('staging')) + ? 'https://stagingapi.blacksmith.sh/cache' + : 'https://api.blacksmith.sh/cache'; } const url = `${baseUrl}/${resource}`; - core.debug(`Blacksmith cache resource URL: ${url}; version: 3.2.40`); + if ((_b = process.env.PETNAME) === null || _b === void 0 ? void 0 : _b.includes('staging')) { + core.info(`Using staging API: ${url}`); + } return url; } exports.getCacheApiUrl = getCacheApiUrl; @@ -394,31 +402,65 @@ function getCacheVersion(paths, compressionMethod, enableCrossOsArchive = false) exports.getCacheVersion = getCacheVersion; function getCacheEntry(keys, paths, options) { return __awaiter(this, void 0, void 0, function* () { - const httpClient = createHttpClient(); const version = getCacheVersion(paths, options === null || options === void 0 ? void 0 : options.compressionMethod, options === null || options === void 0 ? void 0 : options.enableCrossOsArchive); const resource = `?keys=${encodeURIComponent(keys.join(','))}&version=${version}`; - const response = yield (0, requestUtils_1.retryTypedResponse)('getCacheEntry', () => __awaiter(this, void 0, void 0, function* () { return httpClient.getJson(getCacheApiUrl(resource)); })); - // Cache not found - if (response.statusCode === 204) { - // List cache for primary key only if cache miss occurs - if (core.isDebug()) { - yield printCachesListForDiagnostics(keys[0], httpClient, version); + const maxRetries = 2; + let retries = 0; + core.info(`Checking cache for keys ${keys.join(',')} and version ${version}`); + while (retries <= maxRetries) { + try { + const before = Date.now(); + const response = yield axios_1.default.get(getCacheApiUrl(resource), { + headers: { + Accept: createAcceptHeader('application/json', '6.0-preview.1'), + 'X-Github-Repo-Name': process.env['GITHUB_REPO_NAME'], + Authorization: `Bearer ${process.env['BLACKSMITH_CACHE_TOKEN']}` + }, + timeout: 10000 // 10 seconds timeout + }); + core.debug(`Cache lookup took ${Date.now() - before}ms`); + // Cache not found + if (response.status === 204) { + // List cache for primary key only if cache miss occurs + if (core.isDebug()) { + yield printCachesListForDiagnostics(keys[0], createHttpClient(), version); + } + return null; + } + if (response.status < 200 || response.status >= 300) { + throw new Error(`Cache service responded with ${response.status}`); + } + const cacheResult = response.data; + const cacheDownloadUrl = cacheResult === null || cacheResult === void 0 ? void 0 : cacheResult.archiveLocation; + if (!cacheDownloadUrl) { + // Cache archiveLocation not found. This should never happen, and hence bail out. + throw new Error('Cache not found.'); + } + core.setSecret(cacheDownloadUrl); + core.debug(`Cache Result:`); + core.debug(JSON.stringify(cacheResult)); + return cacheResult; + } + catch (error) { + if (error.response && + error.response.status >= 500 && + retries < maxRetries) { + retries++; + core.warning(`Retrying due to server error (attempt ${retries} of ${maxRetries})`); + continue; + } + if (error.response) { + throw new Error(`Cache service responded with ${error.response.status}`); + } + else if (error.code === 'ECONNABORTED') { + throw new Error('Request timed out after 10 seconds'); + } + else { + throw error; + } } - return null; - } - if (!(0, requestUtils_1.isSuccessStatusCode)(response.statusCode)) { - throw new Error(`Cache service responded with ${response.statusCode}`); - } - const cacheResult = response.result; - const cacheDownloadUrl = cacheResult === null || cacheResult === void 0 ? void 0 : cacheResult.archiveLocation; - if (!cacheDownloadUrl) { - // Cache achiveLocation not found. This should never happen, and hence bail out. - throw new Error('Cache not found.'); } - core.setSecret(cacheDownloadUrl); - core.debug(`Cache Result:`); - core.debug(JSON.stringify(cacheResult)); - return cacheResult; + throw new Error(`Failed to get cache entry after ${maxRetries} retries`); }); } exports.getCacheEntry = getCacheEntry; @@ -1059,12 +1101,25 @@ function downloadCacheAxiosMultiPart(archiveLocation, archivePath) { }); try { core.debug(`Downloading from ${archiveLocation} to ${archivePath}`); - const metadataResponse = yield axios_1.default.get(archiveLocation, { - headers: { Range: 'bytes=0-1' } - }); - const contentRangeHeader = metadataResponse.headers['content-range']; + let metadataResponse; + let contentRangeHeader; + let retries = 0; + const maxRetries = 2; + while (retries <= maxRetries) { + metadataResponse = yield axios_1.default.get(archiveLocation, { + headers: { Range: 'bytes=0-1' } + }); + contentRangeHeader = metadataResponse.headers['content-range']; + if (contentRangeHeader) { + break; + } + retries++; + if (retries <= maxRetries) { + core.debug(`Content-Range header not found. Retrying (${retries}/${maxRetries})...`); + } + } if (!contentRangeHeader) { - throw new Error('Content-Range is not defined; unable to determine file size'); + throw new Error('Content-Range is not defined after retries; unable to determine file size'); } // Parse the total file size from the Content-Range header const fileSize = parseInt(contentRangeHeader.split('/')[1]); @@ -1242,7 +1297,6 @@ exports.downloadCacheHttpClient = downloadCacheHttpClient; function downloadCacheHttpClientConcurrent(archiveLocation, archivePath, options) { var _a; return __awaiter(this, void 0, void 0, function* () { - core.info('Downloading from cache using Blacksmith Actions http-client'); const archiveDescriptor = yield fs.promises.open(archivePath, 'w+'); // Set file permissions so that other users can untar the cache yield archiveDescriptor.chmod(0o644); @@ -1257,19 +1311,34 @@ function downloadCacheHttpClientConcurrent(archiveLocation, archivePath, options }, 300000); stallTimeout.unref(); // Don't keep the process alive if the download is stalled. try { - const metadataResponse = yield (0, requestUtils_1.retryHttpClientResponse)('downloadCache', () => __awaiter(this, void 0, void 0, function* () { - return httpClient.get(archiveLocation, { - Range: 'bytes=0-1' + let metadataResponse; + let contentRangeHeader; + let retries = 0; + const maxRetries = 2; + while (retries <= maxRetries) { + metadataResponse = yield (0, requestUtils_1.retryHttpClientResponse)('downloadCache', () => __awaiter(this, void 0, void 0, function* () { + return httpClient.get(archiveLocation, { + Range: 'bytes=0-1' + }); + })); + // Abort download if no traffic received over the socket. + metadataResponse.message.socket.setTimeout(constants_1.SocketTimeout, () => { + metadataResponse.message.destroy(); + core.debug(`Aborting download, socket timed out after ${constants_1.SocketTimeout} ms`); }); - })); - // Abort download if no traffic received over the socket. - metadataResponse.message.socket.setTimeout(constants_1.SocketTimeout, () => { - metadataResponse.message.destroy(); - core.debug(`Aborting download, socket timed out after ${constants_1.SocketTimeout} ms`); - }); - const contentRangeHeader = metadataResponse.message.headers['content-range']; + contentRangeHeader = metadataResponse.message.headers['content-range']; + if (contentRangeHeader) { + break; + } + retries++; + if (retries <= maxRetries) { + core.debug(`Content-Range header not found. Retrying (${retries}/${maxRetries})...`); + } + } if (!contentRangeHeader) { - throw new Error('Content-Range is not defined; unable to determine file size'); + const headers = JSON.stringify(metadataResponse.message.headers); + const statusCode = metadataResponse.message.statusCode; + throw new Error(`Content-Range is not defined; unable to determine file size; Headers: ${headers}; Status Code: ${statusCode}`); } // Parse the total file size from the Content-Range header const length = parseInt(contentRangeHeader.split('/')[1]); @@ -1553,9 +1622,12 @@ function retry(name, method, getStatusCode, maxAttempts = constants_1.DefaultRet isRetryable = isRetryableStatusCode(statusCode); errorMessage = `Cache service responded with ${statusCode}`; } + if (!statusCode) { + isRetryable = true; + } core.debug(`${name} - Attempt ${attempt} of ${maxAttempts} failed with error: ${errorMessage}`); if (!isRetryable) { - core.debug(`${name} - Error is not retryable`); + core.warning(`${name} - Error is not retryable; Status Code: ${statusCode}; Error: ${errorMessage}`); break; } yield sleep(delay); @@ -1683,11 +1755,14 @@ function getTarPath() { } // Return arguments for tar as per tarPath, compressionMethod, method type and os function getTarArgs(tarPath, compressionMethod, type, archivePath = '') { + var _a, _b; return __awaiter(this, void 0, void 0, function* () { const args = [`"${tarPath.path}"`]; const cacheFileName = utils.getCacheFileName(compressionMethod); const tarFile = 'cache.tar'; const workingDirectory = getWorkingDirectory(); + const shouldSkipOldFiles = ((_a = process.env['GITHUB_REPOSITORY']) === null || _a === void 0 ? void 0 : _a.includes('muzzapp')) || + ((_b = process.env['GITHUB_REPOSITORY']) === null || _b === void 0 ? void 0 : _b.includes('FastActions')); // Speficic args for BSD tar on windows for workaround const BSD_TAR_ZSTD = tarPath.type === constants_1.ArchiveToolType.BSD && compressionMethod !== constants_1.CompressionMethod.Gzip && @@ -1702,9 +1777,12 @@ function getTarArgs(tarPath, compressionMethod, type, archivePath = '') { : cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), '-P', '-C', workingDirectory.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), '--files-from', constants_1.ManifestFilename); break; case 'extract': - args.push('--skip-old-files', '-xf', BSD_TAR_ZSTD + args.push('-xf', BSD_TAR_ZSTD ? tarFile : archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), '-P', '-C', workingDirectory.replace(new RegExp(`\\${path.sep}`, 'g'), '/')); + if (shouldSkipOldFiles) { + args.push('--skip-old-files'); + } break; case 'list': args.push('-tf', BSD_TAR_ZSTD diff --git a/packages/setup-ocaml/package.json b/packages/setup-ocaml/package.json index 4ea5e90c..5adf2ac1 100644 --- a/packages/setup-ocaml/package.json +++ b/packages/setup-ocaml/package.json @@ -13,7 +13,7 @@ "typecheck": "tsc" }, "dependencies": { - "@actions/cache": "npm:@useblacksmith/cache@3.2.131", + "@actions/cache": "npm:@useblacksmith/cache@3.2.158", "@actions/core": "1.10.1", "@actions/exec": "1.1.1", "@actions/github": "6.0.0", diff --git a/yarn.lock b/yarn.lock index a673c09c..f4fde496 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,9 +12,9 @@ __metadata: languageName: node linkType: hard -"@actions/cache@npm:@useblacksmith/cache@3.2.131": - version: 3.2.131 - resolution: "@useblacksmith/cache@npm:3.2.131" +"@actions/cache@npm:@useblacksmith/cache@3.2.158": + version: 3.2.158 + resolution: "@useblacksmith/cache@npm:3.2.158" dependencies: "@actions/core": "npm:^1.10.0" "@actions/exec": "npm:^1.0.1" @@ -29,7 +29,7 @@ __metadata: axios-retry: "npm:^4.1.0" semver: "npm:^6.1.0" uuid: "npm:^3.3.3" - checksum: 10c0/a57ba2f7f9667c73b868f23cea4ee142167f6dee1fdcd48742d2efe8619287e55453826b4daaef4f30ba37c3f079951bec1c1f0a9491ba2a2989269abdcbc747 + checksum: 10c0/c60e0bb9ec4da5822baf9c5b66a1fe54f9bf45bbbf11071c03f52c65271e18338a435f376a4029b9415895f0ee5b84e4bf301c824f22308fc8fa2615e887dae8 languageName: node linkType: hard @@ -528,7 +528,7 @@ __metadata: version: 0.0.0-use.local resolution: "@ocaml/setup-ocaml@workspace:packages/setup-ocaml" dependencies: - "@actions/cache": "npm:@useblacksmith/cache@3.2.131" + "@actions/cache": "npm:@useblacksmith/cache@3.2.158" "@actions/core": "npm:1.10.1" "@actions/exec": "npm:1.1.1" "@actions/github": "npm:6.0.0"