Skip to content

Commit

Permalink
Add lookup-only option (#1041)
Browse files Browse the repository at this point in the history
* Add new actions/cache version (with dryRun support)

* Add dry-run option

* Changes after rebase

* Update readme

* Rename option to lookup-only

* Update test name

* Update package.json + changelog

* Update README

* Update custom package version

* Update custom package version

* Update @actions/cache to 3.2.0

* Code review

* Update log statement

* Move test case

---------

Co-authored-by: Sankalp Kotewar <[email protected]>
  • Loading branch information
cdce8p and kotewar committed Mar 9, 2023
1 parent e0d6227 commit 940f3d7
Show file tree
Hide file tree
Showing 18 changed files with 260 additions and 47 deletions.
2 changes: 1 addition & 1 deletion .licenses/npm/@actions/cache.dep.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ See ["Caching dependencies to speed up workflows"](https://docs.github.com/en/ac
* Support cross-os caching as an opt-in feature. See [Cross OS caching](./tips-and-workarounds.md#cross-os-cache) for more info.
* Added option to fail job on cache miss. See [Exit workflow on cache miss](./restore/README.md#exit-workflow-on-cache-miss) for more info.
* Fix zstd not being used after zstd version upgrade to 1.5.4 on hosted runners
* Added option to lookup cache without downloading it.

See the [v2 README.md](https://github.com/actions/cache/blob/v2/README.md) for older updates.

Expand All @@ -52,6 +53,7 @@ If you are using a `self-hosted` Windows runner, `GNU tar` and `zstd` are requir
* `restore-keys` - An ordered list of prefix-matched keys to use for restoring stale cache if no cache hit occurred for key.
* `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`
* `lookup-only` - Skip downloading cache. Only check if cache entry exists. Default: `false`

#### Environment Variables

Expand Down
3 changes: 3 additions & 0 deletions RELEASES.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,6 @@

### 3.2.6
- Fix zstd not being used after zstd version upgrade to 1.5.4 on hosted runners.

### 3.3.0
- Added option to lookup cache without downloading it.
40 changes: 33 additions & 7 deletions __tests__/restore.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,15 @@ test("restore with no cache found", async () => {
await run();

expect(restoreCacheMock).toHaveBeenCalledTimes(1);
expect(restoreCacheMock).toHaveBeenCalledWith([path], key, [], {}, false);
expect(restoreCacheMock).toHaveBeenCalledWith(
[path],
key,
[],
{
lookupOnly: false
},
false
);

expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
expect(stateMock).toHaveBeenCalledTimes(1);
Expand Down Expand Up @@ -113,7 +121,9 @@ test("restore with restore keys and no cache found", async () => {
[path],
key,
[restoreKey],
{},
{
lookupOnly: false
},
false
);

Expand Down Expand Up @@ -149,7 +159,15 @@ test("restore with cache found for key", async () => {
await run();

expect(restoreCacheMock).toHaveBeenCalledTimes(1);
expect(restoreCacheMock).toHaveBeenCalledWith([path], key, [], {}, false);
expect(restoreCacheMock).toHaveBeenCalledWith(
[path],
key,
[],
{
lookupOnly: false
},
false
);

expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
expect(stateMock).toHaveBeenCalledWith("CACHE_RESULT", key);
Expand Down Expand Up @@ -190,7 +208,9 @@ test("restore with cache found for restore key", async () => {
[path],
key,
[restoreKey],
{},
{
lookupOnly: false
},
false
);

Expand Down Expand Up @@ -233,7 +253,9 @@ test("Fail restore when fail on cache miss is enabled and primary + restore keys
[path],
key,
[restoreKey],
{},
{
lookupOnly: false
},
false
);

Expand Down Expand Up @@ -274,7 +296,9 @@ test("restore when fail on cache miss is enabled and primary key doesn't match r
[path],
key,
[restoreKey],
{},
{
lookupOnly: false
},
false
);

Expand Down Expand Up @@ -318,7 +342,9 @@ test("restore with fail on cache miss disabled and no cache found", async () =>
[path],
key,
[restoreKey],
{},
{
lookupOnly: false
},
false
);

Expand Down
107 changes: 99 additions & 8 deletions __tests__/restoreImpl.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,15 @@ test("restore on GHES with AC available ", async () => {
await run(new StateProvider());

expect(restoreCacheMock).toHaveBeenCalledTimes(1);
expect(restoreCacheMock).toHaveBeenCalledWith([path], key, [], {}, false);
expect(restoreCacheMock).toHaveBeenCalledWith(
[path],
key,
[],
{
lookupOnly: false
},
false
);

expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
Expand Down Expand Up @@ -172,7 +180,9 @@ test("restore with too many keys should fail", async () => {
[path],
key,
restoreKeys,
{},
{
lookupOnly: false
},
false
);
expect(failedMock).toHaveBeenCalledWith(
Expand All @@ -192,7 +202,15 @@ test("restore with large key should fail", async () => {
const restoreCacheMock = jest.spyOn(cache, "restoreCache");
await run(new StateProvider());
expect(restoreCacheMock).toHaveBeenCalledTimes(1);
expect(restoreCacheMock).toHaveBeenCalledWith([path], key, [], {}, false);
expect(restoreCacheMock).toHaveBeenCalledWith(
[path],
key,
[],
{
lookupOnly: false
},
false
);
expect(failedMock).toHaveBeenCalledWith(
`Key Validation Error: ${key} cannot be larger than 512 characters.`
);
Expand All @@ -210,7 +228,15 @@ test("restore with invalid key should fail", async () => {
const restoreCacheMock = jest.spyOn(cache, "restoreCache");
await run(new StateProvider());
expect(restoreCacheMock).toHaveBeenCalledTimes(1);
expect(restoreCacheMock).toHaveBeenCalledWith([path], key, [], {}, false);
expect(restoreCacheMock).toHaveBeenCalledWith(
[path],
key,
[],
{
lookupOnly: false
},
false
);
expect(failedMock).toHaveBeenCalledWith(
`Key Validation Error: ${key} cannot contain commas.`
);
Expand All @@ -237,7 +263,15 @@ test("restore with no cache found", async () => {
await run(new StateProvider());

expect(restoreCacheMock).toHaveBeenCalledTimes(1);
expect(restoreCacheMock).toHaveBeenCalledWith([path], key, [], {}, false);
expect(restoreCacheMock).toHaveBeenCalledWith(
[path],
key,
[],
{
lookupOnly: false
},
false
);

expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
expect(failedMock).toHaveBeenCalledTimes(0);
Expand Down Expand Up @@ -274,7 +308,9 @@ test("restore with restore keys and no cache found", async () => {
[path],
key,
[restoreKey],
{},
{
lookupOnly: false
},
false
);

Expand Down Expand Up @@ -308,7 +344,15 @@ test("restore with cache found for key", async () => {
await run(new StateProvider());

expect(restoreCacheMock).toHaveBeenCalledTimes(1);
expect(restoreCacheMock).toHaveBeenCalledWith([path], key, [], {}, false);
expect(restoreCacheMock).toHaveBeenCalledWith(
[path],
key,
[],
{
lookupOnly: false
},
false
);

expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
Expand Down Expand Up @@ -346,7 +390,9 @@ test("restore with cache found for restore key", async () => {
[path],
key,
[restoreKey],
{},
{
lookupOnly: false
},
false
);

Expand All @@ -358,3 +404,48 @@ test("restore with cache found for restore key", async () => {
);
expect(failedMock).toHaveBeenCalledTimes(0);
});

test("restore with lookup-only set", async () => {
const path = "node_modules";
const key = "node-test";
testUtils.setInputs({
path: path,
key,
lookupOnly: true
});

const infoMock = jest.spyOn(core, "info");
const failedMock = jest.spyOn(core, "setFailed");
const stateMock = jest.spyOn(core, "saveState");
const setCacheHitOutputMock = jest.spyOn(core, "setOutput");
const restoreCacheMock = jest
.spyOn(cache, "restoreCache")
.mockImplementationOnce(() => {
return Promise.resolve(key);
});

await run(new StateProvider());

expect(restoreCacheMock).toHaveBeenCalledTimes(1);
expect(restoreCacheMock).toHaveBeenCalledWith(
[path],
key,
[],
{
lookupOnly: true
},
false
);

expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
expect(stateMock).toHaveBeenCalledWith("CACHE_RESULT", key);
expect(stateMock).toHaveBeenCalledTimes(2);

expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
expect(setCacheHitOutputMock).toHaveBeenCalledWith("cache-hit", "true");

expect(infoMock).toHaveBeenCalledWith(
`Cache found and can be restored from key: ${key}`
);
expect(failedMock).toHaveBeenCalledTimes(0);
});
28 changes: 24 additions & 4 deletions __tests__/restoreOnly.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,15 @@ test("restore with no cache found", async () => {
await run();

expect(restoreCacheMock).toHaveBeenCalledTimes(1);
expect(restoreCacheMock).toHaveBeenCalledWith([path], key, [], {}, false);
expect(restoreCacheMock).toHaveBeenCalledWith(
[path],
key,
[],
{
lookupOnly: false
},
false
);

expect(outputMock).toHaveBeenCalledWith("cache-primary-key", key);
expect(outputMock).toHaveBeenCalledTimes(1);
Expand Down Expand Up @@ -113,7 +121,9 @@ test("restore with restore keys and no cache found", async () => {
[path],
key,
[restoreKey],
{},
{
lookupOnly: false
},
false
);

Expand Down Expand Up @@ -146,7 +156,15 @@ test("restore with cache found for key", async () => {
await run();

expect(restoreCacheMock).toHaveBeenCalledTimes(1);
expect(restoreCacheMock).toHaveBeenCalledWith([path], key, [], {}, false);
expect(restoreCacheMock).toHaveBeenCalledWith(
[path],
key,
[],
{
lookupOnly: false
},
false
);

expect(outputMock).toHaveBeenCalledWith("cache-primary-key", key);
expect(outputMock).toHaveBeenCalledWith("cache-hit", "true");
Expand Down Expand Up @@ -185,7 +203,9 @@ test("restore with cache found for restore key", async () => {
[path],
key,
[restoreKey],
{},
{
lookupOnly: false
},
false
);

Expand Down
4 changes: 4 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ inputs:
description: 'Fail the workflow if cache entry is not found'
default: 'false'
required: false
lookup-only:
description: 'Check if a cache entry exists for the given input(s) (key, restore-keys) without downloading the cache'
default: 'false'
required: false
outputs:
cache-hit:
description: 'A boolean value to indicate an exact match was found for the primary key'
Expand Down
Loading

0 comments on commit 940f3d7

Please sign in to comment.