Avoid failing build on distributions cache errors

- Warn and continue on failure to restore a Gradle distribution from cache
- Warn and continue on failure to save a Gradle distribution to cache
- Extract common functionality for consistent handling of cache failures

Fixes #116
This commit is contained in:
Daz DeBoer 2021-11-05 06:54:31 -06:00
parent 3812292b26
commit 4e899835b3
No known key found for this signature in database
GPG key ID: DD6B9F0B06683D5D
7 changed files with 37 additions and 31 deletions

2
dist/main/index.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/post/index.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,7 +1,7 @@
import * as core from '@actions/core' import * as core from '@actions/core'
import * as cache from '@actions/cache' import * as cache from '@actions/cache'
import * as github from '@actions/github' import * as github from '@actions/github'
import {isCacheDebuggingEnabled, getCacheKeyPrefix, hashStrings} from './cache-utils' import {isCacheDebuggingEnabled, getCacheKeyPrefix, hashStrings, handleCacheFailure} from './cache-utils'
const JOB_CONTEXT_PARAMETER = 'workflow-job-context' const JOB_CONTEXT_PARAMETER = 'workflow-job-context'
@ -176,12 +176,7 @@ export abstract class AbstractCache {
try { try {
return await cache.restoreCache(cachePath, cacheKey, cacheRestoreKeys) return await cache.restoreCache(cachePath, cacheKey, cacheRestoreKeys)
} catch (error) { } catch (error) {
if (error instanceof cache.ValidationError) { handleCacheFailure(error, `Failed to restore ${cacheKey}`)
// Validation errors should fail the build action
throw error
}
// Warn about any other error and continue
core.warning(`Failed to restore ${cacheKey}: ${error}`)
return undefined return undefined
} }
} }
@ -231,16 +226,7 @@ export abstract class AbstractCache {
try { try {
return await cache.saveCache(cachePath, cacheKey) return await cache.saveCache(cachePath, cacheKey)
} catch (error) { } catch (error) {
if (error instanceof cache.ValidationError) { handleCacheFailure(error, `Failed to save cache entry ${cacheKey}`)
// Validation errors should fail the build action
throw error
} else if (error instanceof cache.ReserveCacheError) {
// Reserve cache errors are expected if the artifact has been previously cached
this.debug(error.message)
} else {
// Warn about any other error and continue
core.warning(String(error))
}
} }
return undefined return undefined
} }

View file

@ -1,4 +1,5 @@
import * as core from '@actions/core' import * as core from '@actions/core'
import * as cache from '@actions/cache'
import * as crypto from 'crypto' import * as crypto from 'crypto'
import * as path from 'path' import * as path from 'path'
import * as fs from 'fs' import * as fs from 'fs'
@ -39,6 +40,24 @@ export function hashFileNames(fileNames: string[]): string {
return hashStrings(fileNames.map(x => x.replace(new RegExp(`\\${path.sep}`, 'g'), '/'))) return hashStrings(fileNames.map(x => x.replace(new RegExp(`\\${path.sep}`, 'g'), '/')))
} }
export function handleCacheFailure(error: unknown, message: string): void {
if (error instanceof cache.ValidationError) {
// Fail on cache validation errors
throw error
}
if (error instanceof cache.ReserveCacheError) {
// Reserve cache errors are expected if the artifact has been previously cached
if (isCacheDebuggingEnabled()) {
core.info(message)
} else {
core.debug(message)
}
} else {
// Warn on all other errors
core.warning(`${message}: ${error}`)
}
}
/** /**
* Attempt to delete a file or directory, waiting to allow locks to be released * Attempt to delete a file or directory, waiting to allow locks to be released
*/ */

View file

@ -7,7 +7,7 @@ import * as cache from '@actions/cache'
import * as toolCache from '@actions/tool-cache' import * as toolCache from '@actions/tool-cache'
import * as gradlew from './gradlew' import * as gradlew from './gradlew'
import {isCacheDisabled, isCacheReadOnly} from './cache-utils' import {handleCacheFailure, isCacheDisabled, isCacheReadOnly} from './cache-utils'
const gradleVersionsBaseUrl = 'https://services.gradle.org/versions' const gradleVersionsBaseUrl = 'https://services.gradle.org/versions'
@ -109,11 +109,16 @@ async function downloadAndCacheGradleDistribution(versionInfo: GradleVersionInfo
} }
const cacheKey = `gradle-${versionInfo.version}` const cacheKey = `gradle-${versionInfo.version}`
try {
const restoreKey = await cache.restoreCache([downloadPath], cacheKey) const restoreKey = await cache.restoreCache([downloadPath], cacheKey)
if (restoreKey) { if (restoreKey) {
core.info(`Restored Gradle distribution ${cacheKey} from cache to ${downloadPath}`) core.info(`Restored Gradle distribution ${cacheKey} from cache to ${downloadPath}`)
return downloadPath return downloadPath
} }
} catch (error) {
handleCacheFailure(error, `Restore Gradle distribution ${versionInfo.version} failed`)
}
core.info(`Gradle distribution ${versionInfo.version} not found in cache. Will download.`) core.info(`Gradle distribution ${versionInfo.version} not found in cache. Will download.`)
await downloadGradleDistribution(versionInfo, downloadPath) await downloadGradleDistribution(versionInfo, downloadPath)
@ -121,11 +126,7 @@ async function downloadAndCacheGradleDistribution(versionInfo: GradleVersionInfo
try { try {
await cache.saveCache([downloadPath], cacheKey) await cache.saveCache([downloadPath], cacheKey)
} catch (error) { } catch (error) {
// Fail on validation errors or non-errors (the latter to keep Typescript happy) handleCacheFailure(error, `Save Gradle distribution ${versionInfo.version} failed`)
if (error instanceof cache.ValidationError || !(error instanceof Error)) {
throw error
}
core.warning(error.message)
} }
} }
return downloadPath return downloadPath