mirror of
https://github.com/gradle/gradle-build-action.git
synced 2024-11-22 17:12:51 +00:00
Merge pull request #109 from gradle/dd/rc21
Fix issues for 2.0-rc.2 - Support multi-line strings for cache-tuning parameters #106 - Include all downloaded files in `dependencies` bundle #100 - Only restore configuration-cache if Gradle User Home is fully restored #107
This commit is contained in:
commit
613f4ec588
18 changed files with 263 additions and 260 deletions
|
@ -11,7 +11,7 @@
|
||||||
"eslint-comments/no-use": "off",
|
"eslint-comments/no-use": "off",
|
||||||
"import/no-namespace": "off",
|
"import/no-namespace": "off",
|
||||||
"no-unused-vars": "off",
|
"no-unused-vars": "off",
|
||||||
"@typescript-eslint/no-unused-vars": "error",
|
"@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }],
|
||||||
"@typescript-eslint/explicit-member-accessibility": ["error", {"accessibility": "no-public"}],
|
"@typescript-eslint/explicit-member-accessibility": ["error", {"accessibility": "no-public"}],
|
||||||
"@typescript-eslint/no-require-imports": "error",
|
"@typescript-eslint/no-require-imports": "error",
|
||||||
"@typescript-eslint/array-type": "error",
|
"@typescript-eslint/array-type": "error",
|
||||||
|
|
16
.github/workflows/integTest-caching-config.yml
vendored
16
.github/workflows/integTest-caching-config.yml
vendored
|
@ -28,13 +28,15 @@ jobs:
|
||||||
# Add "wrapper" to main cache entry and remove 'wrapper-zips' bundle
|
# Add "wrapper" to main cache entry and remove 'wrapper-zips' bundle
|
||||||
# Exclude build-cache from main cache entry
|
# Exclude build-cache from main cache entry
|
||||||
gradle-home-cache-includes: |
|
gradle-home-cache-includes: |
|
||||||
["caches", "notifications", "wrapper"]
|
caches
|
||||||
|
notifications
|
||||||
|
wrapper
|
||||||
gradle-home-cache-excludes: |
|
gradle-home-cache-excludes: |
|
||||||
["caches/build-cache-1"]
|
caches/build-cache-1
|
||||||
gradle-home-cache-artifact-bundles: |
|
gradle-home-cache-artifact-bundles: |
|
||||||
[
|
[
|
||||||
["generated-gradle-jars", "caches/*/generated-gradle-jars/*.jar"],
|
["generated-gradle-jars", "caches/*/generated-gradle-jars/*.jar"],
|
||||||
["dependency-jars", "caches/modules-*/files-*/**/*.jar"],
|
["dependencies", "caches/modules-*/files-*/*/*/*/*/"],
|
||||||
["instrumented-jars", "caches/jars-*/*/"],
|
["instrumented-jars", "caches/jars-*/*/"],
|
||||||
["kotlin-dsl", "caches/*/kotlin-dsl/*/*/"]
|
["kotlin-dsl", "caches/*/kotlin-dsl/*/*/"]
|
||||||
]
|
]
|
||||||
|
@ -57,13 +59,15 @@ jobs:
|
||||||
cache-read-only: true
|
cache-read-only: true
|
||||||
# Need the same configuration when restoring state from cache
|
# Need the same configuration when restoring state from cache
|
||||||
gradle-home-cache-includes: |
|
gradle-home-cache-includes: |
|
||||||
["caches", "notifications", "wrapper"]
|
caches
|
||||||
|
notifications
|
||||||
|
wrapper
|
||||||
gradle-home-cache-excludes: |
|
gradle-home-cache-excludes: |
|
||||||
["caches/build-cache-1"]
|
caches/build-cache-1
|
||||||
gradle-home-cache-artifact-bundles: |
|
gradle-home-cache-artifact-bundles: |
|
||||||
[
|
[
|
||||||
["generated-gradle-jars", "caches/*/generated-gradle-jars/*.jar"],
|
["generated-gradle-jars", "caches/*/generated-gradle-jars/*.jar"],
|
||||||
["dependency-jars", "caches/modules-*/files-*/**/*.jar"],
|
["dependencies", "caches/modules-*/files-*/*/*/*/*/"],
|
||||||
["instrumented-jars", "caches/jars-*/*/"],
|
["instrumented-jars", "caches/jars-*/*/"],
|
||||||
["kotlin-dsl", "caches/*/kotlin-dsl/*/*/"]
|
["kotlin-dsl", "caches/*/kotlin-dsl/*/*/"]
|
||||||
]
|
]
|
||||||
|
|
65
.github/workflows/integTest-caching-configuration-cache.yml
vendored
Normal file
65
.github/workflows/integTest-caching-configuration-cache.yml
vendored
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
name: Test save/restore configuration-cache state
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
env:
|
||||||
|
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: ${{github.workflow}}#${{github.run_number}}-
|
||||||
|
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# Run initial Gradle builds to push initial cache entries
|
||||||
|
# These builds should start fresh without cache hits, due to the seed injected into the cache key above.
|
||||||
|
seed-build:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, windows-latest]
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout sources
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Build with configuration-cache enabled
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
build-root-directory: __tests__/samples/groovy-dsl
|
||||||
|
arguments: test --configuration-cache
|
||||||
|
|
||||||
|
# Test that the project-dot-gradle cache will cache and restore configuration-cache
|
||||||
|
configuration-cache:
|
||||||
|
needs: seed-build
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, windows-latest]
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout sources
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Execute Gradle build and verify cached configuration
|
||||||
|
uses: ./
|
||||||
|
env:
|
||||||
|
VERIFY_CACHED_CONFIGURATION: true
|
||||||
|
with:
|
||||||
|
build-root-directory: __tests__/samples/groovy-dsl
|
||||||
|
arguments: test --configuration-cache
|
||||||
|
cache-read-only: true
|
||||||
|
|
||||||
|
# Check that the build can run when no bundles are restored
|
||||||
|
no-bundles-restored:
|
||||||
|
needs: seed-build
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, windows-latest]
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout sources
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Execute Gradle build with no cache artifact bundles restored
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
build-root-directory: __tests__/samples/groovy-dsl
|
||||||
|
arguments: test --configuration-cache
|
||||||
|
cache-read-only: true
|
||||||
|
gradle-home-cache-artifact-bundles: '[]'
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
name: Test caching
|
name: Test save/restore Gradle Home directory
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
|
@ -24,11 +24,6 @@ jobs:
|
||||||
with:
|
with:
|
||||||
build-root-directory: __tests__/samples/groovy-dsl
|
build-root-directory: __tests__/samples/groovy-dsl
|
||||||
arguments: test
|
arguments: test
|
||||||
- name: Build with configuration-cache enabled
|
|
||||||
uses: ./
|
|
||||||
with:
|
|
||||||
build-root-directory: __tests__/samples/groovy-dsl
|
|
||||||
arguments: test --configuration-cache
|
|
||||||
|
|
||||||
# Test that the gradle-user-home cache will cache dependencies, by running build with --offline
|
# Test that the gradle-user-home cache will cache dependencies, by running build with --offline
|
||||||
dependencies-cache:
|
dependencies-cache:
|
||||||
|
@ -64,25 +59,6 @@ jobs:
|
||||||
arguments: test -DverifyCachedBuild=true
|
arguments: test -DverifyCachedBuild=true
|
||||||
cache-read-only: true
|
cache-read-only: true
|
||||||
|
|
||||||
# Test that the project-dot-gradle cache will cache and restore configuration-cache
|
|
||||||
configuration-cache:
|
|
||||||
needs: seed-build
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
os: [ubuntu-latest, windows-latest]
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout sources
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
- name: Execute Gradle build and verify cached configuration
|
|
||||||
uses: ./
|
|
||||||
env:
|
|
||||||
VERIFY_CACHED_CONFIGURATION: true
|
|
||||||
with:
|
|
||||||
build-root-directory: __tests__/samples/groovy-dsl
|
|
||||||
arguments: test --configuration-cache
|
|
||||||
cache-read-only: true
|
|
||||||
|
|
||||||
# Check that the build can run when no bundles are restored
|
# Check that the build can run when no bundles are restored
|
||||||
no-bundles-restored:
|
no-bundles-restored:
|
||||||
needs: seed-build
|
needs: seed-build
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"printWidth": 80,
|
"printWidth": 120,
|
||||||
"tabWidth": 4,
|
"tabWidth": 4,
|
||||||
"useTabs": false,
|
"useTabs": false,
|
||||||
"semi": false,
|
"semi": false,
|
||||||
|
|
|
@ -191,10 +191,12 @@ The contents to be cached can be fine tuned by including and excluding certain p
|
||||||
```yaml
|
```yaml
|
||||||
# Cache downloaded JDKs in addition to the default directories.
|
# Cache downloaded JDKs in addition to the default directories.
|
||||||
gradle-home-cache-includes: |
|
gradle-home-cache-includes: |
|
||||||
["caches", "notifications", "jdks"]
|
caches
|
||||||
|
notifications
|
||||||
|
jdks
|
||||||
# Exclude the local build-cache from the directories cached.
|
# Exclude the local build-cache from the directories cached.
|
||||||
gradle-home-cache-excludes: |
|
gradle-home-cache-excludes: |
|
||||||
["caches/build-cache-1"]
|
caches/build-cache-1
|
||||||
```
|
```
|
||||||
|
|
||||||
You can specify any number of fixed paths or patterns to include or exclude.
|
You can specify any number of fixed paths or patterns to include or exclude.
|
||||||
|
|
|
@ -36,13 +36,13 @@ inputs:
|
||||||
description: Paths within Gradle User Home to cache.
|
description: Paths within Gradle User Home to cache.
|
||||||
required: false
|
required: false
|
||||||
default: |
|
default: |
|
||||||
["caches", "notifications"]
|
caches
|
||||||
|
notifications
|
||||||
|
|
||||||
gradle-home-cache-excludes:
|
gradle-home-cache-excludes:
|
||||||
description: Paths within Gradle User Home to exclude from cache.
|
description: Paths within Gradle User Home to exclude from cache.
|
||||||
required: false
|
required: false
|
||||||
default: |
|
|
||||||
[]
|
|
||||||
# e.g. Use the following setting to prevent the local build cache from being saved/restored
|
# e.g. Use the following setting to prevent the local build cache from being saved/restored
|
||||||
# gradle-home-cache-excludes: |
|
# gradle-home-cache-excludes: |
|
||||||
# ["caches/build-cache-1"]
|
# ["caches/build-cache-1"]
|
||||||
|
@ -62,7 +62,7 @@ inputs:
|
||||||
[
|
[
|
||||||
["generated-gradle-jars", "caches/*/generated-gradle-jars/*.jar"],
|
["generated-gradle-jars", "caches/*/generated-gradle-jars/*.jar"],
|
||||||
["wrapper-zips", "wrapper/dists/*/*/*.zip"],
|
["wrapper-zips", "wrapper/dists/*/*/*.zip"],
|
||||||
["dependency-jars", "caches/modules-*/files-*/**/*.jar"],
|
["dependencies", "caches/modules-*/files-*/*/*/*/*/"],
|
||||||
["instrumented-jars", "caches/jars-*/*/"],
|
["instrumented-jars", "caches/jars-*/*/"],
|
||||||
["kotlin-dsl", "caches/*/kotlin-dsl/*/*/"]
|
["kotlin-dsl", "caches/*/kotlin-dsl/*/*/"]
|
||||||
]
|
]
|
||||||
|
|
2
dist/main/index.js
vendored
2
dist/main/index.js
vendored
File diff suppressed because one or more lines are too long
2
dist/main/index.js.map
vendored
2
dist/main/index.js.map
vendored
File diff suppressed because one or more lines are too long
2
dist/post/index.js
vendored
2
dist/post/index.js
vendored
File diff suppressed because one or more lines are too long
2
dist/post/index.js.map
vendored
2
dist/post/index.js.map
vendored
File diff suppressed because one or more lines are too long
|
@ -7,6 +7,8 @@ import * as exec from '@actions/exec'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
AbstractCache,
|
AbstractCache,
|
||||||
|
CacheEntryReport,
|
||||||
|
CachingReport,
|
||||||
getCacheKeyPrefix,
|
getCacheKeyPrefix,
|
||||||
hashFileNames,
|
hashFileNames,
|
||||||
tryDelete
|
tryDelete
|
||||||
|
@ -26,21 +28,38 @@ export class GradleUserHomeCache extends AbstractCache {
|
||||||
this.gradleUserHome = this.determineGradleUserHome(rootDir)
|
this.gradleUserHome = this.determineGradleUserHome(rootDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
async afterRestore(): Promise<void> {
|
async afterRestore(report: CachingReport): Promise<void> {
|
||||||
await this.reportGradleUserHomeSize('as restored from cache')
|
await this.reportGradleUserHomeSize('as restored from cache')
|
||||||
await this.restoreArtifactBundles()
|
await this.restoreArtifactBundles(report)
|
||||||
await this.reportGradleUserHomeSize('after restoring common artifacts')
|
await this.reportGradleUserHomeSize('after restoring common artifacts')
|
||||||
}
|
}
|
||||||
|
|
||||||
private async restoreArtifactBundles(): Promise<void> {
|
private async restoreArtifactBundles(report: CachingReport): Promise<void> {
|
||||||
const processes: Promise<void>[] = []
|
const processes: Promise<void>[] = []
|
||||||
for (const [bundle, pattern] of this.getArtifactBundles()) {
|
|
||||||
const p = this.restoreArtifactBundle(bundle, pattern)
|
const bundleMetaFiles = await this.getBundleMetaFiles()
|
||||||
// Run sequentially when debugging enabled
|
const bundlePatterns = this.getArtifactBundles()
|
||||||
if (this.cacheDebuggingEnabled) {
|
|
||||||
await p
|
// Iterate over all bundle meta files and try to restore
|
||||||
|
for (const bundleMetaFile of bundleMetaFiles) {
|
||||||
|
const bundle = path.basename(bundleMetaFile, '.cache')
|
||||||
|
const bundleEntryReport = report.addEntryReport(bundle)
|
||||||
|
const bundlePattern = bundlePatterns.get(bundle)
|
||||||
|
|
||||||
|
// Handle case where the 'artifactBundlePatterns' have been changed
|
||||||
|
if (bundlePattern === undefined) {
|
||||||
|
core.info(`Found bundle metafile for ${bundle} but no such bundle defined`)
|
||||||
|
bundleEntryReport.markRequested('BUNDLE_NOT_CONFIGURED')
|
||||||
|
tryDelete(bundleMetaFile)
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
const p = this.restoreArtifactBundle(bundle, bundlePattern, bundleMetaFile, bundleEntryReport)
|
||||||
|
// Run sequentially when debugging enabled
|
||||||
|
if (this.cacheDebuggingEnabled) {
|
||||||
|
await p
|
||||||
|
}
|
||||||
|
processes.push(p)
|
||||||
}
|
}
|
||||||
processes.push(p)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all(processes)
|
await Promise.all(processes)
|
||||||
|
@ -48,25 +67,20 @@ export class GradleUserHomeCache extends AbstractCache {
|
||||||
|
|
||||||
private async restoreArtifactBundle(
|
private async restoreArtifactBundle(
|
||||||
bundle: string,
|
bundle: string,
|
||||||
artifactPath: string
|
bundlePattern: string,
|
||||||
|
bundleMetaFile: string,
|
||||||
|
report: CacheEntryReport
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const bundleMetaFile = this.getBundleMetaFile(bundle)
|
const cacheKey = fs.readFileSync(bundleMetaFile, 'utf-8').trim()
|
||||||
if (fs.existsSync(bundleMetaFile)) {
|
report.markRequested(cacheKey)
|
||||||
const cacheKey = fs.readFileSync(bundleMetaFile, 'utf-8').trim()
|
|
||||||
const restoreKey = await this.restoreCache([artifactPath], cacheKey)
|
const restoredKey = await this.restoreCache([bundlePattern], cacheKey)
|
||||||
if (restoreKey) {
|
if (restoredKey) {
|
||||||
core.info(
|
core.info(`Restored ${bundle} with key ${cacheKey} to ${bundlePattern}`)
|
||||||
`Restored ${bundle} with key ${cacheKey} to ${artifactPath}`
|
report.markRestored(restoredKey)
|
||||||
)
|
|
||||||
} else {
|
|
||||||
this.debug(
|
|
||||||
`Did not restore ${bundle} with key ${cacheKey} to ${artifactPath}`
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
this.debug(
|
core.info(`Did not restore ${bundle} with key ${cacheKey} to ${bundlePattern}`)
|
||||||
`No metafile found to restore ${bundle}: ${bundleMetaFile}`
|
tryDelete(bundleMetaFile)
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,6 +88,13 @@ export class GradleUserHomeCache extends AbstractCache {
|
||||||
return path.resolve(this.gradleUserHome, META_FILE_DIR, `${name}.cache`)
|
return path.resolve(this.gradleUserHome, META_FILE_DIR, `${name}.cache`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async getBundleMetaFiles(): Promise<string[]> {
|
||||||
|
const metaFiles = path.resolve(this.gradleUserHome, META_FILE_DIR, '*.cache')
|
||||||
|
const globber = await glob.create(metaFiles)
|
||||||
|
const bundleFiles = await globber.glob()
|
||||||
|
return bundleFiles
|
||||||
|
}
|
||||||
|
|
||||||
async beforeSave(): Promise<void> {
|
async beforeSave(): Promise<void> {
|
||||||
await this.reportGradleUserHomeSize('before saving common artifacts')
|
await this.reportGradleUserHomeSize('before saving common artifacts')
|
||||||
this.removeExcludedPaths()
|
this.removeExcludedPaths()
|
||||||
|
@ -84,12 +105,8 @@ export class GradleUserHomeCache extends AbstractCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
private removeExcludedPaths(): void {
|
private removeExcludedPaths(): void {
|
||||||
const rawPaths: string[] = JSON.parse(
|
const rawPaths: string[] = core.getMultilineInput(EXCLUDE_PATHS_PARAMETER)
|
||||||
core.getInput(EXCLUDE_PATHS_PARAMETER)
|
const resolvedPaths = rawPaths.map(x => path.resolve(this.gradleUserHome, x))
|
||||||
)
|
|
||||||
const resolvedPaths = rawPaths.map(x =>
|
|
||||||
path.resolve(this.gradleUserHome, x)
|
|
||||||
)
|
|
||||||
|
|
||||||
for (const p of resolvedPaths) {
|
for (const p of resolvedPaths) {
|
||||||
this.debug(`Deleting excluded path: ${p}`)
|
this.debug(`Deleting excluded path: ${p}`)
|
||||||
|
@ -111,10 +128,7 @@ export class GradleUserHomeCache extends AbstractCache {
|
||||||
await Promise.all(processes)
|
await Promise.all(processes)
|
||||||
}
|
}
|
||||||
|
|
||||||
private async saveArtifactBundle(
|
private async saveArtifactBundle(bundle: string, artifactPath: string): Promise<void> {
|
||||||
bundle: string,
|
|
||||||
artifactPath: string
|
|
||||||
): Promise<void> {
|
|
||||||
const bundleMetaFile = this.getBundleMetaFile(bundle)
|
const bundleMetaFile = this.getBundleMetaFile(bundle)
|
||||||
|
|
||||||
const globber = await glob.create(artifactPath, {
|
const globber = await glob.create(artifactPath, {
|
||||||
|
@ -138,9 +152,7 @@ export class GradleUserHomeCache extends AbstractCache {
|
||||||
const cacheKey = this.createCacheKey(bundle, bundleFiles)
|
const cacheKey = this.createCacheKey(bundle, bundleFiles)
|
||||||
|
|
||||||
if (previouslyRestoredKey === cacheKey) {
|
if (previouslyRestoredKey === cacheKey) {
|
||||||
this.debug(
|
this.debug(`No change to previously restored ${bundle}. Not caching.`)
|
||||||
`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)
|
await this.saveCache([artifactPath], cacheKey)
|
||||||
|
@ -154,14 +166,10 @@ export class GradleUserHomeCache extends AbstractCache {
|
||||||
|
|
||||||
protected createCacheKey(bundle: string, files: string[]): string {
|
protected createCacheKey(bundle: string, files: string[]): string {
|
||||||
const cacheKeyPrefix = getCacheKeyPrefix()
|
const cacheKeyPrefix = getCacheKeyPrefix()
|
||||||
const relativeFiles = files.map(x =>
|
const relativeFiles = files.map(x => path.relative(this.gradleUserHome, x))
|
||||||
path.relative(this.gradleUserHome, x)
|
|
||||||
)
|
|
||||||
const key = hashFileNames(relativeFiles)
|
const key = hashFileNames(relativeFiles)
|
||||||
|
|
||||||
this.debug(
|
this.debug(`Generating cache key for ${bundle} from files: ${relativeFiles}`)
|
||||||
`Generating cache key for ${bundle} from files: ${relativeFiles}`
|
|
||||||
)
|
|
||||||
|
|
||||||
return `${cacheKeyPrefix}${bundle}-${key}`
|
return `${cacheKeyPrefix}${bundle}-${key}`
|
||||||
}
|
}
|
||||||
|
@ -193,9 +201,7 @@ export class GradleUserHomeCache extends AbstractCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected getCachePath(): string[] {
|
protected getCachePath(): string[] {
|
||||||
const rawPaths: string[] = JSON.parse(
|
const rawPaths: string[] = core.getMultilineInput(INCLUDE_PATHS_PARAMETER)
|
||||||
core.getInput(INCLUDE_PATHS_PARAMETER)
|
|
||||||
)
|
|
||||||
rawPaths.push(META_FILE_DIR)
|
rawPaths.push(META_FILE_DIR)
|
||||||
const resolvedPaths = rawPaths.map(x => this.resolveCachePath(x))
|
const resolvedPaths = rawPaths.map(x => this.resolveCachePath(x))
|
||||||
this.debug(`Using cache paths: ${resolvedPaths}`)
|
this.debug(`Using cache paths: ${resolvedPaths}`)
|
||||||
|
@ -211,19 +217,10 @@ export class GradleUserHomeCache extends AbstractCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
private getArtifactBundles(): Map<string, string> {
|
private getArtifactBundles(): Map<string, string> {
|
||||||
const artifactBundleDefinition = core.getInput(
|
const artifactBundleDefinition = core.getInput(ARTIFACT_BUNDLES_PARAMETER)
|
||||||
ARTIFACT_BUNDLES_PARAMETER
|
this.debug(`Using artifact bundle definition: ${artifactBundleDefinition}`)
|
||||||
)
|
|
||||||
this.debug(
|
|
||||||
`Using artifact bundle definition: ${artifactBundleDefinition}`
|
|
||||||
)
|
|
||||||
const artifactBundles = JSON.parse(artifactBundleDefinition)
|
const artifactBundles = JSON.parse(artifactBundleDefinition)
|
||||||
return new Map(
|
return new Map(Array.from(artifactBundles, ([key, value]) => [key, path.resolve(this.gradleUserHome, value)]))
|
||||||
Array.from(artifactBundles, ([key, value]) => [
|
|
||||||
key,
|
|
||||||
path.resolve(this.gradleUserHome, value)
|
|
||||||
])
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async reportGradleUserHomeSize(label: string): Promise<void> {
|
private async reportGradleUserHomeSize(label: string): Promise<void> {
|
||||||
|
@ -233,15 +230,11 @@ export class GradleUserHomeCache extends AbstractCache {
|
||||||
if (!fs.existsSync(this.gradleUserHome)) {
|
if (!fs.existsSync(this.gradleUserHome)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const result = await exec.getExecOutput(
|
const result = await exec.getExecOutput('du', ['-h', '-c', '-t', '5M'], {
|
||||||
'du',
|
cwd: this.gradleUserHome,
|
||||||
['-h', '-c', '-t', '5M'],
|
silent: true,
|
||||||
{
|
ignoreReturnCode: true
|
||||||
cwd: this.gradleUserHome,
|
})
|
||||||
silent: true,
|
|
||||||
ignoreReturnCode: true
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
core.info(`Gradle User Home (directories >5M): ${label}`)
|
core.info(`Gradle User Home (directories >5M): ${label}`)
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,8 @@ import * as crypto from 'crypto'
|
||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
import * as fs from 'fs'
|
import * as fs from 'fs'
|
||||||
|
|
||||||
|
const CACHE_PROTOCOL_VERSION = 'v4-'
|
||||||
|
|
||||||
const CACHE_DISABLED_PARAMETER = 'cache-disabled'
|
const CACHE_DISABLED_PARAMETER = 'cache-disabled'
|
||||||
const CACHE_READONLY_PARAMETER = 'cache-read-only'
|
const CACHE_READONLY_PARAMETER = 'cache-read-only'
|
||||||
const JOB_CONTEXT_PARAMETER = 'workflow-job-context'
|
const JOB_CONTEXT_PARAMETER = 'workflow-job-context'
|
||||||
|
@ -25,7 +27,7 @@ export function isCacheDebuggingEnabled(): boolean {
|
||||||
|
|
||||||
export function getCacheKeyPrefix(): string {
|
export function getCacheKeyPrefix(): string {
|
||||||
// Prefix can be used to force change all cache keys (defaults to cache protocol version)
|
// Prefix can be used to force change all cache keys (defaults to cache protocol version)
|
||||||
return process.env[CACHE_PREFIX_VAR] || 'v3-'
|
return process.env[CACHE_PREFIX_VAR] || CACHE_PROTOCOL_VERSION
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateCacheKey(cacheName: string): CacheKey {
|
function generateCacheKey(cacheName: string): CacheKey {
|
||||||
|
@ -44,11 +46,7 @@ function generateCacheKey(cacheName: string): CacheKey {
|
||||||
// Exact match on Git SHA
|
// Exact match on Git SHA
|
||||||
const cacheKey = `${cacheKeyForJobContext}-${github.context.sha}`
|
const cacheKey = `${cacheKeyForJobContext}-${github.context.sha}`
|
||||||
|
|
||||||
return new CacheKey(cacheKey, [
|
return new CacheKey(cacheKey, [cacheKeyForJobContext, cacheKeyForJob, cacheKeyForOs])
|
||||||
cacheKeyForJobContext,
|
|
||||||
cacheKeyForJob,
|
|
||||||
cacheKeyForOs
|
|
||||||
])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function determineJobContext(): string {
|
function determineJobContext(): string {
|
||||||
|
@ -66,9 +64,7 @@ export function hashStrings(values: string[]): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hashFileNames(fileNames: string[]): string {
|
export function hashFileNames(fileNames: string[]): string {
|
||||||
return hashStrings(
|
return hashStrings(fileNames.map(x => x.replace(new RegExp(`\\${path.sep}`, 'g'), '/')))
|
||||||
fileNames.map(x => x.replace(new RegExp(`\\${path.sep}`, 'g'), '/'))
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -109,6 +105,48 @@ class CacheKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class CachingReport {
|
||||||
|
cacheEntryReports: CacheEntryReport[] = []
|
||||||
|
|
||||||
|
get fullyRestored(): boolean {
|
||||||
|
return this.cacheEntryReports.every(x => !x.wasRequestedButNotRestored())
|
||||||
|
}
|
||||||
|
|
||||||
|
addEntryReport(name: string): CacheEntryReport {
|
||||||
|
const report = new CacheEntryReport(name)
|
||||||
|
this.cacheEntryReports.push(report)
|
||||||
|
return report
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class CacheEntryReport {
|
||||||
|
entryName: string
|
||||||
|
requestedKey: string | undefined
|
||||||
|
requestedRestoreKeys: string[] | undefined
|
||||||
|
restoredKey: string | undefined
|
||||||
|
restoredSize: number | undefined
|
||||||
|
|
||||||
|
savedKey: string | undefined
|
||||||
|
savedSize: number | undefined
|
||||||
|
|
||||||
|
constructor(entryName: string) {
|
||||||
|
this.entryName = entryName
|
||||||
|
}
|
||||||
|
|
||||||
|
wasRequestedButNotRestored(): boolean {
|
||||||
|
return this.requestedKey !== undefined && this.restoredKey === undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
markRequested(key: string, restoreKeys: string[] = []): void {
|
||||||
|
this.requestedKey = key
|
||||||
|
this.requestedRestoreKeys = restoreKeys
|
||||||
|
}
|
||||||
|
|
||||||
|
markRestored(key: string): void {
|
||||||
|
this.restoredKey = key
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export abstract class AbstractCache {
|
export abstract class AbstractCache {
|
||||||
private cacheName: string
|
private cacheName: string
|
||||||
private cacheDescription: string
|
private cacheDescription: string
|
||||||
|
@ -125,17 +163,15 @@ export abstract class AbstractCache {
|
||||||
this.cacheDebuggingEnabled = isCacheDebuggingEnabled()
|
this.cacheDebuggingEnabled = isCacheDebuggingEnabled()
|
||||||
}
|
}
|
||||||
|
|
||||||
async restore(): Promise<void> {
|
async restore(report: CachingReport): Promise<void> {
|
||||||
if (this.cacheOutputExists()) {
|
if (this.cacheOutputExists()) {
|
||||||
core.info(
|
core.info(`${this.cacheDescription} already exists. Not restoring from cache.`)
|
||||||
`${this.cacheDescription} already exists. Not restoring from cache.`
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const cacheKey = generateCacheKey(this.cacheName)
|
const cacheKey = this.prepareCacheKey()
|
||||||
|
const entryReport = report.addEntryReport(this.cacheName)
|
||||||
core.saveState(this.cacheKeyStateKey, cacheKey.key)
|
entryReport.markRequested(cacheKey.key, cacheKey.restoreKeys)
|
||||||
|
|
||||||
this.debug(
|
this.debug(
|
||||||
`Requesting ${this.cacheDescription} with
|
`Requesting ${this.cacheDescription} with
|
||||||
|
@ -143,34 +179,29 @@ export abstract class AbstractCache {
|
||||||
restoreKeys:[${cacheKey.restoreKeys}]`
|
restoreKeys:[${cacheKey.restoreKeys}]`
|
||||||
)
|
)
|
||||||
|
|
||||||
const cacheResult = await this.restoreCache(
|
const cacheResult = await this.restoreCache(this.getCachePath(), cacheKey.key, cacheKey.restoreKeys)
|
||||||
this.getCachePath(),
|
|
||||||
cacheKey.key,
|
|
||||||
cacheKey.restoreKeys
|
|
||||||
)
|
|
||||||
|
|
||||||
if (!cacheResult) {
|
if (!cacheResult) {
|
||||||
core.info(
|
core.info(`${this.cacheDescription} cache not found. Will start with empty.`)
|
||||||
`${this.cacheDescription} cache not found. Will start with empty.`
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
core.saveState(this.cacheResultStateKey, cacheResult)
|
core.saveState(this.cacheResultStateKey, cacheResult)
|
||||||
|
entryReport.markRestored(cacheResult)
|
||||||
core.info(
|
core.info(`Restored ${this.cacheDescription} from cache key: ${cacheResult}`)
|
||||||
`Restored ${this.cacheDescription} from cache key: ${cacheResult}`
|
|
||||||
)
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.afterRestore()
|
await this.afterRestore(report)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
core.warning(
|
core.warning(`Restore ${this.cacheDescription} failed in 'afterRestore': ${error}`)
|
||||||
`Restore ${this.cacheDescription} failed in 'afterRestore': ${error}`
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return
|
prepareCacheKey(): CacheKey {
|
||||||
|
const cacheKey = generateCacheKey(this.cacheName)
|
||||||
|
|
||||||
|
core.saveState(this.cacheKeyStateKey, cacheKey.key)
|
||||||
|
return cacheKey
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async restoreCache(
|
protected async restoreCache(
|
||||||
|
@ -179,11 +210,7 @@ export abstract class AbstractCache {
|
||||||
cacheRestoreKeys: string[] = []
|
cacheRestoreKeys: string[] = []
|
||||||
): Promise<string | undefined> {
|
): Promise<string | undefined> {
|
||||||
try {
|
try {
|
||||||
return await cache.restoreCache(
|
return await cache.restoreCache(cachePath, cacheKey, cacheRestoreKeys)
|
||||||
cachePath,
|
|
||||||
cacheKey,
|
|
||||||
cacheRestoreKeys
|
|
||||||
)
|
|
||||||
} 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
|
||||||
|
@ -195,7 +222,7 @@ export abstract class AbstractCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async afterRestore(): Promise<void> {}
|
protected async afterRestore(_report: CachingReport): Promise<void> {}
|
||||||
|
|
||||||
async save(): Promise<void> {
|
async save(): Promise<void> {
|
||||||
if (!this.cacheOutputExists()) {
|
if (!this.cacheOutputExists()) {
|
||||||
|
@ -207,31 +234,23 @@ export abstract class AbstractCache {
|
||||||
const cacheResult = core.getState(this.cacheResultStateKey)
|
const cacheResult = core.getState(this.cacheResultStateKey)
|
||||||
|
|
||||||
if (!cacheKey) {
|
if (!cacheKey) {
|
||||||
this.debug(
|
this.debug(`${this.cacheDescription} existed prior to cache restore. Not saving.`)
|
||||||
`${this.cacheDescription} existed prior to cache restore. Not saving.`
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cacheResult && cacheKey === cacheResult) {
|
if (cacheResult && cacheKey === cacheResult) {
|
||||||
core.info(
|
core.info(`Cache hit occurred on the cache key ${cacheKey}, not saving cache.`)
|
||||||
`Cache hit occurred on the cache key ${cacheKey}, not saving cache.`
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.beforeSave()
|
await this.beforeSave()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
core.warning(
|
core.warning(`Save ${this.cacheDescription} failed in 'beforeSave': ${error}`)
|
||||||
`Save ${this.cacheDescription} failed in 'beforeSave': ${error}`
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
core.info(
|
core.info(`Caching ${this.cacheDescription} with cache key: ${cacheKey}`)
|
||||||
`Caching ${this.cacheDescription} with cache key: ${cacheKey}`
|
|
||||||
)
|
|
||||||
const cachePath = this.getCachePath()
|
const cachePath = this.getCachePath()
|
||||||
await this.saveCache(cachePath, cacheKey)
|
await this.saveCache(cachePath, cacheKey)
|
||||||
|
|
||||||
|
@ -240,10 +259,7 @@ export abstract class AbstractCache {
|
||||||
|
|
||||||
protected async beforeSave(): Promise<void> {}
|
protected async beforeSave(): Promise<void> {}
|
||||||
|
|
||||||
protected async saveCache(
|
protected async saveCache(cachePath: string[], cacheKey: string): Promise<void> {
|
||||||
cachePath: string[],
|
|
||||||
cacheKey: string
|
|
||||||
): Promise<void> {
|
|
||||||
try {
|
try {
|
||||||
await cache.saveCache(cachePath, cacheKey)
|
await cache.saveCache(cachePath, cacheKey)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
@ -1,32 +1,37 @@
|
||||||
import {GradleUserHomeCache} from './cache-gradle-user-home'
|
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 {CachingReport, isCacheDisabled, isCacheReadOnly} from './cache-utils'
|
||||||
|
|
||||||
const BUILD_ROOT_DIR = 'BUILD_ROOT_DIR'
|
const BUILD_ROOT_DIR = 'BUILD_ROOT_DIR'
|
||||||
|
|
||||||
export async function restore(buildRootDirectory: string): Promise<void> {
|
export async function restore(buildRootDirectory: string): Promise<void> {
|
||||||
if (isCacheDisabled()) {
|
if (isCacheDisabled()) {
|
||||||
core.info(
|
core.info('Cache is disabled: will not restore state from previous builds.')
|
||||||
'Cache is disabled: will not restore state from previous builds.'
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
await core.group('Restore Gradle state from cache', async () => {
|
await core.group('Restore Gradle state from cache', async () => {
|
||||||
core.saveState(BUILD_ROOT_DIR, buildRootDirectory)
|
core.saveState(BUILD_ROOT_DIR, buildRootDirectory)
|
||||||
return Promise.all([
|
|
||||||
new GradleUserHomeCache(buildRootDirectory).restore(),
|
const cachingReport = new CachingReport()
|
||||||
new ProjectDotGradleCache(buildRootDirectory).restore()
|
|
||||||
])
|
await new GradleUserHomeCache(buildRootDirectory).restore(cachingReport)
|
||||||
|
|
||||||
|
const projectDotGradleCache = new ProjectDotGradleCache(buildRootDirectory)
|
||||||
|
if (cachingReport.fullyRestored) {
|
||||||
|
// Only restore the configuration-cache if the Gradle Home is fully restored
|
||||||
|
await projectDotGradleCache.restore(cachingReport)
|
||||||
|
} else {
|
||||||
|
// Otherwise, prepare the cache key for later save()
|
||||||
|
projectDotGradleCache.prepareCacheKey()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function save(): Promise<void> {
|
export async function save(): Promise<void> {
|
||||||
if (isCacheReadOnly()) {
|
if (isCacheReadOnly()) {
|
||||||
core.info(
|
core.info('Cache is read-only: will not save state for use in subsequent builds.')
|
||||||
'Cache is read-only: will not save state for use in subsequent builds.'
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,7 @@ import fs from 'fs'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import {writeInitScript} from './build-scan-capture'
|
import {writeInitScript} from './build-scan-capture'
|
||||||
|
|
||||||
export async function execute(
|
export async function execute(executable: string, root: string, args: string[]): Promise<BuildResult> {
|
||||||
executable: string,
|
|
||||||
root: string,
|
|
||||||
args: string[]
|
|
||||||
): Promise<BuildResult> {
|
|
||||||
let buildScanUrl: string | undefined
|
let buildScanUrl: string | undefined
|
||||||
|
|
||||||
// TODO: instead of running with no-daemon, run `--stop` in post action.
|
// TODO: instead of running with no-daemon, run `--stop` in post action.
|
||||||
|
|
|
@ -17,10 +17,7 @@ export function locateGradleWrapperScript(buildRootDirectory: string): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
function validateGradleWrapper(buildRootDirectory: string): void {
|
function validateGradleWrapper(buildRootDirectory: string): void {
|
||||||
const wrapperProperties = path.resolve(
|
const wrapperProperties = path.resolve(buildRootDirectory, 'gradle/wrapper/gradle-wrapper.properties')
|
||||||
buildRootDirectory,
|
|
||||||
'gradle/wrapper/gradle-wrapper.properties'
|
|
||||||
)
|
|
||||||
if (!fs.existsSync(wrapperProperties)) {
|
if (!fs.existsSync(wrapperProperties)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Cannot locate a Gradle wrapper properties file at '${wrapperProperties}'. Specify 'gradle-version' or 'gradle-executable' for projects without Gradle wrapper configured.`
|
`Cannot locate a Gradle wrapper properties file at '${wrapperProperties}'. Specify 'gradle-version' or 'gradle-executable' for projects without Gradle wrapper configured.`
|
||||||
|
|
18
src/main.ts
18
src/main.ts
|
@ -18,10 +18,7 @@ export async function run(): Promise<void> {
|
||||||
const args: string[] = parseCommandLineArguments()
|
const args: string[] = parseCommandLineArguments()
|
||||||
|
|
||||||
const result = await execution.execute(
|
const result = await execution.execute(
|
||||||
await resolveGradleExecutable(
|
await resolveGradleExecutable(workspaceDirectory, buildRootDirectory),
|
||||||
workspaceDirectory,
|
|
||||||
buildRootDirectory
|
|
||||||
),
|
|
||||||
buildRootDirectory,
|
buildRootDirectory,
|
||||||
args
|
args
|
||||||
)
|
)
|
||||||
|
@ -34,9 +31,7 @@ export async function run(): Promise<void> {
|
||||||
if (result.buildScanUrl) {
|
if (result.buildScanUrl) {
|
||||||
core.setFailed(`Gradle build failed: ${result.buildScanUrl}`)
|
core.setFailed(`Gradle build failed: ${result.buildScanUrl}`)
|
||||||
} else {
|
} else {
|
||||||
core.setFailed(
|
core.setFailed(`Gradle build failed: process exited with status ${result.status}`)
|
||||||
`Gradle build failed: process exited with status ${result.status}`
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (result.buildScanUrl) {
|
if (result.buildScanUrl) {
|
||||||
|
@ -53,10 +48,7 @@ export async function run(): Promise<void> {
|
||||||
|
|
||||||
run()
|
run()
|
||||||
|
|
||||||
async function resolveGradleExecutable(
|
async function resolveGradleExecutable(workspaceDirectory: string, buildRootDirectory: string): Promise<string> {
|
||||||
workspaceDirectory: string,
|
|
||||||
buildRootDirectory: string
|
|
||||||
): Promise<string> {
|
|
||||||
const gradleVersion = core.getInput('gradle-version')
|
const gradleVersion = core.getInput('gradle-version')
|
||||||
if (gradleVersion !== '' && gradleVersion !== 'wrapper') {
|
if (gradleVersion !== '' && gradleVersion !== 'wrapper') {
|
||||||
return path.resolve(await provision.gradleVersion(gradleVersion))
|
return path.resolve(await provision.gradleVersion(gradleVersion))
|
||||||
|
@ -73,9 +65,7 @@ async function resolveGradleExecutable(
|
||||||
function resolveBuildRootDirectory(baseDirectory: string): string {
|
function resolveBuildRootDirectory(baseDirectory: string): string {
|
||||||
const buildRootDirectory = core.getInput('build-root-directory')
|
const buildRootDirectory = core.getInput('build-root-directory')
|
||||||
const resolvedBuildRootDirectory =
|
const resolvedBuildRootDirectory =
|
||||||
buildRootDirectory === ''
|
buildRootDirectory === '' ? path.resolve(baseDirectory) : path.resolve(baseDirectory, buildRootDirectory)
|
||||||
? path.resolve(baseDirectory)
|
|
||||||
: path.resolve(baseDirectory, buildRootDirectory)
|
|
||||||
return resolvedBuildRootDirectory
|
return resolvedBuildRootDirectory
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,9 +19,7 @@ export async function gradleVersion(version: string): Promise<string> {
|
||||||
case 'current':
|
case 'current':
|
||||||
return gradleCurrent()
|
return gradleCurrent()
|
||||||
case 'rc':
|
case 'rc':
|
||||||
core.warning(
|
core.warning(`Specifying gradle-version 'rc' has been deprecated. Use 'release-candidate' instead.`)
|
||||||
`Specifying gradle-version 'rc' has been deprecated. Use 'release-candidate' instead.`
|
|
||||||
)
|
|
||||||
return gradleReleaseCandidate()
|
return gradleReleaseCandidate()
|
||||||
case 'release-candidate':
|
case 'release-candidate':
|
||||||
return gradleReleaseCandidate()
|
return gradleReleaseCandidate()
|
||||||
|
@ -35,16 +33,12 @@ export async function gradleVersion(version: string): Promise<string> {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function gradleCurrent(): Promise<string> {
|
async function gradleCurrent(): Promise<string> {
|
||||||
const versionInfo = await gradleVersionDeclaration(
|
const versionInfo = await gradleVersionDeclaration(`${gradleVersionsBaseUrl}/current`)
|
||||||
`${gradleVersionsBaseUrl}/current`
|
|
||||||
)
|
|
||||||
return provisionGradle(versionInfo)
|
return provisionGradle(versionInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function gradleReleaseCandidate(): Promise<string> {
|
async function gradleReleaseCandidate(): Promise<string> {
|
||||||
const versionInfo = await gradleVersionDeclaration(
|
const versionInfo = await gradleVersionDeclaration(`${gradleVersionsBaseUrl}/release-candidate`)
|
||||||
`${gradleVersionsBaseUrl}/release-candidate`
|
|
||||||
)
|
|
||||||
if (versionInfo && versionInfo.version && versionInfo.downloadUrl) {
|
if (versionInfo && versionInfo.version && versionInfo.downloadUrl) {
|
||||||
return provisionGradle(versionInfo)
|
return provisionGradle(versionInfo)
|
||||||
}
|
}
|
||||||
|
@ -53,16 +47,12 @@ async function gradleReleaseCandidate(): Promise<string> {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function gradleNightly(): Promise<string> {
|
async function gradleNightly(): Promise<string> {
|
||||||
const versionInfo = await gradleVersionDeclaration(
|
const versionInfo = await gradleVersionDeclaration(`${gradleVersionsBaseUrl}/nightly`)
|
||||||
`${gradleVersionsBaseUrl}/nightly`
|
|
||||||
)
|
|
||||||
return provisionGradle(versionInfo)
|
return provisionGradle(versionInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function gradleReleaseNightly(): Promise<string> {
|
async function gradleReleaseNightly(): Promise<string> {
|
||||||
const versionInfo = await gradleVersionDeclaration(
|
const versionInfo = await gradleVersionDeclaration(`${gradleVersionsBaseUrl}/release-nightly`)
|
||||||
`${gradleVersionsBaseUrl}/release-nightly`
|
|
||||||
)
|
|
||||||
return provisionGradle(versionInfo)
|
return provisionGradle(versionInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,34 +64,24 @@ async function gradle(version: string): Promise<string> {
|
||||||
return provisionGradle(versionInfo)
|
return provisionGradle(versionInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function gradleVersionDeclaration(
|
async function gradleVersionDeclaration(url: string): Promise<GradleVersionInfo> {
|
||||||
url: string
|
|
||||||
): Promise<GradleVersionInfo> {
|
|
||||||
return await httpGetGradleVersion(url)
|
return await httpGetGradleVersion(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function findGradleVersionDeclaration(
|
async function findGradleVersionDeclaration(version: string): Promise<GradleVersionInfo | undefined> {
|
||||||
version: string
|
const gradleVersions = await httpGetGradleVersions(`${gradleVersionsBaseUrl}/all`)
|
||||||
): Promise<GradleVersionInfo | undefined> {
|
|
||||||
const gradleVersions = await httpGetGradleVersions(
|
|
||||||
`${gradleVersionsBaseUrl}/all`
|
|
||||||
)
|
|
||||||
return gradleVersions.find((entry: GradleVersionInfo) => {
|
return gradleVersions.find((entry: GradleVersionInfo) => {
|
||||||
return entry.version === version
|
return entry.version === version
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async function provisionGradle(
|
async function provisionGradle(versionInfo: GradleVersionInfo): Promise<string> {
|
||||||
versionInfo: GradleVersionInfo
|
|
||||||
): Promise<string> {
|
|
||||||
return core.group(`Provision Gradle ${versionInfo.version}`, async () => {
|
return core.group(`Provision Gradle ${versionInfo.version}`, async () => {
|
||||||
return locateGradleAndDownloadIfRequired(versionInfo)
|
return locateGradleAndDownloadIfRequired(versionInfo)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async function locateGradleAndDownloadIfRequired(
|
async function locateGradleAndDownloadIfRequired(versionInfo: GradleVersionInfo): Promise<string> {
|
||||||
versionInfo: GradleVersionInfo
|
|
||||||
): Promise<string> {
|
|
||||||
const installsDir = path.join(os.homedir(), 'gradle-installations/installs')
|
const installsDir = path.join(os.homedir(), 'gradle-installations/installs')
|
||||||
const installDir = path.join(installsDir, `gradle-${versionInfo.version}`)
|
const installDir = path.join(installsDir, `gradle-${versionInfo.version}`)
|
||||||
if (fs.existsSync(installDir)) {
|
if (fs.existsSync(installDir)) {
|
||||||
|
@ -120,13 +100,8 @@ async function locateGradleAndDownloadIfRequired(
|
||||||
return executable
|
return executable
|
||||||
}
|
}
|
||||||
|
|
||||||
async function downloadAndCacheGradleDistribution(
|
async function downloadAndCacheGradleDistribution(versionInfo: GradleVersionInfo): Promise<string> {
|
||||||
versionInfo: GradleVersionInfo
|
const downloadPath = path.join(os.homedir(), `gradle-installations/downloads/gradle-${versionInfo.version}-bin.zip`)
|
||||||
): Promise<string> {
|
|
||||||
const downloadPath = path.join(
|
|
||||||
os.homedir(),
|
|
||||||
`gradle-installations/downloads/gradle-${versionInfo.version}-bin.zip`
|
|
||||||
)
|
|
||||||
|
|
||||||
if (isCacheDisabled()) {
|
if (isCacheDisabled()) {
|
||||||
await downloadGradleDistribution(versionInfo, downloadPath)
|
await downloadGradleDistribution(versionInfo, downloadPath)
|
||||||
|
@ -136,14 +111,10 @@ async function downloadAndCacheGradleDistribution(
|
||||||
const cacheKey = `gradle-${versionInfo.version}`
|
const cacheKey = `gradle-${versionInfo.version}`
|
||||||
const restoreKey = await cache.restoreCache([downloadPath], cacheKey)
|
const restoreKey = await cache.restoreCache([downloadPath], cacheKey)
|
||||||
if (restoreKey) {
|
if (restoreKey) {
|
||||||
core.info(
|
core.info(`Restored Gradle distribution ${cacheKey} from cache to ${downloadPath}`)
|
||||||
`Restored Gradle distribution ${cacheKey} from cache to ${downloadPath}`
|
|
||||||
)
|
|
||||||
return downloadPath
|
return downloadPath
|
||||||
}
|
}
|
||||||
core.info(
|
core.info(`Gradle distribution ${versionInfo.version} not found in cache. Will download.`)
|
||||||
`Gradle distribution ${versionInfo.version} not found in cache. Will download.`
|
|
||||||
)
|
|
||||||
await downloadGradleDistribution(versionInfo, downloadPath)
|
await downloadGradleDistribution(versionInfo, downloadPath)
|
||||||
|
|
||||||
if (!isCacheReadOnly()) {
|
if (!isCacheReadOnly()) {
|
||||||
|
@ -151,10 +122,7 @@ async function downloadAndCacheGradleDistribution(
|
||||||
await cache.saveCache([downloadPath], cacheKey)
|
await cache.saveCache([downloadPath], cacheKey)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Fail on validation errors or non-errors (the latter to keep Typescript happy)
|
// Fail on validation errors or non-errors (the latter to keep Typescript happy)
|
||||||
if (
|
if (error instanceof cache.ValidationError || !(error instanceof Error)) {
|
||||||
error instanceof cache.ValidationError ||
|
|
||||||
!(error instanceof Error)
|
|
||||||
) {
|
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
core.warning(error.message)
|
core.warning(error.message)
|
||||||
|
@ -163,16 +131,9 @@ async function downloadAndCacheGradleDistribution(
|
||||||
return downloadPath
|
return downloadPath
|
||||||
}
|
}
|
||||||
|
|
||||||
async function downloadGradleDistribution(
|
async function downloadGradleDistribution(versionInfo: GradleVersionInfo, downloadPath: string): Promise<void> {
|
||||||
versionInfo: GradleVersionInfo,
|
|
||||||
downloadPath: string
|
|
||||||
): Promise<void> {
|
|
||||||
await toolCache.downloadTool(versionInfo.downloadUrl, downloadPath)
|
await toolCache.downloadTool(versionInfo.downloadUrl, downloadPath)
|
||||||
core.info(
|
core.info(`Downloaded ${versionInfo.downloadUrl} to ${downloadPath} (size ${fs.statSync(downloadPath).size})`)
|
||||||
`Downloaded ${versionInfo.downloadUrl} to ${downloadPath} (size ${
|
|
||||||
fs.statSync(downloadPath).size
|
|
||||||
})`
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function executableFrom(installDir: string): string {
|
function executableFrom(installDir: string): string {
|
||||||
|
@ -183,9 +144,7 @@ async function httpGetGradleVersion(url: string): Promise<GradleVersionInfo> {
|
||||||
return JSON.parse(await httpGetString(url))
|
return JSON.parse(await httpGetString(url))
|
||||||
}
|
}
|
||||||
|
|
||||||
async function httpGetGradleVersions(
|
async function httpGetGradleVersions(url: string): Promise<GradleVersionInfo[]> {
|
||||||
url: string
|
|
||||||
): Promise<GradleVersionInfo[]> {
|
|
||||||
return JSON.parse(await httpGetString(url))
|
return JSON.parse(await httpGetString(url))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue