From 85a278dd2ffa7740a2beaf72f045f1c4f1ad3b30 Mon Sep 17 00:00:00 2001 From: Andrew Marshall Date: Sun, 24 Nov 2024 18:38:20 +0000 Subject: [PATCH 1/4] add 'None' compression type and add tests --- packages/cache/__tests__/tar.test.ts | 102 ++++++++++++++++++++++ packages/cache/src/internal/cacheUtils.ts | 12 ++- packages/cache/src/internal/constants.ts | 6 +- packages/cache/src/internal/tar.ts | 17 +++- 4 files changed, 129 insertions(+), 8 deletions(-) diff --git a/packages/cache/__tests__/tar.test.ts b/packages/cache/__tests__/tar.test.ts index 4145d9a946..43a6f75e99 100644 --- a/packages/cache/__tests__/tar.test.ts +++ b/packages/cache/__tests__/tar.test.ts @@ -46,6 +46,40 @@ afterAll(async () => { await jest.requireActual('@actions/io').rmRF(getTempDir()) }) +test('extract tar', async () => { + const mkdirMock = jest.spyOn(io, 'mkdirP') + const execMock = jest.spyOn(exec, 'exec') + + const archivePath = IS_WINDOWS + ? `${process.env['windir']}\\fakepath\\cache.tar` + : 'cache.tar' + const workspace = process.env['GITHUB_WORKSPACE'] + const tarPath = IS_WINDOWS ? GnuTarPathOnWindows : defaultTarPath + + await tar.extractTar(archivePath, CompressionMethod.None) + + expect(mkdirMock).toHaveBeenCalledWith(workspace) + expect(execMock).toHaveBeenCalledTimes(1) + expect(execMock).toHaveBeenCalledWith( + [ + `"${tarPath}"`, + '-xf', + IS_WINDOWS ? archivePath.replace(/\\/g, '/') : archivePath, + '-P', + '-C', + IS_WINDOWS ? workspace?.replace(/\\/g, '/') : workspace + ] + .concat(IS_WINDOWS ? ['--force-local'] : []) + .concat(IS_MAC ? ['--delay-directory-restore'] : []) + .join(' '), + undefined, + { + cwd: undefined, + env: expect.objectContaining(defaultEnv) + } + ) +}) + test('zstd extract tar', async () => { const mkdirMock = jest.spyOn(io, 'mkdirP') const execMock = jest.spyOn(exec, 'exec') @@ -201,6 +235,45 @@ test('gzip extract GNU tar on windows with GNUtar in path', async () => { } }) +test('create tar', async () => { + const execMock = jest.spyOn(exec, 'exec') + + const archiveFolder = getTempDir() + const workspace = process.env['GITHUB_WORKSPACE'] + const sourceDirectories = ['~/.npm/cache', `${workspace}/dist`] + + await fs.promises.mkdir(archiveFolder, {recursive: true}) + + await tar.createTar(archiveFolder, sourceDirectories, CompressionMethod.None) + + const tarPath = IS_WINDOWS ? GnuTarPathOnWindows : defaultTarPath + + expect(execMock).toHaveBeenCalledTimes(1) + expect(execMock).toHaveBeenCalledWith( + [ + `"${tarPath}"`, + '--posix', + '-cf', + IS_WINDOWS ? CacheFilename.None.replace(/\\/g, '/') : CacheFilename.None, + '--exclude', + IS_WINDOWS ? CacheFilename.None.replace(/\\/g, '/') : CacheFilename.None, + '-P', + '-C', + IS_WINDOWS ? workspace?.replace(/\\/g, '/') : workspace, + '--files-from', + ManifestFilename + ] + .concat(IS_WINDOWS ? ['--force-local'] : []) + .concat(IS_MAC ? ['--delay-directory-restore'] : []) + .join(' '), + undefined, // args + { + cwd: archiveFolder, + env: expect.objectContaining(defaultEnv) + } + ) +}) + test('zstd create tar', async () => { const execMock = jest.spyOn(exec, 'exec') @@ -345,6 +418,35 @@ test('gzip create tar', async () => { ) }) +test('list tar', async () => { + const execMock = jest.spyOn(exec, 'exec') + + const archivePath = IS_WINDOWS + ? `${process.env['windir']}\\fakepath\\cache.tar` + : 'cache.tar' + + await tar.listTar(archivePath, CompressionMethod.None) + + const tarPath = IS_WINDOWS ? GnuTarPathOnWindows : defaultTarPath + expect(execMock).toHaveBeenCalledTimes(1) + expect(execMock).toHaveBeenCalledWith( + [ + `"${tarPath}"`, + '-tf', + IS_WINDOWS ? archivePath.replace(/\\/g, '/') : archivePath, + '-P' + ] + .concat(IS_WINDOWS ? ['--force-local'] : []) + .concat(IS_MAC ? ['--delay-directory-restore'] : []) + .join(' '), + undefined, + { + cwd: undefined, + env: expect.objectContaining(defaultEnv) + } + ) +}) + test('zstd list tar', async () => { const execMock = jest.spyOn(exec, 'exec') diff --git a/packages/cache/src/internal/cacheUtils.ts b/packages/cache/src/internal/cacheUtils.ts index de9053eae0..c44f58daa7 100644 --- a/packages/cache/src/internal/cacheUtils.ts +++ b/packages/cache/src/internal/cacheUtils.ts @@ -112,9 +112,15 @@ export async function getCompressionMethod(): Promise { } export function getCacheFileName(compressionMethod: CompressionMethod): string { - return compressionMethod === CompressionMethod.Gzip - ? CacheFilename.Gzip - : CacheFilename.Zstd + switch (compressionMethod) { + default: + case CompressionMethod.Gzip: + return CacheFilename.Gzip + case CompressionMethod.Zstd: + return CacheFilename.Zstd + case CompressionMethod.None: + return CacheFilename.None + } } export async function getGnuTarPathOnWindows(): Promise { diff --git a/packages/cache/src/internal/constants.ts b/packages/cache/src/internal/constants.ts index 8c5d1ee440..421b6649b0 100644 --- a/packages/cache/src/internal/constants.ts +++ b/packages/cache/src/internal/constants.ts @@ -1,6 +1,7 @@ export enum CacheFilename { Gzip = 'cache.tgz', - Zstd = 'cache.tzst' + Zstd = 'cache.tzst', + None = 'cache.tar' } export enum CompressionMethod { @@ -8,7 +9,8 @@ export enum CompressionMethod { // Long range mode was added to zstd in v1.3.2. // This enum is for earlier version of zstd that does not have --long support ZstdWithoutLong = 'zstd-without-long', - Zstd = 'zstd' + Zstd = 'zstd', + None = 'none' } export enum ArchiveToolType { diff --git a/packages/cache/src/internal/tar.ts b/packages/cache/src/internal/tar.ts index adf610694f..528cd7bdff 100644 --- a/packages/cache/src/internal/tar.ts +++ b/packages/cache/src/internal/tar.ts @@ -5,11 +5,11 @@ import * as path from 'path' import * as utils from './cacheUtils' import {ArchiveTool} from './contracts' import { + ArchiveToolType, CompressionMethod, + ManifestFilename, SystemTarPathOnWindows, - ArchiveToolType, - TarFilename, - ManifestFilename + TarFilename } from './constants' const IS_WINDOWS = process.platform === 'win32' @@ -65,6 +65,7 @@ async function getTarArgs( const BSD_TAR_ZSTD = tarPath.type === ArchiveToolType.BSD && compressionMethod !== CompressionMethod.Gzip && + compressionMethod !== CompressionMethod.None && IS_WINDOWS // Method specific args @@ -139,10 +140,16 @@ async function getCommands( type, archivePath ) + + if (compressionMethod === CompressionMethod.None) { + return [tarArgs.join(' ')] + } + const compressionArgs = type !== 'create' ? await getDecompressionProgram(tarPath, compressionMethod, archivePath) : await getCompressionProgram(tarPath, compressionMethod) + const BSD_TAR_ZSTD = tarPath.type === ArchiveToolType.BSD && compressionMethod !== CompressionMethod.Gzip && @@ -178,6 +185,7 @@ async function getDecompressionProgram( const BSD_TAR_ZSTD = tarPath.type === ArchiveToolType.BSD && compressionMethod !== CompressionMethod.Gzip && + compressionMethod !== CompressionMethod.None && IS_WINDOWS switch (compressionMethod) { case CompressionMethod.Zstd: @@ -199,7 +207,10 @@ async function getDecompressionProgram( archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/') ] : ['--use-compress-program', IS_WINDOWS ? '"zstd -d"' : 'unzstd'] + case CompressionMethod.None: + return [] default: + case CompressionMethod.Gzip: return ['-z'] } } From 8bad37a23091ebe4a45139e98bf56eab0495b005 Mon Sep 17 00:00:00 2001 From: Andrew Marshall Date: Sun, 24 Nov 2024 19:26:37 +0000 Subject: [PATCH 2/4] add explicit compression parameter to cache restore --- packages/cache/__tests__/restoreCache.test.ts | 65 +++++++++++++++++++ packages/cache/src/cache.ts | 32 ++++++--- packages/cache/src/internal/constants.ts | 1 + 3 files changed, 89 insertions(+), 9 deletions(-) diff --git a/packages/cache/__tests__/restoreCache.test.ts b/packages/cache/__tests__/restoreCache.test.ts index 7992490e5a..57078bc874 100644 --- a/packages/cache/__tests__/restoreCache.test.ts +++ b/packages/cache/__tests__/restoreCache.test.ts @@ -219,6 +219,71 @@ test('restore with zstd compressed cache found', async () => { expect(getCompressionMock).toHaveBeenCalledTimes(1) }) +test('restore with uncompressed cache found', async () => { + const paths = ['node_modules'] + const key = 'node-test' + + const infoMock = jest.spyOn(core, 'info') + + 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 tempPath = '/foo/bar' + + const createTempDirectoryMock = jest.spyOn(cacheUtils, 'createTempDirectory') + createTempDirectoryMock.mockImplementation(async () => { + return Promise.resolve(tempPath) + }) + + const archivePath = path.join(tempPath, CacheFilename.None) + const downloadCacheMock = jest.spyOn(cacheHttpClient, 'downloadCache') + + const fileSize = 62915000 + const getArchiveFileSizeInBytesMock = jest + .spyOn(cacheUtils, 'getArchiveFileSizeInBytes') + .mockReturnValue(fileSize) + + const extractTarMock = jest.spyOn(tar, 'extractTar') + const compression = CompressionMethod.None + const getCompressionMock = jest + .spyOn(cacheUtils, 'getCompressionMethod') + .mockReturnValue(Promise.resolve(compression)) + + const cacheKey = await restoreCache( + paths, + key, + undefined, + undefined, + false, + CompressionMethod.None + ) + + expect(cacheKey).toBe(key) + expect(getCacheMock).toHaveBeenCalledWith([key], paths, { + compressionMethod: compression, + enableCrossOsArchive: false + }) + expect(createTempDirectoryMock).toHaveBeenCalledTimes(1) + expect(downloadCacheMock).toHaveBeenCalledWith( + cacheEntry.archiveLocation, + archivePath, + undefined + ) + expect(getArchiveFileSizeInBytesMock).toHaveBeenCalledWith(archivePath) + expect(infoMock).toHaveBeenCalledWith(`Cache Size: ~60 MB (62915000 B)`) + + expect(extractTarMock).toHaveBeenCalledTimes(1) + expect(extractTarMock).toHaveBeenCalledWith(archivePath, compression) + // We can only use no compression by specifying it explicitly + expect(getCompressionMock).toHaveBeenCalledTimes(0) +}) + test('restore with cache found for restore key', async () => { const paths = ['node_modules'] const key = 'node-test' diff --git a/packages/cache/src/cache.ts b/packages/cache/src/cache.ts index 9b02489fbb..a3cacfcd32 100644 --- a/packages/cache/src/cache.ts +++ b/packages/cache/src/cache.ts @@ -12,7 +12,8 @@ import { FinalizeCacheEntryUploadResponse, GetCacheEntryDownloadURLRequest } from './generated/results/api/v1/cache' -import {CacheFileSizeLimit} from './internal/constants' +import {CacheFileSizeLimit, CompressionMethod} from './internal/constants' + export class ValidationError extends Error { constructor(message: string) { super(message) @@ -68,6 +69,8 @@ export function isFeatureAvailable(): boolean { * @param restoreKeys an optional ordered list of keys to use for restoring the cache if no cache hit occurred for primaryKey * @param downloadOptions cache download options * @param enableCrossOsArchive an optional boolean enabled to restore on windows any cache created on any platform + * @param compressionMethod optionally explicitly set the compression method. The default behaviour is 'Auto' which will + * use Zstd if it is available, otherwise Gzip * @returns string returns the key for the cache hit, otherwise returns undefined */ export async function restoreCache( @@ -75,7 +78,8 @@ export async function restoreCache( primaryKey: string, restoreKeys?: string[], options?: DownloadOptions, - enableCrossOsArchive = false + enableCrossOsArchive = false, + compressionMethod = CompressionMethod.Auto ): Promise { const cacheServiceVersion: string = getCacheServiceVersion() core.debug(`Cache service version: ${cacheServiceVersion}`) @@ -89,7 +93,8 @@ export async function restoreCache( primaryKey, restoreKeys, options, - enableCrossOsArchive + enableCrossOsArchive, + compressionMethod ) case 'v1': default: @@ -98,7 +103,8 @@ export async function restoreCache( primaryKey, restoreKeys, options, - enableCrossOsArchive + enableCrossOsArchive, + compressionMethod ) } } @@ -111,6 +117,7 @@ export async function restoreCache( * @param restoreKeys an optional ordered list of keys to use for restoring the cache if no cache hit occurred for primaryKey * @param options cache download options * @param enableCrossOsArchive an optional boolean enabled to restore on Windows any cache created on any platform + * @param compressionMethod Optionally specify the cache compression method. The default is to use Zstd if it is available, otherwise Gzip * @returns string returns the key for the cache hit, otherwise returns undefined */ async function restoreCacheV1( @@ -118,7 +125,8 @@ async function restoreCacheV1( primaryKey: string, restoreKeys?: string[], options?: DownloadOptions, - enableCrossOsArchive = false + enableCrossOsArchive = false, + compressionMethod = CompressionMethod.Auto ): Promise { restoreKeys = restoreKeys || [] const keys = [primaryKey, ...restoreKeys] @@ -135,7 +143,9 @@ async function restoreCacheV1( checkKey(key) } - const compressionMethod = await utils.getCompressionMethod() + if (compressionMethod === CompressionMethod.Auto) { + compressionMethod = await utils.getCompressionMethod() + } let archivePath = '' try { // path are needed to compute version @@ -209,6 +219,8 @@ async function restoreCacheV1( * @param restoreKeys an optional ordered list of keys to use for restoring the cache if no cache hit occurred for primaryKey * @param downloadOptions cache download options * @param enableCrossOsArchive an optional boolean enabled to restore on windows any cache created on any platform + * @param compressionMethod optionally explicitly set the compression method. The default behaviour is 'Auto' which will + * use Zstd if it is available, otherwise Gzip * @returns string returns the key for the cache hit, otherwise returns undefined */ async function restoreCacheV2( @@ -216,7 +228,8 @@ async function restoreCacheV2( primaryKey: string, restoreKeys?: string[], options?: DownloadOptions, - enableCrossOsArchive = false + enableCrossOsArchive = false, + compressionMethod = CompressionMethod.Auto ): Promise { // Override UploadOptions to force the use of Azure options = { @@ -241,7 +254,9 @@ async function restoreCacheV2( let archivePath = '' try { const twirpClient = cacheTwirpClient.internalCacheTwirpClient() - const compressionMethod = await utils.getCompressionMethod() + if (compressionMethod === CompressionMethod.Auto) { + compressionMethod = await utils.getCompressionMethod() + } const request: GetCacheEntryDownloadURLRequest = { key: primaryKey, @@ -254,7 +269,6 @@ async function restoreCacheV2( } const response = await twirpClient.GetCacheEntryDownloadURL(request) - if (!response.ok) { core.warning(`Cache not found for keys: ${keys.join(', ')}`) return undefined diff --git a/packages/cache/src/internal/constants.ts b/packages/cache/src/internal/constants.ts index 421b6649b0..7e0db0b833 100644 --- a/packages/cache/src/internal/constants.ts +++ b/packages/cache/src/internal/constants.ts @@ -10,6 +10,7 @@ export enum CompressionMethod { // This enum is for earlier version of zstd that does not have --long support ZstdWithoutLong = 'zstd-without-long', Zstd = 'zstd', + Auto = 'auto', None = 'none' } From 9c96e97e98e2aef1f3299b6b05815ff0f548c8df Mon Sep 17 00:00:00 2001 From: Andrew Marshall Date: Mon, 25 Nov 2024 08:30:48 +0000 Subject: [PATCH 3/4] add explicit compression support to cache save --- packages/cache/__tests__/saveCache.test.ts | 52 +++++++++++++++++++++- packages/cache/src/cache.ts | 39 ++++++++++++---- 2 files changed, 81 insertions(+), 10 deletions(-) diff --git a/packages/cache/__tests__/saveCache.test.ts b/packages/cache/__tests__/saveCache.test.ts index e5ed695b1f..7eee40dd4b 100644 --- a/packages/cache/__tests__/saveCache.test.ts +++ b/packages/cache/__tests__/saveCache.test.ts @@ -8,8 +8,8 @@ import {CacheFilename, CompressionMethod} from '../src/internal/constants' import * as tar from '../src/internal/tar' import {TypedResponse} from '@actions/http-client/lib/interfaces' import { - ReserveCacheResponse, - ITypedResponseWithError + ITypedResponseWithError, + ReserveCacheResponse } from '../src/internal/contracts' import {HttpClientError} from '@actions/http-client' @@ -329,6 +329,54 @@ test('save with valid inputs uploads a cache', async () => { expect(getCompressionMock).toHaveBeenCalledTimes(1) }) +test('upload a cache without compression', async () => { + const filePath = 'node_modules' + const primaryKey = 'Linux-node-bb828da54c148048dd17899ba9fda624811cfb43' + const cachePaths = [path.resolve(filePath)] + + const cacheId = 4 + const reserveCacheMock = jest + .spyOn(cacheHttpClient, 'reserveCache') + .mockImplementation(async () => { + const response: TypedResponse = { + statusCode: 500, + result: {cacheId}, + headers: {} + } + return response + }) + const createTarMock = jest.spyOn(tar, 'createTar') + + const saveCacheMock = jest.spyOn(cacheHttpClient, 'saveCache') + const getCompressionMock = jest.spyOn(cacheUtils, 'getCompressionMethod') + + await saveCache( + [filePath], + primaryKey, + undefined, + false, + CompressionMethod.None + ) + + expect(reserveCacheMock).toHaveBeenCalledTimes(1) + expect(reserveCacheMock).toHaveBeenCalledWith(primaryKey, [filePath], { + cacheSize: undefined, + compressionMethod: CompressionMethod.None, + enableCrossOsArchive: false + }) + const archiveFolder = '/foo/bar' + const archiveFile = path.join(archiveFolder, CacheFilename.None) + expect(createTarMock).toHaveBeenCalledTimes(1) + expect(createTarMock).toHaveBeenCalledWith( + archiveFolder, + cachePaths, + CompressionMethod.None + ) + expect(saveCacheMock).toHaveBeenCalledTimes(1) + expect(saveCacheMock).toHaveBeenCalledWith(cacheId, archiveFile, undefined) + expect(getCompressionMock).toHaveBeenCalledTimes(0) +}) + test('save with non existing path should not save cache', async () => { const path = 'node_modules' const primaryKey = 'Linux-node-bb828da54c148048dd17899ba9fda624811cfb43' diff --git a/packages/cache/src/cache.ts b/packages/cache/src/cache.ts index a3cacfcd32..888bc9b277 100644 --- a/packages/cache/src/cache.ts +++ b/packages/cache/src/cache.ts @@ -335,15 +335,18 @@ async function restoreCacheV2( * * @param paths a list of file paths to be cached * @param key an explicit key for restoring the cache - * @param enableCrossOsArchive an optional boolean enabled to save cache on windows which could be restored on any platform * @param options cache upload options + * @param enableCrossOsArchive an optional boolean enabled to save cache on windows which could be restored on any platform + * @param compressionMethod optionally explicitly set the compression method. The default behaviour is 'Auto' which will + * use Zstd if it is available, otherwise Gzip * @returns number returns cacheId if the cache was saved successfully and throws an error if save fails */ export async function saveCache( paths: string[], key: string, options?: UploadOptions, - enableCrossOsArchive = false + enableCrossOsArchive = false, + compressionMethod = CompressionMethod.Auto ): Promise { const cacheServiceVersion: string = getCacheServiceVersion() core.debug(`Cache service version: ${cacheServiceVersion}`) @@ -351,10 +354,22 @@ export async function saveCache( checkKey(key) switch (cacheServiceVersion) { case 'v2': - return await saveCacheV2(paths, key, options, enableCrossOsArchive) + return await saveCacheV2( + paths, + key, + options, + enableCrossOsArchive, + compressionMethod + ) case 'v1': default: - return await saveCacheV1(paths, key, options, enableCrossOsArchive) + return await saveCacheV1( + paths, + key, + options, + enableCrossOsArchive, + compressionMethod + ) } } @@ -365,15 +380,19 @@ export async function saveCache( * @param key * @param options * @param enableCrossOsArchive + * @param compressionMethod * @returns */ async function saveCacheV1( paths: string[], key: string, options?: UploadOptions, - enableCrossOsArchive = false + enableCrossOsArchive = false, + compressionMethod = CompressionMethod.Auto ): Promise { - const compressionMethod = await utils.getCompressionMethod() + if (compressionMethod === CompressionMethod.Auto) { + compressionMethod = await utils.getCompressionMethod() + } let cacheId = -1 const cachePaths = await utils.resolvePaths(paths) @@ -468,13 +487,15 @@ async function saveCacheV1( * @param key an explicit key for restoring the cache * @param options cache upload options * @param enableCrossOsArchive an optional boolean enabled to save cache on windows which could be restored on any platform + * @param compressionMethod Optionally specify the compression method. The default is to use Zstd if available, otherwise Gzip * @returns */ async function saveCacheV2( paths: string[], key: string, options?: UploadOptions, - enableCrossOsArchive = false + enableCrossOsArchive = false, + compressionMethod = CompressionMethod.Auto ): Promise { // Override UploadOptions to force the use of Azure // ...options goes first because we want to override the default values @@ -485,7 +506,9 @@ async function saveCacheV2( uploadConcurrency: 8, // 8 workers for parallel upload useAzureSdk: true } - const compressionMethod = await utils.getCompressionMethod() + if (compressionMethod === CompressionMethod.Auto) { + compressionMethod = await utils.getCompressionMethod() + } const twirpClient = cacheTwirpClient.internalCacheTwirpClient() let cacheId = -1 From 7342dfb68f4eb1feb990b1ab77580918f9bced20 Mon Sep 17 00:00:00 2001 From: Andrew Marshall Date: Mon, 25 Nov 2024 08:46:04 +0000 Subject: [PATCH 4/4] add compression args to workflow cache test --- .github/workflows/cache-tests.yml | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/.github/workflows/cache-tests.yml b/.github/workflows/cache-tests.yml index dfe89f68ac..d8bde206e2 100644 --- a/.github/workflows/cache-tests.yml +++ b/.github/workflows/cache-tests.yml @@ -16,6 +16,7 @@ jobs: strategy: matrix: runs-on: [ubuntu-latest, windows-latest, macOS-latest] + compression: [auto, gzip, zstd, none] fail-fast: false runs-on: ${{ matrix.runs-on }} @@ -55,8 +56,14 @@ jobs: # We're using node -e to call the functions directly available in the @actions/cache package - name: Save cache using saveCache() - run: | - node -e "Promise.resolve(require('./packages/cache/lib/cache').saveCache(['test-cache','~/test-cache'],'test-${{ runner.os }}-${{ github.run_id }}'))" + run: > + node -e "Promise.resolve(require('./packages/cache/lib/cache').saveCache( + ['test-cache','~/test-cache'], + 'test-${{ runner.os }}-${{ github.run_id }}', + undefined, + false, + '${{ matrix.compression }}' + ))" - name: Delete cache folders before restoring shell: bash @@ -65,8 +72,15 @@ jobs: rm -rf ~/test-cache - name: Restore cache using restoreCache() with http-client - run: | - node -e "Promise.resolve(require('./packages/cache/lib/cache').restoreCache(['test-cache','~/test-cache'],'test-${{ runner.os }}-${{ github.run_id }}',[],{useAzureSdk: false}))" + run: > + node -e "Promise.resolve(require('./packages/cache/lib/cache').restoreCache( + ['test-cache','~/test-cache'], + 'test-${{ runner.os }}-${{ github.run_id }}', + [], + {useAzureSdk: false}, + false, + '${{ matrix.compression }}' + ))" - name: Verify cache restored with http-client shell: bash