mirror of
https://github.com/actions/cache.git
synced 2025-04-22 03:56:45 +00:00
Introduce save-only option for parity
This commit is contained in:
parent
e44e77f968
commit
42580c43b4
7 changed files with 83 additions and 10 deletions
|
@ -401,3 +401,57 @@ test("restore with cache found for restore key", async () => {
|
||||||
);
|
);
|
||||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("restore skipped with save-only", async () => {
|
||||||
|
const key = "node-test";
|
||||||
|
const restoreKey = "node-";
|
||||||
|
testUtils.setInputs({
|
||||||
|
path: "node_modules",
|
||||||
|
key,
|
||||||
|
restoreKeys: [restoreKey],
|
||||||
|
saveOnly: "true"
|
||||||
|
});
|
||||||
|
|
||||||
|
const infoMock = jest.spyOn(core, "info");
|
||||||
|
const failedMock = jest.spyOn(core, "setFailed");
|
||||||
|
const stateMock = jest.spyOn(core, "saveState");
|
||||||
|
|
||||||
|
const cacheEntry: ArtifactCacheEntry = {
|
||||||
|
cacheKey: restoreKey,
|
||||||
|
scope: "refs/heads/master",
|
||||||
|
archiveLocation: "www.actionscache.test/download"
|
||||||
|
};
|
||||||
|
const getCacheMock = jest.spyOn(cacheHttpClient, "getCacheEntry");
|
||||||
|
getCacheMock.mockImplementation(() => {
|
||||||
|
return Promise.resolve(cacheEntry);
|
||||||
|
});
|
||||||
|
const tempPath = "/foo/bar";
|
||||||
|
|
||||||
|
const createTempDirectoryMock = jest.spyOn(
|
||||||
|
actionUtils,
|
||||||
|
"createTempDirectory"
|
||||||
|
);
|
||||||
|
createTempDirectoryMock.mockImplementation(() => {
|
||||||
|
return Promise.resolve(tempPath);
|
||||||
|
});
|
||||||
|
|
||||||
|
const setCacheStateMock = jest.spyOn(actionUtils, "setCacheState");
|
||||||
|
const downloadCacheMock = jest.spyOn(cacheHttpClient, "downloadCache");
|
||||||
|
const setCacheHitOutputMock = jest.spyOn(actionUtils, "setCacheHitOutput");
|
||||||
|
|
||||||
|
await run();
|
||||||
|
|
||||||
|
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
|
||||||
|
expect(getCacheMock).toHaveBeenCalledWith([key, restoreKey]);
|
||||||
|
expect(setCacheStateMock).toHaveBeenCalledWith(cacheEntry);
|
||||||
|
expect(createTempDirectoryMock).toHaveBeenCalledTimes(0);
|
||||||
|
expect(downloadCacheMock).toHaveBeenCalledTimes(0);
|
||||||
|
|
||||||
|
expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
|
||||||
|
expect(setCacheHitOutputMock).toHaveBeenCalledWith(false);
|
||||||
|
|
||||||
|
expect(infoMock).toHaveBeenCalledWith(
|
||||||
|
"Cache action configured for save-only, skipping restore step."
|
||||||
|
);
|
||||||
|
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||||
|
});
|
||||||
|
|
|
@ -414,7 +414,7 @@ test("save skipped with restore only", async () => {
|
||||||
await run();
|
await run();
|
||||||
|
|
||||||
expect(infoMock).toHaveBeenCalledWith(
|
expect(infoMock).toHaveBeenCalledWith(
|
||||||
"Cache action configured for restore-only, skipping save step"
|
"Cache action configured for restore-only, skipping save step."
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(reserveCacheMock).toHaveBeenCalledTimes(0);
|
expect(reserveCacheMock).toHaveBeenCalledTimes(0);
|
||||||
|
|
|
@ -14,6 +14,9 @@ inputs:
|
||||||
restore-only:
|
restore-only:
|
||||||
description: 'Disables saving a new cache entry when true'
|
description: 'Disables saving a new cache entry when true'
|
||||||
required: false
|
required: false
|
||||||
|
save-only:
|
||||||
|
description: 'Disables downloading and restoring a new cache entry when true'
|
||||||
|
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",
|
||||||
RestoreOnly = "restore-only"
|
RestoreOnly = "restore-only",
|
||||||
|
SaveOnly = "save-only"
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum Outputs {
|
export enum Outputs {
|
||||||
|
|
|
@ -67,15 +67,28 @@ async function run(): Promise<void> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isExactKeyMatch = utils.isExactKeyMatch(
|
||||||
|
primaryKey,
|
||||||
|
cacheEntry
|
||||||
|
);
|
||||||
|
|
||||||
|
// Store the cache result
|
||||||
|
utils.setCacheState(cacheEntry);
|
||||||
|
|
||||||
|
if (core.getInput(Inputs.SaveOnly) === "true") {
|
||||||
|
core.info(
|
||||||
|
"Cache action configured for save-only, skipping restore step."
|
||||||
|
);
|
||||||
|
utils.setCacheHitOutput(isExactKeyMatch);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const archivePath = path.join(
|
const archivePath = path.join(
|
||||||
await utils.createTempDirectory(),
|
await utils.createTempDirectory(),
|
||||||
"cache.tgz"
|
"cache.tgz"
|
||||||
);
|
);
|
||||||
core.debug(`Archive Path: ${archivePath}`);
|
core.debug(`Archive Path: ${archivePath}`);
|
||||||
|
|
||||||
// Store the cache result
|
|
||||||
utils.setCacheState(cacheEntry);
|
|
||||||
|
|
||||||
// Download the cache from the cache entry
|
// Download the cache from the cache entry
|
||||||
await cacheHttpClient.downloadCache(
|
await cacheHttpClient.downloadCache(
|
||||||
cacheEntry.archiveLocation,
|
cacheEntry.archiveLocation,
|
||||||
|
@ -91,10 +104,6 @@ async function run(): Promise<void> {
|
||||||
|
|
||||||
await extractTar(archivePath, cachePath);
|
await extractTar(archivePath, cachePath);
|
||||||
|
|
||||||
const isExactKeyMatch = utils.isExactKeyMatch(
|
|
||||||
primaryKey,
|
|
||||||
cacheEntry
|
|
||||||
);
|
|
||||||
utils.setCacheHitOutput(isExactKeyMatch);
|
utils.setCacheHitOutput(isExactKeyMatch);
|
||||||
|
|
||||||
core.info(
|
core.info(
|
||||||
|
|
|
@ -20,7 +20,7 @@ async function run(): Promise<void> {
|
||||||
|
|
||||||
if (core.getInput(Inputs.RestoreOnly) === "true") {
|
if (core.getInput(Inputs.RestoreOnly) === "true") {
|
||||||
core.info(
|
core.info(
|
||||||
"Cache action configured for restore-only, skipping save step"
|
"Cache action configured for restore-only, skipping save step."
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,8 @@ interface CacheInput {
|
||||||
path: string;
|
path: string;
|
||||||
key: string;
|
key: string;
|
||||||
restoreKeys?: string[];
|
restoreKeys?: string[];
|
||||||
|
restoreOnly?: string;
|
||||||
|
saveOnly?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setInputs(input: CacheInput): void {
|
export function setInputs(input: CacheInput): void {
|
||||||
|
@ -20,10 +22,14 @@ 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"));
|
||||||
|
input.restoreOnly && setInput(Inputs.RestoreOnly, input.restoreOnly);
|
||||||
|
input.saveOnly && setInput(Inputs.SaveOnly, input.saveOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function clearInputs(): void {
|
export function clearInputs(): void {
|
||||||
delete process.env[getInputName(Inputs.Path)];
|
delete process.env[getInputName(Inputs.Path)];
|
||||||
delete process.env[getInputName(Inputs.Key)];
|
delete process.env[getInputName(Inputs.Key)];
|
||||||
delete process.env[getInputName(Inputs.RestoreKeys)];
|
delete process.env[getInputName(Inputs.RestoreKeys)];
|
||||||
|
delete process.env[getInputName(Inputs.RestoreOnly)];
|
||||||
|
delete process.env[getInputName(Inputs.SaveOnly)];
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue