diff --git a/packages/warp-cache/package.json b/packages/warp-cache/package.json index b4d2d03f..366251b3 100644 --- a/packages/warp-cache/package.json +++ b/packages/warp-cache/package.json @@ -1,6 +1,6 @@ { "name": "github-actions.warp-cache", - "version": "1.1.5", + "version": "1.1.6", "preview": true, "description": "Github action to use WarpBuild's in-house cache offering", "keywords": [ diff --git a/packages/warp-cache/src/cache.ts b/packages/warp-cache/src/cache.ts index 715015df..65adce85 100644 --- a/packages/warp-cache/src/cache.ts +++ b/packages/warp-cache/src/cache.ts @@ -225,14 +225,31 @@ export async function restoreCache( downloadCommandPipe ) } catch (error) { - core.info(`Streaming download failed. Retrying: ${error}`) - // Try to download the cache using the non-streaming method - await cacheHttpClient.downloadCache( - cacheEntry.provider, - archiveLocation, - archivePath, - cacheEntry.gcs?.short_lived_token?.access_token ?? '' + core.info( + `Streaming download failed. Retrying with multipart: ${error}` ) + // Wait 1 second + await new Promise(resolve => setTimeout(resolve, 1000)) + // Try to download the cache using the non-streaming method + try { + await cacheHttpClient.downloadCache( + cacheEntry.provider, + archiveLocation, + archivePath, + cacheEntry.gcs?.short_lived_token?.access_token ?? '' + ) + } catch (error) { + core.info( + `Multipart Download failed. Retrying with basic download: ${error}` + ) + await new Promise(resolve => setTimeout(resolve, 1000)) + await cacheHttpClient.downloadCacheSingleThread( + cacheEntry.provider, + archiveLocation, + archivePath, + cacheEntry.gcs?.short_lived_token?.access_token ?? '' + ) + } if (core.isDebug()) { await listTar(archivePath, compressionMethod) diff --git a/packages/warp-cache/src/internal/cacheHttpClient.ts b/packages/warp-cache/src/internal/cacheHttpClient.ts index 566f8c94..b3e11bce 100644 --- a/packages/warp-cache/src/internal/cacheHttpClient.ts +++ b/packages/warp-cache/src/internal/cacheHttpClient.ts @@ -15,6 +15,7 @@ import { InternalS3CompletedPart } from './contracts' import { + downloadCacheGCP, downloadCacheMultiConnection, downloadCacheMultipartGCP, downloadCacheStreamingGCP @@ -230,6 +231,33 @@ export async function downloadCache( } } +export async function downloadCacheSingleThread( + provider: string, + archiveLocation: string, + archivePath: string, + gcsToken?: string +): Promise { + switch (provider) { + case 's3': + break + case 'gcs': { + if (!gcsToken) { + throw new Error( + 'Unable to download cache from GCS. GCP token is not provided.' + ) + } + + const oauth2Client = new OAuth2Client() + oauth2Client.setCredentials({access_token: gcsToken}) + const storage = new Storage({ + authClient: oauth2Client + }) + await downloadCacheGCP(storage, archiveLocation, archivePath) + break + } + } +} + export function downloadCacheStreaming( provider: string, archiveLocation: string, diff --git a/packages/warp-cache/src/internal/downloadUtils.ts b/packages/warp-cache/src/internal/downloadUtils.ts index a02507db..611f87a1 100644 --- a/packages/warp-cache/src/internal/downloadUtils.ts +++ b/packages/warp-cache/src/internal/downloadUtils.ts @@ -322,6 +322,26 @@ export async function downloadCacheMultipartGCP( } } +export async function downloadCacheGCP( + storage: Storage, + archiveLocation: string, + archivePath: string +) { + try { + const {bucketName, objectName} = + utils.retrieveGCSBucketAndObjectName(archiveLocation) + + await storage.bucket(bucketName).file(objectName).download({ + destination: archivePath, + validation: 'crc32c' + }) + } catch (error) { + core.debug(`Failed to download cache: ${error}`) + core.error(`Failed to download cache.`) + throw error + } +} + /** * Download the cache to a provider writable stream using GCloud SDK *