Generate cache key based on Job invocation

Attempt to capture as much context as possible about the job run
to generate a unique cache key. Unfortunately much of the matrix context
is not available to the action implementation.
This commit is contained in:
Daz DeBoer 2021-09-05 21:35:17 -06:00
parent d7ed6d7e8d
commit 777a6fc967
No known key found for this signature in database
GPG key ID: DD6B9F0B06683D5D
3 changed files with 47 additions and 33 deletions

View file

@ -1,5 +1,6 @@
import * as core from '@actions/core'
import * as github from '@actions/github'
import * as crypto from 'crypto'
export function isCacheReadEnabled(cacheName: string): boolean {
const configValue = getCacheEnabledValue(cacheName)
@ -25,19 +26,48 @@ function getCacheEnabledValue(cacheName: string): string {
}
export function generateCacheKey(cacheName: string): CacheKey {
const cacheKeySeed = process.env[`CACHE_KEY_SEED`] || ''
const runnerOs = process.env[`RUNNER_OS`] || ''
const cacheKeyPrefix = `${cacheKeySeed}${runnerOs}|${cacheName}|`
// Prefix can be used to force change all cache keys
const cacheKeyPrefix = process.env['CACHE_KEY_PREFIX'] || ''
const args = truncateArgs(core.getInput('arguments'))
const cacheKeyWithArgs = `${cacheKeyPrefix}${args}|`
// At the most general level, share caches for all executions on the same OS
const runnerOs = process.env['RUNNER_OS'] || ''
const cacheKeyForOs = `${cacheKeyPrefix}${cacheName}|${runnerOs}`
const cacheKey = `${cacheKeyWithArgs}${github.context.sha}`
return new CacheKey(cacheKey, [cacheKeyWithArgs, cacheKeyPrefix])
// Prefer caches that run this job
const cacheKeyForJob = `${cacheKeyForOs}|${github.context.job}`
// Prefer (even more) jobs that run this job with the same context (matrix)
const cacheKeyForJobContext = `${cacheKeyForJob}[${determineJobContext()}]`
// Exact match on Git SHA
const cacheKey = `${cacheKeyForJobContext}-${github.context.sha}`
return new CacheKey(cacheKey, [
cacheKeyForJobContext,
cacheKeyForJob,
cacheKeyForOs
])
}
function truncateArgs(args: string): string {
return args.trim().replace(/\s+/g, ' ').substr(0, 400)
function determineJobContext(): string {
// Ideally we'd serialize the entire matrix values here, but matrix is not available within the action invocation.
// Use the JAVA_HOME value as a proxy for the java version
const javaHome = process.env['JAVA_HOME'] || ''
// Approximate overall context based on the first gradle invocation in the Job
const args = core.getInput('arguments')
const buildRootDirectory = core.getInput('build-root-directory')
const gradleVersion = core.getInput('gradle-version')
return hashStrings([javaHome, args, buildRootDirectory, gradleVersion])
}
export function hashStrings(values: string[]): string {
const hash = crypto.createHash('md5')
for (const value of values) {
hash.update(value)
}
return hash.digest('hex')
}
export class CacheKey {