diff --git a/README.md b/README.md index a4c8f1b..9cd177e 100644 --- a/README.md +++ b/README.md @@ -50,10 +50,12 @@ If you are using this inside a container, a POSIX-compliant `tar` needs to be in ### Outputs -* `cache-hit` - A boolean value to indicate an exact match was found for the key +* `cache-hit` - A boolean value to indicate an exact match was found for the key. It will be `false` if a `restore-key` is matched. > See [Skipping steps based on cache-hit](#Skipping-steps-based-on-cache-hit) for info on using this output +* `cache-key` - A string indicating the matching cache key (if any). + ### Cache scopes The cache is scoped to the key and branch. The default branch cache is available to other branches. diff --git a/__tests__/actionUtils.test.ts b/__tests__/actionUtils.test.ts index e36a6a5..3cbb3c5 100644 --- a/__tests__/actionUtils.test.ts +++ b/__tests__/actionUtils.test.ts @@ -104,7 +104,8 @@ test("setOutputAndState with exact match to set cache-hit output and state", () actionUtils.setOutputAndState(key, cacheKey); expect(setOutputMock).toHaveBeenCalledWith(Outputs.CacheHit, "true"); - expect(setOutputMock).toHaveBeenCalledTimes(1); + expect(setOutputMock).toHaveBeenCalledWith(Outputs.CacheKey, key); + expect(setOutputMock).toHaveBeenCalledTimes(2); expect(saveStateMock).toHaveBeenCalledWith(State.CacheMatchedKey, cacheKey); expect(saveStateMock).toHaveBeenCalledTimes(1); @@ -120,7 +121,8 @@ test("setOutputAndState with no exact match to set cache-hit output and state", actionUtils.setOutputAndState(key, cacheKey); expect(setOutputMock).toHaveBeenCalledWith(Outputs.CacheHit, "false"); - expect(setOutputMock).toHaveBeenCalledTimes(1); + expect(setOutputMock).toHaveBeenCalledWith(Outputs.CacheKey, key); + expect(setOutputMock).toHaveBeenCalledTimes(2); expect(saveStateMock).toHaveBeenCalledWith(State.CacheMatchedKey, cacheKey); expect(saveStateMock).toHaveBeenCalledTimes(1); diff --git a/__tests__/restore.test.ts b/__tests__/restore.test.ts index b4dbba9..eaa006b 100644 --- a/__tests__/restore.test.ts +++ b/__tests__/restore.test.ts @@ -208,6 +208,7 @@ test("restore with no cache found", async () => { const infoMock = jest.spyOn(core, "info"); const failedMock = jest.spyOn(core, "setFailed"); const stateMock = jest.spyOn(core, "saveState"); + const setOutputMock = jest.spyOn(core, "setOutput"); const restoreCacheMock = jest .spyOn(cache, "restoreCache") .mockImplementationOnce(() => { @@ -222,6 +223,8 @@ test("restore with no cache found", async () => { expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key); expect(failedMock).toHaveBeenCalledTimes(0); + expect(setOutputMock).toHaveBeenCalledTimes(0); + expect(infoMock).toHaveBeenCalledWith( `Cache not found for input keys: ${key}` ); @@ -320,7 +323,7 @@ test("restore with cache found for key", async () => { expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1); expect(setCacheHitOutputMock).toHaveBeenCalledWith(true); - expect(infoMock).toHaveBeenCalledWith(`Cache restored from key: ${key}`); + expect(infoMock).toHaveBeenCalledWith(`Cache restored for key: ${key}`); expect(failedMock).toHaveBeenCalledTimes(0); }); diff --git a/dist/restore/index.js b/dist/restore/index.js index 7779b16..7f5c2c5 100644 --- a/dist/restore/index.js +++ b/dist/restore/index.js @@ -4614,6 +4614,7 @@ var Inputs; var Outputs; (function (Outputs) { Outputs["CacheHit"] = "cache-hit"; + Outputs["CacheKey"] = "cache-key"; })(Outputs = exports.Outputs || (exports.Outputs = {})); var State; (function (State) { @@ -37444,8 +37445,9 @@ function isExactKeyMatch(key, cacheKey) { }) === 0); } exports.isExactKeyMatch = isExactKeyMatch; -function setCacheState(state) { +function setCacheState(state, key) { core.saveState(constants_1.State.CacheMatchedKey, state); + core.setOutput(constants_1.Outputs.CacheKey, key); } exports.setCacheState = setCacheState; function setCacheHitOutput(isCacheHit) { @@ -37455,7 +37457,7 @@ exports.setCacheHitOutput = setCacheHitOutput; function setOutputAndState(key, cacheKey) { setCacheHitOutput(isExactKeyMatch(key, cacheKey)); // Store the matched cache key if it exists - cacheKey && setCacheState(cacheKey); + cacheKey && setCacheState(cacheKey, key); } exports.setOutputAndState = setOutputAndState; function getCacheState() { @@ -47945,7 +47947,22 @@ function run() { utils.setCacheState(cacheKey); const isExactKeyMatch = utils.isExactKeyMatch(primaryKey, cacheKey); utils.setCacheHitOutput(isExactKeyMatch); - core.info(`Cache restored from key: ${cacheKey}`); + let foundKey; + if (isExactKeyMatch) { + foundKey = primaryKey; + core.info(`Cache restored for key: ${foundKey}`); + } + else { + let i; + for (i = 0; i < restoreKeys.length - 1; i++) { + const fallbackCacheKey = yield cache.restoreCache(cachePaths, restoreKeys[i]); + if (cacheKey) { + break; + } + } + foundKey = restoreKeys[i]; + core.info(`Cache restored from key: ${foundKey}`); + } } catch (error) { if (error.name === cache.ValidationError.name) { diff --git a/dist/save/index.js b/dist/save/index.js index 582e9bf..be99aae 100644 --- a/dist/save/index.js +++ b/dist/save/index.js @@ -4614,6 +4614,7 @@ var Inputs; var Outputs; (function (Outputs) { Outputs["CacheHit"] = "cache-hit"; + Outputs["CacheKey"] = "cache-key"; })(Outputs = exports.Outputs || (exports.Outputs = {})); var State; (function (State) { @@ -37444,8 +37445,9 @@ function isExactKeyMatch(key, cacheKey) { }) === 0); } exports.isExactKeyMatch = isExactKeyMatch; -function setCacheState(state) { +function setCacheState(state, key) { core.saveState(constants_1.State.CacheMatchedKey, state); + core.setOutput(constants_1.Outputs.CacheKey, key); } exports.setCacheState = setCacheState; function setCacheHitOutput(isCacheHit) { @@ -37455,7 +37457,7 @@ exports.setCacheHitOutput = setCacheHitOutput; function setOutputAndState(key, cacheKey) { setCacheHitOutput(isExactKeyMatch(key, cacheKey)); // Store the matched cache key if it exists - cacheKey && setCacheState(cacheKey); + cacheKey && setCacheState(cacheKey, key); } exports.setOutputAndState = setOutputAndState; function getCacheState() { diff --git a/src/constants.ts b/src/constants.ts index 133f47d..c16344e 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -6,7 +6,8 @@ export enum Inputs { } export enum Outputs { - CacheHit = "cache-hit" + CacheHit = "cache-hit", + CacheKey = "cache-key" } export enum State { diff --git a/src/restore.ts b/src/restore.ts index df3dcac..6e1d757 100644 --- a/src/restore.ts +++ b/src/restore.ts @@ -51,7 +51,25 @@ async function run(): Promise { const isExactKeyMatch = utils.isExactKeyMatch(primaryKey, cacheKey); utils.setCacheHitOutput(isExactKeyMatch); - core.info(`Cache restored from key: ${cacheKey}`); + let foundKey: string; + if (isExactKeyMatch) { + foundKey = primaryKey; + core.info(`Cache restored for key: ${foundKey}`); + } else { + let i: number; + for (i = 0; i < restoreKeys.length - 1; i++) { + const fallbackCacheKey = await cache.restoreCache( + cachePaths, + restoreKeys[i] + ); + if (cacheKey) { + break; + } + } + foundKey = restoreKeys[i]; + core.info(`Cache restored from key: ${foundKey}`); + } + } catch (error) { if (error.name === cache.ValidationError.name) { throw error; diff --git a/src/utils/actionUtils.ts b/src/utils/actionUtils.ts index 69e0220..4d645b1 100644 --- a/src/utils/actionUtils.ts +++ b/src/utils/actionUtils.ts @@ -19,8 +19,9 @@ export function isExactKeyMatch(key: string, cacheKey?: string): boolean { ); } -export function setCacheState(state: string): void { +export function setCacheState(state: string, key?: string): void { core.saveState(State.CacheMatchedKey, state); + core.setOutput(Outputs.CacheKey, key); } export function setCacheHitOutput(isCacheHit: boolean): void { @@ -30,7 +31,7 @@ export function setCacheHitOutput(isCacheHit: boolean): void { export function setOutputAndState(key: string, cacheKey?: string): void { setCacheHitOutput(isExactKeyMatch(key, cacheKey)); // Store the matched cache key if it exists - cacheKey && setCacheState(cacheKey); + cacheKey && setCacheState(cacheKey, key); } export function getCacheState(): string | undefined {