Truncate Gradle args when constructing cache key (#71)

Cache keys have a hard limit of 512 characters, so we need to ensure that we don't generate a key longer than this.

- Remove excess whitespace
- Truncate to 400 characters

Fixes #70
This commit is contained in:
Daz DeBoer 2021-08-24 12:46:48 -06:00 committed by GitHub
parent e0c2736e35
commit b3afdc78a7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 45 additions and 13 deletions

View File

@ -1,10 +1,10 @@
import * as cryptoUtils from '../src/crypto-utils' import * as cacheUtils from '../src/cache-utils'
import * as path from 'path' import * as path from 'path'
describe('crypto-utils', () => { describe('cacheUtils-utils', () => {
describe('can hash', () => { describe('can hash', () => {
it('a directory', async () => { it('a directory', async () => {
const hash = await cryptoUtils.hashFiles( const hash = await cacheUtils.hashFiles(
path.resolve('__tests__/data/crypto-utils-test/gradle') path.resolve('__tests__/data/crypto-utils-test/gradle')
) )
expect(hash).toBe( expect(hash).toBe(
@ -14,7 +14,7 @@ describe('crypto-utils', () => {
) )
}) })
it('a directory with a glob', async () => { it('a directory with a glob', async () => {
const hash = await cryptoUtils.hashFiles( const hash = await cacheUtils.hashFiles(
path.resolve('__tests__/data/crypto-utils-test/'), path.resolve('__tests__/data/crypto-utils-test/'),
['gradle/**'] ['gradle/**']
) )
@ -25,7 +25,7 @@ describe('crypto-utils', () => {
) )
}) })
it('a directory with globs', async () => { it('a directory with globs', async () => {
const hash = await cryptoUtils.hashFiles( const hash = await cacheUtils.hashFiles(
path.resolve('__tests__/data/crypto-utils-test/'), path.resolve('__tests__/data/crypto-utils-test/'),
['**/*.gradle', 'gradle/**'] ['**/*.gradle', 'gradle/**']
) )
@ -36,4 +36,30 @@ describe('crypto-utils', () => {
) )
}) })
}) })
describe('can truncate args', () => {
test('handles zero-length string', () => {
expect(cacheUtils.truncateArgs('')).toBe('')
})
test('leaves short string untouched', () => {
expect(
cacheUtils.truncateArgs('short string that-should-be-untouched')
).toBe('short string that-should-be-untouched')
})
test('truncates long string', () => {
const longString = 'a'.repeat(500)
expect(cacheUtils.truncateArgs(longString)).toBe('a'.repeat(400))
})
test('trims leading and trailing whitespace', () => {
expect(cacheUtils.truncateArgs(' this is an arg ')).toBe(
'this is an arg'
)
})
test('removes repeated whitespace', () => {
expect(
cacheUtils.truncateArgs(
' this one has long \t\n\t\r spaces '
)
).toBe('this one has long spaces')
})
})
}) })

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

@ -4,7 +4,7 @@ import * as fs from 'fs'
import * as core from '@actions/core' import * as core from '@actions/core'
import * as cache from '@actions/cache' import * as cache from '@actions/cache'
import * as crypto from './crypto-utils' import * as cacheUtils from './cache-utils'
import { import {
inputCacheKeyGlobs, inputCacheKeyGlobs,
@ -35,10 +35,11 @@ export async function restoreCachedConfiguration(
const cacheKeyPrefix = 'configuration|' const cacheKeyPrefix = 'configuration|'
const args = core.getInput('arguments') const args = core.getInput('arguments')
const cacheKeyWithArgs = `${cacheKeyPrefix}${args}|` const argsKey = cacheUtils.truncateArgs(args)
const cacheKeyWithArgs = `${cacheKeyPrefix}${argsKey}|`
const cacheKeyGlobs = inputCacheKeyGlobs('configuration-cache-key') const cacheKeyGlobs = inputCacheKeyGlobs('configuration-cache-key')
const hash = await crypto.hashFiles(rootDir, cacheKeyGlobs) const hash = await cacheUtils.hashFiles(rootDir, cacheKeyGlobs)
const cacheKey = `${cacheKeyWithArgs}${hash}` const cacheKey = `${cacheKeyWithArgs}${hash}`
core.saveState(CONFIGURATION_CACHE_KEY, cacheKey) core.saveState(CONFIGURATION_CACHE_KEY, cacheKey)

View File

@ -5,7 +5,7 @@ import * as os from 'os'
import * as core from '@actions/core' import * as core from '@actions/core'
import * as cache from '@actions/cache' import * as cache from '@actions/cache'
import * as crypto from './crypto-utils' import * as cacheUtils from './cache-utils'
const DEPENDENCIES_CACHE_PATH = 'DEPENDENCIES_CACHE_PATH' const DEPENDENCIES_CACHE_PATH = 'DEPENDENCIES_CACHE_PATH'
const DEPENDENCIES_CACHE_KEY = 'DEPENDENCIES_CACHE_KEY' const DEPENDENCIES_CACHE_KEY = 'DEPENDENCIES_CACHE_KEY'
@ -24,10 +24,11 @@ export async function restoreCachedDependencies(
const cacheKeyPrefix = 'dependencies|' const cacheKeyPrefix = 'dependencies|'
const args = core.getInput('arguments') const args = core.getInput('arguments')
const cacheKeyWithArgs = `${cacheKeyPrefix}${args}|` const argsKey = cacheUtils.truncateArgs(args)
const cacheKeyWithArgs = `${cacheKeyPrefix}${argsKey}|`
const cacheKeyGlobs = inputCacheKeyGlobs('dependencies-cache-key') const cacheKeyGlobs = inputCacheKeyGlobs('dependencies-cache-key')
const hash = await crypto.hashFiles(rootDir, cacheKeyGlobs) const hash = await cacheUtils.hashFiles(rootDir, cacheKeyGlobs)
const cacheKey = `${cacheKeyWithArgs}${hash}` const cacheKey = `${cacheKeyWithArgs}${hash}`
core.saveState(DEPENDENCIES_CACHE_KEY, cacheKey) core.saveState(DEPENDENCIES_CACHE_KEY, cacheKey)

View File

@ -11,3 +11,7 @@ export async function hashFiles(
.join('\n') .join('\n')
return glob.hashFiles(combinedPatterns, {followSymbolicLinks}) return glob.hashFiles(combinedPatterns, {followSymbolicLinks})
} }
export function truncateArgs(args: string): string {
return args.trim().replace(/\s+/g, ' ').substr(0, 400)
}