Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions __tests__/options.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -23,7 +24,8 @@ test('getDownloadOptions sets defaults', async () => {
downloadConcurrency,
timeoutInMs,
segmentTimeoutInMs,
lookupOnly
lookupOnly,
enableCrossArchArchive
})
})

Expand All @@ -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)
Expand All @@ -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)
Expand Down
38 changes: 26 additions & 12 deletions src/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -67,19 +72,20 @@ 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(
paths: string[],
primaryKey: string,
restoreKeys?: string[],
options?: DownloadOptions,
enableCrossOsArchive = false,
enableCrossArchArchive = false
enableCrossOsArchive = false
): Promise<string | undefined> {
const enableCrossArchArchive =
getDownloadOptions(options).enableCrossArchArchive ?? false
checkPaths(paths)
checkKey(primaryKey)

Expand Down Expand Up @@ -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<string> {
options?: UploadOptions,
enableCrossOsArchive = false
): Promise<number> {
checkPaths(paths)
checkKey(key)

const enableCrossArchArchive =
getUploadOptions(options).enableCrossArchArchive ?? false

const compressionMethod = await utils.getCompressionMethod()

const cachePaths = await utils.resolvePaths(paths)
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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
}

/**
Expand Down
31 changes: 29 additions & 2 deletions src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

/**
Expand Down Expand Up @@ -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
}

/**
Expand All @@ -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) {
Expand All @@ -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
}
Expand All @@ -109,7 +130,8 @@ export function getDownloadOptions(copy?: DownloadOptions): DownloadOptions {
downloadConcurrency: 8,
timeoutInMs: 30000,
segmentTimeoutInMs: 600000,
lookupOnly: false
lookupOnly: false,
enableCrossArchArchive: false
}

if (copy) {
Expand All @@ -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']
Expand All @@ -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
}