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:
parent
baed3516c3
commit
5ab49b24e0
8 changed files with 63 additions and 5 deletions
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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";
|
||||||
|
|
|
@ -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();
|
||||||
});
|
});
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
});
|
});
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Add table
Reference in a new issue