Compare commits

..

14 Commits

Author SHA1 Message Date
Daz DeBoer
db2b34260f Merge pull request #101 from gradle/dd/rename-parameters
Rename and document parameters for clarity 

- cache-paths -> gradle-home-cache-includes
- cache-exclude-paths -> gradle-home-cache-excludes
- CACHE_DEBUG_ENABLED -> GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED
2021-10-28 00:18:36 +02:00
Daz DeBoer
c031dc946b Build outputs 2021-10-27 16:09:53 -06:00
Daz DeBoer
0eb881f067 Adapt workflows to renamed parameters 2021-10-27 16:07:24 -06:00
Daz DeBoer
27f2dc276c Rename and document parameters for clarity
- cache-paths -> gradle-home-cache-includes
- cache-exclude-paths -> gradle-home-cache-excludes
- CACHE_DEBUG_ENABLED -> GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED
2021-10-27 16:05:07 -06:00
Daz DeBoer
cba1833dde Run test builds on Ubuntu and Windows
- Remove MacOS since the agents are current flaky
- Add Windows to a few more test pipelines
2021-10-21 12:08:17 -06:00
Daz DeBoer
39db90e99b Include build scan link in failure notice 2021-10-21 12:04:25 -06:00
Daz DeBoer
947a893558 Merge pull request #97 from gradle/dd/configurable-cache
Add some internal options for fine-tuning the gradle-build-action cache

- Can specify cache-paths to override the default directories cached from Gradle User Home
- Can specify cache-exclude-paths to exclude files from the Gradle User Home cache
- Files under caches/<gradle-version>/kotlin-dsl are now cached as a bundle
2021-10-21 19:26:19 +02:00
Daz DeBoer
b99e9f0bc3 Build outputs 2021-10-21 11:13:10 -06:00
Daz DeBoer
4cf255df10 Move bundle metadata files out of caches directory
Instead, use a separate '.gradle-build-action' directory for bundle
metadata files. This directory is always part of the cache-path.
2021-10-21 11:13:09 -06:00
Daz DeBoer
614d8770a4 Add test for cache configuration 2021-10-21 11:13:09 -06:00
Daz DeBoer
69453dbfc5 Include 'kotlin-dsl' as a cache-artifact-bundle 2021-10-21 11:13:09 -06:00
Daz DeBoer
1113cb87cb Allow cache-exclude-paths to be configured for action
All excluded paths are deleted prior to caching the Gradle User Home.
2021-10-21 11:13:09 -06:00
Daz DeBoer
9c95294209 Allow cache-paths to be set via action config 2021-10-21 11:13:08 -06:00
Daz DeBoer
f901ec9c20 Bump cache-protocol version 2021-10-20 15:04:14 -06:00
16 changed files with 248 additions and 61 deletions

View File

@@ -4,7 +4,7 @@ on:
workflow_dispatch:
env:
CACHE_KEY_PREFIX: ${{github.workflow}}#${{github.run_number}}-
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: ${{github.workflow}}#${{github.run_number}}-
jobs:

View File

@@ -6,11 +6,14 @@ on:
workflow_dispatch:
env:
CACHE_KEY_PREFIX: ${{github.workflow}}#${{github.run_number}}-
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: ${{github.workflow}}#${{github.run_number}}-
jobs:
action-inputs:
runs-on: ubuntu-latest
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout sources
uses: actions/checkout@v2

View File

@@ -0,0 +1,71 @@
name: Test caching configuration
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 using Gradle wrapper
uses: ./
with:
build-root-directory: __tests__/samples/groovy-dsl
arguments: test
# Add "wrapper" to main cache entry and remove 'wrapper-zips' bundle
# Exclude build-cache from main cache entry
gradle-home-cache-includes: |
["caches", "notifications", "wrapper"]
gradle-home-cache-excludes: |
["caches/build-cache-1"]
gradle-home-cache-artifact-bundles: |
[
["generated-gradle-jars", "caches/*/generated-gradle-jars/*.jar"],
["dependency-jars", "caches/modules-*/files-*/**/*.jar"],
["instrumented-jars", "caches/jars-*/*/"],
["kotlin-dsl", "caches/*/kotlin-dsl/*/*/"]
]
# Test that the gradle-user-home cache will cache dependencies, by running build with --offline
verify-build:
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 --offline
uses: ./
with:
build-root-directory: __tests__/samples/groovy-dsl
arguments: test --offline
cache-read-only: true
# Need the same configuration when restoring state from cache
gradle-home-cache-includes: |
["caches", "notifications", "wrapper"]
gradle-home-cache-excludes: |
["caches/build-cache-1"]
gradle-home-cache-artifact-bundles: |
[
["generated-gradle-jars", "caches/*/generated-gradle-jars/*.jar"],
["dependency-jars", "caches/modules-*/files-*/**/*.jar"],
["instrumented-jars", "caches/jars-*/*/"],
["kotlin-dsl", "caches/*/kotlin-dsl/*/*/"]
]

View File

@@ -6,7 +6,7 @@ on:
workflow_dispatch:
env:
CACHE_KEY_PREFIX: ${{github.workflow}}#${{github.run_number}}-
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: ${{github.workflow}}#${{github.run_number}}-
jobs:
# Run initial Gradle builds to push initial cache entries
@@ -14,7 +14,7 @@ jobs:
seed-build:
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout sources
@@ -35,7 +35,7 @@ jobs:
needs: seed-build
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout sources
@@ -52,7 +52,7 @@ jobs:
needs: seed-build
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout sources
@@ -69,7 +69,7 @@ jobs:
needs: seed-build
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout sources
@@ -86,7 +86,10 @@ jobs:
# Check that the build can run when no bundles are restored
no-bundles-restored:
needs: seed-build
runs-on: ubuntu-latest
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout sources
uses: actions/checkout@v2
@@ -95,6 +98,6 @@ jobs:
with:
build-root-directory: __tests__/samples/groovy-dsl
arguments: test
cache-artifact-bundles: '[]'
cache-read-only: true
gradle-home-cache-artifact-bundles: '[]'

View File

@@ -6,7 +6,7 @@ on:
workflow_dispatch:
env:
CACHE_KEY_PREFIX: ${{github.workflow}}#${{github.run_number}}-
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: ${{github.workflow}}#${{github.run_number}}-
jobs:
# Tests for executing with different Gradle versions.
@@ -14,7 +14,7 @@ jobs:
gradle-execution:
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
os: [ubuntu-latest, windows-latest]
include:
- os: windows-latest
script-suffix: '.bat'
@@ -44,7 +44,7 @@ jobs:
gradle-versions:
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
os: [ubuntu-latest, windows-latest]
include:
- os: windows-latest
script-suffix: '.bat'

View File

@@ -6,14 +6,17 @@ on:
workflow_dispatch:
env:
CACHE_KEY_PREFIX: ${{github.workflow}}#${{github.run_number}}-
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: ${{github.workflow}}#${{github.run_number}}-
GRADLE_USER_HOME: custom/gradle/home
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:
runs-on: ubuntu-latest
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout sources
uses: actions/checkout@v2
@@ -26,7 +29,10 @@ jobs:
# Test that the gradle-user-home cache will cache dependencies, by running build with --offline
dependencies-cache:
needs: seed-build
runs-on: ubuntu-latest
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout sources
uses: actions/checkout@v2
@@ -40,7 +46,10 @@ jobs:
# Test that the gradle-user-home cache will cache and restore local build-cache
build-cache:
needs: seed-build
runs-on: ubuntu-latest
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout sources
uses: actions/checkout@v2

View File

@@ -6,13 +6,16 @@ on:
workflow_dispatch:
env:
CACHE_KEY_PREFIX: ${{github.workflow}}#${{github.run_number}}-
CACHE_DEBUG_ENABLED: true
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: ${{github.workflow}}#${{github.run_number}}-
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
jobs:
# Use kotlin-dsl project to verify caching of generated jars and compiled scripts
seed-build:
runs-on: ubuntu-latest
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout sources
uses: actions/checkout@v2
@@ -25,7 +28,10 @@ jobs:
# Check that the build can run --offline
verify-build:
needs: seed-build
runs-on: ubuntu-latest
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout sources
uses: actions/checkout@v2

View File

@@ -159,12 +159,9 @@ Caching is enabled by default. You can disable caching for the action as follows
cache-disabled: true
```
At this time it is not possible to fine-tune the caching performed by this action.
If you have a legitimate use case for fine-grained caching or restricting which files are cached, please raise an issue.
### Cache keys
For cached distributions, the cache key is unique to the downloaded distribution. This will not change over time.
For cached distributions outside of Gradle User Home, the cache key is unique to the downloaded distribution. This will not change over time.
The state of the Gradle User Home and configuration-cache are highly dependent on the Gradle execution, so the cache key is composed of the current commit hash and the GitHub actions job id.
As such, the cache key is likely to change on each subsequent run of GitHub actions.
@@ -183,16 +180,36 @@ For example, you may want to write cache entries for builds on your `main` branc
You can enable read-only caching for any of the caches as follows:
```yaml
cache-read-only: true
# Only write to the cache for builds on the 'main' branch.
# Builds on other branches will only read existing entries from the cache.
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
```
### Gradle User Home cache tuning
As well as any wrapper distributions, the action will attempt to save and restore the `caches` and `notifications` directories from Gradle User Home.
The contents to be cached can be fine tuned by including and excluding certain paths with Gradle User Home.
```yaml
# Cache downloaded JDKs in addition to the default directories.
gradle-home-cache-includes: |
["caches", "notifications", "jdks"]
# Exclude the local build-cache from the directories cached.
gradle-home-cache-excludes: |
["caches/build-cache-1"]
```
You can specify any number of fixed paths or patterns to include or exclude.
File pattern support is documented at https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions#patterns-to-match-file-paths.
### Cache debugging
It is possible to enable additional debug logging for cache operations. You do via the `CACHE_DEBUG_ENABLED` environment variable:
It is possible to enable additional debug logging for cache operations. You do via the `GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED` environment variable:
```yaml
env:
CACHE_DEBUG_ENABLED: true
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
```
Note that this setting will also prevent certain cache operations from running in parallel, further assisting with debugging.

View File

@@ -7,38 +7,64 @@ inputs:
gradle-executable:
description: Path to the Gradle executable
required: false
gradle-version:
description: Gradle version to use
required: false
build-root-directory:
description: Path to the root directory of the build
required: false
arguments:
description: Gradle command line arguments (supports multi-line input)
required: false
cache-disabled:
description: When 'true', all caching is disabled. No entries will be written to or read from the cache.
required: false
default: false
cache-read-only:
description: When 'true', existing entries will be read from the cache but no entries will be written
description: When 'true', existing entries will be read from the cache but no entries will be written.
required: false
# TODO: It might be useful to default to read-only for PRs, or non-main branch.
default: false
# e.g. Use the following setting to only write cache entries from your 'main' branch
# cache-read-only: ${{ github.ref != 'refs/heads/main' }}
gradle-home-cache-includes:
description: Paths within Gradle User Home to cache.
required: false
default: |
["caches", "notifications"]
gradle-home-cache-excludes:
description: Paths within Gradle User Home to exclude from cache.
required: false
default: |
[]
# e.g. Use the following setting to prevent the local build cache from being saved/restored
# gradle-home-cache-excludes: |
# ["caches/build-cache-1"]
# EXPERIMENTAL & INTERNAL CONFIGURATION PROPERTIES
# The following action properties allow fine-grained tweaking of the action caching behaviour.
# These properties are not designed for production use, and may change without notice in a subsequent release of `gradle-build-action`.
# Use at your own risk!
workflow-job-context:
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 (INTERNAL).
required: false
default: ${{ toJSON(matrix) }}
cache-artifact-bundles:
description: Names and patterns of artifact bundles to cache separately. For internal use only.
gradle-home-cache-artifact-bundles:
description: Names and patterns of artifact bundles to cache separately. (EXPERIMENTAL - may be changed/removed without notice)
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-*/*/"]
["instrumented-jars", "caches/jars-*/*/"],
["kotlin-dsl", "caches/*/kotlin-dsl/*/*/"]
]
outputs:

2
dist/main/index.js vendored

File diff suppressed because one or more lines are too long

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

File diff suppressed because one or more lines are too long

View File

@@ -12,8 +12,11 @@ import {
tryDelete
} from './cache-utils'
// Which paths under Gradle User Home should be cached
const CACHE_PATH = ['caches', 'notifications']
const META_FILE_DIR = '.gradle-build-action'
const INCLUDE_PATHS_PARAMETER = 'gradle-home-cache-includes'
const EXCLUDE_PATHS_PARAMETER = 'gradle-home-cache-excludes'
const ARTIFACT_BUNDLES_PARAMETER = 'gradle-home-cache-artifact-bundles'
export class GradleUserHomeCache extends AbstractCache {
private gradleUserHome: string
@@ -68,21 +71,32 @@ export class GradleUserHomeCache extends AbstractCache {
}
private getBundleMetaFile(name: string): string {
return path.resolve(
this.gradleUserHome,
'caches',
`.gradle-build-action.${name}.cache`
)
return path.resolve(this.gradleUserHome, META_FILE_DIR, `${name}.cache`)
}
async beforeSave(): Promise<void> {
await this.reportGradleUserHomeSize('before saving common artifacts')
this.removeExcludedPaths()
await this.saveArtifactBundles()
await this.reportGradleUserHomeSize(
'after saving common artifacts (./wrapper dir is not cached)'
"after saving common artifacts (only 'caches' and 'notifications' will be stored)"
)
}
private removeExcludedPaths(): void {
const rawPaths: string[] = JSON.parse(
core.getInput(EXCLUDE_PATHS_PARAMETER)
)
const resolvedPaths = rawPaths.map(x =>
path.resolve(this.gradleUserHome, x)
)
for (const p of resolvedPaths) {
this.debug(`Deleting excluded path: ${p}`)
tryDelete(p)
}
}
private async saveArtifactBundles(): Promise<void> {
const processes: Promise<void>[] = []
for (const [bundle, pattern] of this.getArtifactBundles()) {
@@ -130,9 +144,7 @@ export class GradleUserHomeCache extends AbstractCache {
} else {
core.info(`Caching ${bundle} with cache key: ${cacheKey}`)
await this.saveCache([artifactPath], cacheKey)
this.debug(`Writing cache metafile: ${bundleMetaFile}`)
fs.writeFileSync(bundleMetaFile, cacheKey)
this.writeBundleMetaFile(bundleMetaFile, cacheKey)
}
for (const file of bundleFiles) {
@@ -154,6 +166,17 @@ export class GradleUserHomeCache extends AbstractCache {
return `${cacheKeyPrefix}${bundle}-${key}`
}
private writeBundleMetaFile(metaFile: string, cacheKey: string): void {
this.debug(`Writing bundle metafile: ${metaFile}`)
const dirName = path.dirname(metaFile)
if (!fs.existsSync(dirName)) {
fs.mkdirSync(dirName)
}
fs.writeFileSync(metaFile, cacheKey)
}
protected determineGradleUserHome(rootDir: string): string {
const customGradleUserHome = process.env['GRADLE_USER_HOME']
if (customGradleUserHome) {
@@ -170,11 +193,27 @@ export class GradleUserHomeCache extends AbstractCache {
}
protected getCachePath(): string[] {
return CACHE_PATH.map(x => path.resolve(this.gradleUserHome, x))
const rawPaths: string[] = JSON.parse(
core.getInput(INCLUDE_PATHS_PARAMETER)
)
rawPaths.push(META_FILE_DIR)
const resolvedPaths = rawPaths.map(x => this.resolveCachePath(x))
this.debug(`Using cache paths: ${resolvedPaths}`)
return resolvedPaths
}
private resolveCachePath(rawPath: string): string {
if (rawPath.startsWith('!')) {
const resolved = this.resolveCachePath(rawPath.substring(1))
return `!${resolved}`
}
return path.resolve(this.gradleUserHome, rawPath)
}
private getArtifactBundles(): Map<string, string> {
const artifactBundleDefinition = core.getInput('cache-artifact-bundles')
const artifactBundleDefinition = core.getInput(
ARTIFACT_BUNDLES_PARAMETER
)
this.debug(
`Using artifact bundle definition: ${artifactBundleDefinition}`
)

View File

@@ -5,21 +5,27 @@ import * as crypto from 'crypto'
import * as path from 'path'
import * as fs from 'fs'
const CACHE_DISABLED_PARAMETER = 'cache-disabled'
const CACHE_READONLY_PARAMETER = 'cache-read-only'
const JOB_CONTEXT_PARAMETER = 'workflow-job-context'
const CACHE_DEBUG_VAR = 'GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED'
const CACHE_PREFIX_VAR = 'GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX'
export function isCacheDisabled(): boolean {
return core.getBooleanInput('cache-disabled')
return core.getBooleanInput(CACHE_DISABLED_PARAMETER)
}
export function isCacheReadOnly(): boolean {
return core.getBooleanInput('cache-read-only')
return core.getBooleanInput(CACHE_READONLY_PARAMETER)
}
export function isCacheDebuggingEnabled(): boolean {
return process.env['CACHE_DEBUG_ENABLED'] ? true : false
return process.env[CACHE_DEBUG_VAR] ? 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-'
return process.env[CACHE_PREFIX_VAR] || 'v3-'
}
function generateCacheKey(cacheName: string): CacheKey {
@@ -47,7 +53,7 @@ function generateCacheKey(cacheName: string): CacheKey {
function determineJobContext(): string {
// By default, we hash the full `matrix` data for the run, to uniquely identify this job invocation
const workflowJobContext = core.getInput('workflow-job-context')
const workflowJobContext = core.getInput(JOB_CONTEXT_PARAMETER)
return hashStrings([workflowJobContext])
}

View File

@@ -28,13 +28,20 @@ export async function run(): Promise<void> {
if (result.buildScanUrl) {
core.setOutput('build-scan-url', result.buildScanUrl)
// TODO Include context about the invocation (eg step name) in this message
// Unfortunately it doesn't seem possible to access the current step name here
core.notice(`Gradle build scan: ${result.buildScanUrl}`)
}
if (result.status !== 0) {
core.setFailed(`Gradle process exited with status ${result.status}`)
if (result.buildScanUrl) {
core.setFailed(`Gradle build failed: ${result.buildScanUrl}`)
} else {
core.setFailed(
`Gradle build failed: process exited with status ${result.status}`
)
}
} else {
if (result.buildScanUrl) {
core.notice(`Gradle build succeeded: ${result.buildScanUrl}`)
}
}
} catch (error) {
core.setFailed(String(error))