gcsCache: return matched cache key, not gcs path

@actions/cache restoreCache contract returns the matched key (primary or
restore) so callers can compare to primaryKey for cache-hit. Our wrapper
was returning the full gcs object path, so restoreImpl.ts always set
cache-hit=false → every job ran pnpm install --frozen-lockfile on top of
a restored node_modules, burning ~34s per job for nothing.

findFileOnGCS now returns { key, path }; outer wrapper returns the key.
pull/1786/head
Jasperhino 3 months ago
parent 01f9143258
commit be02de94c3

@ -92559,15 +92559,21 @@ function restoreFromGCS(_paths_1, primaryKey_1) {
const archiveFolder = yield utils.createTempDirectory(); const archiveFolder = yield utils.createTempDirectory();
const archivePath = path.join(archiveFolder, utils.getCacheFileName(compressionMethod)); const archivePath = path.join(archiveFolder, utils.getCacheFileName(compressionMethod));
const keys = [primaryKey, ...restoreKeys]; const keys = [primaryKey, ...restoreKeys];
const gcsPath = yield findFileOnGCS(storage, bucket, pathPrefix, keys, compressionMethod); const match = yield findFileOnGCS(storage, bucket, pathPrefix, keys, compressionMethod);
if (!gcsPath) { if (!match) {
core.info(`No matching cache found`); core.info(`No matching cache found`);
return undefined; return undefined;
} }
// Preserve the @actions/cache contract: return the matched cache KEY
// (primaryKey or a restoreKey), not the GCS object path. The caller
// (restoreImpl) compares the return value against primaryKey to set the
// `cache-hit` output — returning the gcs path makes `cache-hit` always
// false, re-triggering downstream install/build steps that gate on it.
const { key: matchedKey, path: gcsPath } = match;
// If lookup only, just return the key // If lookup only, just return the key
if (options === null || options === void 0 ? void 0 : options.lookupOnly) { if (options === null || options === void 0 ? void 0 : options.lookupOnly) {
core.info(`Cache found in GCS with key: ${gcsPath}`); core.info(`Cache found in GCS with key: ${matchedKey}`);
return gcsPath; return matchedKey;
} }
try { try {
core.info(`Downloading from GCS: ${bucket}/${gcsPath}`); core.info(`Downloading from GCS: ${bucket}/${gcsPath}`);
@ -92580,7 +92586,7 @@ function restoreFromGCS(_paths_1, primaryKey_1) {
core.info(`Cache Size: ~${Math.round(archiveFileSize / (1024 * 1024))} MB (${archiveFileSize} B)`); core.info(`Cache Size: ~${Math.round(archiveFileSize / (1024 * 1024))} MB (${archiveFileSize} B)`);
yield (0, tar_1.extractTar)(archivePath, compressionMethod); yield (0, tar_1.extractTar)(archivePath, compressionMethod);
core.info("Cache restored successfully"); core.info("Cache restored successfully");
return gcsPath; return matchedKey;
} }
catch (error) { catch (error) {
core.warning(`Failed to restore: ${error.message}`); core.warning(`Failed to restore: ${error.message}`);
@ -92649,7 +92655,7 @@ function findFileOnGCS(storage, bucket, pathPrefix, keys, compressionMethod) {
const gcsPath = getGCSPath(pathPrefix, key, compressionMethod); const gcsPath = getGCSPath(pathPrefix, key, compressionMethod);
if (yield checkFileExists(storage, bucket, gcsPath)) { if (yield checkFileExists(storage, bucket, gcsPath)) {
core.info(`Found file on bucket: ${bucket} with key: ${gcsPath}`); core.info(`Found file on bucket: ${bucket} with key: ${gcsPath}`);
return gcsPath; return { key, path: gcsPath };
} }
} }
return undefined; return undefined;

@ -92559,15 +92559,21 @@ function restoreFromGCS(_paths_1, primaryKey_1) {
const archiveFolder = yield utils.createTempDirectory(); const archiveFolder = yield utils.createTempDirectory();
const archivePath = path.join(archiveFolder, utils.getCacheFileName(compressionMethod)); const archivePath = path.join(archiveFolder, utils.getCacheFileName(compressionMethod));
const keys = [primaryKey, ...restoreKeys]; const keys = [primaryKey, ...restoreKeys];
const gcsPath = yield findFileOnGCS(storage, bucket, pathPrefix, keys, compressionMethod); const match = yield findFileOnGCS(storage, bucket, pathPrefix, keys, compressionMethod);
if (!gcsPath) { if (!match) {
core.info(`No matching cache found`); core.info(`No matching cache found`);
return undefined; return undefined;
} }
// Preserve the @actions/cache contract: return the matched cache KEY
// (primaryKey or a restoreKey), not the GCS object path. The caller
// (restoreImpl) compares the return value against primaryKey to set the
// `cache-hit` output — returning the gcs path makes `cache-hit` always
// false, re-triggering downstream install/build steps that gate on it.
const { key: matchedKey, path: gcsPath } = match;
// If lookup only, just return the key // If lookup only, just return the key
if (options === null || options === void 0 ? void 0 : options.lookupOnly) { if (options === null || options === void 0 ? void 0 : options.lookupOnly) {
core.info(`Cache found in GCS with key: ${gcsPath}`); core.info(`Cache found in GCS with key: ${matchedKey}`);
return gcsPath; return matchedKey;
} }
try { try {
core.info(`Downloading from GCS: ${bucket}/${gcsPath}`); core.info(`Downloading from GCS: ${bucket}/${gcsPath}`);
@ -92580,7 +92586,7 @@ function restoreFromGCS(_paths_1, primaryKey_1) {
core.info(`Cache Size: ~${Math.round(archiveFileSize / (1024 * 1024))} MB (${archiveFileSize} B)`); core.info(`Cache Size: ~${Math.round(archiveFileSize / (1024 * 1024))} MB (${archiveFileSize} B)`);
yield (0, tar_1.extractTar)(archivePath, compressionMethod); yield (0, tar_1.extractTar)(archivePath, compressionMethod);
core.info("Cache restored successfully"); core.info("Cache restored successfully");
return gcsPath; return matchedKey;
} }
catch (error) { catch (error) {
core.warning(`Failed to restore: ${error.message}`); core.warning(`Failed to restore: ${error.message}`);
@ -92649,7 +92655,7 @@ function findFileOnGCS(storage, bucket, pathPrefix, keys, compressionMethod) {
const gcsPath = getGCSPath(pathPrefix, key, compressionMethod); const gcsPath = getGCSPath(pathPrefix, key, compressionMethod);
if (yield checkFileExists(storage, bucket, gcsPath)) { if (yield checkFileExists(storage, bucket, gcsPath)) {
core.info(`Found file on bucket: ${bucket} with key: ${gcsPath}`); core.info(`Found file on bucket: ${bucket} with key: ${gcsPath}`);
return gcsPath; return { key, path: gcsPath };
} }
} }
return undefined; return undefined;

@ -92572,15 +92572,21 @@ function restoreFromGCS(_paths_1, primaryKey_1) {
const archiveFolder = yield utils.createTempDirectory(); const archiveFolder = yield utils.createTempDirectory();
const archivePath = path.join(archiveFolder, utils.getCacheFileName(compressionMethod)); const archivePath = path.join(archiveFolder, utils.getCacheFileName(compressionMethod));
const keys = [primaryKey, ...restoreKeys]; const keys = [primaryKey, ...restoreKeys];
const gcsPath = yield findFileOnGCS(storage, bucket, pathPrefix, keys, compressionMethod); const match = yield findFileOnGCS(storage, bucket, pathPrefix, keys, compressionMethod);
if (!gcsPath) { if (!match) {
core.info(`No matching cache found`); core.info(`No matching cache found`);
return undefined; return undefined;
} }
// Preserve the @actions/cache contract: return the matched cache KEY
// (primaryKey or a restoreKey), not the GCS object path. The caller
// (restoreImpl) compares the return value against primaryKey to set the
// `cache-hit` output — returning the gcs path makes `cache-hit` always
// false, re-triggering downstream install/build steps that gate on it.
const { key: matchedKey, path: gcsPath } = match;
// If lookup only, just return the key // If lookup only, just return the key
if (options === null || options === void 0 ? void 0 : options.lookupOnly) { if (options === null || options === void 0 ? void 0 : options.lookupOnly) {
core.info(`Cache found in GCS with key: ${gcsPath}`); core.info(`Cache found in GCS with key: ${matchedKey}`);
return gcsPath; return matchedKey;
} }
try { try {
core.info(`Downloading from GCS: ${bucket}/${gcsPath}`); core.info(`Downloading from GCS: ${bucket}/${gcsPath}`);
@ -92593,7 +92599,7 @@ function restoreFromGCS(_paths_1, primaryKey_1) {
core.info(`Cache Size: ~${Math.round(archiveFileSize / (1024 * 1024))} MB (${archiveFileSize} B)`); core.info(`Cache Size: ~${Math.round(archiveFileSize / (1024 * 1024))} MB (${archiveFileSize} B)`);
yield (0, tar_1.extractTar)(archivePath, compressionMethod); yield (0, tar_1.extractTar)(archivePath, compressionMethod);
core.info("Cache restored successfully"); core.info("Cache restored successfully");
return gcsPath; return matchedKey;
} }
catch (error) { catch (error) {
core.warning(`Failed to restore: ${error.message}`); core.warning(`Failed to restore: ${error.message}`);
@ -92662,7 +92668,7 @@ function findFileOnGCS(storage, bucket, pathPrefix, keys, compressionMethod) {
const gcsPath = getGCSPath(pathPrefix, key, compressionMethod); const gcsPath = getGCSPath(pathPrefix, key, compressionMethod);
if (yield checkFileExists(storage, bucket, gcsPath)) { if (yield checkFileExists(storage, bucket, gcsPath)) {
core.info(`Found file on bucket: ${bucket} with key: ${gcsPath}`); core.info(`Found file on bucket: ${bucket} with key: ${gcsPath}`);
return gcsPath; return { key, path: gcsPath };
} }
} }
return undefined; return undefined;

18
dist/save/index.js vendored

@ -92572,15 +92572,21 @@ function restoreFromGCS(_paths_1, primaryKey_1) {
const archiveFolder = yield utils.createTempDirectory(); const archiveFolder = yield utils.createTempDirectory();
const archivePath = path.join(archiveFolder, utils.getCacheFileName(compressionMethod)); const archivePath = path.join(archiveFolder, utils.getCacheFileName(compressionMethod));
const keys = [primaryKey, ...restoreKeys]; const keys = [primaryKey, ...restoreKeys];
const gcsPath = yield findFileOnGCS(storage, bucket, pathPrefix, keys, compressionMethod); const match = yield findFileOnGCS(storage, bucket, pathPrefix, keys, compressionMethod);
if (!gcsPath) { if (!match) {
core.info(`No matching cache found`); core.info(`No matching cache found`);
return undefined; return undefined;
} }
// Preserve the @actions/cache contract: return the matched cache KEY
// (primaryKey or a restoreKey), not the GCS object path. The caller
// (restoreImpl) compares the return value against primaryKey to set the
// `cache-hit` output — returning the gcs path makes `cache-hit` always
// false, re-triggering downstream install/build steps that gate on it.
const { key: matchedKey, path: gcsPath } = match;
// If lookup only, just return the key // If lookup only, just return the key
if (options === null || options === void 0 ? void 0 : options.lookupOnly) { if (options === null || options === void 0 ? void 0 : options.lookupOnly) {
core.info(`Cache found in GCS with key: ${gcsPath}`); core.info(`Cache found in GCS with key: ${matchedKey}`);
return gcsPath; return matchedKey;
} }
try { try {
core.info(`Downloading from GCS: ${bucket}/${gcsPath}`); core.info(`Downloading from GCS: ${bucket}/${gcsPath}`);
@ -92593,7 +92599,7 @@ function restoreFromGCS(_paths_1, primaryKey_1) {
core.info(`Cache Size: ~${Math.round(archiveFileSize / (1024 * 1024))} MB (${archiveFileSize} B)`); core.info(`Cache Size: ~${Math.round(archiveFileSize / (1024 * 1024))} MB (${archiveFileSize} B)`);
yield (0, tar_1.extractTar)(archivePath, compressionMethod); yield (0, tar_1.extractTar)(archivePath, compressionMethod);
core.info("Cache restored successfully"); core.info("Cache restored successfully");
return gcsPath; return matchedKey;
} }
catch (error) { catch (error) {
core.warning(`Failed to restore: ${error.message}`); core.warning(`Failed to restore: ${error.message}`);
@ -92662,7 +92668,7 @@ function findFileOnGCS(storage, bucket, pathPrefix, keys, compressionMethod) {
const gcsPath = getGCSPath(pathPrefix, key, compressionMethod); const gcsPath = getGCSPath(pathPrefix, key, compressionMethod);
if (yield checkFileExists(storage, bucket, gcsPath)) { if (yield checkFileExists(storage, bucket, gcsPath)) {
core.info(`Found file on bucket: ${bucket} with key: ${gcsPath}`); core.info(`Found file on bucket: ${bucket} with key: ${gcsPath}`);
return gcsPath; return { key, path: gcsPath };
} }
} }
return undefined; return undefined;

@ -128,7 +128,7 @@ async function restoreFromGCS(
); );
const keys = [primaryKey, ...restoreKeys]; const keys = [primaryKey, ...restoreKeys];
const gcsPath = await findFileOnGCS( const match = await findFileOnGCS(
storage, storage,
bucket, bucket,
pathPrefix, pathPrefix,
@ -136,15 +136,22 @@ async function restoreFromGCS(
compressionMethod compressionMethod
); );
if (!gcsPath) { if (!match) {
core.info(`No matching cache found`); core.info(`No matching cache found`);
return undefined; return undefined;
} }
// Preserve the @actions/cache contract: return the matched cache KEY
// (primaryKey or a restoreKey), not the GCS object path. The caller
// (restoreImpl) compares the return value against primaryKey to set the
// `cache-hit` output — returning the gcs path makes `cache-hit` always
// false, re-triggering downstream install/build steps that gate on it.
const { key: matchedKey, path: gcsPath } = match;
// If lookup only, just return the key // If lookup only, just return the key
if (options?.lookupOnly) { if (options?.lookupOnly) {
core.info(`Cache found in GCS with key: ${gcsPath}`); core.info(`Cache found in GCS with key: ${matchedKey}`);
return gcsPath; return matchedKey;
} }
try { try {
@ -166,7 +173,7 @@ async function restoreFromGCS(
await extractTar(archivePath, compressionMethod); await extractTar(archivePath, compressionMethod);
core.info("Cache restored successfully"); core.info("Cache restored successfully");
return gcsPath; return matchedKey;
} catch (error) { } catch (error) {
core.warning(`Failed to restore: ${(error as Error).message}`); core.warning(`Failed to restore: ${(error as Error).message}`);
} finally { } finally {
@ -254,12 +261,12 @@ async function findFileOnGCS(
pathPrefix: string, pathPrefix: string,
keys: string[], keys: string[],
compressionMethod: CompressionMethod compressionMethod: CompressionMethod
): Promise<string | undefined> { ): Promise<{ key: string; path: string } | undefined> {
for (const key of keys) { for (const key of keys) {
const gcsPath = getGCSPath(pathPrefix, key, compressionMethod); const gcsPath = getGCSPath(pathPrefix, key, compressionMethod);
if (await checkFileExists(storage, bucket, gcsPath)) { if (await checkFileExists(storage, bucket, gcsPath)) {
core.info(`Found file on bucket: ${bucket} with key: ${gcsPath}`); core.info(`Found file on bucket: ${bucket} with key: ${gcsPath}`);
return gcsPath; return { key, path: gcsPath };
} }
} }
return undefined; return undefined;

Loading…
Cancel
Save