Compare commits

...

10 Commits

Author SHA1 Message Date
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
14 changed files with 193 additions and 38 deletions

View File

@@ -10,7 +10,10 @@ env:
jobs: jobs:
action-inputs: action-inputs:
runs-on: ubuntu-latest strategy:
matrix:
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps: steps:
- name: Checkout sources - name: Checkout sources
uses: actions/checkout@v2 uses: actions/checkout@v2

View File

@@ -0,0 +1,71 @@
name: Test caching configuration
on:
pull_request:
push:
workflow_dispatch:
env:
CACHE_KEY_PREFIX: ${{github.workflow}}#${{github.run_number}}-
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
cache-paths: |
["caches", "notifications", "wrapper"]
cache-exclude-paths: |
["caches/build-cache-1"]
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
cache-paths: |
["caches", "notifications", "wrapper"]
cache-exclude-paths: |
["caches/build-cache-1"]
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

@@ -14,7 +14,7 @@ jobs:
seed-build: seed-build:
strategy: strategy:
matrix: matrix:
os: [ubuntu-latest, macos-latest, windows-latest] os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
- name: Checkout sources - name: Checkout sources
@@ -35,7 +35,7 @@ jobs:
needs: seed-build needs: seed-build
strategy: strategy:
matrix: matrix:
os: [ubuntu-latest, macos-latest, windows-latest] os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
- name: Checkout sources - name: Checkout sources
@@ -52,7 +52,7 @@ jobs:
needs: seed-build needs: seed-build
strategy: strategy:
matrix: matrix:
os: [ubuntu-latest, macos-latest, windows-latest] os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
- name: Checkout sources - name: Checkout sources
@@ -69,7 +69,7 @@ jobs:
needs: seed-build needs: seed-build
strategy: strategy:
matrix: matrix:
os: [ubuntu-latest, macos-latest, windows-latest] os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
- name: Checkout sources - name: Checkout sources
@@ -86,7 +86,10 @@ jobs:
# 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
runs-on: ubuntu-latest strategy:
matrix:
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps: steps:
- name: Checkout sources - name: Checkout sources
uses: actions/checkout@v2 uses: actions/checkout@v2

View File

@@ -14,7 +14,7 @@ jobs:
gradle-execution: gradle-execution:
strategy: strategy:
matrix: matrix:
os: [ubuntu-latest, macos-latest, windows-latest] os: [ubuntu-latest, windows-latest]
include: include:
- os: windows-latest - os: windows-latest
script-suffix: '.bat' script-suffix: '.bat'
@@ -44,7 +44,7 @@ jobs:
gradle-versions: gradle-versions:
strategy: strategy:
matrix: matrix:
os: [ubuntu-latest, macos-latest, windows-latest] os: [ubuntu-latest, windows-latest]
include: include:
- os: windows-latest - os: windows-latest
script-suffix: '.bat' script-suffix: '.bat'

View File

@@ -13,7 +13,10 @@ jobs:
# Run initial Gradle builds to push initial cache entries # 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. # These builds should start fresh without cache hits, due to the seed injected into the cache key above.
seed-build: seed-build:
runs-on: ubuntu-latest strategy:
matrix:
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps: steps:
- name: Checkout sources - name: Checkout sources
uses: actions/checkout@v2 uses: actions/checkout@v2
@@ -26,7 +29,10 @@ jobs:
# 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:
needs: seed-build needs: seed-build
runs-on: ubuntu-latest strategy:
matrix:
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps: steps:
- name: Checkout sources - name: Checkout sources
uses: actions/checkout@v2 uses: actions/checkout@v2
@@ -40,7 +46,10 @@ jobs:
# Test that the gradle-user-home cache will cache and restore local build-cache # Test that the gradle-user-home cache will cache and restore local build-cache
build-cache: build-cache:
needs: seed-build needs: seed-build
runs-on: ubuntu-latest strategy:
matrix:
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps: steps:
- name: Checkout sources - name: Checkout sources
uses: actions/checkout@v2 uses: actions/checkout@v2

View File

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

View File

@@ -7,38 +7,63 @@ inputs:
gradle-executable: gradle-executable:
description: Path to the Gradle executable description: Path to the Gradle executable
required: false required: false
gradle-version: gradle-version:
description: Gradle version to use description: Gradle version to use
required: false required: false
build-root-directory: build-root-directory:
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 (supports multi-line input) 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.
required: false required: false
default: false default: false
cache-read-only: 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 required: false
# TODO: It might be useful to default to read-only for PRs, or non-main branch. # TODO: It might be useful to default to read-only for PRs, or non-main branch.
default: false default: false
# 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: 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 required: false
default: ${{ toJSON(matrix) }} default: ${{ toJSON(matrix) }}
cache-paths:
description: Paths in Gradle User Home to cache. (EXPERIMENTAL - may be changed/removed without notice)
required: false
default: |
["caches", "notifications"]
cache-exclude-paths:
description: Paths in Gradle User Home to exclude from cache. (EXPERIMENTAL - may be changed/removed without notice)
required: false
# eg ["caches/build-cache-1"] will prevent the local build cache from being saved/restored.
default: |
[]
cache-artifact-bundles: cache-artifact-bundles:
description: Names and patterns of artifact bundles to cache separately. For internal use only. description: Names and patterns of artifact bundles to cache separately. (EXPERIMENTAL - may be changed/removed without notice)
required: false required: false
default: | default: |
[ [
["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"], ["dependency-jars", "caches/modules-*/files-*/**/*.jar"],
["instrumented-jars", "caches/jars-*/*/"] ["instrumented-jars", "caches/jars-*/*/"],
["kotlin-dsl", "caches/*/kotlin-dsl/*/*/"]
] ]
outputs: 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,7 @@ import {
tryDelete tryDelete
} from './cache-utils' } from './cache-utils'
// Which paths under Gradle User Home should be cached const META_FILE_DIR = '.gradle-build-action'
const CACHE_PATH = ['caches', 'notifications']
export class GradleUserHomeCache extends AbstractCache { export class GradleUserHomeCache extends AbstractCache {
private gradleUserHome: string private gradleUserHome: string
@@ -68,21 +67,32 @@ export class GradleUserHomeCache extends AbstractCache {
} }
private getBundleMetaFile(name: string): string { private getBundleMetaFile(name: string): string {
return path.resolve( return path.resolve(this.gradleUserHome, META_FILE_DIR, `${name}.cache`)
this.gradleUserHome,
'caches',
`.gradle-build-action.${name}.cache`
)
} }
async beforeSave(): Promise<void> { async beforeSave(): Promise<void> {
await this.reportGradleUserHomeSize('before saving common artifacts') await this.reportGradleUserHomeSize('before saving common artifacts')
this.removeExcludedPaths()
await this.saveArtifactBundles() await this.saveArtifactBundles()
await this.reportGradleUserHomeSize( 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('cache-exclude-paths')
)
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> { private async saveArtifactBundles(): Promise<void> {
const processes: Promise<void>[] = [] const processes: Promise<void>[] = []
for (const [bundle, pattern] of this.getArtifactBundles()) { for (const [bundle, pattern] of this.getArtifactBundles()) {
@@ -130,9 +140,7 @@ export class GradleUserHomeCache extends AbstractCache {
} 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)
this.writeBundleMetaFile(bundleMetaFile, cacheKey)
this.debug(`Writing cache metafile: ${bundleMetaFile}`)
fs.writeFileSync(bundleMetaFile, cacheKey)
} }
for (const file of bundleFiles) { for (const file of bundleFiles) {
@@ -154,6 +162,17 @@ export class GradleUserHomeCache extends AbstractCache {
return `${cacheKeyPrefix}${bundle}-${key}` 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 { protected determineGradleUserHome(rootDir: string): string {
const customGradleUserHome = process.env['GRADLE_USER_HOME'] const customGradleUserHome = process.env['GRADLE_USER_HOME']
if (customGradleUserHome) { if (customGradleUserHome) {
@@ -170,7 +189,19 @@ export class GradleUserHomeCache extends AbstractCache {
} }
protected getCachePath(): string[] { protected getCachePath(): string[] {
return CACHE_PATH.map(x => path.resolve(this.gradleUserHome, x)) const rawPaths: string[] = JSON.parse(core.getInput('cache-paths'))
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> { private getArtifactBundles(): Map<string, string> {

View File

@@ -19,7 +19,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_KEY_PREFIX'] || 'v2-' return process.env['CACHE_KEY_PREFIX'] || 'v3-'
} }
function generateCacheKey(cacheName: string): CacheKey { function generateCacheKey(cacheName: string): CacheKey {

View File

@@ -28,13 +28,20 @@ export async function run(): Promise<void> {
if (result.buildScanUrl) { if (result.buildScanUrl) {
core.setOutput('build-scan-url', 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) { 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) { } catch (error) {
core.setFailed(String(error)) core.setFailed(String(error))