mirror of
https://github.com/gradle/actions.git
synced 2025-02-03 15:26:42 -05:00
Attempt to provision best gradle version for cache-cleanup
This commit is contained in:
parent
edf9e3c8c7
commit
c6e631b4a7
4 changed files with 47 additions and 11 deletions
|
@ -1,5 +1,6 @@
|
|||
import * as fs from 'fs'
|
||||
import * as path from 'path'
|
||||
import {versionIsAtLeast} from './execution/gradle'
|
||||
|
||||
export interface BuildResult {
|
||||
get rootProjectName(): string
|
||||
|
@ -32,6 +33,18 @@ export class BuildResults {
|
|||
const allHomes = this.results.map(buildResult => buildResult.gradleHomeDir)
|
||||
return Array.from(new Set(allHomes))
|
||||
}
|
||||
|
||||
highestGradleVersion(): string | null {
|
||||
if (this.results.length === 0) {
|
||||
return null
|
||||
}
|
||||
return this.results
|
||||
.map(result => result.gradleVersion)
|
||||
.reduce((maxVersion: string, currentVersion: string) => {
|
||||
if (!maxVersion) return currentVersion
|
||||
return versionIsAtLeast(currentVersion, maxVersion) ? currentVersion : maxVersion
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export function loadBuildResults(): BuildResults {
|
||||
|
|
|
@ -4,6 +4,8 @@ import * as exec from '@actions/exec'
|
|||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import * as provisioner from '../execution/provision'
|
||||
import {BuildResults} from '../build-results'
|
||||
import {versionIsAtLeast} from '../execution/gradle'
|
||||
|
||||
export class CacheCleaner {
|
||||
private readonly gradleUserHome: string
|
||||
|
@ -21,13 +23,37 @@ export class CacheCleaner {
|
|||
return timestamp
|
||||
}
|
||||
|
||||
async forceCleanup(): Promise<void> {
|
||||
async forceCleanup(buildResults: BuildResults): Promise<void> {
|
||||
const executable = await this.gradleExecutableForCleanup(buildResults)
|
||||
const cleanTimestamp = core.getState('clean-timestamp')
|
||||
await this.forceCleanupFilesOlderThan(cleanTimestamp)
|
||||
await this.forceCleanupFilesOlderThan(cleanTimestamp, executable)
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to use the newest Gradle version that was used to run a build, at least 8.11.
|
||||
*
|
||||
* This will avoid the need to provision a Gradle version for the cleanup when not necessary.
|
||||
*/
|
||||
private async gradleExecutableForCleanup(buildResults: BuildResults): Promise<string> {
|
||||
const preferredVersion = buildResults.highestGradleVersion()
|
||||
if (preferredVersion && versionIsAtLeast(preferredVersion, '8.11')) {
|
||||
try {
|
||||
return await provisioner.provisionGradleAtLeast(preferredVersion)
|
||||
} catch (e) {
|
||||
// Ignore the case where the preferred version cannot be located in https://services.gradle.org/versions/all.
|
||||
// This can happen for snapshot Gradle versions.
|
||||
core.info(
|
||||
`Failed to provision Gradle ${preferredVersion} for cache cleanup. Falling back to default version.`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to the minimum version required for cache-cleanup
|
||||
return await provisioner.provisionGradleAtLeast('8.11')
|
||||
}
|
||||
|
||||
// Visible for testing
|
||||
async forceCleanupFilesOlderThan(cleanTimestamp: string): Promise<void> {
|
||||
async forceCleanupFilesOlderThan(cleanTimestamp: string, executable: string): Promise<void> {
|
||||
// Run a dummy Gradle build to trigger cache cleanup
|
||||
const cleanupProjectDir = path.resolve(this.tmpDir, 'dummy-cleanup-project')
|
||||
fs.mkdirSync(cleanupProjectDir, {recursive: true})
|
||||
|
@ -55,9 +81,6 @@ export class CacheCleaner {
|
|||
)
|
||||
fs.writeFileSync(path.resolve(cleanupProjectDir, 'build.gradle'), 'task("noop") {}')
|
||||
|
||||
// TODO: This is ineffective: we should be using the newest version of Gradle that ran a build, or a newer version if it's available on PATH.
|
||||
const executable = await provisioner.provisionGradleAtLeast('8.12')
|
||||
|
||||
await core.group('Executing Gradle to clean up caches', async () => {
|
||||
core.info(`Cleaning up caches last used before ${cleanTimestamp}`)
|
||||
await this.executeCleanupBuild(executable, cleanupProjectDir)
|
||||
|
|
|
@ -102,7 +102,7 @@ export async function save(
|
|||
cacheListener.setCacheCleanupDisabled(CLEANUP_DISABLED_DUE_TO_CONFIG_CACHE_HIT)
|
||||
} else if (cacheConfig.shouldPerformCacheCleanup(buildResults.anyFailed())) {
|
||||
cacheListener.setCacheCleanupEnabled()
|
||||
await performCacheCleanup(gradleUserHome)
|
||||
await performCacheCleanup(gradleUserHome, buildResults)
|
||||
} else {
|
||||
core.info('Not performing cache-cleanup due to build failure')
|
||||
cacheListener.setCacheCleanupDisabled(CLEANUP_DISABLED_DUE_TO_FAILURE)
|
||||
|
@ -114,10 +114,10 @@ export async function save(
|
|||
})
|
||||
}
|
||||
|
||||
async function performCacheCleanup(gradleUserHome: string): Promise<void> {
|
||||
async function performCacheCleanup(gradleUserHome: string, buildResults: BuildResults): Promise<void> {
|
||||
const cacheCleaner = new CacheCleaner(gradleUserHome, process.env['RUNNER_TEMP']!)
|
||||
try {
|
||||
await cacheCleaner.forceCleanup()
|
||||
await cacheCleaner.forceCleanup(buildResults)
|
||||
} catch (e) {
|
||||
core.warning(`Cache cleanup failed. Will continue. ${String(e)}`)
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ test('will cleanup unused dependency jars and build-cache entries', async () =>
|
|||
expect(fs.existsSync(commonsMath311)).toBe(true)
|
||||
expect(fs.readdirSync(buildCacheDir).length).toBe(4) // gc.properties, build-cache-1.lock, and 2 task entries
|
||||
|
||||
await cacheCleaner.forceCleanupFilesOlderThan(timestamp)
|
||||
await cacheCleaner.forceCleanupFilesOlderThan(timestamp, 'gradle')
|
||||
|
||||
expect(fs.existsSync(commonsMath31)).toBe(false)
|
||||
expect(fs.existsSync(commonsMath311)).toBe(true)
|
||||
|
@ -68,7 +68,7 @@ test('will cleanup unused gradle versions', async () => {
|
|||
// The wrapper won't be removed if it was recently downloaded. Age it.
|
||||
setUtimes(wrapper802, new Date(Date.now() - 48 * 60 * 60 * 1000))
|
||||
|
||||
await cacheCleaner.forceCleanupFilesOlderThan(timestamp)
|
||||
await cacheCleaner.forceCleanupFilesOlderThan(timestamp, 'gradle')
|
||||
|
||||
expect(fs.existsSync(gradle802)).toBe(false)
|
||||
expect(fs.existsSync(transforms3)).toBe(false)
|
||||
|
|
Loading…
Reference in a new issue