Allow better control over cache-cleanup

Adds new 'cache-cleanup' parameter with 3 settings: 'never', 'on-success' and 'always'.
This gives users more control over whether cache cleanup should occur.

Fixes #71
This commit is contained in:
daz
2024-07-17 19:02:31 -06:00
parent 91a526b647
commit 27dea2df09
8 changed files with 122 additions and 29 deletions

View File

@@ -10,9 +10,14 @@ export const DEFAULT_WRITEONLY_REASON = `[Cache was set to write-only](https://g
export const EXISTING_GRADLE_HOME = `[Cache was disabled to avoid overwriting a pre-existing Gradle User Home](https://github.com/gradle/actions/blob/v3/docs/setup-gradle.md#overwriting-an-existing-gradle-user-home). Gradle User Home was not restored from or saved to the cache.`
export const DEFAULT_CLEANUP_DISABLED_REASON = `[Cache cleanup](https://github.com/gradle/actions/blob/v3/docs/setup-gradle.md#remove-unused-files-from-gradle-user-home-before-saving-to-the-cache) was not enabled. It must be explicitly enabled.`
export const CLEANUP_DISABLED_READONLY = `[Cache cleanup](https://github.com/gradle/actions/blob/v3/docs/setup-gradle.md#enabling-cache-cleanup) is always disabled when cache is read-only or disabled.`
export const DEFAULT_CLEANUP_ENABLED_REASON = `[Cache cleanup](https://github.com/gradle/actions/blob/v3/docs/setup-gradle.md#remove-unused-files-from-gradle-user-home-before-saving-to-the-cache) was enabled.`
export const DEFAULT_CLEANUP_DISABLED_REASON = `[Cache cleanup](https://github.com/gradle/actions/blob/v3/docs/setup-gradle.md#enabling-cache-cleanup) was not enabled. It must be explicitly enabled.`
export const DEFAULT_CLEANUP_ENABLED_REASON = `[Cache cleanup](https://github.com/gradle/actions/blob/v3/docs/setup-gradle.md#enabling-cache-cleanup) was enabled.`
export const CLEANUP_DISABLED_DUE_TO_FAILURE =
'[Cache cleanup was disabled due to build failure](https://github.com/gradle/actions/blob/v3/docs/setup-gradle.md#enabling-cache-cleanup). Use `cache-cleanup: always` to override this behavior.'
/**
* Collects information on what entries were saved and restored during the action.
@@ -41,11 +46,13 @@ export class CacheListener {
setReadOnly(reason: string = DEFAULT_READONLY_REASON): void {
this.cacheReadOnly = true
this.cacheStatusReason = reason
this.cacheCleanupMessage = CLEANUP_DISABLED_READONLY
}
setDisabled(reason: string = DEFAULT_DISABLED_REASON): void {
this.cacheDisabled = true
this.cacheStatusReason = reason
this.cacheCleanupMessage = CLEANUP_DISABLED_READONLY
}
setWriteOnly(reason: string = DEFAULT_WRITEONLY_REASON): void {
@@ -57,6 +64,10 @@ export class CacheListener {
this.cacheCleanupMessage = DEFAULT_CLEANUP_ENABLED_REASON
}
setCacheCleanupDisabled(reason: string = DEFAULT_CLEANUP_DISABLED_REASON): void {
this.cacheCleanupMessage = reason
}
entry(name: string): CacheEntryListener {
for (const entry of this.cacheEntries) {
if (entry.entryName === name) {

View File

@@ -1,9 +1,10 @@
import * as core from '@actions/core'
import {CacheListener, EXISTING_GRADLE_HOME} from './cache-reporting'
import {CacheListener, EXISTING_GRADLE_HOME, CLEANUP_DISABLED_DUE_TO_FAILURE} from './cache-reporting'
import {GradleUserHomeCache} from './gradle-user-home-cache'
import {CacheCleaner} from './cache-cleaner'
import {DaemonController} from '../daemon-controller'
import {CacheConfig} from '../configuration'
import {BuildResults} from '../build-results'
const CACHE_RESTORED_VAR = 'GRADLE_BUILD_ACTION_CACHE_RESTORED'
@@ -67,6 +68,7 @@ export async function save(
gradleUserHome: string,
cacheListener: CacheListener,
daemonController: DaemonController,
buildResults: BuildResults,
cacheConfig: CacheConfig
): Promise<void> {
if (cacheConfig.isCacheDisabled()) {
@@ -88,13 +90,12 @@ export async function save(
await daemonController.stopAllDaemons()
if (cacheConfig.isCacheCleanupEnabled()) {
cacheListener.setCacheCleanupEnabled()
core.info('Forcing cache cleanup.')
const cacheCleaner = new CacheCleaner(gradleUserHome, process.env['RUNNER_TEMP']!)
try {
await cacheCleaner.forceCleanup()
} catch (e) {
core.warning(`Cache cleanup failed. Will continue. ${String(e)}`)
if (cacheConfig.shouldPerformCacheCleanup(buildResults.anyFailed())) {
cacheListener.setCacheCleanupEnabled()
await performCacheCleanup(gradleUserHome)
} else {
core.info('Not performing cache-cleanup due to build failure')
cacheListener.setCacheCleanupDisabled(CLEANUP_DISABLED_DUE_TO_FAILURE)
}
}
@@ -102,3 +103,13 @@ export async function save(
return new GradleUserHomeCache(userHome, gradleUserHome, cacheConfig).save(cacheListener)
})
}
async function performCacheCleanup(gradleUserHome: string): Promise<void> {
core.info('Forcing cache cleanup.')
const cacheCleaner = new CacheCleaner(gradleUserHome, process.env['RUNNER_TEMP']!)
try {
await cacheCleaner.forceCleanup()
} catch (e) {
core.warning(`Cache cleanup failed. Will continue. ${String(e)}`)
}
}

View File

@@ -111,7 +111,40 @@ export class CacheConfig {
}
isCacheCleanupEnabled(): boolean {
return getBooleanInput('gradle-home-cache-cleanup') && !this.isCacheReadOnly()
if (this.isCacheReadOnly()) {
return false
}
const cleanupOption = this.getCacheCleanupOption()
return cleanupOption === CacheCleanupOption.Always || cleanupOption === CacheCleanupOption.OnSuccess
}
shouldPerformCacheCleanup(hasFailure: boolean): boolean {
const cleanupOption = this.getCacheCleanupOption()
if (cleanupOption === CacheCleanupOption.Always) {
return true
}
if (cleanupOption === CacheCleanupOption.OnSuccess) {
return !hasFailure
}
return false
}
private getCacheCleanupOption(): CacheCleanupOption {
const val = core.getInput('cache-cleanup')
switch (val.toLowerCase().trim()) {
case 'always':
return CacheCleanupOption.Always
case 'on-success':
return CacheCleanupOption.OnSuccess
case 'never':
// When set to 'never' (the default), honour the legacy parameter setting.
return getBooleanInput('gradle-home-cache-cleanup')
? CacheCleanupOption.Always
: CacheCleanupOption.Never
}
throw TypeError(
`The value '${val}' is not valid for cache-cleanup. Valid values are: [never, always, on-success].`
)
}
getCacheEncryptionKey(): string {
@@ -127,6 +160,12 @@ export class CacheConfig {
}
}
export enum CacheCleanupOption {
Never = 'never',
OnSuccess = 'on-success',
Always = 'always'
}
export class SummaryConfig {
shouldGenerateJobSummary(hasFailure: boolean): boolean {
// Check if Job Summary is supported on this platform

View File

@@ -60,7 +60,7 @@ export async function complete(cacheConfig: CacheConfig, summaryConfig: SummaryC
const cacheListener: CacheListener = CacheListener.rehydrate(core.getState(CACHE_LISTENER))
const daemonController = new DaemonController(buildResults)
await caches.save(userHome, gradleUserHome, cacheListener, daemonController, cacheConfig)
await caches.save(userHome, gradleUserHome, cacheListener, daemonController, buildResults, cacheConfig)
const cachingReport = generateCachingReport(cacheListener)
await jobSummary.generateJobSummary(buildResults, cachingReport, summaryConfig)