mirror of
https://github.com/actions/cache.git
synced 2025-04-19 02:26:45 +00:00
Enabling actions/cache for GHES based on presence of AC service (#774)
* initial changes * Update package-lock.json * Update package-lock.json * review comments and updated test cases * package.json * changed name * added new line * changed tookit * updated with 2.0 * changed with public released package * ran code format * linting errors * Update actionUtils.test.ts * Update cache.dep.yml * Update package.json * Update README.md * Create RELEASES.md * Update RELEASES.md * Update package.json * Update package-lock.json * typo
This commit is contained in:
parent
7d4f40b464
commit
136d96b4ae
13 changed files with 7680 additions and 105 deletions
|
@ -1,3 +1,4 @@
|
|||
import * as cache from "@actions/cache";
|
||||
import * as core from "@actions/core";
|
||||
|
||||
import { Events, Outputs, RefKey, State } from "../src/constants";
|
||||
|
@ -5,6 +6,7 @@ import * as actionUtils from "../src/utils/actionUtils";
|
|||
import * as testUtils from "../src/utils/testUtils";
|
||||
|
||||
jest.mock("@actions/core");
|
||||
jest.mock("@actions/cache");
|
||||
|
||||
beforeAll(() => {
|
||||
jest.spyOn(core, "getInput").mockImplementation((name, options) => {
|
||||
|
@ -232,3 +234,41 @@ test("getInputAsInt throws if required and value missing", () => {
|
|||
actionUtils.getInputAsInt("undefined", { required: true })
|
||||
).toThrowError();
|
||||
});
|
||||
|
||||
test("isCacheFeatureAvailable for ac enabled", () => {
|
||||
jest.spyOn(cache, "isFeatureAvailable").mockImplementation(() => true);
|
||||
|
||||
expect(actionUtils.isCacheFeatureAvailable()).toBe(true);
|
||||
});
|
||||
|
||||
test("isCacheFeatureAvailable for ac disabled on GHES", () => {
|
||||
jest.spyOn(cache, "isFeatureAvailable").mockImplementation(() => false);
|
||||
|
||||
const message =
|
||||
"Cache action is only supported on GHES version >= 3.5. If you are on version >=3.5 Please check with GHES admin if Actions cache service is enabled or not.";
|
||||
const infoMock = jest.spyOn(core, "info");
|
||||
|
||||
try {
|
||||
process.env["GITHUB_SERVER_URL"] = "http://example.com";
|
||||
expect(actionUtils.isCacheFeatureAvailable()).toBe(false);
|
||||
expect(infoMock).toHaveBeenCalledWith(`[warning]${message}`);
|
||||
} finally {
|
||||
delete process.env["GITHUB_SERVER_URL"];
|
||||
}
|
||||
});
|
||||
|
||||
test("isCacheFeatureAvailable for ac disabled on dotcom", () => {
|
||||
jest.spyOn(cache, "isFeatureAvailable").mockImplementation(() => false);
|
||||
|
||||
const message =
|
||||
"An internal error has occurred in cache backend. Please check https://www.githubstatus.com/ for any ongoing issue in actions.";
|
||||
const infoMock = jest.spyOn(core, "info");
|
||||
|
||||
try {
|
||||
process.env["GITHUB_SERVER_URL"] = "http://github.com";
|
||||
expect(actionUtils.isCacheFeatureAvailable()).toBe(false);
|
||||
expect(infoMock).toHaveBeenCalledWith(`[warning]${message}`);
|
||||
} finally {
|
||||
delete process.env["GITHUB_SERVER_URL"];
|
||||
}
|
||||
});
|
||||
|
|
|
@ -34,6 +34,9 @@ beforeEach(() => {
|
|||
process.env[RefKey] = "refs/heads/feature-branch";
|
||||
|
||||
jest.spyOn(actionUtils, "isGhes").mockImplementation(() => false);
|
||||
jest.spyOn(actionUtils, "isCacheFeatureAvailable").mockImplementation(
|
||||
() => true
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
@ -55,10 +58,12 @@ test("restore with invalid event outputs warning", async () => {
|
|||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("restore on GHES should no-op", async () => {
|
||||
jest.spyOn(actionUtils, "isGhes").mockImplementation(() => true);
|
||||
test("restore without AC available should no-op", async () => {
|
||||
jest.spyOn(actionUtils, "isGhes").mockImplementation(() => false);
|
||||
jest.spyOn(actionUtils, "isCacheFeatureAvailable").mockImplementation(
|
||||
() => false
|
||||
);
|
||||
|
||||
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
||||
const restoreCacheMock = jest.spyOn(cache, "restoreCache");
|
||||
const setCacheHitOutputMock = jest.spyOn(actionUtils, "setCacheHitOutput");
|
||||
|
||||
|
@ -67,9 +72,54 @@ test("restore on GHES should no-op", async () => {
|
|||
expect(restoreCacheMock).toHaveBeenCalledTimes(0);
|
||||
expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
|
||||
expect(setCacheHitOutputMock).toHaveBeenCalledWith(false);
|
||||
expect(logWarningMock).toHaveBeenCalledWith(
|
||||
"Cache action is not supported on GHES. See https://github.com/actions/cache/issues/505 for more details"
|
||||
});
|
||||
|
||||
test("restore on GHES without AC available should no-op", async () => {
|
||||
jest.spyOn(actionUtils, "isGhes").mockImplementation(() => true);
|
||||
jest.spyOn(actionUtils, "isCacheFeatureAvailable").mockImplementation(
|
||||
() => false
|
||||
);
|
||||
|
||||
const restoreCacheMock = jest.spyOn(cache, "restoreCache");
|
||||
const setCacheHitOutputMock = jest.spyOn(actionUtils, "setCacheHitOutput");
|
||||
|
||||
await run();
|
||||
|
||||
expect(restoreCacheMock).toHaveBeenCalledTimes(0);
|
||||
expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
|
||||
expect(setCacheHitOutputMock).toHaveBeenCalledWith(false);
|
||||
});
|
||||
|
||||
test("restore on GHES with AC available ", async () => {
|
||||
jest.spyOn(actionUtils, "isGhes").mockImplementation(() => true);
|
||||
const path = "node_modules";
|
||||
const key = "node-test";
|
||||
testUtils.setInputs({
|
||||
path: path,
|
||||
key
|
||||
});
|
||||
|
||||
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);
|
||||
});
|
||||
|
||||
test("restore with no path should fail", async () => {
|
||||
|
|
|
@ -54,6 +54,9 @@ beforeEach(() => {
|
|||
process.env[RefKey] = "refs/heads/feature-branch";
|
||||
|
||||
jest.spyOn(actionUtils, "isGhes").mockImplementation(() => false);
|
||||
jest.spyOn(actionUtils, "isCacheFeatureAvailable").mockImplementation(
|
||||
() => true
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
@ -101,18 +104,67 @@ test("save with no primary key in state outputs warning", async () => {
|
|||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("save on GHES should no-op", async () => {
|
||||
jest.spyOn(actionUtils, "isGhes").mockImplementation(() => true);
|
||||
test("save without AC available should no-op", async () => {
|
||||
jest.spyOn(actionUtils, "isCacheFeatureAvailable").mockImplementation(
|
||||
() => false
|
||||
);
|
||||
|
||||
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
||||
const saveCacheMock = jest.spyOn(cache, "saveCache");
|
||||
|
||||
await run();
|
||||
|
||||
expect(saveCacheMock).toHaveBeenCalledTimes(0);
|
||||
expect(logWarningMock).toHaveBeenCalledWith(
|
||||
"Cache action is not supported on GHES. See https://github.com/actions/cache/issues/505 for more details"
|
||||
});
|
||||
|
||||
test("save on ghes without AC available should no-op", async () => {
|
||||
jest.spyOn(actionUtils, "isGhes").mockImplementation(() => true);
|
||||
jest.spyOn(actionUtils, "isCacheFeatureAvailable").mockImplementation(
|
||||
() => false
|
||||
);
|
||||
|
||||
const saveCacheMock = jest.spyOn(cache, "saveCache");
|
||||
|
||||
await run();
|
||||
|
||||
expect(saveCacheMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("save on GHES with AC available", async () => {
|
||||
jest.spyOn(actionUtils, "isGhes").mockImplementation(() => true);
|
||||
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.UploadChunkSize, "4000000");
|
||||
|
||||
const cacheId = 4;
|
||||
const saveCacheMock = jest
|
||||
.spyOn(cache, "saveCache")
|
||||
.mockImplementationOnce(() => {
|
||||
return Promise.resolve(cacheId);
|
||||
});
|
||||
|
||||
await run();
|
||||
|
||||
expect(saveCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(saveCacheMock).toHaveBeenCalledWith([inputPath], primaryKey, {
|
||||
uploadChunkSize: 4000000
|
||||
});
|
||||
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("save with exact match returns early", async () => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue