mirror of
https://github.com/actions/cache.git
synced 2025-05-19 15:26:33 +00:00
Merge 11a6324cc7
into 5a3ec84eff
This commit is contained in:
commit
ebd392318b
BIN
.licenses/NOTICE
generated
BIN
.licenses/NOTICE
generated
Binary file not shown.
BIN
.licenses/npm/@actions/exec.dep.yml
generated
BIN
.licenses/npm/@actions/exec.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@actions/http-client.dep.yml
generated
BIN
.licenses/npm/@actions/http-client.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@azure/abort-controller-2.1.2.dep.yml
generated
Normal file
BIN
.licenses/npm/@azure/abort-controller-2.1.2.dep.yml
generated
Normal file
Binary file not shown.
BIN
.licenses/npm/@azure/core-auth.dep.yml
generated
BIN
.licenses/npm/@azure/core-auth.dep.yml
generated
Binary file not shown.
Binary file not shown.
BIN
.licenses/npm/@azure/core-http-compat.dep.yml
generated
Normal file
BIN
.licenses/npm/@azure/core-http-compat.dep.yml
generated
Normal file
Binary file not shown.
BIN
.licenses/npm/@azure/core-lro.dep.yml
generated
BIN
.licenses/npm/@azure/core-lro.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@azure/core-paging.dep.yml
generated
BIN
.licenses/npm/@azure/core-paging.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@azure/core-rest-pipeline.dep.yml
generated
Normal file
BIN
.licenses/npm/@azure/core-rest-pipeline.dep.yml
generated
Normal file
Binary file not shown.
BIN
.licenses/npm/@azure/core-tracing.dep.yml
generated
BIN
.licenses/npm/@azure/core-tracing.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@azure/core-util.dep.yml
generated
BIN
.licenses/npm/@azure/core-util.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@azure/core-xml.dep.yml
generated
Normal file
BIN
.licenses/npm/@azure/core-xml.dep.yml
generated
Normal file
Binary file not shown.
BIN
.licenses/npm/@azure/logger.dep.yml
generated
BIN
.licenses/npm/@azure/logger.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@azure/storage-blob.dep.yml
generated
BIN
.licenses/npm/@azure/storage-blob.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@fastify/busboy.dep.yml
generated
Normal file
BIN
.licenses/npm/@fastify/busboy.dep.yml
generated
Normal file
Binary file not shown.
BIN
.licenses/npm/@octokit/action.dep.yml
generated
Normal file
BIN
.licenses/npm/@octokit/action.dep.yml
generated
Normal file
Binary file not shown.
BIN
.licenses/npm/@octokit/auth-action.dep.yml
generated
Normal file
BIN
.licenses/npm/@octokit/auth-action.dep.yml
generated
Normal file
Binary file not shown.
Binary file not shown.
BIN
.licenses/npm/@octokit/core.dep.yml
generated
Normal file
BIN
.licenses/npm/@octokit/core.dep.yml
generated
Normal file
Binary file not shown.
BIN
.licenses/npm/@octokit/endpoint.dep.yml
generated
Normal file
BIN
.licenses/npm/@octokit/endpoint.dep.yml
generated
Normal file
Binary file not shown.
BIN
.licenses/npm/@octokit/graphql.dep.yml
generated
Normal file
BIN
.licenses/npm/@octokit/graphql.dep.yml
generated
Normal file
Binary file not shown.
BIN
.licenses/npm/@octokit/openapi-types.dep.yml
generated
Normal file
BIN
.licenses/npm/@octokit/openapi-types.dep.yml
generated
Normal file
Binary file not shown.
BIN
.licenses/npm/@octokit/plugin-paginate-rest.dep.yml
generated
Normal file
BIN
.licenses/npm/@octokit/plugin-paginate-rest.dep.yml
generated
Normal file
Binary file not shown.
BIN
.licenses/npm/@octokit/plugin-rest-endpoint-methods.dep.yml
generated
Normal file
BIN
.licenses/npm/@octokit/plugin-rest-endpoint-methods.dep.yml
generated
Normal file
Binary file not shown.
BIN
.licenses/npm/@octokit/request-error.dep.yml
generated
Normal file
BIN
.licenses/npm/@octokit/request-error.dep.yml
generated
Normal file
Binary file not shown.
BIN
.licenses/npm/@octokit/request.dep.yml
generated
Normal file
BIN
.licenses/npm/@octokit/request.dep.yml
generated
Normal file
Binary file not shown.
BIN
.licenses/npm/@octokit/tsconfig.dep.yml
generated
Normal file
BIN
.licenses/npm/@octokit/tsconfig.dep.yml
generated
Normal file
Binary file not shown.
BIN
.licenses/npm/@octokit/types-10.0.0.dep.yml
generated
Normal file
BIN
.licenses/npm/@octokit/types-10.0.0.dep.yml
generated
Normal file
Binary file not shown.
BIN
.licenses/npm/@octokit/types-9.3.2.dep.yml
generated
Normal file
BIN
.licenses/npm/@octokit/types-9.3.2.dep.yml
generated
Normal file
Binary file not shown.
BIN
.licenses/npm/@opentelemetry/api.dep.yml
generated
BIN
.licenses/npm/@opentelemetry/api.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@protobuf-ts/plugin-framework.dep.yml
generated
BIN
.licenses/npm/@protobuf-ts/plugin-framework.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@protobuf-ts/plugin.dep.yml
generated
BIN
.licenses/npm/@protobuf-ts/plugin.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@protobuf-ts/protoc.dep.yml
generated
BIN
.licenses/npm/@protobuf-ts/protoc.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@protobuf-ts/runtime-rpc.dep.yml
generated
BIN
.licenses/npm/@protobuf-ts/runtime-rpc.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@protobuf-ts/runtime.dep.yml
generated
BIN
.licenses/npm/@protobuf-ts/runtime.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@types/node-fetch.dep.yml
generated
BIN
.licenses/npm/@types/node-fetch.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@types/node.dep.yml
generated
BIN
.licenses/npm/@types/node.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@types/tunnel.dep.yml
generated
BIN
.licenses/npm/@types/tunnel.dep.yml
generated
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.licenses/npm/camel-case.dep.yml
generated
BIN
.licenses/npm/camel-case.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/concat-map.dep.yml
generated
BIN
.licenses/npm/concat-map.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/debug.dep.yml
generated
Normal file
BIN
.licenses/npm/debug.dep.yml
generated
Normal file
Binary file not shown.
Binary file not shown.
BIN
.licenses/npm/dot-object.dep.yml
generated
BIN
.licenses/npm/dot-object.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/event-target-shim.dep.yml
generated
BIN
.licenses/npm/event-target-shim.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/events.dep.yml
generated
BIN
.licenses/npm/events.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/fast-xml-parser.dep.yml
generated
Normal file
BIN
.licenses/npm/fast-xml-parser.dep.yml
generated
Normal file
Binary file not shown.
BIN
.licenses/npm/form-data-2.5.1.dep.yml
generated
BIN
.licenses/npm/form-data-2.5.1.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/form-data-3.0.1.dep.yml
generated
BIN
.licenses/npm/form-data-3.0.1.dep.yml
generated
Binary file not shown.
Binary file not shown.
BIN
.licenses/npm/fs.realpath.dep.yml
generated
BIN
.licenses/npm/fs.realpath.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/glob.dep.yml
generated
BIN
.licenses/npm/glob.dep.yml
generated
Binary file not shown.
Binary file not shown.
BIN
.licenses/npm/https-proxy-agent.dep.yml
generated
Normal file
BIN
.licenses/npm/https-proxy-agent.dep.yml
generated
Normal file
Binary file not shown.
BIN
.licenses/npm/inherits.dep.yml
generated
BIN
.licenses/npm/inherits.dep.yml
generated
Binary file not shown.
Binary file not shown.
BIN
.licenses/npm/lodash.dep.yml
generated
BIN
.licenses/npm/lodash.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/mime-db.dep.yml
generated
BIN
.licenses/npm/mime-db.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/mime-types.dep.yml
generated
BIN
.licenses/npm/mime-types.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/minimatch.dep.yml
generated
BIN
.licenses/npm/minimatch.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/ms.dep.yml
generated
Normal file
BIN
.licenses/npm/ms.dep.yml
generated
Normal file
Binary file not shown.
BIN
.licenses/npm/node-fetch.dep.yml
generated
BIN
.licenses/npm/node-fetch.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/pascal-case.dep.yml
generated
BIN
.licenses/npm/pascal-case.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/path-to-regexp.dep.yml
generated
BIN
.licenses/npm/path-to-regexp.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/prettier.dep.yml
generated
BIN
.licenses/npm/prettier.dep.yml
generated
Binary file not shown.
Binary file not shown.
BIN
.licenses/npm/sax.dep.yml
generated
BIN
.licenses/npm/sax.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/semver.dep.yml
generated
BIN
.licenses/npm/semver.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/strnum.dep.yml
generated
Normal file
BIN
.licenses/npm/strnum.dep.yml
generated
Normal file
Binary file not shown.
BIN
.licenses/npm/tslib-1.14.1.dep.yml
generated
BIN
.licenses/npm/tslib-1.14.1.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/tslib-2.3.1.dep.yml
generated
BIN
.licenses/npm/tslib-2.3.1.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/tslib-2.5.0.dep.yml
generated
BIN
.licenses/npm/tslib-2.5.0.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/twirp-ts.dep.yml
generated
BIN
.licenses/npm/twirp-ts.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/typescript.dep.yml
generated
BIN
.licenses/npm/typescript.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/undici.dep.yml
generated
Normal file
BIN
.licenses/npm/undici.dep.yml
generated
Normal file
Binary file not shown.
BIN
.licenses/npm/universal-user-agent.dep.yml
generated
Normal file
BIN
.licenses/npm/universal-user-agent.dep.yml
generated
Normal file
Binary file not shown.
BIN
.licenses/npm/webidl-conversions.dep.yml
generated
BIN
.licenses/npm/webidl-conversions.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/whatwg-url.dep.yml
generated
BIN
.licenses/npm/whatwg-url.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/xmlbuilder.dep.yml
generated
BIN
.licenses/npm/xmlbuilder.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/yaml.dep.yml
generated
BIN
.licenses/npm/yaml.dep.yml
generated
Binary file not shown.
@ -7,5 +7,6 @@
|
|||||||
"trailingComma": "none",
|
"trailingComma": "none",
|
||||||
"bracketSpacing": true,
|
"bracketSpacing": true,
|
||||||
"arrowParens": "avoid",
|
"arrowParens": "avoid",
|
||||||
"parser": "typescript"
|
"parser": "typescript",
|
||||||
|
"endOfLine": "lf"
|
||||||
}
|
}
|
@ -38,6 +38,7 @@ Read more about the change & access the migration guide: [reference to the annou
|
|||||||
|
|
||||||
### v3
|
### v3
|
||||||
|
|
||||||
|
* Added a workaround to allow updating/refreshing existing caches, via the `refresh-cache` option and requiring a valid Github API token.
|
||||||
* Integrated with the new cache service (v2) APIs.
|
* Integrated with the new cache service (v2) APIs.
|
||||||
* Added support for caching in GHES 3.5+.
|
* Added support for caching in GHES 3.5+.
|
||||||
* Fixed download issue for files > 2GB during restore.
|
* Fixed download issue for files > 2GB during restore.
|
||||||
@ -76,10 +77,12 @@ If you are using a `self-hosted` Windows runner, `GNU tar` and `zstd` are requir
|
|||||||
* `enableCrossOsArchive` - An optional boolean when enabled, allows Windows runners to save or restore caches that can be restored or saved respectively on other platforms. Default: `false`
|
* `enableCrossOsArchive` - An optional boolean when enabled, allows Windows runners to save or restore caches that can be restored or saved respectively on other platforms. Default: `false`
|
||||||
* `fail-on-cache-miss` - Fail the workflow if cache entry is not found. Default: `false`
|
* `fail-on-cache-miss` - Fail the workflow if cache entry is not found. Default: `false`
|
||||||
* `lookup-only` - If true, only checks if cache entry exists and skips download. Does not change save cache behavior. Default: `false`
|
* `lookup-only` - If true, only checks if cache entry exists and skips download. Does not change save cache behavior. Default: `false`
|
||||||
|
* `refresh-cache` - An optional boolean, when enabled it will result in a matched key being deleted after being restored, allowing it to be reused with refreshed/updated content. Default: false
|
||||||
|
|
||||||
#### Environment Variables
|
#### Environment Variables
|
||||||
|
|
||||||
* `SEGMENT_DOWNLOAD_TIMEOUT_MINS` - Segment download timeout (in minutes, default `10`) to abort download of the segment if not completed in the defined number of minutes. [Read more](https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout)
|
* `SEGMENT_DOWNLOAD_TIMEOUT_MINS` - Segment download timeout (in minutes, default `10`) to abort download of the segment if not completed in the defined number of minutes. [Read more](https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout)
|
||||||
|
* `GITHUB_TOKEN` - A Github API token, required for authenticating to the API when the `refresh-cache` option is enabled.
|
||||||
|
|
||||||
### Outputs
|
### Outputs
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import * as cache from "@actions/cache";
|
import * as cache from "@actions/cache";
|
||||||
import * as core from "@actions/core";
|
import * as core from "@actions/core";
|
||||||
|
import nock from "nock";
|
||||||
|
|
||||||
import { Events, RefKey } from "../src/constants";
|
import { Events, RefKey } from "../src/constants";
|
||||||
import * as actionUtils from "../src/utils/actionUtils";
|
import * as actionUtils from "../src/utils/actionUtils";
|
||||||
@ -12,9 +13,13 @@ let pristineEnv: NodeJS.ProcessEnv;
|
|||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
pristineEnv = process.env;
|
pristineEnv = process.env;
|
||||||
|
nock.disableNetConnect();
|
||||||
jest.spyOn(core, "getInput").mockImplementation((name, options) => {
|
jest.spyOn(core, "getInput").mockImplementation((name, options) => {
|
||||||
return jest.requireActual("@actions/core").getInput(name, options);
|
return jest.requireActual("@actions/core").getInput(name, options);
|
||||||
});
|
});
|
||||||
|
testUtils.mockServer.listen({
|
||||||
|
onUnhandledRequest: "warn"
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@ -22,10 +27,15 @@ beforeEach(() => {
|
|||||||
process.env = pristineEnv;
|
process.env = pristineEnv;
|
||||||
delete process.env[Events.Key];
|
delete process.env[Events.Key];
|
||||||
delete process.env[RefKey];
|
delete process.env[RefKey];
|
||||||
|
delete process.env["GITHUB_REPOSITORY"];
|
||||||
|
delete process.env["GITHUB_TOKEN"];
|
||||||
|
delete process.env["GITHUB_ACTION"];
|
||||||
});
|
});
|
||||||
|
|
||||||
afterAll(() => {
|
afterAll(() => {
|
||||||
process.env = pristineEnv;
|
process.env = pristineEnv;
|
||||||
|
testUtils.mockServer.close();
|
||||||
|
nock.enableNetConnect();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("isGhes returns true if server url is not github.com", () => {
|
test("isGhes returns true if server url is not github.com", () => {
|
||||||
@ -203,6 +213,133 @@ test("getInputAsBool throws if required and value missing", () => {
|
|||||||
).toThrowError();
|
).toThrowError();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("deleteCacheByKey produces 'HttpError: 404' when cache is not found.", async () => {
|
||||||
|
const event = Events.Push;
|
||||||
|
|
||||||
|
process.env["GITHUB_REPOSITORY"] = "owner/repo";
|
||||||
|
process.env["GITHUB_TOKEN"] =
|
||||||
|
"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";
|
||||||
|
process.env["GITHUB_ACTION"] = "__owner___run-repo";
|
||||||
|
process.env[Events.Key] = event;
|
||||||
|
process.env[RefKey] = "ref/heads/feature";
|
||||||
|
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
||||||
|
const response = await actionUtils.deleteCacheByKey(
|
||||||
|
testUtils.failureCacheKey,
|
||||||
|
"owner",
|
||||||
|
"repo"
|
||||||
|
);
|
||||||
|
expect(logWarningMock).toHaveBeenCalledWith(
|
||||||
|
expect.stringMatching(/404: Not Found/i)
|
||||||
|
);
|
||||||
|
expect(response).toBe(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("deleteCacheByKey does not delete anything if it finds more than one entry for the given key.", async () => {
|
||||||
|
const event = Events.Push;
|
||||||
|
|
||||||
|
process.env["GITHUB_REPOSITORY"] = "owner/repo";
|
||||||
|
process.env["GITHUB_TOKEN"] =
|
||||||
|
"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";
|
||||||
|
process.env["GITHUB_ACTION"] = "__owner___run-repo";
|
||||||
|
process.env[Events.Key] = event;
|
||||||
|
process.env[RefKey] = "";
|
||||||
|
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
||||||
|
const response = await actionUtils.deleteCacheByKey(
|
||||||
|
testUtils.failureCacheKey,
|
||||||
|
"owner",
|
||||||
|
"repo"
|
||||||
|
);
|
||||||
|
expect(logWarningMock).toHaveBeenCalledWith(
|
||||||
|
`More than one cache entry found for key ${testUtils.failureCacheKey}`
|
||||||
|
);
|
||||||
|
expect(response).toBe(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("deleteCacheByKey does not delete anything if the key matches a cache belonging to another ref.", async () => {
|
||||||
|
const event = Events.Push;
|
||||||
|
|
||||||
|
process.env["GITHUB_REPOSITORY"] = "owner/repo";
|
||||||
|
process.env["GITHUB_TOKEN"] =
|
||||||
|
"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";
|
||||||
|
process.env["GITHUB_ACTION"] = "__owner___run-repo";
|
||||||
|
process.env[Events.Key] = event;
|
||||||
|
process.env[RefKey] = "ref/heads/feature";
|
||||||
|
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
||||||
|
const response = await actionUtils.deleteCacheByKey(
|
||||||
|
testUtils.wrongRefCacheKey,
|
||||||
|
"owner",
|
||||||
|
"repo"
|
||||||
|
);
|
||||||
|
expect(logWarningMock).toHaveBeenCalledWith(
|
||||||
|
`No cache entries for key ${testUtils.wrongRefCacheKey} belong to gitref ${process.env[RefKey]}.`
|
||||||
|
);
|
||||||
|
expect(response).toBe(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("deleteCacheByKey produces 'HttpError: 404' when cache is not found.", async () => {
|
||||||
|
const event = Events.Push;
|
||||||
|
|
||||||
|
process.env["GITHUB_REPOSITORY"] = "owner/repo";
|
||||||
|
process.env["GITHUB_TOKEN"] =
|
||||||
|
"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";
|
||||||
|
process.env["GITHUB_ACTION"] = "__owner___run-repo";
|
||||||
|
process.env[Events.Key] = event;
|
||||||
|
process.env[RefKey] = "ref/heads/feature";
|
||||||
|
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
||||||
|
const response = await actionUtils.deleteCacheByKey(
|
||||||
|
testUtils.failureCacheKey,
|
||||||
|
"owner",
|
||||||
|
"repo"
|
||||||
|
);
|
||||||
|
expect(logWarningMock).toHaveBeenCalledWith(
|
||||||
|
expect.stringMatching(/404: Not Found/i)
|
||||||
|
);
|
||||||
|
expect(response).toBe(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("deleteCacheByKey produces 'HttpError: 401' on an invalid non-mocked request.", async () => {
|
||||||
|
const event = Events.Push;
|
||||||
|
|
||||||
|
process.env["GITHUB_REPOSITORY"] = "owner/repo";
|
||||||
|
process.env["GITHUB_TOKEN"] =
|
||||||
|
"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";
|
||||||
|
process.env["GITHUB_ACTION"] = "__owner___run-repo";
|
||||||
|
process.env[Events.Key] = event;
|
||||||
|
process.env[RefKey] = "ref/heads/feature";
|
||||||
|
await nock.enableNetConnect();
|
||||||
|
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
||||||
|
const response = await actionUtils.deleteCacheByKey(
|
||||||
|
testUtils.passThroughCacheKey,
|
||||||
|
"owner",
|
||||||
|
"repo"
|
||||||
|
);
|
||||||
|
expect(logWarningMock).toHaveBeenCalledWith(
|
||||||
|
expect.stringMatching(/401: Bad Credentials/i)
|
||||||
|
);
|
||||||
|
expect(response).toBe(undefined);
|
||||||
|
nock.disableNetConnect();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("deleteCacheByKey returns 204 / No Content when successful.", async () => {
|
||||||
|
const event = Events.Push;
|
||||||
|
|
||||||
|
process.env["GITHUB_REPOSITORY"] = "owner/repo";
|
||||||
|
process.env["GITHUB_TOKEN"] =
|
||||||
|
"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";
|
||||||
|
process.env["GITHUB_ACTION"] = "__owner___run-repo";
|
||||||
|
process.env[Events.Key] = event;
|
||||||
|
process.env[RefKey] = "ref/heads/feature";
|
||||||
|
|
||||||
|
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
||||||
|
const response = await actionUtils.deleteCacheByKey(
|
||||||
|
testUtils.successCacheKey,
|
||||||
|
"owner",
|
||||||
|
"repo"
|
||||||
|
);
|
||||||
|
expect(response).toBe(204);
|
||||||
|
expect(logWarningMock).toHaveBeenCalledTimes(0);
|
||||||
|
});
|
||||||
|
|
||||||
test("isCacheFeatureAvailable for ac enabled", () => {
|
test("isCacheFeatureAvailable for ac enabled", () => {
|
||||||
jest.spyOn(cache, "isFeatureAvailable").mockImplementation(() => true);
|
jest.spyOn(cache, "isFeatureAvailable").mockImplementation(() => true);
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import * as cache from "@actions/cache";
|
import * as cache from "@actions/cache";
|
||||||
import * as core from "@actions/core";
|
import * as core from "@actions/core";
|
||||||
|
import nock from "nock";
|
||||||
|
|
||||||
import { Events, RefKey } from "../src/constants";
|
import { Events, RefKey } from "../src/constants";
|
||||||
import { restoreRun } from "../src/restoreImpl";
|
import { restoreRun } from "../src/restoreImpl";
|
||||||
@ -9,6 +10,7 @@ import * as testUtils from "../src/utils/testUtils";
|
|||||||
jest.mock("../src/utils/actionUtils");
|
jest.mock("../src/utils/actionUtils");
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
|
nock.disableNetConnect();
|
||||||
jest.spyOn(actionUtils, "isExactKeyMatch").mockImplementation(
|
jest.spyOn(actionUtils, "isExactKeyMatch").mockImplementation(
|
||||||
(key, cacheResult) => {
|
(key, cacheResult) => {
|
||||||
const actualUtils = jest.requireActual("../src/utils/actionUtils");
|
const actualUtils = jest.requireActual("../src/utils/actionUtils");
|
||||||
@ -53,6 +55,10 @@ afterEach(() => {
|
|||||||
delete process.env[RefKey];
|
delete process.env[RefKey];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
nock.enableNetConnect();
|
||||||
|
});
|
||||||
|
|
||||||
test("restore with no cache found", async () => {
|
test("restore with no cache found", async () => {
|
||||||
const path = "node_modules";
|
const path = "node_modules";
|
||||||
const key = "node-test";
|
const key = "node-test";
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import * as cache from "@actions/cache";
|
import * as cache from "@actions/cache";
|
||||||
import * as core from "@actions/core";
|
import * as core from "@actions/core";
|
||||||
|
import nock from "nock";
|
||||||
|
|
||||||
import { Events, Inputs, RefKey } from "../src/constants";
|
import { Events, Inputs, RefKey } from "../src/constants";
|
||||||
import { restoreImpl } from "../src/restoreImpl";
|
import { restoreImpl } from "../src/restoreImpl";
|
||||||
@ -10,6 +11,7 @@ import * as testUtils from "../src/utils/testUtils";
|
|||||||
jest.mock("../src/utils/actionUtils");
|
jest.mock("../src/utils/actionUtils");
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
|
nock.disableNetConnect();
|
||||||
jest.spyOn(actionUtils, "isExactKeyMatch").mockImplementation(
|
jest.spyOn(actionUtils, "isExactKeyMatch").mockImplementation(
|
||||||
(key, cacheResult) => {
|
(key, cacheResult) => {
|
||||||
const actualUtils = jest.requireActual("../src/utils/actionUtils");
|
const actualUtils = jest.requireActual("../src/utils/actionUtils");
|
||||||
@ -54,6 +56,10 @@ afterEach(() => {
|
|||||||
delete process.env[RefKey];
|
delete process.env[RefKey];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
nock.enableNetConnect();
|
||||||
|
});
|
||||||
|
|
||||||
test("restore with invalid event outputs warning", async () => {
|
test("restore with invalid event outputs warning", async () => {
|
||||||
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
||||||
const failedMock = jest.spyOn(core, "setFailed");
|
const failedMock = jest.spyOn(core, "setFailed");
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import * as cache from "@actions/cache";
|
import * as cache from "@actions/cache";
|
||||||
import * as core from "@actions/core";
|
import * as core from "@actions/core";
|
||||||
|
import nock from "nock";
|
||||||
|
|
||||||
import { Events, RefKey } from "../src/constants";
|
import { Events, RefKey } from "../src/constants";
|
||||||
import { restoreOnlyRun } from "../src/restoreImpl";
|
import { restoreOnlyRun } from "../src/restoreImpl";
|
||||||
@ -9,6 +10,7 @@ import * as testUtils from "../src/utils/testUtils";
|
|||||||
jest.mock("../src/utils/actionUtils");
|
jest.mock("../src/utils/actionUtils");
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
|
nock.disableNetConnect();
|
||||||
jest.spyOn(actionUtils, "isExactKeyMatch").mockImplementation(
|
jest.spyOn(actionUtils, "isExactKeyMatch").mockImplementation(
|
||||||
(key, cacheResult) => {
|
(key, cacheResult) => {
|
||||||
const actualUtils = jest.requireActual("../src/utils/actionUtils");
|
const actualUtils = jest.requireActual("../src/utils/actionUtils");
|
||||||
@ -54,6 +56,10 @@ afterEach(() => {
|
|||||||
delete process.env[RefKey];
|
delete process.env[RefKey];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
nock.enableNetConnect();
|
||||||
|
});
|
||||||
|
|
||||||
test("restore with no cache found", async () => {
|
test("restore with no cache found", async () => {
|
||||||
const path = "node_modules";
|
const path = "node_modules";
|
||||||
const key = "node-test";
|
const key = "node-test";
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import * as cache from "@actions/cache";
|
import * as cache from "@actions/cache";
|
||||||
import * as core from "@actions/core";
|
import * as core from "@actions/core";
|
||||||
|
import nock from "nock";
|
||||||
|
|
||||||
import { Events, Inputs, RefKey } from "../src/constants";
|
import { Events, Inputs, RefKey } from "../src/constants";
|
||||||
import { saveRun } from "../src/saveImpl";
|
import { saveRun } from "../src/saveImpl";
|
||||||
@ -11,6 +12,7 @@ jest.mock("@actions/cache");
|
|||||||
jest.mock("../src/utils/actionUtils");
|
jest.mock("../src/utils/actionUtils");
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
|
nock.disableNetConnect();
|
||||||
jest.spyOn(core, "getInput").mockImplementation((name, options) => {
|
jest.spyOn(core, "getInput").mockImplementation((name, options) => {
|
||||||
return jest.requireActual("@actions/core").getInput(name, options);
|
return jest.requireActual("@actions/core").getInput(name, options);
|
||||||
});
|
});
|
||||||
@ -73,10 +75,14 @@ afterEach(() => {
|
|||||||
delete process.env[RefKey];
|
delete process.env[RefKey];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
nock.enableNetConnect();
|
||||||
|
});
|
||||||
|
|
||||||
test("save with valid inputs uploads a cache", async () => {
|
test("save with valid inputs uploads a cache", async () => {
|
||||||
const failedMock = jest.spyOn(core, "setFailed");
|
const failedMock = jest.spyOn(core, "setFailed");
|
||||||
|
|
||||||
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
|
const primaryKey = testUtils.successCacheKey;
|
||||||
const savedCacheKey = "Linux-node-";
|
const savedCacheKey = "Linux-node-";
|
||||||
|
|
||||||
jest.spyOn(core, "getState")
|
jest.spyOn(core, "getState")
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import * as cache from "@actions/cache";
|
import * as cache from "@actions/cache";
|
||||||
import * as core from "@actions/core";
|
import * as core from "@actions/core";
|
||||||
|
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";
|
||||||
|
|
||||||
@ -12,6 +13,19 @@ jest.mock("@actions/cache");
|
|||||||
jest.mock("../src/utils/actionUtils");
|
jest.mock("../src/utils/actionUtils");
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
|
nock.disableNetConnect();
|
||||||
|
testUtils.mockServer.listen({
|
||||||
|
onUnhandledRequest: "warn"
|
||||||
|
});
|
||||||
|
|
||||||
|
jest.spyOn(actionUtils, "deleteCacheByKey").mockImplementation(
|
||||||
|
(key: string, owner: string, repo: string) => {
|
||||||
|
return jest
|
||||||
|
.requireActual("../src/utils/actionUtils")
|
||||||
|
.deleteCacheByKey(key, owner, repo);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
jest.spyOn(core, "getInput").mockImplementation((name, options) => {
|
jest.spyOn(core, "getInput").mockImplementation((name, options) => {
|
||||||
return jest.requireActual("@actions/core").getInput(name, options);
|
return jest.requireActual("@actions/core").getInput(name, options);
|
||||||
});
|
});
|
||||||
@ -52,6 +66,14 @@ beforeAll(() => {
|
|||||||
const actualUtils = jest.requireActual("../src/utils/actionUtils");
|
const actualUtils = jest.requireActual("../src/utils/actionUtils");
|
||||||
return actualUtils.isValidEvent();
|
return actualUtils.isValidEvent();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
jest.spyOn(actionUtils, "logWarning").mockImplementation(
|
||||||
|
(message: string) => {
|
||||||
|
return jest
|
||||||
|
.requireActual("../src/utils/actionUtils")
|
||||||
|
.logWarning(message);
|
||||||
|
}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@ -69,6 +91,13 @@ afterEach(() => {
|
|||||||
testUtils.clearInputs();
|
testUtils.clearInputs();
|
||||||
delete process.env[Events.Key];
|
delete process.env[Events.Key];
|
||||||
delete process.env[RefKey];
|
delete process.env[RefKey];
|
||||||
|
delete process.env["GITHUB_TOKEN"];
|
||||||
|
delete process.env["GITHUB_REPOSITORY"];
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
testUtils.mockServer.close();
|
||||||
|
nock.enableNetConnect();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("save with invalid event outputs warning", async () => {
|
test("save with invalid event outputs warning", async () => {
|
||||||
@ -88,7 +117,7 @@ test("save with no primary key in state outputs warning", async () => {
|
|||||||
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
||||||
const failedMock = jest.spyOn(core, "setFailed");
|
const failedMock = jest.spyOn(core, "setFailed");
|
||||||
|
|
||||||
const savedCacheKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
|
const savedCacheKey = testUtils.successCacheKey;
|
||||||
jest.spyOn(core, "getState")
|
jest.spyOn(core, "getState")
|
||||||
// Cache Entry State
|
// Cache Entry State
|
||||||
.mockImplementationOnce(() => {
|
.mockImplementationOnce(() => {
|
||||||
@ -137,7 +166,7 @@ test("save on GHES with AC available", async () => {
|
|||||||
jest.spyOn(actionUtils, "isGhes").mockImplementation(() => true);
|
jest.spyOn(actionUtils, "isGhes").mockImplementation(() => true);
|
||||||
const failedMock = jest.spyOn(core, "setFailed");
|
const failedMock = jest.spyOn(core, "setFailed");
|
||||||
|
|
||||||
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
|
const primaryKey = testUtils.successCacheKey;
|
||||||
const savedCacheKey = "Linux-node-";
|
const savedCacheKey = "Linux-node-";
|
||||||
|
|
||||||
jest.spyOn(core, "getState")
|
jest.spyOn(core, "getState")
|
||||||
@ -179,8 +208,10 @@ test("save on GHES with AC available", async () => {
|
|||||||
test("save with exact match returns early", async () => {
|
test("save with exact match returns early", async () => {
|
||||||
const infoMock = jest.spyOn(core, "info");
|
const infoMock = jest.spyOn(core, "info");
|
||||||
const failedMock = jest.spyOn(core, "setFailed");
|
const failedMock = jest.spyOn(core, "setFailed");
|
||||||
|
testUtils.setInput(Inputs.RefreshCache, "false");
|
||||||
|
|
||||||
|
const primaryKey = testUtils.successCacheKey;
|
||||||
|
|
||||||
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
|
|
||||||
const savedCacheKey = primaryKey;
|
const savedCacheKey = primaryKey;
|
||||||
|
|
||||||
jest.spyOn(core, "getState")
|
jest.spyOn(core, "getState")
|
||||||
@ -207,7 +238,7 @@ test("save with missing input outputs warning", async () => {
|
|||||||
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
||||||
const failedMock = jest.spyOn(core, "setFailed");
|
const failedMock = jest.spyOn(core, "setFailed");
|
||||||
|
|
||||||
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
|
const primaryKey = testUtils.successCacheKey;
|
||||||
const savedCacheKey = "Linux-node-";
|
const savedCacheKey = "Linux-node-";
|
||||||
|
|
||||||
jest.spyOn(core, "getState")
|
jest.spyOn(core, "getState")
|
||||||
@ -235,7 +266,7 @@ test("save with large cache outputs warning", async () => {
|
|||||||
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
||||||
const failedMock = jest.spyOn(core, "setFailed");
|
const failedMock = jest.spyOn(core, "setFailed");
|
||||||
|
|
||||||
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
|
const primaryKey = testUtils.successCacheKey;
|
||||||
const savedCacheKey = "Linux-node-";
|
const savedCacheKey = "Linux-node-";
|
||||||
|
|
||||||
jest.spyOn(core, "getState")
|
jest.spyOn(core, "getState")
|
||||||
@ -280,7 +311,7 @@ test("save with reserve cache failure outputs warning", async () => {
|
|||||||
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
||||||
const failedMock = jest.spyOn(core, "setFailed");
|
const failedMock = jest.spyOn(core, "setFailed");
|
||||||
|
|
||||||
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
|
const primaryKey = testUtils.successCacheKey;
|
||||||
const savedCacheKey = "Linux-node-";
|
const savedCacheKey = "Linux-node-";
|
||||||
|
|
||||||
jest.spyOn(core, "getState")
|
jest.spyOn(core, "getState")
|
||||||
@ -327,7 +358,7 @@ test("save with server error outputs warning", async () => {
|
|||||||
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
||||||
const failedMock = jest.spyOn(core, "setFailed");
|
const failedMock = jest.spyOn(core, "setFailed");
|
||||||
|
|
||||||
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
|
const primaryKey = testUtils.successCacheKey;
|
||||||
const savedCacheKey = "Linux-node-";
|
const savedCacheKey = "Linux-node-";
|
||||||
|
|
||||||
jest.spyOn(core, "getState")
|
jest.spyOn(core, "getState")
|
||||||
@ -368,7 +399,7 @@ test("save with server error outputs warning", async () => {
|
|||||||
test("save with valid inputs uploads a cache", async () => {
|
test("save with valid inputs uploads a cache", async () => {
|
||||||
const failedMock = jest.spyOn(core, "setFailed");
|
const failedMock = jest.spyOn(core, "setFailed");
|
||||||
|
|
||||||
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
|
const primaryKey = testUtils.successCacheKey;
|
||||||
const savedCacheKey = "Linux-node-";
|
const savedCacheKey = "Linux-node-";
|
||||||
|
|
||||||
jest.spyOn(core, "getState")
|
jest.spyOn(core, "getState")
|
||||||
@ -406,3 +437,179 @@ test("save with valid inputs uploads a cache", async () => {
|
|||||||
|
|
||||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("save with cache hit and refresh-cache will try to delete and re-create entry", 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 savedCacheKey = primaryKey;
|
||||||
|
|
||||||
|
jest.spyOn(core, "getState")
|
||||||
|
// Cache Entry State
|
||||||
|
.mockImplementationOnce(() => {
|
||||||
|
return savedCacheKey;
|
||||||
|
})
|
||||||
|
.mockImplementationOnce(() => {
|
||||||
|
return primaryKey;
|
||||||
|
});
|
||||||
|
|
||||||
|
const inputPath = "node_modules";
|
||||||
|
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 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,
|
||||||
|
expect.stringMatching(
|
||||||
|
new RegExp(
|
||||||
|
`Succesfully deleted cache with key: ${primaryKey}, id: \\d+`
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
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).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,
|
||||||
|
expect.stringMatching(
|
||||||
|
new RegExp(
|
||||||
|
`Succesfully deleted cache with key: ${primaryKey}, id: \\d+`
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
expect(infoMock).toHaveBeenNthCalledWith(
|
||||||
|
3,
|
||||||
|
`Cache saved with key: ${primaryKey}`
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("save with cache hit and refresh-cache will throw a warning if there's no GITHUB_TOKEN", async () => {
|
||||||
|
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
||||||
|
const failedMock = jest.spyOn(core, "setFailed");
|
||||||
|
|
||||||
|
const primaryKey = testUtils.successCacheKey;
|
||||||
|
const savedCacheKey = primaryKey;
|
||||||
|
|
||||||
|
const inputPath = "node_modules";
|
||||||
|
testUtils.setInput(Inputs.Path, inputPath);
|
||||||
|
testUtils.setInput(Inputs.RefreshCache, "true");
|
||||||
|
|
||||||
|
jest.spyOn(core, "getState")
|
||||||
|
// Cache Entry State
|
||||||
|
.mockImplementationOnce(() => {
|
||||||
|
return savedCacheKey;
|
||||||
|
})
|
||||||
|
// Cache Key State
|
||||||
|
.mockImplementationOnce(() => {
|
||||||
|
return primaryKey;
|
||||||
|
});
|
||||||
|
|
||||||
|
const saveCacheMock = jest.spyOn(cache, "saveCache");
|
||||||
|
await saveImpl(new StateProvider());
|
||||||
|
|
||||||
|
expect(saveCacheMock).toHaveBeenCalledTimes(0);
|
||||||
|
expect(logWarningMock).toHaveBeenCalledWith(
|
||||||
|
`Can't refresh cache, either the repository info or a valid token are missing.`
|
||||||
|
);
|
||||||
|
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||||
|
});
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import * as cache from "@actions/cache";
|
import * as cache from "@actions/cache";
|
||||||
import * as core from "@actions/core";
|
import * as core from "@actions/core";
|
||||||
|
import nock from "nock";
|
||||||
|
|
||||||
import { Events, Inputs, RefKey } from "../src/constants";
|
import { Events, Inputs, RefKey } from "../src/constants";
|
||||||
import { saveOnlyRun } from "../src/saveImpl";
|
import { saveOnlyRun } from "../src/saveImpl";
|
||||||
@ -11,6 +12,7 @@ jest.mock("@actions/cache");
|
|||||||
jest.mock("../src/utils/actionUtils");
|
jest.mock("../src/utils/actionUtils");
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
|
nock.disableNetConnect();
|
||||||
jest.spyOn(core, "getInput").mockImplementation((name, options) => {
|
jest.spyOn(core, "getInput").mockImplementation((name, options) => {
|
||||||
return jest.requireActual("@actions/core").getInput(name, options);
|
return jest.requireActual("@actions/core").getInput(name, options);
|
||||||
});
|
});
|
||||||
@ -73,6 +75,10 @@ afterEach(() => {
|
|||||||
delete process.env[RefKey];
|
delete process.env[RefKey];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
nock.enableNetConnect();
|
||||||
|
});
|
||||||
|
|
||||||
test("save with valid inputs uploads a cache", async () => {
|
test("save with valid inputs uploads a cache", async () => {
|
||||||
const failedMock = jest.spyOn(core, "setFailed");
|
const failedMock = jest.spyOn(core, "setFailed");
|
||||||
|
|
||||||
@ -105,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");
|
||||||
|
|
||||||
|
@ -34,6 +34,10 @@ inputs:
|
|||||||
save-always does not work as intended and will be removed in a future release.
|
save-always does not work as intended and will be removed in a future release.
|
||||||
A separate `actions/cache/restore` step should be used instead.
|
A separate `actions/cache/restore` step should be used instead.
|
||||||
See https://github.com/actions/cache/tree/main/save#always-save-cache for more details.
|
See https://github.com/actions/cache/tree/main/save#always-save-cache for more details.
|
||||||
|
refresh-cache:
|
||||||
|
description: 'An optional boolean, when enabled it will result in a matched key being deleted after being restored, allowing it to be reused with refreshed/updated content. Default: false'
|
||||||
|
required: false
|
||||||
|
default: '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'
|
||||||
|
96251
dist/restore-only/index.js
vendored
96251
dist/restore-only/index.js
vendored
File diff suppressed because one or more lines are too long
96251
dist/restore/index.js
vendored
96251
dist/restore/index.js
vendored
File diff suppressed because one or more lines are too long
96282
dist/save-only/index.js
vendored
96282
dist/save-only/index.js
vendored
File diff suppressed because one or more lines are too long
96282
dist/save/index.js
vendored
96282
dist/save/index.js
vendored
File diff suppressed because one or more lines are too long
@ -1,5 +1,3 @@
|
|||||||
require("nock").disableNetConnect();
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
clearMocks: true,
|
clearMocks: true,
|
||||||
moduleFileExtensions: ["js", "ts"],
|
moduleFileExtensions: ["js", "ts"],
|
||||||
|
17076
package-lock.json
generated
17076
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
14
package.json
14
package.json
@ -7,9 +7,9 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc && ncc build -o dist/restore src/restore.ts && ncc build -o dist/save src/save.ts && ncc build -o dist/restore-only src/restoreOnly.ts && ncc build -o dist/save-only src/saveOnly.ts",
|
"build": "tsc && ncc build -o dist/restore src/restore.ts && ncc build -o dist/save src/save.ts && ncc build -o dist/restore-only src/restoreOnly.ts && ncc build -o dist/save-only src/saveOnly.ts",
|
||||||
"test": "tsc --noEmit && jest --coverage",
|
"test": "tsc --noEmit && jest --coverage",
|
||||||
"lint": "eslint **/*.ts --cache",
|
"lint": "eslint src/**/*.ts --cache __tests__/*.ts --cache",
|
||||||
"format": "prettier --write **/*.ts",
|
"format": "prettier --write **/**/*.ts",
|
||||||
"format-check": "prettier --check **/*.ts"
|
"format-check": "prettier --check **/**/*.ts"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -26,12 +26,13 @@
|
|||||||
"@actions/cache": "^4.0.3",
|
"@actions/cache": "^4.0.3",
|
||||||
"@actions/core": "^1.11.1",
|
"@actions/core": "^1.11.1",
|
||||||
"@actions/exec": "^1.1.1",
|
"@actions/exec": "^1.1.1",
|
||||||
"@actions/io": "^1.1.3"
|
"@actions/io": "^1.1.2",
|
||||||
|
"@octokit/action": "^5.0.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/jest": "^27.5.2",
|
"@types/jest": "^27.5.2",
|
||||||
"@types/nock": "^11.1.0",
|
"@types/nock": "^11.1.0",
|
||||||
"@types/node": "^16.18.3",
|
"@types/node": "^20.14.8",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.45.0",
|
"@typescript-eslint/eslint-plugin": "^5.45.0",
|
||||||
"@typescript-eslint/parser": "^5.45.0",
|
"@typescript-eslint/parser": "^5.45.0",
|
||||||
"@vercel/ncc": "^0.38.3",
|
"@vercel/ncc": "^0.38.3",
|
||||||
@ -43,9 +44,10 @@
|
|||||||
"eslint-plugin-simple-import-sort": "^7.0.0",
|
"eslint-plugin-simple-import-sort": "^7.0.0",
|
||||||
"jest": "^28.1.3",
|
"jest": "^28.1.3",
|
||||||
"jest-circus": "^27.5.1",
|
"jest-circus": "^27.5.1",
|
||||||
|
"msw": "^1.3.5",
|
||||||
"nock": "^13.2.9",
|
"nock": "^13.2.9",
|
||||||
"prettier": "^2.8.0",
|
"prettier": "^2.8.0",
|
||||||
"ts-jest": "^28.0.8",
|
"ts-jest": "^28.0.8",
|
||||||
"typescript": "^4.9.3"
|
"typescript": "^4.9.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user