Skip to content

Commit

Permalink
Simplifies cache fallback + add timed invalidation
Browse files Browse the repository at this point in the history
  • Loading branch information
voxpelli committed Feb 27, 2023
1 parent 117e7f5 commit a3e058a
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 9 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ The action has a built-in functionality for caching and restoring dependencies.

The action defaults to search for the dependency file (`package-lock.json` or `yarn.lock`) in the repository root, and uses its hash as a part of the cache key. Use `cache-dependency-path` for cases when multiple dependency files are used, or they are located in different subdirectories.

Use `cache-invalidate-after-days` to change the default fallback cache invalidation of every 120 days. Set to 0 to deactivate.

See the examples of using cache for `yarn` / `pnpm` and `cache-dependency-path` input in the [Advanced usage](docs/advanced-usage.md#caching-packages-dependencies) guide.

**Caching npm dependencies:**
Expand Down
10 changes: 5 additions & 5 deletions __tests__/cache-restore.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,13 +132,13 @@ describe('cache-restore', () => {
}
});

await restoreCache(packageManager);
await restoreCache(packageManager, undefined, '0');
expect(hashFilesSpy).toHaveBeenCalled();
expect(infoSpy).toHaveBeenCalledWith(
`Cache restored from key: ${platform}-setup-node-${packageManager}-${fileHash}`
`Cache restored from key: ${platform}-0-setup-node-${packageManager}-${fileHash}`
);
expect(infoSpy).not.toHaveBeenCalledWith(
`Cache not found for input keys: ${platform}-setup-node-${packageManager}-${fileHash}, ${platform}-setup-node-${packageManager}-, ${platform}-setup-node-`
`Cache not found for input keys: ${platform}-0-setup-node-${packageManager}-${fileHash}, ${platform}-0-setup-node-${packageManager}-`
);
}
);
Expand All @@ -162,10 +162,10 @@ describe('cache-restore', () => {
});

restoreCacheSpy.mockImplementationOnce(() => undefined);
await restoreCache(packageManager);
await restoreCache(packageManager, undefined, '0');
expect(hashFilesSpy).toHaveBeenCalled();
expect(infoSpy).toHaveBeenCalledWith(
`Cache not found for input keys: ${platform}-setup-node-${packageManager}-${fileHash}, ${platform}-setup-node-${packageManager}-, ${platform}-setup-node-`
`Cache not found for input keys: ${platform}-0-setup-node-${packageManager}-${fileHash}, ${platform}-0-setup-node-${packageManager}-`
);
}
);
Expand Down
2 changes: 2 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ inputs:
description: 'Used to specify a package manager for caching in the default directory. Supported values: npm, yarn, pnpm'
cache-dependency-path:
description: 'Used to specify the path to a dependency file: package-lock.json, yarn.lock, etc. Supports wildcards or a list of file names for caching multiple dependencies.'
cache-invalidate-after-days:
description: 'Used to control how often the fallback cache is invalidated automatically.'
# TODO: add input to control forcing to pull from cloud or dist.
# escape valve for someone having issues or needing the absolute latest which isn't cached yet
# Deprecated option, do not use. Will not be supported after October 1, 2019
Expand Down
13 changes: 10 additions & 3 deletions src/cache-restore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import {

export const restoreCache = async (
packageManager: string,
cacheDependencyPath?: string
cacheDependencyPath?: string,
cacheInvalidateAfterDays?: string
) => {
const packageManagerInfo = await getPackageManagerInfo(packageManager);
if (!packageManagerInfo) {
Expand All @@ -35,9 +36,15 @@ export const restoreCache = async (
'Some specified paths were not resolved, unable to cache dependencies.'
);
}
const keyPrefix = `${platform}-setup-node-`;
const numericCacheInvalidateAfterDays = cacheInvalidateAfterDays && cacheInvalidateAfterDays === '0'
? 0
: (parseInt(cacheInvalidateAfterDays || '', 10) || 120)
const timedInvalidationPrefix = numericCacheInvalidateAfterDays
? Math.floor(Date.now() / (1000 * 60 * 60 * 24 * numericCacheInvalidateAfterDays)) % 10 // % 10 to get a rolling prefix between 0 and 9 rather than a possibly infinitely large
: 0;
const keyPrefix = `${platform}-${timedInvalidationPrefix}-setup-node-`;
const primaryKey = `${keyPrefix}${packageManager}-${fileHash}`;
const restoreKeys = [`${keyPrefix}${packageManager}-`, keyPrefix];
const restoreKeys = [`${keyPrefix}${packageManager}-`];
core.debug(`primary key is ${primaryKey}`);
core.saveState(State.CachePrimaryKey, primaryKey);
const cacheKey = await cache.restoreCache(paths, primaryKey, restoreKeys);
Expand Down
3 changes: 2 additions & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ export async function run() {
throw new Error('Caching is not supported on GHES');
}
const cacheDependencyPath = core.getInput('cache-dependency-path');
await restoreCache(cache, cacheDependencyPath);
const cacheInvalidateAfterDays = core.getInput('cache-invalidate-after-days');
await restoreCache(cache, cacheDependencyPath, cacheInvalidateAfterDays);
}

const matchersPath = path.join(__dirname, '../..', '.github');
Expand Down

0 comments on commit a3e058a

Please sign in to comment.