Add read-only feature

When `read-only` is `true`, the cache is only restored and not saved. This allows for sharing the cache with multiple steps even if these steps may change them, and speeds them up regardless.
This commit is contained in:
Martijn Hols 2020-11-29 10:50:39 +01:00
parent 9c77c9dbfc
commit b917253c33
9 changed files with 2425 additions and 2323 deletions

View file

@ -308,3 +308,35 @@ test("restore with cache found for restore key", async () => {
);
expect(failedMock).toHaveBeenCalledTimes(0);
});
test("restore with read-only with cache found for key", async () => {
const path = "node_modules";
const key = "node-test";
testUtils.setInputs({
path: path,
key,
readOnly: true
});
const infoMock = jest.spyOn(core, "info");
const failedMock = jest.spyOn(core, "setFailed");
const stateMock = jest.spyOn(core, "saveState");
const setCacheHitOutputMock = jest.spyOn(actionUtils, "setCacheHitOutput");
const restoreCacheMock = jest
.spyOn(cache, "restoreCache")
.mockImplementationOnce(() => {
return Promise.resolve(key);
});
await run();
expect(restoreCacheMock).toHaveBeenCalledTimes(1);
expect(restoreCacheMock).toHaveBeenCalledWith([path], key, []);
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
expect(setCacheHitOutputMock).toHaveBeenCalledWith(true);
expect(infoMock).toHaveBeenCalledWith(`Cache restored from key: ${key}`);
expect(failedMock).toHaveBeenCalledTimes(0);
});

View file

@ -35,6 +35,14 @@ beforeAll(() => {
}
);
jest.spyOn(actionUtils, "getInputAsBoolean").mockImplementation(
(name, options) => {
return jest
.requireActual("../src/utils/actionUtils")
.getInputAsBoolean(name, options);
}
);
jest.spyOn(actionUtils, "isExactKeyMatch").mockImplementation(
(key, cacheResult) => {
return jest
@ -338,3 +346,32 @@ test("save with valid inputs uploads a cache", async () => {
expect(failedMock).toHaveBeenCalledTimes(0);
});
test("save with read-only does not upload cache", async () => {
const infoMock = jest.spyOn(core, "info");
const failedMock = jest.spyOn(core, "setFailed");
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
const savedCacheKey = primaryKey;
jest.spyOn(core, "getState")
// Cache Entry State
.mockImplementationOnce(() => {
return savedCacheKey;
})
// Cache Key State
.mockImplementationOnce(() => {
return primaryKey;
});
const saveCacheMock = jest.spyOn(cache, "saveCache");
testUtils.setInput(Inputs.ReadOnly, "true");
await run();
expect(saveCacheMock).toHaveBeenCalledTimes(0);
expect(infoMock).toHaveBeenCalledWith(
"Cache running in read-only mode, not saving cache."
);
expect(failedMock).toHaveBeenCalledTimes(0);
});

View file

@ -14,6 +14,9 @@ inputs:
upload-chunk-size:
description: 'The chunk size used to split up large files during upload, in bytes'
required: false
read-only:
description: 'Set to true to never save the cache'
required: false
outputs:
cache-hit:
description: 'A boolean value to indicate an exact match was found for the primary key'

2327
dist/restore/index.js vendored

File diff suppressed because it is too large Load diff

2331
dist/save/index.js vendored

File diff suppressed because it is too large Load diff

View file

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

View file

@ -11,6 +11,11 @@ async function run(): Promise<void> {
return;
}
if (utils.getInputAsBoolean(Inputs.ReadOnly)) {
core.info("Cache running in read-only mode, not saving cache.");
return;
}
if (!utils.isValidEvent()) {
utils.logWarning(
`Event Validation Error: The event type ${

View file

@ -74,3 +74,10 @@ export function getInputAsInt(
}
return value;
}
export function getInputAsBoolean(
name: string,
options?: core.InputOptions
): boolean {
return core.getInput(name, options) === "true";
}

View file

@ -13,6 +13,7 @@ interface CacheInput {
path: string;
key: string;
restoreKeys?: string[];
readOnly?: boolean;
}
export function setInputs(input: CacheInput): void {
@ -20,6 +21,7 @@ export function setInputs(input: CacheInput): void {
setInput(Inputs.Key, input.key);
input.restoreKeys &&
setInput(Inputs.RestoreKeys, input.restoreKeys.join("\n"));
setInput(Inputs.ReadOnly, input.readOnly ? "true" : "false");
}
export function clearInputs(): void {
@ -27,4 +29,5 @@ export function clearInputs(): void {
delete process.env[getInputName(Inputs.Key)];
delete process.env[getInputName(Inputs.RestoreKeys)];
delete process.env[getInputName(Inputs.UploadChunkSize)];
delete process.env[getInputName(Inputs.ReadOnly)];
}