mirror of
https://code.forgejo.org/actions/cache.git
synced 2025-02-23 08:51:21 +01:00
Allow refreshing cache also with granular save.
This commit is contained in:
parent
df9df7396d
commit
ed8571e5e3
6 changed files with 153 additions and 10 deletions
|
@ -4,7 +4,7 @@ import nock from "nock";
|
||||||
|
|
||||||
import { Events, Inputs, RefKey } from "../src/constants";
|
import { Events, Inputs, RefKey } from "../src/constants";
|
||||||
import { saveImpl } from "../src/saveImpl";
|
import { saveImpl } from "../src/saveImpl";
|
||||||
import { StateProvider } from "../src/stateProvider";
|
import { NullStateProvider, StateProvider } from "../src/stateProvider";
|
||||||
import * as actionUtils from "../src/utils/actionUtils";
|
import * as actionUtils from "../src/utils/actionUtils";
|
||||||
import * as testUtils from "../src/utils/testUtils";
|
import * as testUtils from "../src/utils/testUtils";
|
||||||
|
|
||||||
|
@ -471,7 +471,80 @@ test("save with cache hit and refresh-cache will try to delete and re-create ent
|
||||||
.mockImplementationOnce(() => {
|
.mockImplementationOnce(() => {
|
||||||
return Promise.resolve(cacheId);
|
return Promise.resolve(cacheId);
|
||||||
});
|
});
|
||||||
await run(new StateProvider());
|
await saveImpl(new StateProvider());
|
||||||
|
|
||||||
|
expect(saveCacheMock).toHaveBeenCalledTimes(1);
|
||||||
|
expect(saveCacheMock).toHaveBeenCalledWith(
|
||||||
|
[inputPath],
|
||||||
|
primaryKey,
|
||||||
|
{
|
||||||
|
uploadChunkSize: 4000000
|
||||||
|
},
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(logWarningMock).toHaveBeenCalledTimes(0);
|
||||||
|
expect(infoMock).toHaveBeenCalledTimes(3);
|
||||||
|
|
||||||
|
expect(infoMock).toHaveBeenNthCalledWith(
|
||||||
|
1,
|
||||||
|
`Cache hit occurred on the primary key ${primaryKey}, attempting to refresh the contents of the cache.`
|
||||||
|
);
|
||||||
|
expect(infoMock).toHaveBeenNthCalledWith(
|
||||||
|
2,
|
||||||
|
`Succesfully deleted cache with key: ${primaryKey}`
|
||||||
|
);
|
||||||
|
expect(infoMock).toHaveBeenNthCalledWith(
|
||||||
|
3,
|
||||||
|
`Cache saved with key: ${primaryKey}`
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Granular save will use lookup to determine if cache needs to be updated or (not) saved.", async () => {
|
||||||
|
process.env["GITHUB_REPOSITORY"] = "owner/repo";
|
||||||
|
process.env["GITHUB_TOKEN"] =
|
||||||
|
"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";
|
||||||
|
process.env["GITHUB_ACTION"] = "__owner___run-repo";
|
||||||
|
|
||||||
|
const infoMock = jest.spyOn(core, "info");
|
||||||
|
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
||||||
|
const failedMock = jest.spyOn(core, "setFailed");
|
||||||
|
|
||||||
|
const primaryKey = testUtils.successCacheKey;
|
||||||
|
|
||||||
|
const inputPath = "node_modules";
|
||||||
|
testUtils.setInput(Inputs.Key, primaryKey);
|
||||||
|
testUtils.setInput(Inputs.RefreshCache, "true");
|
||||||
|
testUtils.setInput(Inputs.Path, inputPath);
|
||||||
|
testUtils.setInput(Inputs.UploadChunkSize, "4000000");
|
||||||
|
|
||||||
|
const restoreCacheMock = jest
|
||||||
|
.spyOn(cache, "restoreCache")
|
||||||
|
.mockImplementation(() => {
|
||||||
|
return Promise.resolve(primaryKey);
|
||||||
|
});
|
||||||
|
|
||||||
|
const cacheId = 4;
|
||||||
|
const saveCacheMock = jest
|
||||||
|
.spyOn(cache, "saveCache")
|
||||||
|
.mockImplementationOnce(() => {
|
||||||
|
return Promise.resolve(cacheId);
|
||||||
|
});
|
||||||
|
|
||||||
|
await saveImpl(new NullStateProvider());
|
||||||
|
|
||||||
|
expect(restoreCacheMock).toHaveBeenCalledTimes(1);
|
||||||
|
expect(restoreCacheMock).toHaveBeenCalledWith(
|
||||||
|
[inputPath],
|
||||||
|
primaryKey,
|
||||||
|
[],
|
||||||
|
{
|
||||||
|
lookupOnly: true
|
||||||
|
},
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
expect(saveCacheMock).toHaveBeenCalledTimes(1);
|
expect(saveCacheMock).toHaveBeenCalledTimes(1);
|
||||||
expect(saveCacheMock).toHaveBeenCalledWith(
|
expect(saveCacheMock).toHaveBeenCalledWith(
|
||||||
|
@ -524,7 +597,7 @@ test("save with cache hit and refresh-cache will throw a warning if there's no G
|
||||||
});
|
});
|
||||||
|
|
||||||
const saveCacheMock = jest.spyOn(cache, "saveCache");
|
const saveCacheMock = jest.spyOn(cache, "saveCache");
|
||||||
await run(new StateProvider());
|
await saveImpl(new StateProvider());
|
||||||
|
|
||||||
expect(saveCacheMock).toHaveBeenCalledTimes(0);
|
expect(saveCacheMock).toHaveBeenCalledTimes(0);
|
||||||
expect(logWarningMock).toHaveBeenCalledWith(
|
expect(logWarningMock).toHaveBeenCalledWith(
|
||||||
|
|
|
@ -111,6 +111,45 @@ test("save with valid inputs uploads a cache", async () => {
|
||||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("Granular save with refreshCache is able to save cache", async () => {
|
||||||
|
process.env["GITHUB_REPOSITORY"] = "owner/repo";
|
||||||
|
process.env["GITHUB_TOKEN"] =
|
||||||
|
"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";
|
||||||
|
process.env["GITHUB_ACTION"] = "__owner___run-repo";
|
||||||
|
const failedMock = jest.spyOn(core, "setFailed");
|
||||||
|
|
||||||
|
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
|
||||||
|
|
||||||
|
const inputPath = "node_modules";
|
||||||
|
process.env.CACHE_RESTORE_ONLY_MATCHED_KEY = primaryKey;
|
||||||
|
testUtils.setInput(Inputs.Key, primaryKey);
|
||||||
|
testUtils.setInput(Inputs.RefreshCache, "true");
|
||||||
|
testUtils.setInput(Inputs.Path, inputPath);
|
||||||
|
testUtils.setInput(Inputs.UploadChunkSize, "4000000");
|
||||||
|
|
||||||
|
const cacheId = 4;
|
||||||
|
|
||||||
|
const saveCacheMock = jest
|
||||||
|
.spyOn(cache, "saveCache")
|
||||||
|
.mockImplementationOnce(() => {
|
||||||
|
return Promise.resolve(cacheId);
|
||||||
|
});
|
||||||
|
|
||||||
|
await saveOnlyRun();
|
||||||
|
|
||||||
|
expect(saveCacheMock).toHaveBeenCalledTimes(1);
|
||||||
|
expect(saveCacheMock).toHaveBeenCalledWith(
|
||||||
|
[inputPath],
|
||||||
|
primaryKey,
|
||||||
|
{
|
||||||
|
uploadChunkSize: 4000000
|
||||||
|
},
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||||
|
});
|
||||||
|
|
||||||
test("save failing logs the warning message", async () => {
|
test("save failing logs the warning message", async () => {
|
||||||
const warningMock = jest.spyOn(core, "warning");
|
const warningMock = jest.spyOn(core, "warning");
|
||||||
|
|
||||||
|
|
12
dist/save-only/index.js
vendored
12
dist/save-only/index.js
vendored
|
@ -78737,8 +78737,16 @@ function saveImpl(stateProvider) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const refreshCache = utils.getInputAsBool(constants_1.Inputs.RefreshCache, { required: false });
|
const refreshCache = utils.getInputAsBool(constants_1.Inputs.RefreshCache, { required: false });
|
||||||
// If matched restore key is same as primary key, either try to refresh the cache, or just notify and do not save (NO-OP in case of SaveOnly action)
|
// If matched restore key is same as primary key, either try to refresh the cache, or just notify and do not save.
|
||||||
const restoredKey = stateProvider.getCacheState();
|
let restoredKey = stateProvider.getCacheState();
|
||||||
|
if (refreshCache && !restoredKey) {
|
||||||
|
// If getCacheState didn't give us a key, we're likely using granular actions. Do a lookup to see if we need to refresh or just do a regular save.
|
||||||
|
const cachePaths = utils.getInputAsArray(constants_1.Inputs.Path, {
|
||||||
|
required: true
|
||||||
|
});
|
||||||
|
const enableCrossOsArchive = utils.getInputAsBool(constants_1.Inputs.EnableCrossOsArchive);
|
||||||
|
restoredKey = yield cache.restoreCache(cachePaths, primaryKey, [], { lookupOnly: true }, enableCrossOsArchive);
|
||||||
|
}
|
||||||
if (utils.isExactKeyMatch(primaryKey, restoredKey)) {
|
if (utils.isExactKeyMatch(primaryKey, restoredKey)) {
|
||||||
const { GITHUB_TOKEN, GITHUB_REPOSITORY } = process.env || null;
|
const { GITHUB_TOKEN, GITHUB_REPOSITORY } = process.env || null;
|
||||||
if (GITHUB_TOKEN && GITHUB_REPOSITORY && refreshCache === true) {
|
if (GITHUB_TOKEN && GITHUB_REPOSITORY && refreshCache === true) {
|
||||||
|
|
12
dist/save/index.js
vendored
12
dist/save/index.js
vendored
|
@ -78737,8 +78737,16 @@ function saveImpl(stateProvider) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const refreshCache = utils.getInputAsBool(constants_1.Inputs.RefreshCache, { required: false });
|
const refreshCache = utils.getInputAsBool(constants_1.Inputs.RefreshCache, { required: false });
|
||||||
// If matched restore key is same as primary key, either try to refresh the cache, or just notify and do not save (NO-OP in case of SaveOnly action)
|
// If matched restore key is same as primary key, either try to refresh the cache, or just notify and do not save.
|
||||||
const restoredKey = stateProvider.getCacheState();
|
let restoredKey = stateProvider.getCacheState();
|
||||||
|
if (refreshCache && !restoredKey) {
|
||||||
|
// If getCacheState didn't give us a key, we're likely using granular actions. Do a lookup to see if we need to refresh or just do a regular save.
|
||||||
|
const cachePaths = utils.getInputAsArray(constants_1.Inputs.Path, {
|
||||||
|
required: true
|
||||||
|
});
|
||||||
|
const enableCrossOsArchive = utils.getInputAsBool(constants_1.Inputs.EnableCrossOsArchive);
|
||||||
|
restoredKey = yield cache.restoreCache(cachePaths, primaryKey, [], { lookupOnly: true }, enableCrossOsArchive);
|
||||||
|
}
|
||||||
if (utils.isExactKeyMatch(primaryKey, restoredKey)) {
|
if (utils.isExactKeyMatch(primaryKey, restoredKey)) {
|
||||||
const { GITHUB_TOKEN, GITHUB_REPOSITORY } = process.env || null;
|
const { GITHUB_TOKEN, GITHUB_REPOSITORY } = process.env || null;
|
||||||
if (GITHUB_TOKEN && GITHUB_REPOSITORY && refreshCache === true) {
|
if (GITHUB_TOKEN && GITHUB_REPOSITORY && refreshCache === true) {
|
||||||
|
|
|
@ -82,7 +82,6 @@ export async function restoreImpl(
|
||||||
} else {
|
} else {
|
||||||
core.info(`Cache restored from key: ${cacheKey}`);
|
core.info(`Cache restored from key: ${cacheKey}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return cacheKey;
|
return cacheKey;
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
core.setFailed((error as Error).message);
|
core.setFailed((error as Error).message);
|
||||||
|
|
|
@ -48,10 +48,26 @@ export async function saveImpl(
|
||||||
{ required: false }
|
{ required: false }
|
||||||
);
|
);
|
||||||
|
|
||||||
// If matched restore key is same as primary key, either try to refresh the cache, or just notify and do not save (NO-OP in case of SaveOnly action)
|
// If matched restore key is same as primary key, either try to refresh the cache, or just notify and do not save.
|
||||||
|
|
||||||
const restoredKey = stateProvider.getCacheState();
|
let restoredKey = stateProvider.getCacheState();
|
||||||
|
|
||||||
|
if (refreshCache && !restoredKey) {
|
||||||
|
// If getCacheState didn't give us a key, we're likely using granular actions. Do a lookup to see if we need to refresh or just do a regular save.
|
||||||
|
const cachePaths = utils.getInputAsArray(Inputs.Path, {
|
||||||
|
required: true
|
||||||
|
});
|
||||||
|
const enableCrossOsArchive = utils.getInputAsBool(
|
||||||
|
Inputs.EnableCrossOsArchive
|
||||||
|
);
|
||||||
|
restoredKey = await cache.restoreCache(
|
||||||
|
cachePaths,
|
||||||
|
primaryKey,
|
||||||
|
[],
|
||||||
|
{ lookupOnly: true },
|
||||||
|
enableCrossOsArchive
|
||||||
|
);
|
||||||
|
}
|
||||||
if (utils.isExactKeyMatch(primaryKey, restoredKey)) {
|
if (utils.isExactKeyMatch(primaryKey, restoredKey)) {
|
||||||
const { GITHUB_TOKEN, GITHUB_REPOSITORY } = process.env || null;
|
const { GITHUB_TOKEN, GITHUB_REPOSITORY } = process.env || null;
|
||||||
if (GITHUB_TOKEN && GITHUB_REPOSITORY && refreshCache === true) {
|
if (GITHUB_TOKEN && GITHUB_REPOSITORY && refreshCache === true) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue