Cache downloaded wrapper dists separately

In the current model, each cached Gradle User Home could contain
a copy of one or more downloaded wrapper distributions. This results
in large cache entries which could easily lead to premature eviction.

With this change, wrapper dists are cached separately from the rest
of the Gradle User Home directory. The artifact file is replaced by
a marker file which allows the action to restore the artifact from
cache when the Gradle user Home cache is restored.
This commit is contained in:
Daz DeBoer 2021-09-11 09:10:44 -06:00
parent b5a08466b4
commit e833360307
No known key found for this signature in database
GPG key ID: DD6B9F0B06683D5D
3 changed files with 94 additions and 3 deletions

2
dist/main/index.js vendored

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

View file

@ -1,13 +1,16 @@
import path from 'path' import path from 'path'
import fs from 'fs' import fs from 'fs'
import os from 'os' import os from 'os'
import * as core from '@actions/core'
import * as glob from '@actions/glob'
import * as cache from '@actions/cache'
import {AbstractCache} from './cache-utils' import {AbstractCache} from './cache-utils'
const CACHE_PATH = [ const CACHE_PATH = [
'~/.gradle/caches/*', // All directories in 'caches' '~/.gradle/caches/*', // All directories in 'caches'
'~/.gradle/notifications/*', // Prevent the re-rendering of first-use message for version '~/.gradle/notifications/*', // Prevent the re-rendering of first-use message for version
'~/.gradle/wrapper/dists/*/*/*.zip' // Only wrapper zips are required : Gradle will expand these on demand '~/.gradle/wrapper/dists/*/*/*.zip.txt' // Only wrapper zips are required : Gradle will expand these on demand
] ]
export class GradleUserHomeCache extends AbstractCache { export class GradleUserHomeCache extends AbstractCache {
@ -15,6 +18,94 @@ export class GradleUserHomeCache extends AbstractCache {
super('gradle', 'Gradle User Home') super('gradle', 'Gradle User Home')
} }
async restore(): Promise<void> {
await super.restore()
const globber = await glob.create(
'~/.gradle/wrapper/dists/*/*/*.zip.txt'
)
const wrapperMarkers = await globber.glob()
core.info('Found the following wrapper zips')
for (const wrapperMarker of wrapperMarkers) {
const wrapperZip = wrapperMarker.substring(
0,
wrapperMarker.length - '.txt'.length
)
core.info(
`Wrapper marker: ${wrapperMarker}. Looking for zip ${wrapperZip}`
)
if (!fs.existsSync(wrapperZip)) {
// Extract the wrapper URL hash
const wrapperKey = path.basename(path.dirname(wrapperMarker))
core.info(`Wrapper key: ${wrapperKey}`)
const cacheKey = `gradle-wrapper-${wrapperKey}`
core.info(`Cache key: ${cacheKey}. Cache path: ${wrapperZip}`)
const restoreKey = await cache.restoreCache(
[wrapperZip],
cacheKey
)
if (restoreKey) {
core.info(
`Restored wrapper zip ${cacheKey} from cache to ${wrapperZip}`
)
} else {
core.info(
`Did NOT restore wrapper zip from ${cacheKey} to ${wrapperZip}`
)
}
} else {
core.info(`Wrapper zip file already exists: ${wrapperZip}`)
}
}
}
async save(): Promise<void> {
const globber = await glob.create('~/.gradle/wrapper/dists/*/*/*.zip')
const wrapperZips = await globber.glob()
core.info('Found the following wrapper zips')
for (const wrapperZip of wrapperZips) {
core.info(`Wrapper zip: ${wrapperZip}`)
const wrapperMarkerFile = `${wrapperZip}.txt`
if (!fs.existsSync(wrapperMarkerFile)) {
// Extract the wrapper URL hash
const wrapperKey = path.basename(path.dirname(wrapperZip))
core.info(`Wrapper key: ${wrapperKey}`)
const cacheKey = `gradle-wrapper-${wrapperKey}`
core.info(`Caching wrapper with cache key: ${cacheKey}`)
try {
await cache.saveCache([wrapperZip], cacheKey)
} catch (error) {
// Fail on validation errors or non-errors (the latter to keep Typescript happy)
if (
error instanceof cache.ValidationError ||
!(error instanceof Error)
) {
throw error
}
core.warning(error.message)
}
// Write the marker file and delete the original
fs.writeFileSync(wrapperMarkerFile, 'dummy')
} else {
core.info(
`Wrapper marker file already exists: ${wrapperMarkerFile}`
)
}
}
await super.save()
}
protected cacheOutputExists(): boolean { protected cacheOutputExists(): boolean {
// Need to check for 'caches' directory to avoid incorrect detection on MacOS agents // Need to check for 'caches' directory to avoid incorrect detection on MacOS agents
const dir = path.resolve(os.homedir(), '.gradle/caches') const dir = path.resolve(os.homedir(), '.gradle/caches')