From 09cb531b12d46c5fb318038ad5bd28a13744a277 Mon Sep 17 00:00:00 2001 From: Janaki Ram Puli Date: Wed, 29 Jul 2026 14:07:32 +0530 Subject: [PATCH 1/2] feat!: match @actions/cache v6 signatures for save and restore --- src/cache.ts | 38 ++++++++++++++++++++++++++------------ src/options.ts | 31 +++++++++++++++++++++++++++++-- 2 files changed, 55 insertions(+), 14 deletions(-) diff --git a/src/cache.ts b/src/cache.ts index a303406..520e276 100644 --- a/src/cache.ts +++ b/src/cache.ts @@ -8,7 +8,12 @@ import { extractTar, listTar } from './internal/tar.js' -import {DownloadOptions, getUploadOptions} from './options.js' +import { + DownloadOptions, + UploadOptions, + getDownloadOptions, + getUploadOptions +} from './options.js' import {isSuccessStatusCode} from './internal/requestUtils.js' import {getDownloadCommandPipeForWget} from './internal/downloadUtils.js' import {ChildProcessWithoutNullStreams} from 'child_process' @@ -67,9 +72,9 @@ export function isFeatureAvailable(): boolean { * @param paths a list of file paths to restore from the cache * @param primaryKey an explicit key for restoring the cache * @param restoreKeys an optional ordered list of keys to use for restoring the cache if no cache hit occurred for key - * @param downloadOptions cache download options + * @param options cache download options. Set enableCrossArchArchive here to + * restore a cache saved on a different CPU architecture. * @param enableCrossOsArchive an optional boolean enabled to restore on windows any cache created on any platform - * @param enableCrossArchArchive an optional boolean enabled to restore cache created on any arch * @returns string returns the key for the cache hit, otherwise returns undefined */ export async function restoreCache( @@ -77,9 +82,10 @@ export async function restoreCache( primaryKey: string, restoreKeys?: string[], options?: DownloadOptions, - enableCrossOsArchive = false, - enableCrossArchArchive = false + enableCrossOsArchive = false ): Promise { + const enableCrossArchArchive = + getDownloadOptions(options).enableCrossArchArchive ?? false checkPaths(paths) checkKey(primaryKey) @@ -324,19 +330,26 @@ export async function restoreCache( * * @param paths a list of file paths to be cached * @param key an explicit key for restoring the cache + * @param options cache upload options. Set enableCrossArchArchive here to save + * a cache restorable on a different CPU architecture. * @param enableCrossOsArchive an optional boolean enabled to save cache on windows which could be restored on any platform - * @param enableCrossArchArchive an optional boolean enabled to save cache on any arch which could be restored on any arch - * @returns string returns cacheId if the cache was saved successfully and throws an error if save fails + * @returns number a positive id if the cache was saved, or -1 if it was not. + * The service keys caches by string, so the id carries no meaning + * beyond success; it matches @actions/cache v6 so upstream callers + * that test `!== -1` work unchanged. */ export async function saveCache( paths: string[], key: string, - enableCrossOsArchive = false, - enableCrossArchArchive = false -): Promise { + options?: UploadOptions, + enableCrossOsArchive = false +): Promise { checkPaths(paths) checkKey(key) + const enableCrossArchArchive = + getUploadOptions(options).enableCrossArchArchive ?? false + const compressionMethod = await utils.getCompressionMethod() const cachePaths = await utils.resolvePaths(paths) @@ -384,7 +397,7 @@ export async function saveCache( core.debug('Reserving Cache') // Calculate number of chunks required. This is only required if backend is S3 as Google Cloud SDK will do it for us - const uploadOptions = getUploadOptions() + const uploadOptions = getUploadOptions(options) const maxChunkSize = uploadOptions?.uploadChunkSize ?? 32 * 1024 * 1024 // Default 32MB const numberOfChunks = Math.max( Math.floor(archiveFileSize / maxChunkSize), @@ -485,7 +498,8 @@ export async function saveCache( } } - return cacheKey + // cacheKey stays empty when the save was skipped or failed non-fatally. + return cacheKey === '' ? -1 : 1 } /** diff --git a/src/options.ts b/src/options.ts index d768ff5..d4e2c3b 100644 --- a/src/options.ts +++ b/src/options.ts @@ -16,6 +16,13 @@ export interface UploadOptions { * @default 32MB */ uploadChunkSize?: number + /** + * Save a cache that can be restored on any CPU architecture. + * Excludes the architecture from the cache version. + * + * @default false + */ + enableCrossArchArchive?: boolean } /** @@ -68,6 +75,14 @@ export interface DownloadOptions { * @default false */ lookupOnly?: boolean + + /** + * Restore a cache saved on any CPU architecture. + * Excludes the architecture from the cache version. + * + * @default false + */ + enableCrossArchArchive?: boolean } /** @@ -78,7 +93,8 @@ export interface DownloadOptions { export function getUploadOptions(copy?: UploadOptions): UploadOptions { const result: UploadOptions = { uploadConcurrency: 4, - uploadChunkSize: 32 * 1024 * 1024 + uploadChunkSize: 32 * 1024 * 1024, + enableCrossArchArchive: false } if (copy) { @@ -89,10 +105,15 @@ export function getUploadOptions(copy?: UploadOptions): UploadOptions { if (typeof copy.uploadChunkSize === 'number') { result.uploadChunkSize = copy.uploadChunkSize } + + if (typeof copy.enableCrossArchArchive === 'boolean') { + result.enableCrossArchArchive = copy.enableCrossArchArchive + } } core.debug(`Upload concurrency: ${result.uploadConcurrency}`) core.debug(`Upload chunk size: ${result.uploadChunkSize}`) + core.debug(`Cross arch archive: ${result.enableCrossArchArchive}`) return result } @@ -109,7 +130,8 @@ export function getDownloadOptions(copy?: DownloadOptions): DownloadOptions { downloadConcurrency: 8, timeoutInMs: 30000, segmentTimeoutInMs: 600000, - lookupOnly: false + lookupOnly: false, + enableCrossArchArchive: false } if (copy) { @@ -136,6 +158,10 @@ export function getDownloadOptions(copy?: DownloadOptions): DownloadOptions { if (typeof copy.lookupOnly === 'boolean') { result.lookupOnly = copy.lookupOnly } + + if (typeof copy.enableCrossArchArchive === 'boolean') { + result.enableCrossArchArchive = copy.enableCrossArchArchive + } } const segmentDownloadTimeoutMins = process.env['SEGMENT_DOWNLOAD_TIMEOUT_MINS'] @@ -155,6 +181,7 @@ export function getDownloadOptions(copy?: DownloadOptions): DownloadOptions { ) core.debug(`Segment download timeout (ms): ${result.segmentTimeoutInMs}`) core.debug(`Lookup only: ${result.lookupOnly}`) + core.debug(`Cross arch archive: ${result.enableCrossArchArchive}`) return result } From 1b2f73c69e844972a18adbf946dba4bf8a0b4350 Mon Sep 17 00:00:00 2001 From: Janaki Ram Puli Date: Wed, 29 Jul 2026 14:39:24 +0530 Subject: [PATCH 2/2] test: add enableCrossArchArchive to options expectations --- __tests__/options.test.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/__tests__/options.test.ts b/__tests__/options.test.ts index f56fa5c..ae84cec 100644 --- a/__tests__/options.test.ts +++ b/__tests__/options.test.ts @@ -13,6 +13,7 @@ const segmentTimeoutInMs = 600000 const lookupOnly = false const uploadConcurrency = 4 const uploadChunkSize = 32 * 1024 * 1024 +const enableCrossArchArchive = false test('getDownloadOptions sets defaults', async () => { const actualOptions = getDownloadOptions() @@ -23,7 +24,8 @@ test('getDownloadOptions sets defaults', async () => { downloadConcurrency, timeoutInMs, segmentTimeoutInMs, - lookupOnly + lookupOnly, + enableCrossArchArchive }) }) @@ -34,7 +36,8 @@ test('getDownloadOptions overrides all settings', async () => { downloadConcurrency: 14, timeoutInMs: 20000, segmentTimeoutInMs: 3600000, - lookupOnly: true + lookupOnly: true, + enableCrossArchArchive: true } const actualOptions = getDownloadOptions(expectedOptions) @@ -47,14 +50,16 @@ test('getUploadOptions sets defaults', async () => { expect(actualOptions).toEqual({ uploadConcurrency, - uploadChunkSize + uploadChunkSize, + enableCrossArchArchive }) }) test('getUploadOptions overrides all settings', async () => { const expectedOptions: UploadOptions = { uploadConcurrency: 2, - uploadChunkSize: 16 * 1024 * 1024 + uploadChunkSize: 16 * 1024 * 1024, + enableCrossArchArchive: true } const actualOptions = getUploadOptions(expectedOptions)