Add skip-save feature

The skip-save option allows users to force the cache to skip saving the cache.  skip-save can be set to a constant or to an expression that will be evaluated at the end of the CI job, such as an environment variable.

This is for #498
This commit is contained in:
eyal0 2021-04-21 21:33:20 -06:00
parent 3a696372f2
commit ffdb03bc68
8 changed files with 8110 additions and 3 deletions

View file

@ -52,7 +52,6 @@ beforeAll(() => {
beforeEach(() => {
process.env[Events.Key] = Events.Push;
process.env[RefKey] = "refs/heads/feature-branch";
jest.spyOn(actionUtils, "isGhes").mockImplementation(() => false);
});
@ -142,6 +141,75 @@ test("save with exact match returns early", async () => {
expect(failedMock).toHaveBeenCalledTimes(0);
});
test("save with skip-save false", async () => {
const infoMock = jest.spyOn(core, "info");
const failedMock = jest.spyOn(core, "setFailed");
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);
const cacheId = 5;
const saveCacheMock = jest
.spyOn(cache, "saveCache")
.mockImplementationOnce(() => {
return Promise.resolve(cacheId);
});
await run();
expect(infoMock).toHaveBeenCalledWith(
`Cache saved with key: ${primaryKey}`
);
expect(saveCacheMock).toHaveBeenCalledTimes(1);
expect(saveCacheMock).toHaveBeenCalledWith([inputPath], primaryKey, {
uploadChunkSize: undefined
});
expect(failedMock).toHaveBeenCalledTimes(0);
});
test("save with skip-save true doesn't save", async () => {
const infoMock = jest.spyOn(core, "info");
const failedMock = jest.spyOn(core, "setFailed");
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.SkipSave, "true");
const saveCacheMock = jest.spyOn(cache, "saveCache");
await run();
expect(infoMock).toHaveBeenCalledWith(
"Cache saving was disabled by setting skip-save."
);
expect(saveCacheMock).toHaveBeenCalledTimes(0);
expect(failedMock).toHaveBeenCalledTimes(0);
});
test("save with missing input outputs warning", async () => {
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
const failedMock = jest.spyOn(core, "setFailed");

View file

@ -14,6 +14,10 @@ inputs:
upload-chunk-size:
description: 'The chunk size used to split up large files during upload, in bytes'
required: false
skip-save:
description: 'Whether or not to skip the saving of the cache. If this is set to "true", the cache will not be saved. It can also be set to an evironment variable such as "\$\{\{ env.MY_SKIP_SAVE \}\}". If the MY_SKIP_SAVE environment variable is "true" by the end of the CI, caching will be skipped. Default is to update if and only if there was no primary-key exact cache hit.'
required: false
default: false
outputs:
cache-hit:
description: 'A boolean value to indicate an exact match was found for the primary key'

View file

@ -5469,6 +5469,7 @@ var Inputs;
Inputs["Path"] = "path";
Inputs["RestoreKeys"] = "restore-keys";
Inputs["UploadChunkSize"] = "upload-chunk-size";
Inputs["SkipSave"] = "skip-save";
})(Inputs = exports.Inputs || (exports.Inputs = {}));
var Outputs;
(function (Outputs) {

6
dist/save/index.js vendored
View file

@ -5469,6 +5469,7 @@ var Inputs;
Inputs["Path"] = "path";
Inputs["RestoreKeys"] = "restore-keys";
Inputs["UploadChunkSize"] = "upload-chunk-size";
Inputs["SkipSave"] = "skip-save";
})(Inputs = exports.Inputs || (exports.Inputs = {}));
var Outputs;
(function (Outputs) {
@ -47172,6 +47173,11 @@ function run() {
utils.logWarning(`Error retrieving key from state.`);
return;
}
const skipSave = ["true", "yes"].includes(core.getInput(constants_1.Inputs.SkipSave).toLowerCase());
if (skipSave) {
core.info(`Cache saving was disabled by setting skip-save.`);
return;
}
if (utils.isExactKeyMatch(primaryKey, state)) {
core.info(`Cache hit occurred on the primary key ${primaryKey}, not saving cache.`);
return;

8019
package-lock.json generated

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",
SkipSave = "skip-save"
}
export enum Outputs {

View file

@ -29,6 +29,13 @@ async function run(): Promise<void> {
return;
}
const skipSave = ["true", "yes"].includes(
core.getInput(Inputs.SkipSave).toLowerCase()
);
if (skipSave) {
core.info(`Cache saving was disabled by setting skip-save.`);
return;
}
if (utils.isExactKeyMatch(primaryKey, state)) {
core.info(
`Cache hit occurred on the primary key ${primaryKey}, not saving cache.`

View file

@ -13,11 +13,13 @@ interface CacheInput {
path: string;
key: string;
restoreKeys?: string[];
skipSave?: string;
}
export function setInputs(input: CacheInput): void {
setInput(Inputs.Path, input.path);
setInput(Inputs.Key, input.key);
input.skipSave && setInput(Inputs.SkipSave, input.skipSave);
input.restoreKeys &&
setInput(Inputs.RestoreKeys, input.restoreKeys.join("\n"));
}
@ -25,6 +27,7 @@ export function setInputs(input: CacheInput): void {
export function clearInputs(): void {
delete process.env[getInputName(Inputs.Path)];
delete process.env[getInputName(Inputs.Key)];
delete process.env[getInputName(Inputs.SkipSave)];
delete process.env[getInputName(Inputs.RestoreKeys)];
delete process.env[getInputName(Inputs.UploadChunkSize)];
}