diff --git a/packages/cache/RELEASES.md b/packages/cache/RELEASES.md index 76bec600..424b7688 100644 --- a/packages/cache/RELEASES.md +++ b/packages/cache/RELEASES.md @@ -117,4 +117,7 @@ - Fix to prevent from setting MYSYS environement variable globally [#1329](https://github.com/actions/toolkit/pull/1329). ### 3.1.4 -- Fix zstd not being used due to `zstd --version` output change in zstd 1.5.4 release. See [#1353](https://github.com/actions/toolkit/pull/1353). \ No newline at end of file +- Fix zstd not being used due to `zstd --version` output change in zstd 1.5.4 release. See [#1353](https://github.com/actions/toolkit/pull/1353). + +### 3.2.0 +- Add `lookupOnly` to cache restore `DownloadOptions`. diff --git a/packages/cache/__tests__/options.test.ts b/packages/cache/__tests__/options.test.ts index 83d9b227..79f04241 100644 --- a/packages/cache/__tests__/options.test.ts +++ b/packages/cache/__tests__/options.test.ts @@ -9,6 +9,7 @@ const useAzureSdk = true const downloadConcurrency = 8 const timeoutInMs = 30000 const segmentTimeoutInMs = 3600000 +const lookupOnly = false const uploadConcurrency = 4 const uploadChunkSize = 32 * 1024 * 1024 @@ -19,7 +20,8 @@ test('getDownloadOptions sets defaults', async () => { useAzureSdk, downloadConcurrency, timeoutInMs, - segmentTimeoutInMs + segmentTimeoutInMs, + lookupOnly }) }) @@ -28,7 +30,8 @@ test('getDownloadOptions overrides all settings', async () => { useAzureSdk: false, downloadConcurrency: 14, timeoutInMs: 20000, - segmentTimeoutInMs: 3600000 + segmentTimeoutInMs: 3600000, + lookupOnly: true } const actualOptions = getDownloadOptions(expectedOptions) @@ -61,7 +64,8 @@ test('getDownloadOptions overrides download timeout minutes', async () => { useAzureSdk: false, downloadConcurrency: 14, timeoutInMs: 20000, - segmentTimeoutInMs: 3600000 + segmentTimeoutInMs: 3600000, + lookupOnly: true } process.env.SEGMENT_DOWNLOAD_TIMEOUT_MINS = '10' const actualOptions = getDownloadOptions(expectedOptions) @@ -72,4 +76,5 @@ test('getDownloadOptions overrides download timeout minutes', async () => { ) expect(actualOptions.timeoutInMs).toEqual(expectedOptions.timeoutInMs) expect(actualOptions.segmentTimeoutInMs).toEqual(600000) + expect(actualOptions.lookupOnly).toEqual(expectedOptions.lookupOnly) }) diff --git a/packages/cache/__tests__/restoreCache.test.ts b/packages/cache/__tests__/restoreCache.test.ts index 5318a007..7992490e 100644 --- a/packages/cache/__tests__/restoreCache.test.ts +++ b/packages/cache/__tests__/restoreCache.test.ts @@ -276,3 +276,39 @@ test('restore with cache found for restore key', async () => { expect(extractTarMock).toHaveBeenCalledWith(archivePath, compression) expect(getCompressionMock).toHaveBeenCalledTimes(1) }) + +test('restore with dry run', async () => { + const paths = ['node_modules'] + const key = 'node-test' + const options = {lookupOnly: true} + + const cacheEntry: ArtifactCacheEntry = { + cacheKey: key, + scope: 'refs/heads/main', + archiveLocation: 'www.actionscache.test/download' + } + const getCacheMock = jest.spyOn(cacheHttpClient, 'getCacheEntry') + getCacheMock.mockImplementation(async () => { + return Promise.resolve(cacheEntry) + }) + + const createTempDirectoryMock = jest.spyOn(cacheUtils, 'createTempDirectory') + const downloadCacheMock = jest.spyOn(cacheHttpClient, 'downloadCache') + + const compression = CompressionMethod.Gzip + const getCompressionMock = jest + .spyOn(cacheUtils, 'getCompressionMethod') + .mockReturnValue(Promise.resolve(compression)) + + const cacheKey = await restoreCache(paths, key, undefined, options) + + expect(cacheKey).toBe(key) + expect(getCompressionMock).toHaveBeenCalledTimes(1) + expect(getCacheMock).toHaveBeenCalledWith([key], paths, { + compressionMethod: compression, + enableCrossOsArchive: false + }) + // creating a tempDir and downloading the cache are skipped + expect(createTempDirectoryMock).toHaveBeenCalledTimes(0) + expect(downloadCacheMock).toHaveBeenCalledTimes(0) +}) diff --git a/packages/cache/package-lock.json b/packages/cache/package-lock.json index 408660cb..0d568ff5 100644 --- a/packages/cache/package-lock.json +++ b/packages/cache/package-lock.json @@ -1,12 +1,12 @@ { "name": "@actions/cache", - "version": "3.1.4", + "version": "3.2.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@actions/cache", - "version": "3.1.4", + "version": "3.2.0", "license": "MIT", "dependencies": { "@actions/core": "^1.10.0", diff --git a/packages/cache/package.json b/packages/cache/package.json index 3d5dda6b..b411de1c 100644 --- a/packages/cache/package.json +++ b/packages/cache/package.json @@ -1,6 +1,6 @@ { "name": "@actions/cache", - "version": "3.1.4", + "version": "3.2.0", "preview": true, "description": "Actions cache lib", "keywords": [ diff --git a/packages/cache/src/cache.ts b/packages/cache/src/cache.ts index ffa13e78..f7fadb6f 100644 --- a/packages/cache/src/cache.ts +++ b/packages/cache/src/cache.ts @@ -100,6 +100,11 @@ export async function restoreCache( return undefined } + if (options?.lookupOnly) { + core.info('Lookup only - skipping download') + return cacheEntry.cacheKey + } + archivePath = path.join( await utils.createTempDirectory(), utils.getCacheFileName(compressionMethod) diff --git a/packages/cache/src/options.ts b/packages/cache/src/options.ts index 652899a2..cdddeeca 100644 --- a/packages/cache/src/options.ts +++ b/packages/cache/src/options.ts @@ -53,6 +53,15 @@ export interface DownloadOptions { * @default 3600000 */ segmentTimeoutInMs?: number + + /** + * Weather to skip downloading the cache entry. + * If lookupOnly is set to true, the restore function will only check if + * a matching cache entry exists and return the cache key if it does. + * + * @default false + */ + lookupOnly?: boolean } /** @@ -92,7 +101,8 @@ export function getDownloadOptions(copy?: DownloadOptions): DownloadOptions { useAzureSdk: true, downloadConcurrency: 8, timeoutInMs: 30000, - segmentTimeoutInMs: 3600000 + segmentTimeoutInMs: 3600000, + lookupOnly: false } if (copy) { @@ -111,6 +121,10 @@ export function getDownloadOptions(copy?: DownloadOptions): DownloadOptions { if (typeof copy.segmentTimeoutInMs === 'number') { result.segmentTimeoutInMs = copy.segmentTimeoutInMs } + + if (typeof copy.lookupOnly === 'boolean') { + result.lookupOnly = copy.lookupOnly + } } const segmentDownloadTimeoutMins = process.env['SEGMENT_DOWNLOAD_TIMEOUT_MINS'] @@ -129,6 +143,7 @@ export function getDownloadOptions(copy?: DownloadOptions): DownloadOptions { `Cache segment download timeout mins env var: ${process.env['SEGMENT_DOWNLOAD_TIMEOUT_MINS']}` ) core.debug(`Segment download timeout (ms): ${result.segmentTimeoutInMs}`) + core.debug(`Lookup only: ${result.lookupOnly}`) return result }