mirror of
https://github.com/gradle/gradle-build-action.git
synced 2024-11-23 01:22:50 +00:00
Report sizes of cache entries
Using the patched version of @actions/cache, we now report the total size of cache entries restored/saved, as well as details of each one.
This commit is contained in:
parent
3ba05ede1f
commit
472ac8a356
4 changed files with 63 additions and 26 deletions
|
@ -5,7 +5,7 @@ describe('caching report', () => {
|
||||||
it('with one requested entry report', async () => {
|
it('with one requested entry report', async () => {
|
||||||
const report = new CacheListener()
|
const report = new CacheListener()
|
||||||
report.entry('foo').markRequested('1', ['2'])
|
report.entry('foo').markRequested('1', ['2'])
|
||||||
report.entry('bar').markRequested('3').markRestored('4')
|
report.entry('bar').markRequested('3').markRestored('4', 500)
|
||||||
expect(report.fullyRestored).toBe(false)
|
expect(report.fullyRestored).toBe(false)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -22,13 +22,13 @@ describe('caching report', () => {
|
||||||
})
|
})
|
||||||
it('with restored entry report', async () => {
|
it('with restored entry report', async () => {
|
||||||
const report = new CacheListener()
|
const report = new CacheListener()
|
||||||
report.entry('bar').markRequested('3').markRestored('4')
|
report.entry('bar').markRequested('3').markRestored('4', 300)
|
||||||
expect(report.fullyRestored).toBe(true)
|
expect(report.fullyRestored).toBe(true)
|
||||||
})
|
})
|
||||||
it('with multiple restored entry reportss', async () => {
|
it('with multiple restored entry reportss', async () => {
|
||||||
const report = new CacheListener()
|
const report = new CacheListener()
|
||||||
report.entry('foo').markRestored('4')
|
report.entry('foo').markRestored('4', 3300)
|
||||||
report.entry('bar').markRequested('3').markRestored('4')
|
report.entry('bar').markRequested('3').markRestored('4', 333)
|
||||||
expect(report.fullyRestored).toBe(true)
|
expect(report.fullyRestored).toBe(true)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -64,7 +64,7 @@ describe('caching report', () => {
|
||||||
const report = new CacheListener()
|
const report = new CacheListener()
|
||||||
const entryReport = report.entry('foo')
|
const entryReport = report.entry('foo')
|
||||||
entryReport.markRequested('1', ['2', '3'])
|
entryReport.markRequested('1', ['2', '3'])
|
||||||
entryReport.markSaved('4')
|
entryReport.markSaved('4', 100)
|
||||||
|
|
||||||
const stringRep = report.stringify()
|
const stringRep = report.stringify()
|
||||||
const reportClone: CacheListener = CacheListener.rehydrate(stringRep)
|
const reportClone: CacheListener = CacheListener.rehydrate(stringRep)
|
||||||
|
@ -85,7 +85,7 @@ describe('caching report', () => {
|
||||||
|
|
||||||
// Check type and call method on rehydrated entry report
|
// Check type and call method on rehydrated entry report
|
||||||
expect(entryClone).toBeInstanceOf(CacheEntryListener)
|
expect(entryClone).toBeInstanceOf(CacheEntryListener)
|
||||||
entryClone.markSaved('4')
|
entryClone.markSaved('4', 100)
|
||||||
|
|
||||||
expect(entryClone.requestedKey).toBe('1')
|
expect(entryClone.requestedKey).toBe('1')
|
||||||
expect(entryClone.requestedRestoreKeys).toEqual(['2', '3'])
|
expect(entryClone.requestedRestoreKeys).toEqual(['2', '3'])
|
||||||
|
|
|
@ -98,13 +98,15 @@ export class CacheEntryListener {
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
markRestored(key: string): CacheEntryListener {
|
markRestored(key: string, size: number | undefined): CacheEntryListener {
|
||||||
this.restoredKey = key
|
this.restoredKey = key
|
||||||
|
this.restoredSize = size
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
markSaved(key: string): CacheEntryListener {
|
markSaved(key: string, size: number | undefined): CacheEntryListener {
|
||||||
this.savedKey = key
|
this.savedKey = key
|
||||||
|
this.savedSize = size
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -149,7 +151,7 @@ export abstract class AbstractCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
core.saveState(this.cacheResultStateKey, cacheResult)
|
core.saveState(this.cacheResultStateKey, cacheResult)
|
||||||
entryReport.markRestored(cacheResult)
|
entryReport.markRestored(cacheResult.key, cacheResult.size)
|
||||||
core.info(`Restored ${this.cacheDescription} from cache key: ${cacheResult}`)
|
core.info(`Restored ${this.cacheDescription} from cache key: ${cacheResult}`)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -170,7 +172,7 @@ export abstract class AbstractCache {
|
||||||
cachePath: string[],
|
cachePath: string[],
|
||||||
cacheKey: string,
|
cacheKey: string,
|
||||||
cacheRestoreKeys: string[] = []
|
cacheRestoreKeys: string[] = []
|
||||||
): Promise<string | undefined> {
|
): Promise<cache.CacheEntry | undefined> {
|
||||||
try {
|
try {
|
||||||
return await cache.restoreCache(cachePath, cacheKey, cacheRestoreKeys)
|
return await cache.restoreCache(cachePath, cacheKey, cacheRestoreKeys)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -214,18 +216,20 @@ export abstract class AbstractCache {
|
||||||
|
|
||||||
core.info(`Caching ${this.cacheDescription} with cache key: ${cacheKey}`)
|
core.info(`Caching ${this.cacheDescription} with cache key: ${cacheKey}`)
|
||||||
const cachePath = this.getCachePath()
|
const cachePath = this.getCachePath()
|
||||||
await this.saveCache(cachePath, cacheKey)
|
const savedEntry = await this.saveCache(cachePath, cacheKey)
|
||||||
|
|
||||||
listener.entry(this.cacheDescription).markSaved(cacheKey)
|
if (savedEntry) {
|
||||||
|
listener.entry(this.cacheDescription).markSaved(savedEntry.key, savedEntry.size)
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async beforeSave(_listener: CacheListener): Promise<void> {}
|
protected async beforeSave(_listener: CacheListener): Promise<void> {}
|
||||||
|
|
||||||
protected async saveCache(cachePath: string[], cacheKey: string): Promise<void> {
|
protected async saveCache(cachePath: string[], cacheKey: string): Promise<cache.CacheEntry | undefined> {
|
||||||
try {
|
try {
|
||||||
await cache.saveCache(cachePath, cacheKey)
|
return await cache.saveCache(cachePath, cacheKey)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof cache.ValidationError) {
|
if (error instanceof cache.ValidationError) {
|
||||||
// Validation errors should fail the build action
|
// Validation errors should fail the build action
|
||||||
|
@ -238,6 +242,7 @@ export abstract class AbstractCache {
|
||||||
core.warning(String(error))
|
core.warning(String(error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
protected debug(message: string): void {
|
protected debug(message: string): void {
|
||||||
|
|
|
@ -67,10 +67,10 @@ export class GradleUserHomeCache extends AbstractCache {
|
||||||
const cacheKey = fs.readFileSync(bundleMetaFile, 'utf-8').trim()
|
const cacheKey = fs.readFileSync(bundleMetaFile, 'utf-8').trim()
|
||||||
listener.markRequested(cacheKey)
|
listener.markRequested(cacheKey)
|
||||||
|
|
||||||
const restoredKey = await this.restoreCache([bundlePattern], cacheKey)
|
const restoredEntry = await this.restoreCache([bundlePattern], cacheKey)
|
||||||
if (restoredKey) {
|
if (restoredEntry) {
|
||||||
core.info(`Restored ${bundle} with key ${cacheKey} to ${bundlePattern}`)
|
core.info(`Restored ${bundle} with key ${cacheKey} to ${bundlePattern}`)
|
||||||
listener.markRestored(restoredKey)
|
listener.markRestored(restoredEntry.key, restoredEntry.size)
|
||||||
} else {
|
} else {
|
||||||
core.info(`Did not restore ${bundle} with key ${cacheKey} to ${bundlePattern}`)
|
core.info(`Did not restore ${bundle} with key ${cacheKey} to ${bundlePattern}`)
|
||||||
tryDelete(bundleMetaFile)
|
tryDelete(bundleMetaFile)
|
||||||
|
@ -154,9 +154,11 @@ export class GradleUserHomeCache extends AbstractCache {
|
||||||
this.debug(`No change to previously restored ${bundle}. Not caching.`)
|
this.debug(`No change to previously restored ${bundle}. Not caching.`)
|
||||||
} else {
|
} else {
|
||||||
core.info(`Caching ${bundle} with cache key: ${cacheKey}`)
|
core.info(`Caching ${bundle} with cache key: ${cacheKey}`)
|
||||||
await this.saveCache([artifactPath], cacheKey)
|
const savedEntry = await this.saveCache([artifactPath], cacheKey)
|
||||||
this.writeBundleMetaFile(bundleMetaFile, cacheKey)
|
if (savedEntry !== undefined) {
|
||||||
listener.markSaved(cacheKey)
|
this.writeBundleMetaFile(bundleMetaFile, cacheKey)
|
||||||
|
listener.markSaved(savedEntry.key, savedEntry.size)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const file of bundleFiles) {
|
for (const file of bundleFiles) {
|
||||||
|
|
|
@ -2,7 +2,7 @@ import {GradleUserHomeCache} from './cache-gradle-user-home'
|
||||||
import {ProjectDotGradleCache} from './cache-project-dot-gradle'
|
import {ProjectDotGradleCache} from './cache-project-dot-gradle'
|
||||||
import * as core from '@actions/core'
|
import * as core from '@actions/core'
|
||||||
import {isCacheDisabled, isCacheReadOnly} from './cache-utils'
|
import {isCacheDisabled, isCacheReadOnly} from './cache-utils'
|
||||||
import {CacheListener} from './cache-base'
|
import {CacheEntryListener, CacheListener} from './cache-base'
|
||||||
|
|
||||||
const BUILD_ROOT_DIR = 'BUILD_ROOT_DIR'
|
const BUILD_ROOT_DIR = 'BUILD_ROOT_DIR'
|
||||||
const CACHE_LISTENER = 'CACHE_LISTENER'
|
const CACHE_LISTENER = 'CACHE_LISTENER'
|
||||||
|
@ -54,11 +54,41 @@ export async function save(): Promise<void> {
|
||||||
}
|
}
|
||||||
|
|
||||||
function logCachingReport(listener: CacheListener): void {
|
function logCachingReport(listener: CacheListener): void {
|
||||||
core.info('---------- CACHING REPORT -------------')
|
core.info(`---------- Caching Summary -------------
|
||||||
|
Restored Entries Count: ${getCount(listener.cacheEntries, e => e.restoredSize)}
|
||||||
|
Size: ${getSum(listener.cacheEntries, e => e.restoredSize)}
|
||||||
|
Saved Entries Count: ${getCount(listener.cacheEntries, e => e.savedSize)}
|
||||||
|
Size: ${getSum(listener.cacheEntries, e => e.savedSize)}`)
|
||||||
|
|
||||||
|
core.startGroup('Cache Entry details')
|
||||||
for (const entry of listener.cacheEntries) {
|
for (const entry of listener.cacheEntries) {
|
||||||
core.info(`${entry.entryName}
|
core.info(`Entry: ${entry.entryName}
|
||||||
Requested Key: ${entry.requestedKey ?? ''}
|
Requested Key : ${entry.requestedKey ?? ''}
|
||||||
Restored Key : ${entry.restoredKey ?? ''}
|
Restored Key : ${entry.restoredKey ?? ''}
|
||||||
Saved Key : ${entry.savedKey ?? ''}`)
|
Size: ${formatSize(entry.restoredSize)}
|
||||||
|
Saved Key : ${entry.savedKey ?? ''}
|
||||||
|
Size: ${formatSize(entry.savedSize)}`)
|
||||||
}
|
}
|
||||||
|
core.endGroup()
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCount(
|
||||||
|
cacheEntries: CacheEntryListener[],
|
||||||
|
predicate: (value: CacheEntryListener) => number | undefined
|
||||||
|
): number {
|
||||||
|
return cacheEntries.filter(e => predicate(e) !== undefined).length
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSum(
|
||||||
|
cacheEntries: CacheEntryListener[],
|
||||||
|
predicate: (value: CacheEntryListener) => number | undefined
|
||||||
|
): string {
|
||||||
|
return formatSize(cacheEntries.map(e => predicate(e) ?? 0).reduce((p, v) => p + v, 0))
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatSize(bytes: number | undefined): string {
|
||||||
|
if (bytes === undefined || bytes === 0) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
return `${Math.round(bytes / (1024 * 1024))} MB (${bytes} B)`
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue