Only restore configuration-cache if Gradle Home is fully restored

Fixes #107
This commit is contained in:
Daz DeBoer 2021-10-29 08:44:08 -06:00
parent 079e4844d6
commit 9edc2a11bd
No known key found for this signature in database
GPG key ID: DD6B9F0B06683D5D
4 changed files with 48 additions and 21 deletions

View file

@ -11,7 +11,7 @@
"eslint-comments/no-use": "off", "eslint-comments/no-use": "off",
"import/no-namespace": "off", "import/no-namespace": "off",
"no-unused-vars": "off", "no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": "error", "@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }],
"@typescript-eslint/explicit-member-accessibility": ["error", {"accessibility": "no-public"}], "@typescript-eslint/explicit-member-accessibility": ["error", {"accessibility": "no-public"}],
"@typescript-eslint/no-require-imports": "error", "@typescript-eslint/no-require-imports": "error",
"@typescript-eslint/array-type": "error", "@typescript-eslint/array-type": "error",

View file

@ -5,7 +5,7 @@ import * as core from '@actions/core'
import * as glob from '@actions/glob' import * as glob from '@actions/glob'
import * as exec from '@actions/exec' import * as exec from '@actions/exec'
import {AbstractCache, getCacheKeyPrefix, hashFileNames, tryDelete} from './cache-utils' import {AbstractCache, CachingReport, getCacheKeyPrefix, hashFileNames, tryDelete} from './cache-utils'
const META_FILE_DIR = '.gradle-build-action' const META_FILE_DIR = '.gradle-build-action'
@ -21,14 +21,17 @@ export class GradleUserHomeCache extends AbstractCache {
this.gradleUserHome = this.determineGradleUserHome(rootDir) this.gradleUserHome = this.determineGradleUserHome(rootDir)
} }
async afterRestore(): Promise<void> { async afterRestore(report: CachingReport): Promise<void> {
await this.reportGradleUserHomeSize('as restored from cache') await this.reportGradleUserHomeSize('as restored from cache')
await this.restoreArtifactBundles() const result = await this.restoreArtifactBundles()
await this.reportGradleUserHomeSize('after restoring common artifacts') await this.reportGradleUserHomeSize('after restoring common artifacts')
if (!result) {
report.fullyRestored = false
}
} }
private async restoreArtifactBundles(): Promise<void> { private async restoreArtifactBundles(): Promise<boolean> {
const processes: Promise<void>[] = [] const processes: Promise<boolean>[] = []
for (const [bundle, pattern] of this.getArtifactBundles()) { for (const [bundle, pattern] of this.getArtifactBundles()) {
const p = this.restoreArtifactBundle(bundle, pattern) const p = this.restoreArtifactBundle(bundle, pattern)
// Run sequentially when debugging enabled // Run sequentially when debugging enabled
@ -38,10 +41,12 @@ export class GradleUserHomeCache extends AbstractCache {
processes.push(p) processes.push(p)
} }
await Promise.all(processes) const results = await Promise.all(processes)
// Assume that no-bundles means not-fully-restored
return results.length > 0 && results.every(Boolean)
} }
private async restoreArtifactBundle(bundle: string, artifactPath: string): Promise<void> { private async restoreArtifactBundle(bundle: string, artifactPath: string): Promise<boolean> {
const bundleMetaFile = this.getBundleMetaFile(bundle) const bundleMetaFile = this.getBundleMetaFile(bundle)
if (fs.existsSync(bundleMetaFile)) { if (fs.existsSync(bundleMetaFile)) {
const cacheKey = fs.readFileSync(bundleMetaFile, 'utf-8').trim() const cacheKey = fs.readFileSync(bundleMetaFile, 'utf-8').trim()
@ -50,10 +55,12 @@ export class GradleUserHomeCache extends AbstractCache {
core.info(`Restored ${bundle} with key ${cacheKey} to ${artifactPath}`) core.info(`Restored ${bundle} with key ${cacheKey} to ${artifactPath}`)
} else { } else {
this.debug(`Did not restore ${bundle} with key ${cacheKey} to ${artifactPath}`) this.debug(`Did not restore ${bundle} with key ${cacheKey} to ${artifactPath}`)
return false
} }
} else { } else {
this.debug(`No metafile found to restore ${bundle}: ${bundleMetaFile}`) this.debug(`No metafile found to restore ${bundle}: ${bundleMetaFile}`)
} }
return true
} }
private getBundleMetaFile(name: string): string { private getBundleMetaFile(name: string): string {

View file

@ -105,6 +105,14 @@ class CacheKey {
} }
} }
export class CachingReport {
fullyRestored: boolean
constructor(fullyRestored: boolean) {
this.fullyRestored = fullyRestored
}
}
export abstract class AbstractCache { export abstract class AbstractCache {
private cacheName: string private cacheName: string
private cacheDescription: string private cacheDescription: string
@ -121,15 +129,13 @@ export abstract class AbstractCache {
this.cacheDebuggingEnabled = isCacheDebuggingEnabled() this.cacheDebuggingEnabled = isCacheDebuggingEnabled()
} }
async restore(): Promise<void> { async restore(): Promise<CachingReport> {
if (this.cacheOutputExists()) { if (this.cacheOutputExists()) {
core.info(`${this.cacheDescription} already exists. Not restoring from cache.`) core.info(`${this.cacheDescription} already exists. Not restoring from cache.`)
return return new CachingReport(false)
} }
const cacheKey = generateCacheKey(this.cacheName) const cacheKey = this.prepareCacheKey()
core.saveState(this.cacheKeyStateKey, cacheKey.key)
this.debug( this.debug(
`Requesting ${this.cacheDescription} with `Requesting ${this.cacheDescription} with
@ -141,20 +147,28 @@ export abstract class AbstractCache {
if (!cacheResult) { if (!cacheResult) {
core.info(`${this.cacheDescription} cache not found. Will start with empty.`) core.info(`${this.cacheDescription} cache not found. Will start with empty.`)
return return new CachingReport(false)
} }
core.saveState(this.cacheResultStateKey, cacheResult) core.saveState(this.cacheResultStateKey, cacheResult)
core.info(`Restored ${this.cacheDescription} from cache key: ${cacheResult}`) core.info(`Restored ${this.cacheDescription} from cache key: ${cacheResult}`)
const report = new CachingReport(true)
try { try {
await this.afterRestore() await this.afterRestore(report)
} catch (error) { } catch (error) {
core.warning(`Restore ${this.cacheDescription} failed in 'afterRestore': ${error}`) core.warning(`Restore ${this.cacheDescription} failed in 'afterRestore': ${error}`)
} }
return return report
}
prepareCacheKey(): CacheKey {
const cacheKey = generateCacheKey(this.cacheName)
core.saveState(this.cacheKeyStateKey, cacheKey.key)
return cacheKey
} }
protected async restoreCache( protected async restoreCache(
@ -175,7 +189,7 @@ export abstract class AbstractCache {
} }
} }
protected async afterRestore(): Promise<void> {} protected async afterRestore(_report: CachingReport): Promise<void> {}
async save(): Promise<void> { async save(): Promise<void> {
if (!this.cacheOutputExists()) { if (!this.cacheOutputExists()) {

View file

@ -13,10 +13,16 @@ export async function restore(buildRootDirectory: string): Promise<void> {
await core.group('Restore Gradle state from cache', async () => { await core.group('Restore Gradle state from cache', async () => {
core.saveState(BUILD_ROOT_DIR, buildRootDirectory) core.saveState(BUILD_ROOT_DIR, buildRootDirectory)
return Promise.all([ const gradleHomeRestore = await new GradleUserHomeCache(buildRootDirectory).restore()
new GradleUserHomeCache(buildRootDirectory).restore(),
new ProjectDotGradleCache(buildRootDirectory).restore() const projectDotGradleCache = new ProjectDotGradleCache(buildRootDirectory)
]) if (gradleHomeRestore.fullyRestored) {
// Only restore the configuration-cache if the Gradle Home is fully restored
await projectDotGradleCache.restore()
} else {
// Otherwise, prepare the cache key for later save()
projectDotGradleCache.prepareCacheKey()
}
}) })
} }