mirror of
https://github.com/gradle/gradle-build-action.git
synced 2025-10-20 15:18:56 +08:00
Compare commits
24 Commits
v2.0-beta.
...
v2.0-beta.
Author | SHA1 | Date | |
---|---|---|---|
|
a94b9252d5 | ||
|
25672bf196 | ||
|
cb6a0acca4 | ||
|
aa2ed2e033 | ||
|
263f84178a | ||
|
0eb5996567 | ||
|
fe55bf4667 | ||
|
709ded51a5 | ||
|
8b1f1a3817 | ||
|
7abf13ee48 | ||
|
da64595ccc | ||
|
29b14c7fca | ||
|
d1ab42cddf | ||
|
422726cec5 | ||
|
4bc52c85c3 | ||
|
e7b5fd0b28 | ||
|
53ccc3e0d7 | ||
|
8ab7c9d8dd | ||
|
0cf00ed767 | ||
|
aedc5fc8f9 | ||
|
78e25cd233 | ||
|
29894757f3 | ||
|
5328161026 | ||
|
4968d2280b |
27
.github/workflows/integTest-action-inputs.yml
vendored
Normal file
27
.github/workflows/integTest-action-inputs.yml
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
name: Test different action inputs
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
env:
|
||||||
|
CACHE_KEY_PREFIX: ${{github.workflow}}#${{github.run_number}}-
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
action-inputs:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout sources
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Invoke with multi-line arguments
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
build-root-directory: __tests__/samples/groovy-dsl
|
||||||
|
arguments: |
|
||||||
|
--configuration-cache
|
||||||
|
--build-cache
|
||||||
|
-DsystemProperty=FOO
|
||||||
|
-PgradleProperty=BAR
|
||||||
|
test
|
||||||
|
jar
|
16
.github/workflows/integTest-caching.yml
vendored
16
.github/workflows/integTest-caching.yml
vendored
@@ -82,3 +82,19 @@ jobs:
|
|||||||
build-root-directory: __tests__/samples/groovy-dsl
|
build-root-directory: __tests__/samples/groovy-dsl
|
||||||
arguments: test --configuration-cache
|
arguments: test --configuration-cache
|
||||||
cache-read-only: true
|
cache-read-only: true
|
||||||
|
|
||||||
|
# Check that the build can run when no bundles are restored
|
||||||
|
no-bundles-restored:
|
||||||
|
needs: seed-build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
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
|
||||||
|
cache-artifact-bundles: '[]'
|
||||||
|
cache-read-only: true
|
||||||
|
|
||||||
|
2
.github/workflows/integTest-execution.yml
vendored
2
.github/workflows/integTest-execution.yml
vendored
@@ -33,7 +33,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
gradle-version: release-candidate
|
gradle-version: release-candidate
|
||||||
build-root-directory: __tests__/samples/no-wrapper
|
build-root-directory: __tests__/samples/no-wrapper
|
||||||
arguments: help -DgradleVersionCheck=7.2
|
arguments: help
|
||||||
- name: Test use defined Gradle executable
|
- name: Test use defined Gradle executable
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
|
19
README.md
19
README.md
@@ -47,6 +47,7 @@ Each invocation will start its run with the filesystem state remaining from the
|
|||||||
### Command-line arguments
|
### Command-line arguments
|
||||||
|
|
||||||
The `arguments` input can used to pass arbitrary arguments to the `gradle` command line.
|
The `arguments` input can used to pass arbitrary arguments to the `gradle` command line.
|
||||||
|
Arguments can be supplied in a single line, or as a multi-line input.
|
||||||
|
|
||||||
Here are some valid examples:
|
Here are some valid examples:
|
||||||
```yaml
|
```yaml
|
||||||
@@ -54,8 +55,11 @@ arguments: build
|
|||||||
arguments: check --scan
|
arguments: check --scan
|
||||||
arguments: some arbitrary tasks
|
arguments: some arbitrary tasks
|
||||||
arguments: build -PgradleProperty=foo
|
arguments: build -PgradleProperty=foo
|
||||||
arguments: build -DsystemProperty=bar
|
arguments: |
|
||||||
....
|
build
|
||||||
|
--scan
|
||||||
|
-PgradleProperty=foo
|
||||||
|
-DsystemProperty=bar
|
||||||
```
|
```
|
||||||
|
|
||||||
See `gradle --help` for more information.
|
See `gradle --help` for more information.
|
||||||
@@ -182,6 +186,17 @@ You can enable read-only caching for any of the caches as follows:
|
|||||||
cache-read-only: true
|
cache-read-only: true
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Cache debugging
|
||||||
|
|
||||||
|
It is possible to enable additional debug logging for cache operations. You do via the `CACHE_DEBUG_ENABLED` environment variable:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
env:
|
||||||
|
CACHE_DEBUG_ENABLED: true
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that this setting will also prevent certain cache operations from running in parallel, further assisting with debugging.
|
||||||
|
|
||||||
## Build scans
|
## Build scans
|
||||||
|
|
||||||
If your build publishes a [build scan](https://gradle.com/build-scans/) the `gradle-build-action` action will:
|
If your build publishes a [build scan](https://gradle.com/build-scans/) the `gradle-build-action` action will:
|
||||||
|
12
action.yml
12
action.yml
@@ -14,7 +14,7 @@ inputs:
|
|||||||
description: Path to the root directory of the build
|
description: Path to the root directory of the build
|
||||||
required: false
|
required: false
|
||||||
arguments:
|
arguments:
|
||||||
description: Gradle command line arguments, see gradle --help
|
description: Gradle command line arguments (supports multi-line input)
|
||||||
required: false
|
required: false
|
||||||
cache-disabled:
|
cache-disabled:
|
||||||
description: When 'true', all caching is disabled. No entries will be written to or read from the cache.
|
description: When 'true', all caching is disabled. No entries will be written to or read from the cache.
|
||||||
@@ -30,6 +30,16 @@ inputs:
|
|||||||
description: Used to uniquely identify the current job invocation. Defaults to the matrix values for this job; this should not be overridden by users.
|
description: Used to uniquely identify the current job invocation. Defaults to the matrix values for this job; this should not be overridden by users.
|
||||||
required: false
|
required: false
|
||||||
default: ${{ toJSON(matrix) }}
|
default: ${{ toJSON(matrix) }}
|
||||||
|
cache-artifact-bundles:
|
||||||
|
description: Names and patterns of artifact bundles to cache separately. For internal use only.
|
||||||
|
required: false
|
||||||
|
default: |
|
||||||
|
[
|
||||||
|
["generated-gradle-jars", "caches/*/generated-gradle-jars/*.jar"],
|
||||||
|
["wrapper-zips", "wrapper/dists/*/*/*.zip"],
|
||||||
|
["dependency-jars", "caches/modules-*/files-*/**/*.jar"],
|
||||||
|
["instrumented-jars", "caches/jars-*/*/"]
|
||||||
|
]
|
||||||
|
|
||||||
outputs:
|
outputs:
|
||||||
build-scan-url:
|
build-scan-url:
|
||||||
|
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
@@ -5,18 +5,16 @@ import * as core from '@actions/core'
|
|||||||
import * as glob from '@actions/glob'
|
import * as glob from '@actions/glob'
|
||||||
import * as exec from '@actions/exec'
|
import * as exec from '@actions/exec'
|
||||||
|
|
||||||
import {AbstractCache, hashFileNames} from './cache-utils'
|
import {
|
||||||
|
AbstractCache,
|
||||||
|
getCacheKeyPrefix,
|
||||||
|
hashFileNames,
|
||||||
|
tryDelete
|
||||||
|
} from './cache-utils'
|
||||||
|
|
||||||
// Which paths under Gradle User Home should be cached
|
// Which paths under Gradle User Home should be cached
|
||||||
const CACHE_PATH = ['caches', 'notifications']
|
const CACHE_PATH = ['caches', 'notifications']
|
||||||
|
|
||||||
const COMMON_ARTIFACT_CACHES = new Map([
|
|
||||||
['generated-gradle-jars', 'caches/*/generated-gradle-jars/*.jar'],
|
|
||||||
['wrapper-zips', 'wrapper/dists/*/*/*.zip'],
|
|
||||||
['dependency-jars', 'caches/modules-*/files-*/**/*.jar'],
|
|
||||||
['instrumented-jars', 'caches/jars-*/*/*.jar']
|
|
||||||
])
|
|
||||||
|
|
||||||
export class GradleUserHomeCache extends AbstractCache {
|
export class GradleUserHomeCache extends AbstractCache {
|
||||||
private gradleUserHome: string
|
private gradleUserHome: string
|
||||||
|
|
||||||
@@ -26,15 +24,15 @@ export class GradleUserHomeCache extends AbstractCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async afterRestore(): Promise<void> {
|
async afterRestore(): Promise<void> {
|
||||||
await this.reportCacheEntrySize('as restored from cache')
|
await this.reportGradleUserHomeSize('as restored from cache')
|
||||||
await this.restoreCommonArtifacts()
|
await this.restoreArtifactBundles()
|
||||||
await this.reportCacheEntrySize('after restoring common artifacts')
|
await this.reportGradleUserHomeSize('after restoring common artifacts')
|
||||||
}
|
}
|
||||||
|
|
||||||
private async restoreCommonArtifacts(): Promise<void> {
|
private async restoreArtifactBundles(): Promise<void> {
|
||||||
const processes: Promise<void>[] = []
|
const processes: Promise<void>[] = []
|
||||||
for (const [bundle, pattern] of this.getCommonArtifactPaths()) {
|
for (const [bundle, pattern] of this.getArtifactBundles()) {
|
||||||
const p = this.restoreCommonArtifactBundle(bundle, pattern)
|
const p = this.restoreArtifactBundle(bundle, pattern)
|
||||||
// Run sequentially when debugging enabled
|
// Run sequentially when debugging enabled
|
||||||
if (this.cacheDebuggingEnabled) {
|
if (this.cacheDebuggingEnabled) {
|
||||||
await p
|
await p
|
||||||
@@ -45,13 +43,13 @@ export class GradleUserHomeCache extends AbstractCache {
|
|||||||
await Promise.all(processes)
|
await Promise.all(processes)
|
||||||
}
|
}
|
||||||
|
|
||||||
private async restoreCommonArtifactBundle(
|
private async restoreArtifactBundle(
|
||||||
bundle: string,
|
bundle: string,
|
||||||
artifactPath: string
|
artifactPath: string
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const cacheMetaFile = this.getCacheMetaFile(bundle)
|
const bundleMetaFile = this.getBundleMetaFile(bundle)
|
||||||
if (fs.existsSync(cacheMetaFile)) {
|
if (fs.existsSync(bundleMetaFile)) {
|
||||||
const cacheKey = fs.readFileSync(cacheMetaFile, 'utf-8').trim()
|
const cacheKey = fs.readFileSync(bundleMetaFile, 'utf-8').trim()
|
||||||
const restoreKey = await this.restoreCache([artifactPath], cacheKey)
|
const restoreKey = await this.restoreCache([artifactPath], cacheKey)
|
||||||
if (restoreKey) {
|
if (restoreKey) {
|
||||||
core.info(
|
core.info(
|
||||||
@@ -59,17 +57,17 @@ export class GradleUserHomeCache extends AbstractCache {
|
|||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
this.debug(
|
this.debug(
|
||||||
`Failed to restore ${bundle} with key ${cacheKey} to ${artifactPath}`
|
`Did not restore ${bundle} with key ${cacheKey} to ${artifactPath}`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.debug(
|
this.debug(
|
||||||
`No metafile found to restore ${bundle}: ${cacheMetaFile}`
|
`No metafile found to restore ${bundle}: ${bundleMetaFile}`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private getCacheMetaFile(name: string): string {
|
private getBundleMetaFile(name: string): string {
|
||||||
return path.resolve(
|
return path.resolve(
|
||||||
this.gradleUserHome,
|
this.gradleUserHome,
|
||||||
'caches',
|
'caches',
|
||||||
@@ -77,47 +75,18 @@ export class GradleUserHomeCache extends AbstractCache {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private async reportCacheEntrySize(label: string): Promise<void> {
|
|
||||||
if (!this.cacheDebuggingEnabled) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (!fs.existsSync(this.gradleUserHome)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const result = await exec.getExecOutput(
|
|
||||||
'du',
|
|
||||||
['-h', '-c', '-t', '5M'],
|
|
||||||
{
|
|
||||||
cwd: this.gradleUserHome,
|
|
||||||
silent: true,
|
|
||||||
ignoreReturnCode: true
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
core.info(`Gradle User Home cache entry (directories >5M): ${label}`)
|
|
||||||
|
|
||||||
core.info(
|
|
||||||
result.stdout
|
|
||||||
.trimEnd()
|
|
||||||
.replace(/\t/g, ' ')
|
|
||||||
.split('\n')
|
|
||||||
.map(it => {
|
|
||||||
return ` ${it}`
|
|
||||||
})
|
|
||||||
.join('\n')
|
|
||||||
)
|
|
||||||
|
|
||||||
core.info('-----------------------')
|
|
||||||
}
|
|
||||||
|
|
||||||
async beforeSave(): Promise<void> {
|
async beforeSave(): Promise<void> {
|
||||||
await this.saveCommonArtifacts()
|
await this.reportGradleUserHomeSize('before saving common artifacts')
|
||||||
|
await this.saveArtifactBundles()
|
||||||
|
await this.reportGradleUserHomeSize(
|
||||||
|
'after saving common artifacts (./wrapper dir is not cached)'
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private async saveCommonArtifacts(): Promise<void> {
|
private async saveArtifactBundles(): Promise<void> {
|
||||||
const processes: Promise<void>[] = []
|
const processes: Promise<void>[] = []
|
||||||
for (const [bundle, pattern] of this.getCommonArtifactPaths()) {
|
for (const [bundle, pattern] of this.getArtifactBundles()) {
|
||||||
const p = this.saveCommonArtifactBundle(bundle, pattern)
|
const p = this.saveArtifactBundle(bundle, pattern)
|
||||||
// Run sequentially when debugging enabled
|
// Run sequentially when debugging enabled
|
||||||
if (this.cacheDebuggingEnabled) {
|
if (this.cacheDebuggingEnabled) {
|
||||||
await p
|
await p
|
||||||
@@ -128,28 +97,31 @@ export class GradleUserHomeCache extends AbstractCache {
|
|||||||
await Promise.all(processes)
|
await Promise.all(processes)
|
||||||
}
|
}
|
||||||
|
|
||||||
private async saveCommonArtifactBundle(
|
private async saveArtifactBundle(
|
||||||
bundle: string,
|
bundle: string,
|
||||||
artifactPath: string
|
artifactPath: string
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const cacheMetaFile = this.getCacheMetaFile(bundle)
|
const bundleMetaFile = this.getBundleMetaFile(bundle)
|
||||||
|
|
||||||
const globber = await glob.create(artifactPath)
|
const globber = await glob.create(artifactPath, {
|
||||||
const commonArtifactFiles = await globber.glob()
|
implicitDescendants: false,
|
||||||
|
followSymbolicLinks: false
|
||||||
|
})
|
||||||
|
const bundleFiles = await globber.glob()
|
||||||
|
|
||||||
// Handle no matching files
|
// Handle no matching files
|
||||||
if (commonArtifactFiles.length === 0) {
|
if (bundleFiles.length === 0) {
|
||||||
this.debug(`No files found to cache for ${bundle}`)
|
this.debug(`No files found to cache for ${bundle}`)
|
||||||
if (fs.existsSync(cacheMetaFile)) {
|
if (fs.existsSync(bundleMetaFile)) {
|
||||||
fs.unlinkSync(cacheMetaFile)
|
tryDelete(bundleMetaFile)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const previouslyRestoredKey = fs.existsSync(cacheMetaFile)
|
const previouslyRestoredKey = fs.existsSync(bundleMetaFile)
|
||||||
? fs.readFileSync(cacheMetaFile, 'utf-8').trim()
|
? fs.readFileSync(bundleMetaFile, 'utf-8').trim()
|
||||||
: ''
|
: ''
|
||||||
const cacheKey = this.createCacheKey(bundle, commonArtifactFiles)
|
const cacheKey = this.createCacheKey(bundle, bundleFiles)
|
||||||
|
|
||||||
if (previouslyRestoredKey === cacheKey) {
|
if (previouslyRestoredKey === cacheKey) {
|
||||||
this.debug(
|
this.debug(
|
||||||
@@ -159,22 +131,26 @@ export class GradleUserHomeCache extends AbstractCache {
|
|||||||
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)
|
||||||
|
|
||||||
this.debug(`Writing cache metafile: ${cacheMetaFile}`)
|
this.debug(`Writing cache metafile: ${bundleMetaFile}`)
|
||||||
fs.writeFileSync(cacheMetaFile, cacheKey)
|
fs.writeFileSync(bundleMetaFile, cacheKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const file of commonArtifactFiles) {
|
for (const file of bundleFiles) {
|
||||||
fs.unlinkSync(file)
|
tryDelete(file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected createCacheKey(bundle: string, files: string[]): string {
|
protected createCacheKey(bundle: string, files: string[]): string {
|
||||||
const cacheKeyPrefix = process.env['CACHE_KEY_PREFIX'] || ''
|
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(
|
||||||
|
`Generating cache key for ${bundle} from files: ${relativeFiles}`
|
||||||
|
)
|
||||||
|
|
||||||
return `${cacheKeyPrefix}${bundle}-${key}`
|
return `${cacheKeyPrefix}${bundle}-${key}`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,12 +173,50 @@ export class GradleUserHomeCache extends AbstractCache {
|
|||||||
return CACHE_PATH.map(x => path.resolve(this.gradleUserHome, x))
|
return CACHE_PATH.map(x => path.resolve(this.gradleUserHome, x))
|
||||||
}
|
}
|
||||||
|
|
||||||
private getCommonArtifactPaths(): Map<string, string> {
|
private getArtifactBundles(): Map<string, string> {
|
||||||
|
const artifactBundleDefinition = core.getInput('cache-artifact-bundles')
|
||||||
|
this.debug(
|
||||||
|
`Using artifact bundle definition: ${artifactBundleDefinition}`
|
||||||
|
)
|
||||||
|
const artifactBundles = JSON.parse(artifactBundleDefinition)
|
||||||
return new Map(
|
return new Map(
|
||||||
Array.from(COMMON_ARTIFACT_CACHES, ([key, value]) => [
|
Array.from(artifactBundles, ([key, value]) => [
|
||||||
key,
|
key,
|
||||||
path.resolve(this.gradleUserHome, value)
|
path.resolve(this.gradleUserHome, value)
|
||||||
])
|
])
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async reportGradleUserHomeSize(label: string): Promise<void> {
|
||||||
|
if (!this.cacheDebuggingEnabled) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!fs.existsSync(this.gradleUserHome)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const result = await exec.getExecOutput(
|
||||||
|
'du',
|
||||||
|
['-h', '-c', '-t', '5M'],
|
||||||
|
{
|
||||||
|
cwd: this.gradleUserHome,
|
||||||
|
silent: true,
|
||||||
|
ignoreReturnCode: true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
core.info(`Gradle User Home (directories >5M): ${label}`)
|
||||||
|
|
||||||
|
core.info(
|
||||||
|
result.stdout
|
||||||
|
.trimEnd()
|
||||||
|
.replace(/\t/g, ' ')
|
||||||
|
.split('\n')
|
||||||
|
.map(it => {
|
||||||
|
return ` ${it}`
|
||||||
|
})
|
||||||
|
.join('\n')
|
||||||
|
)
|
||||||
|
|
||||||
|
core.info('-----------------------')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,6 +3,7 @@ import * as cache from '@actions/cache'
|
|||||||
import * as github from '@actions/github'
|
import * as github from '@actions/github'
|
||||||
import * as crypto from 'crypto'
|
import * as crypto from 'crypto'
|
||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
|
import * as fs from 'fs'
|
||||||
|
|
||||||
export function isCacheDisabled(): boolean {
|
export function isCacheDisabled(): boolean {
|
||||||
return core.getBooleanInput('cache-disabled')
|
return core.getBooleanInput('cache-disabled')
|
||||||
@@ -16,9 +17,13 @@ export function isCacheDebuggingEnabled(): boolean {
|
|||||||
return process.env['CACHE_DEBUG_ENABLED'] ? true : false
|
return process.env['CACHE_DEBUG_ENABLED'] ? true : false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getCacheKeyPrefix(): string {
|
||||||
|
// Prefix can be used to force change all cache keys (defaults to cache protocol version)
|
||||||
|
return process.env['CACHE_KEY_PREFIX'] || 'v2-'
|
||||||
|
}
|
||||||
|
|
||||||
function generateCacheKey(cacheName: string): CacheKey {
|
function generateCacheKey(cacheName: string): CacheKey {
|
||||||
// Prefix can be used to force change all cache keys
|
const cacheKeyPrefix = getCacheKeyPrefix()
|
||||||
const cacheKeyPrefix = process.env['CACHE_KEY_PREFIX'] || ''
|
|
||||||
|
|
||||||
// At the most general level, share caches for all executions on the same OS
|
// At the most general level, share caches for all executions on the same OS
|
||||||
const runnerOs = process.env['RUNNER_OS'] || ''
|
const runnerOs = process.env['RUNNER_OS'] || ''
|
||||||
@@ -60,6 +65,34 @@ export function hashFileNames(fileNames: string[]): string {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to delete a file or directory, waiting to allow locks to be released
|
||||||
|
*/
|
||||||
|
export async function tryDelete(file: string): Promise<void> {
|
||||||
|
const stat = fs.lstatSync(file)
|
||||||
|
for (let count = 0; count < 3; count++) {
|
||||||
|
try {
|
||||||
|
if (stat.isDirectory()) {
|
||||||
|
fs.rmdirSync(file, {recursive: true})
|
||||||
|
} else {
|
||||||
|
fs.unlinkSync(file)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
} catch (error) {
|
||||||
|
if (count === 2) {
|
||||||
|
throw error
|
||||||
|
} else {
|
||||||
|
core.warning(String(error))
|
||||||
|
await delay(1000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function delay(ms: number): Promise<void> {
|
||||||
|
return new Promise(resolve => setTimeout(resolve, ms))
|
||||||
|
}
|
||||||
|
|
||||||
class CacheKey {
|
class CacheKey {
|
||||||
key: string
|
key: string
|
||||||
restoreKeys: string[]
|
restoreKeys: string[]
|
||||||
@@ -98,6 +131,12 @@ export abstract class AbstractCache {
|
|||||||
|
|
||||||
core.saveState(this.cacheKeyStateKey, cacheKey.key)
|
core.saveState(this.cacheKeyStateKey, cacheKey.key)
|
||||||
|
|
||||||
|
this.debug(
|
||||||
|
`Requesting ${this.cacheDescription} with
|
||||||
|
key:${cacheKey.key}
|
||||||
|
restoreKeys:[${cacheKey.restoreKeys}]`
|
||||||
|
)
|
||||||
|
|
||||||
const cacheResult = await this.restoreCache(
|
const cacheResult = await this.restoreCache(
|
||||||
this.getCachePath(),
|
this.getCachePath(),
|
||||||
cacheKey.key,
|
cacheKey.key,
|
||||||
@@ -117,7 +156,13 @@ export abstract class AbstractCache {
|
|||||||
`Restored ${this.cacheDescription} from cache key: ${cacheResult}`
|
`Restored ${this.cacheDescription} from cache key: ${cacheResult}`
|
||||||
)
|
)
|
||||||
|
|
||||||
await this.afterRestore()
|
try {
|
||||||
|
await this.afterRestore()
|
||||||
|
} catch (error) {
|
||||||
|
core.warning(
|
||||||
|
`Restore ${this.cacheDescription} failed in 'afterRestore': ${error}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -169,7 +214,14 @@ export abstract class AbstractCache {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.beforeSave()
|
try {
|
||||||
|
await this.beforeSave()
|
||||||
|
} catch (error) {
|
||||||
|
core.warning(
|
||||||
|
`Save ${this.cacheDescription} failed in 'beforeSave': ${error}`
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
core.info(
|
core.info(
|
||||||
`Caching ${this.cacheDescription} with cache key: ${cacheKey}`
|
`Caching ${this.cacheDescription} with cache key: ${cacheKey}`
|
||||||
|
@@ -7,7 +7,9 @@ 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.debug('Cache read disabled')
|
core.info(
|
||||||
|
'Cache is disabled: will not restore state from previous builds.'
|
||||||
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -22,7 +24,9 @@ export async function restore(buildRootDirectory: string): Promise<void> {
|
|||||||
|
|
||||||
export async function save(): Promise<void> {
|
export async function save(): Promise<void> {
|
||||||
if (isCacheReadOnly()) {
|
if (isCacheReadOnly()) {
|
||||||
core.debug('Cache is read-only: not saving cache entry')
|
core.info(
|
||||||
|
'Cache is read-only: will not save state for use in subsequent builds.'
|
||||||
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user