diff --git a/README.md b/README.md index 6cb71e7..d77abf2 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,7 @@ If you are using a `self-hosted` Windows runner, `GNU tar` and `zstd` are requir * `enableCrossOsArchive` - An optional boolean when enabled, allows Windows runners to save or restore caches that can be restored or saved respectively on other platforms. Default: `false` * `fail-on-cache-miss` - Fail the workflow if cache entry is not found. Default: `false` * `lookup-only` - If true, only checks if cache entry exists and skips download. Does not change save cache behavior. Default: `false` +* `restore-only` - If true, only restores cache and skips save cache behavior. Default: `false`. Set it to `${{ github.event.repository != null && github.ref_name != github.event.repository.default_branch }}` to only save the cache when running on the default branch. #### Environment Variables diff --git a/__tests__/saveImpl.test.ts b/__tests__/saveImpl.test.ts index ad154f6..802e0c7 100644 --- a/__tests__/saveImpl.test.ts +++ b/__tests__/saveImpl.test.ts @@ -406,3 +406,34 @@ test("save with valid inputs uploads a cache", async () => { expect(failedMock).toHaveBeenCalledTimes(0); }); + +test("save with restore-only should no-op", async () => { + const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43"; + const savedCacheKey = "Linux-node-"; + + jest.spyOn(core, "getState") + // Cache Entry State + .mockImplementationOnce(() => { + return savedCacheKey; + }) + // Cache Key State + .mockImplementationOnce(() => { + return primaryKey; + }); + + const inputPath = "node_modules"; + testUtils.setInput(Inputs.Path, inputPath); + + testUtils.setInput(Inputs.RestoreOnly, "true"); + + const infoMock = jest.spyOn(core, "info"); + + const saveCacheMock = jest.spyOn(cache, "saveCache"); + + await saveImpl(new StateProvider()); + + expect(saveCacheMock).toHaveBeenCalledTimes(0); + expect(infoMock).toHaveBeenCalledWith( + "Skipping saving cache as 'restore-only' option is set." + ); +}); diff --git a/action.yml b/action.yml index 2606455..9e738ee 100644 --- a/action.yml +++ b/action.yml @@ -26,6 +26,10 @@ inputs: description: 'Check if a cache entry exists for the given input(s) (key, restore-keys) without downloading the cache' default: 'false' required: false + restore-only: + description: 'Downloads the cache if it exists, but skips saving it at the end of the job' + default: 'false' + required: false save-always: description: 'Run the post step to save the cache even if another step before fails' default: 'false' diff --git a/dist/restore-only/index.js b/dist/restore-only/index.js index 14456c6..ab4b175 100644 --- a/dist/restore-only/index.js +++ b/dist/restore-only/index.js @@ -46306,7 +46306,8 @@ var Inputs; Inputs["UploadChunkSize"] = "upload-chunk-size"; Inputs["EnableCrossOsArchive"] = "enableCrossOsArchive"; Inputs["FailOnCacheMiss"] = "fail-on-cache-miss"; - Inputs["LookupOnly"] = "lookup-only"; // Input for cache, restore action + Inputs["LookupOnly"] = "lookup-only"; + Inputs["RestoreOnly"] = "restore-only"; // Input for cache, restore action })(Inputs || (exports.Inputs = Inputs = {})); var Outputs; (function (Outputs) { diff --git a/dist/restore/index.js b/dist/restore/index.js index e59abc1..12e1fe8 100644 --- a/dist/restore/index.js +++ b/dist/restore/index.js @@ -46306,7 +46306,8 @@ var Inputs; Inputs["UploadChunkSize"] = "upload-chunk-size"; Inputs["EnableCrossOsArchive"] = "enableCrossOsArchive"; Inputs["FailOnCacheMiss"] = "fail-on-cache-miss"; - Inputs["LookupOnly"] = "lookup-only"; // Input for cache, restore action + Inputs["LookupOnly"] = "lookup-only"; + Inputs["RestoreOnly"] = "restore-only"; // Input for cache, restore action })(Inputs || (exports.Inputs = Inputs = {})); var Outputs; (function (Outputs) { diff --git a/dist/save-only/index.js b/dist/save-only/index.js index 3205b8e..da59e1d 100644 --- a/dist/save-only/index.js +++ b/dist/save-only/index.js @@ -46306,7 +46306,8 @@ var Inputs; Inputs["UploadChunkSize"] = "upload-chunk-size"; Inputs["EnableCrossOsArchive"] = "enableCrossOsArchive"; Inputs["FailOnCacheMiss"] = "fail-on-cache-miss"; - Inputs["LookupOnly"] = "lookup-only"; // Input for cache, restore action + Inputs["LookupOnly"] = "lookup-only"; + Inputs["RestoreOnly"] = "restore-only"; // Input for cache, restore action })(Inputs || (exports.Inputs = Inputs = {})); var Outputs; (function (Outputs) { @@ -46401,6 +46402,10 @@ function saveImpl(stateProvider) { utils.logWarning(`Event Validation Error: The event type ${process.env[constants_1.Events.Key]} is not supported because it's not tied to a branch or tag ref.`); return; } + if (utils.getInputAsBool(constants_1.Inputs.RestoreOnly)) { + core.info("Skipping saving cache as 'restore-only' option is set."); + return; + } // If restore has stored a primary key in state, reuse that // Else re-evaluate from inputs const primaryKey = stateProvider.getState(constants_1.State.CachePrimaryKey) || diff --git a/dist/save/index.js b/dist/save/index.js index c714a9d..bc87a80 100644 --- a/dist/save/index.js +++ b/dist/save/index.js @@ -46306,7 +46306,8 @@ var Inputs; Inputs["UploadChunkSize"] = "upload-chunk-size"; Inputs["EnableCrossOsArchive"] = "enableCrossOsArchive"; Inputs["FailOnCacheMiss"] = "fail-on-cache-miss"; - Inputs["LookupOnly"] = "lookup-only"; // Input for cache, restore action + Inputs["LookupOnly"] = "lookup-only"; + Inputs["RestoreOnly"] = "restore-only"; // Input for cache, restore action })(Inputs || (exports.Inputs = Inputs = {})); var Outputs; (function (Outputs) { @@ -46401,6 +46402,10 @@ function saveImpl(stateProvider) { utils.logWarning(`Event Validation Error: The event type ${process.env[constants_1.Events.Key]} is not supported because it's not tied to a branch or tag ref.`); return; } + if (utils.getInputAsBool(constants_1.Inputs.RestoreOnly)) { + core.info("Skipping saving cache as 'restore-only' option is set."); + return; + } // If restore has stored a primary key in state, reuse that // Else re-evaluate from inputs const primaryKey = stateProvider.getState(constants_1.State.CachePrimaryKey) || diff --git a/src/constants.ts b/src/constants.ts index 0158ae0..8431135 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -5,7 +5,8 @@ export enum Inputs { UploadChunkSize = "upload-chunk-size", // Input for cache, save action EnableCrossOsArchive = "enableCrossOsArchive", // Input for cache, restore, save action FailOnCacheMiss = "fail-on-cache-miss", // Input for cache, restore action - LookupOnly = "lookup-only" // Input for cache, restore action + LookupOnly = "lookup-only", // Input for cache, restore action + RestoreOnly = "restore-only" // Input for cache, restore action } export enum Outputs { diff --git a/src/saveImpl.ts b/src/saveImpl.ts index 4e5c312..1872e69 100644 --- a/src/saveImpl.ts +++ b/src/saveImpl.ts @@ -32,6 +32,11 @@ export async function saveImpl( return; } + if (utils.getInputAsBool(Inputs.RestoreOnly)) { + core.info("Skipping saving cache as 'restore-only' option is set."); + return; + } + // If restore has stored a primary key in state, reuse that // Else re-evaluate from inputs const primaryKey = diff --git a/src/utils/testUtils.ts b/src/utils/testUtils.ts index ba0670b..7cfd2d7 100644 --- a/src/utils/testUtils.ts +++ b/src/utils/testUtils.ts @@ -16,6 +16,7 @@ interface CacheInput { enableCrossOsArchive?: boolean; failOnCacheMiss?: boolean; lookupOnly?: boolean; + restoreOnly?: boolean; } export function setInputs(input: CacheInput): void { @@ -32,6 +33,8 @@ export function setInputs(input: CacheInput): void { setInput(Inputs.FailOnCacheMiss, input.failOnCacheMiss.toString()); input.lookupOnly !== undefined && setInput(Inputs.LookupOnly, input.lookupOnly.toString()); + input.restoreOnly !== undefined && + setInput(Inputs.RestoreOnly, input.restoreOnly.toString()); } export function clearInputs(): void { @@ -42,4 +45,5 @@ export function clearInputs(): void { delete process.env[getInputName(Inputs.EnableCrossOsArchive)]; delete process.env[getInputName(Inputs.FailOnCacheMiss)]; delete process.env[getInputName(Inputs.LookupOnly)]; + delete process.env[getInputName(Inputs.RestoreOnly)]; }