1
0
Fork 0
mirror of https://code.forgejo.org/actions/cache.git synced 2025-04-19 19:46:17 +02:00

feat: Adding "always-save" flag that allows to save the new cache over the old cache.

This commit is contained in:
Martin Heidegger 2022-07-03 10:14:51 +09:00
parent baed3516c3
commit 5ab49b24e0
No known key found for this signature in database
GPG key ID: 5933F4B5CC304AFC
8 changed files with 63 additions and 5 deletions

View file

@ -31,6 +31,7 @@ If you are using this inside a container, a POSIX-compliant `tar` needs to be in
* `key` - An explicit key for restoring and saving the cache * `key` - An explicit key for restoring and saving the cache
* `restore-keys` - An ordered list of keys to use for restoring stale cache if no cache hit occurred for key. Note * `restore-keys` - An ordered list of keys to use for restoring stale cache if no cache hit occurred for key. Note
`cache-hit` returns false in this case. `cache-hit` returns false in this case.
* `always-save` - Flag indicating that it the cache should always be written
### Outputs ### Outputs

View file

@ -293,6 +293,41 @@ test("restore with restore keys and no cache found", async () => {
); );
}); });
test("restore with always-save", async () => {
const path = "node_modules";
const key = "node-test";
testUtils.setInputs({
path: path,
key,
alwaysSave: true
});
const infoMock = jest.spyOn(core, "info");
const failedMock = jest.spyOn(core, "setFailed");
const stateMock = jest.spyOn(core, "saveState");
const restoreCacheMock = jest
.spyOn(cache, "restoreCache")
.mockImplementationOnce(() => {
return Promise.resolve(undefined);
});
process.env['GITHUB_RUN_ID'] = '1234'
await run();
process.env['GITHUB_RUN_ID'] = ''
expect(restoreCacheMock).toHaveBeenCalledTimes(1);
expect(restoreCacheMock).toHaveBeenCalledWith([path], `${key}-1234`, [`${key}-`]);
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", `${key}-1234`);
expect(failedMock).toHaveBeenCalledTimes(0);
expect(infoMock).toHaveBeenCalledWith(
`Cache not found for input keys: ${key}-1234, ${key}-`
);
});
test("restore with cache found for key", async () => { test("restore with cache found for key", async () => {
const path = "node_modules"; const path = "node_modules";
const key = "node-test"; const key = "node-test";

View file

@ -15,6 +15,12 @@ beforeAll(() => {
return jest.requireActual("@actions/core").getInput(name, options); return jest.requireActual("@actions/core").getInput(name, options);
}); });
jest.spyOn(core, "getBooleanInput").mockImplementation((name, options) => {
return jest
.requireActual("@actions/core")
.getBooleanInput(name, options);
});
jest.spyOn(actionUtils, "getCacheState").mockImplementation(() => { jest.spyOn(actionUtils, "getCacheState").mockImplementation(() => {
return jest.requireActual("../src/utils/actionUtils").getCacheState(); return jest.requireActual("../src/utils/actionUtils").getCacheState();
}); });

View file

@ -14,6 +14,9 @@ inputs:
upload-chunk-size: upload-chunk-size:
description: 'The chunk size used to split up large files during upload, in bytes' description: 'The chunk size used to split up large files during upload, in bytes'
required: false required: false
always-save:
description: 'Flag indicating that it the cache should always be written'
required: false
outputs: outputs:
cache-hit: cache-hit:
description: 'A boolean value to indicate an exact match was found for the primary key' description: 'A boolean value to indicate an exact match was found for the primary key'

View file

@ -2,7 +2,8 @@ export enum Inputs {
Key = "key", Key = "key",
Path = "path", Path = "path",
RestoreKeys = "restore-keys", RestoreKeys = "restore-keys",
UploadChunkSize = "upload-chunk-size" UploadChunkSize = "upload-chunk-size",
AlwaysSave = "always-save"
} }
export enum Outputs { export enum Outputs {

View file

@ -21,10 +21,20 @@ async function run(): Promise<void> {
return; return;
} }
const primaryKey = core.getInput(Inputs.Key, { required: true }); let primaryKey = core.getInput(Inputs.Key, { required: true });
core.saveState(State.CachePrimaryKey, primaryKey);
const restoreKeys = utils.getInputAsArray(Inputs.RestoreKeys); const restoreKeys = utils.getInputAsArray(Inputs.RestoreKeys);
// https://github.com/actions/toolkit/issues/844
let alwaysSave = false;
if (core.getInput(Inputs.AlwaysSave)) {
alwaysSave = core.getBooleanInput(Inputs.AlwaysSave);
}
if (alwaysSave) {
restoreKeys.push(`${primaryKey}-`);
primaryKey = `${primaryKey}-${process.env['GITHUB_RUN_ID'] ?? Date.now()}`;
}
core.saveState(State.CachePrimaryKey, primaryKey);
const cachePaths = utils.getInputAsArray(Inputs.Path, { const cachePaths = utils.getInputAsArray(Inputs.Path, {
required: true required: true
}); });

View file

@ -27,7 +27,7 @@ async function run(): Promise<void> {
const state = utils.getCacheState(); const state = utils.getCacheState();
// Inputs are re-evaluted before the post action, so we want the original key used for restore // Inputs are re-evaluted before the post action, so we want the original key used for restore
const primaryKey = core.getState(State.CachePrimaryKey); let primaryKey = core.getState(State.CachePrimaryKey);
if (!primaryKey) { if (!primaryKey) {
utils.logWarning(`Error retrieving key from state.`); utils.logWarning(`Error retrieving key from state.`);
return; return;

View file

@ -13,6 +13,7 @@ interface CacheInput {
path: string; path: string;
key: string; key: string;
restoreKeys?: string[]; restoreKeys?: string[];
alwaysSave?: boolean;
} }
export function setInputs(input: CacheInput): void { export function setInputs(input: CacheInput): void {
@ -20,6 +21,7 @@ export function setInputs(input: CacheInput): void {
setInput(Inputs.Key, input.key); setInput(Inputs.Key, input.key);
input.restoreKeys && input.restoreKeys &&
setInput(Inputs.RestoreKeys, input.restoreKeys.join("\n")); setInput(Inputs.RestoreKeys, input.restoreKeys.join("\n"));
setInput(Inputs.AlwaysSave, input.alwaysSave ? "true" : "");
} }
export function clearInputs(): void { export function clearInputs(): void {