mirror of
https://github.com/gradle/gradle-build-action.git
synced 2025-10-20 15:18:56 +08:00
Compare commits
23 Commits
v2.0-beta.
...
v2.0-beta.
Author | SHA1 | Date | |
---|---|---|---|
|
c000a0b58f | ||
|
6ff498182a | ||
|
60b1ffac6b | ||
|
9b7c81f8f6 | ||
|
b650771559 | ||
|
17f624cb5b | ||
|
21dee71590 | ||
|
83e2129213 | ||
|
b16787d530 | ||
|
204870af89 | ||
|
0918f5f2a4 | ||
|
1b1a3c48ad | ||
|
a7174b82a2 | ||
|
3de71f2c52 | ||
|
5576baa56b | ||
|
1026c62889 | ||
|
1fb8644035 | ||
|
5a5a5b4387 | ||
|
cc5cdb7fe0 | ||
|
e0d37eb073 | ||
|
bdd89aa34f | ||
|
18cdc8bf28 | ||
|
656ad4b5f2 |
3
.github/workflows/dev.yml
vendored
3
.github/workflows/dev.yml
vendored
@@ -1,5 +1,4 @@
|
||||
# make sure the build works and doesn't produce spurious changes
|
||||
name: dev
|
||||
name: Verify generated outputs
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
|
10
.github/workflows/failure-cases.yml
vendored
10
.github/workflows/failure-cases.yml
vendored
@@ -1,10 +1,6 @@
|
||||
# Run builds under certain failure conditions to allow the output to be manually inspected.
|
||||
# These build invocations are informational only, and are expected to fail
|
||||
name: failure-cases
|
||||
name: Execute failure cases
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
@@ -13,25 +9,25 @@ env:
|
||||
jobs:
|
||||
|
||||
wrapper-missing:
|
||||
continue-on-error: true
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Test wrapper missing
|
||||
uses: ./
|
||||
continue-on-error: true
|
||||
with:
|
||||
build-root-directory: __tests__/samples/no-wrapper
|
||||
arguments: help
|
||||
|
||||
bad-configuration:
|
||||
continue-on-error: true
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Test bad config value
|
||||
uses: ./
|
||||
continue-on-error: true
|
||||
with:
|
||||
build-root-directory: __tests__/samples/no-wrapper
|
||||
arguments: help
|
||||
|
@@ -1,5 +1,4 @@
|
||||
# Verify the functionality works as expected
|
||||
name: integration-testing
|
||||
name: Test caching
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
@@ -23,49 +22,13 @@ jobs:
|
||||
- name: Build using Gradle wrapper
|
||||
uses: ./
|
||||
with:
|
||||
build-root-directory: __tests__/samples/basic
|
||||
build-root-directory: __tests__/samples/groovy-dsl
|
||||
arguments: test
|
||||
- name: Build with configuration-cache enabled
|
||||
uses: ./
|
||||
with:
|
||||
build-root-directory: __tests__/samples/basic
|
||||
build-root-directory: __tests__/samples/groovy-dsl
|
||||
arguments: test --configuration-cache
|
||||
|
||||
# Tests for executing with different Gradle versions.
|
||||
# Each build verifies that it is executed with the expected Gradle version.
|
||||
gradle-execution:
|
||||
needs: seed-build
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
include:
|
||||
- os: windows-latest
|
||||
script-suffix: '.bat'
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Test use defined Gradle version
|
||||
uses: ./
|
||||
with:
|
||||
gradle-version: 6.9
|
||||
build-root-directory: __tests__/samples/no-wrapper
|
||||
arguments: help -DgradleVersionCheck=6.9
|
||||
cache-read-only: true
|
||||
- name: Test use Gradle version alias
|
||||
uses: ./
|
||||
with:
|
||||
gradle-version: release-candidate
|
||||
build-root-directory: __tests__/samples/no-wrapper
|
||||
arguments: help -DgradleVersionCheck=7.2
|
||||
cache-read-only: true
|
||||
- name: Test use defined Gradle executable
|
||||
uses: ./
|
||||
with:
|
||||
gradle-executable: __tests__/samples/basic/gradlew${{ matrix.script-suffix }}
|
||||
build-root-directory: __tests__/samples/no-wrapper
|
||||
arguments: help -DgradleVersionCheck=7.1.1
|
||||
cache-read-only: true
|
||||
|
||||
# Test that the gradle-user-home cache will cache dependencies, by running build with --offline
|
||||
dependencies-cache:
|
||||
@@ -80,7 +43,7 @@ jobs:
|
||||
- name: Execute Gradle build with --offline
|
||||
uses: ./
|
||||
with:
|
||||
build-root-directory: __tests__/samples/basic
|
||||
build-root-directory: __tests__/samples/groovy-dsl
|
||||
arguments: test --offline
|
||||
cache-read-only: true
|
||||
|
||||
@@ -97,7 +60,7 @@ jobs:
|
||||
- name: Execute Gradle build and verify tasks from cache
|
||||
uses: ./
|
||||
with:
|
||||
build-root-directory: __tests__/samples/basic
|
||||
build-root-directory: __tests__/samples/groovy-dsl
|
||||
arguments: test -DverifyCachedBuild=true
|
||||
cache-read-only: true
|
||||
|
||||
@@ -116,6 +79,6 @@ jobs:
|
||||
env:
|
||||
VERIFY_CACHED_CONFIGURATION: true
|
||||
with:
|
||||
build-root-directory: __tests__/samples/basic
|
||||
build-root-directory: __tests__/samples/groovy-dsl
|
||||
arguments: test --configuration-cache
|
||||
cache-read-only: true
|
107
.github/workflows/integTest-execution.yml
vendored
Normal file
107
.github/workflows/integTest-execution.yml
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
name: Test Gradle execution
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
CACHE_KEY_PREFIX: ${{github.workflow}}#${{github.run_number}}-
|
||||
|
||||
jobs:
|
||||
# Tests for executing with different Gradle versions.
|
||||
# Each build verifies that it is executed with the expected Gradle version.
|
||||
gradle-execution:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
include:
|
||||
- os: windows-latest
|
||||
script-suffix: '.bat'
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Test use defined Gradle version
|
||||
uses: ./
|
||||
with:
|
||||
gradle-version: 6.9
|
||||
build-root-directory: __tests__/samples/no-wrapper
|
||||
arguments: help -DgradleVersionCheck=6.9
|
||||
- name: Test use Gradle version alias
|
||||
uses: ./
|
||||
with:
|
||||
gradle-version: release-candidate
|
||||
build-root-directory: __tests__/samples/no-wrapper
|
||||
arguments: help -DgradleVersionCheck=7.2
|
||||
- name: Test use defined Gradle executable
|
||||
uses: ./
|
||||
with:
|
||||
gradle-executable: __tests__/samples/groovy-dsl/gradlew${{ matrix.script-suffix }}
|
||||
build-root-directory: __tests__/samples/no-wrapper
|
||||
arguments: help -DgradleVersionCheck=7.1.1
|
||||
|
||||
gradle-versions:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
include:
|
||||
- os: windows-latest
|
||||
script-suffix: '.bat'
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Test Gradle 7
|
||||
uses: ./
|
||||
id: gradle7
|
||||
with:
|
||||
gradle-version: 7.2
|
||||
build-root-directory: __tests__/samples/no-wrapper
|
||||
arguments: help -DgradleVersionCheck=7.2
|
||||
- name: Check Gradle 7 scan
|
||||
if: ${{ !steps.gradle7.outputs.build-scan-url }}
|
||||
uses: actions/github-script@v3
|
||||
with:
|
||||
script: |
|
||||
core.setFailed('No build scan detected')
|
||||
- name: Test Gradle 6
|
||||
uses: ./
|
||||
id: gradle6
|
||||
with:
|
||||
gradle-version: 6.9
|
||||
build-root-directory: __tests__/samples/no-wrapper
|
||||
arguments: help -DgradleVersionCheck=6.9
|
||||
- name: Check Gradle 6 scan
|
||||
if: ${{ !steps.gradle6.outputs.build-scan-url }}
|
||||
uses: actions/github-script@v3
|
||||
with:
|
||||
script: |
|
||||
core.setFailed('No build scan detected')
|
||||
- name: Test Gradle 5
|
||||
uses: ./
|
||||
id: gradle5
|
||||
with:
|
||||
gradle-version: 5.6.4
|
||||
build-root-directory: __tests__/samples/no-wrapper-gradle-5
|
||||
arguments: help -DgradleVersionCheck=5.6.4
|
||||
- name: Check Gradle 5 scan
|
||||
if: ${{ !steps.gradle5.outputs.build-scan-url }}
|
||||
uses: actions/github-script@v3
|
||||
with:
|
||||
script: |
|
||||
core.setFailed('No build scan detected')
|
||||
- name: Test Gradle 4
|
||||
uses: ./
|
||||
id: gradle4
|
||||
with:
|
||||
gradle-version: 4.10.3
|
||||
build-root-directory: __tests__/samples/no-wrapper-gradle-4
|
||||
arguments: help -DgradleVersionCheck=4.10.3
|
||||
- name: Check Gradle 4 scan
|
||||
if: ${{ !steps.gradle4.outputs.build-scan-url }}
|
||||
uses: actions/github-script@v3
|
||||
with:
|
||||
script: |
|
||||
core.setFailed('No build scan detected')
|
||||
|
52
.github/workflows/integTest-gradle-user-home.yml
vendored
Normal file
52
.github/workflows/integTest-gradle-user-home.yml
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
name: Test caching with a custom GRADLE_USER_HOME
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
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
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Build using Gradle wrapper
|
||||
uses: ./
|
||||
with:
|
||||
build-root-directory: __tests__/samples/groovy-dsl
|
||||
arguments: test
|
||||
|
||||
# Test that the gradle-user-home cache will cache dependencies, by running build with --offline
|
||||
dependencies-cache:
|
||||
needs: seed-build
|
||||
runs-on: ubuntu-latest
|
||||
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
|
||||
|
||||
# Test that the gradle-user-home cache will cache and restore local build-cache
|
||||
build-cache:
|
||||
needs: seed-build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Execute Gradle build and verify tasks from cache
|
||||
uses: ./
|
||||
with:
|
||||
build-root-directory: __tests__/samples/groovy-dsl
|
||||
arguments: test -DverifyCachedBuild=true
|
||||
cache-read-only: true
|
@@ -1,5 +1,4 @@
|
||||
# Make sure the action works on a clean machine without building
|
||||
name: integration-testing-kotlin-dsl
|
||||
name: Test caching with Kotlin DSL
|
||||
|
||||
on:
|
||||
pull_request:
|
134
README.md
134
README.md
@@ -2,9 +2,13 @@
|
||||
|
||||
This GitHub Action can be used to execute a Gradle build on any platform supported by GitHub Actions.
|
||||
|
||||
**Note:** The following documentation is for `gradle/gradle-build-action@v2`, currently in Beta release.
|
||||
You can view the documentation for the latest stable release (v1.5.1) [on the GitHub Marketplace](https://github.com/marketplace/actions/gradle-build-action?version=v1.5.1).
|
||||
|
||||
## Usage
|
||||
|
||||
The following workflow will run `./gradlew build` using the wrapper from the repository on ubuntu, macos and windows. The only prerequisite is to have Java installed: you define the version of Java you need to run the build using the `actions/setup-java` action.
|
||||
The following workflow will run `./gradlew build` on ubuntu, macos and windows.
|
||||
The only prerequisite is to have Java installed: you define the version of Java you need to run the build using the `actions/setup-java` action.
|
||||
|
||||
```yaml
|
||||
# .github/workflows/gradle-build-pr.yml
|
||||
@@ -21,12 +25,26 @@ jobs:
|
||||
- uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 11
|
||||
- uses: gradle/gradle-build-action@v1
|
||||
- uses: gradle/gradle-build-action@v2
|
||||
with:
|
||||
arguments: build
|
||||
```
|
||||
|
||||
## Gradle arguments
|
||||
It is possible to configure multiple Gradle executions to run sequentially in the same job.
|
||||
Each invocation will start its run with the filesystem state remaining from the previous execution.
|
||||
|
||||
```yaml
|
||||
- uses: gradle/gradle-build-action@v2
|
||||
with:
|
||||
arguments: assemble
|
||||
- uses: gradle/gradle-build-action@v2
|
||||
with:
|
||||
arguments: check
|
||||
```
|
||||
|
||||
## Gradle Execution
|
||||
|
||||
### Command-line arguments
|
||||
|
||||
The `arguments` input can used to pass arbitrary arguments to the `gradle` command line.
|
||||
|
||||
@@ -42,42 +60,47 @@ arguments: build -DsystemProperty=bar
|
||||
|
||||
See `gradle --help` for more information.
|
||||
|
||||
If you need to pass environment variables, simply use the GitHub Actions workflow syntax:
|
||||
If you need to pass environment variables, use the GitHub Actions workflow syntax:
|
||||
|
||||
```yaml
|
||||
- uses: gradle/gradle-build-action@v1
|
||||
- uses: gradle/gradle-build-action@v2
|
||||
env:
|
||||
CI: true
|
||||
with:
|
||||
arguments: build
|
||||
```
|
||||
|
||||
## Run a build from a different directory
|
||||
### Gradle build located in a subdirectory
|
||||
|
||||
By default, the action will execute Gradle in the root directory of your project.
|
||||
Use the `build-root-directory` input to target a Gradle build in a subdirectory.
|
||||
|
||||
```yaml
|
||||
- uses: gradle/gradle-build-action@v1
|
||||
- uses: gradle/gradle-build-action@v2
|
||||
with:
|
||||
build-root-directory: some/subdirectory
|
||||
```
|
||||
|
||||
## Use a specific `gradle` executable
|
||||
### Using a specific Gradle executable
|
||||
|
||||
The action will first look for a Gradle wrapper script in the root directory of your project.
|
||||
If not found, `gradle` will be executed from the PATH.
|
||||
Use the `gradle-executable` input to execute using a specific Gradle installation.
|
||||
|
||||
```yaml
|
||||
- uses: gradle/gradle-build-action@v1
|
||||
- uses: gradle/gradle-build-action@v2
|
||||
with:
|
||||
gradle-executable: path/to/gradle
|
||||
gradle-executable: /path/to/installed/gradle
|
||||
```
|
||||
|
||||
## Use a Gradle wrapper from a different directory
|
||||
|
||||
```yaml
|
||||
- uses: gradle/gradle-build-action@v1
|
||||
with:
|
||||
gradle-executable: path/to/gradlew
|
||||
```
|
||||
This mechanism can also be used to target a Gradle wrapper script that is located in a non-default location.
|
||||
|
||||
## Setup and use a declared Gradle version
|
||||
### Download, install and use a specific Gradle version
|
||||
|
||||
The `gradle-build-action` is able to download and install a specific Gradle version to execute.
|
||||
|
||||
```yaml
|
||||
- uses: gradle/gradle-build-action@v1
|
||||
- uses: gradle/gradle-build-action@v2
|
||||
with:
|
||||
gradle-version: 6.5
|
||||
```
|
||||
@@ -94,7 +117,7 @@ Moreover, you can use the following aliases:
|
||||
| `nightly` | The latest [nightly](https://gradle.org/nightly/), fails if none. |
|
||||
| `release-nightly` | The latest [release nightly](https://gradle.org/release-nightly/), fails if none. |
|
||||
|
||||
This can be handy to, for example, automatically test your build with the next Gradle version once a release candidate is out:
|
||||
This can be handy to automatically verify your build works with the latest release candidate of Gradle:
|
||||
|
||||
```yaml
|
||||
# .github/workflows/test-gradle-rc.yml
|
||||
@@ -110,7 +133,7 @@ jobs:
|
||||
- uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 11
|
||||
- uses: gradle/gradle-build-action@v1
|
||||
- uses: gradle/gradle-build-action@v2
|
||||
with:
|
||||
gradle-version: release-candidate
|
||||
arguments: build --dry-run # just test build configuration
|
||||
@@ -118,28 +141,34 @@ jobs:
|
||||
|
||||
## Caching
|
||||
|
||||
This action provides 3 levels of caching to help speed up your GitHub Actions:
|
||||
|
||||
- `distributions` caches any distributions downloaded to satisfy a `gradle-version` parameter ;
|
||||
- `gradle-user-home` caches downloaded dependencies, wrapper distributions, and other stuff from the Gradle User home directory ;
|
||||
- `project-dot-gradle` caches stored [configuration-cache](https://docs.gradle.org/nightly/userguide/configuration_cache.html) state, saving time configuring the build.
|
||||
|
||||
Each of these are enabled by default. To save caching space, you can disable any of them as follows:
|
||||
|
||||
```yaml
|
||||
distributions-cache-enabled: true
|
||||
gradle-user-home-cache-enabled: true
|
||||
project-dot-gradle-cache-enabled: true
|
||||
```
|
||||
|
||||
The distributions cache uses a cache key that is unique to the downloaded distribution. This will not change over time.
|
||||
|
||||
The `gradle-user-home` and `project-dot-gradle` caches compute a cache key based on the current commit and the Gradle invocation.
|
||||
As such, these are likely to change on each subsequent run of GitHub actions, allowing the most recent state to always be available in the GitHub actions cache.
|
||||
|
||||
By default, this action aims to cache any and all reusable state that may be speed up a subsequent build invocation.
|
||||
|
||||
At this time it is not possible to fine-tune this caching. If you have a legitimate use case for fine-grained caching or restricting which files are cached, please raise an issue.
|
||||
The state that is cached includes:
|
||||
- Any distributions downloaded to satisfy a `gradle-version` parameter ;
|
||||
- A subset of the Gradle User Home directory, including downloaded dependencies, wrapper distributions, and the local build cache ;
|
||||
- Any [configuration-cache](https://docs.gradle.org/nightly/userguide/configuration_cache.html) data stored in the project `.gradle` directory.
|
||||
|
||||
To reduce the space required for caching, this action makes a best effort to reduce duplication in cache entries.
|
||||
|
||||
Caching is enabled by default. You can disable caching for the action as follows:
|
||||
```yaml
|
||||
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.
|
||||
|
||||
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.
|
||||
This allows the most recent state to always be available in the GitHub actions cache.
|
||||
|
||||
To reduce duplication between cache entries, certain artifacts are cached independently based on their identity.
|
||||
Artifacts that are cached independently include downloaded dependencies, downloaded wrapper distributions and generated Gradle API jars.
|
||||
For example, this means that all jobs executing a particular version of the Gradle wrapper will share common entries for wrapper distributions and for generated Gradle API jars.
|
||||
|
||||
### Using the caches read-only
|
||||
|
||||
@@ -147,21 +176,19 @@ Cache storage space is limited for GitHub actions, and writing new cache entries
|
||||
In some circumstances, it makes sense for a Gradle invocation to read any existing cache entries but not to write changes back.
|
||||
For example, you may want to write cache entries for builds on your `main` branch, but not for any PR build invocations.
|
||||
|
||||
You can enable read-only caching for any of the caches asfollows:
|
||||
You can enable read-only caching for any of the caches as follows:
|
||||
|
||||
```yaml
|
||||
distributions-cache-enabled: read-only
|
||||
gradle-user-home-cache-enabled: read-only
|
||||
project-dot-gradle-cache-enabled: read-only
|
||||
cache-read-only: true
|
||||
```
|
||||
|
||||
## Build scans
|
||||
|
||||
If your build publishes a [build scan](https://gradle.com/build-scans/) the `gradle-build-action` action will emit the link to the published build scan as an output named `build-scan-url`.
|
||||
If your build publishes a [build scan](https://gradle.com/build-scans/) the `gradle-build-action` action will:
|
||||
- Add a notice with the link to the GitHub Actions user interface
|
||||
- Emit the link to the published build scan as an output named `build-scan-url`.
|
||||
|
||||
You can then use that link in subsequent actions of your workflow.
|
||||
|
||||
For example:
|
||||
You can then use that link in subsequent actions of your workflow. For example:
|
||||
|
||||
```yaml
|
||||
# .github/workflows/gradle-build-pr.yml
|
||||
@@ -169,19 +196,16 @@ name: Run Gradle on PRs
|
||||
on: pull_request
|
||||
jobs:
|
||||
gradle:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 11
|
||||
- uses: gradle/gradle-build-action@v1
|
||||
- uses: gradle/gradle-build-action@v2
|
||||
id: gradle
|
||||
with:
|
||||
arguments: build
|
||||
id: gradle
|
||||
- name: "Comment build scan url"
|
||||
uses: actions/github-script@v3
|
||||
if: github.event_name == 'pull_request' && failure()
|
||||
|
@@ -11,5 +11,11 @@ describe('cacheUtils-utils', () => {
|
||||
const hash = cacheUtils.hashStrings(['foo', 'bar', 'baz'])
|
||||
expect(hash).toBe('6df23dc03f9b54cc38a0fc1483df6e21')
|
||||
})
|
||||
it('normalized filenames', async () => {
|
||||
const fileNames = ['/foo/bar/baz.zip', '../boo.html']
|
||||
const posixHash = cacheUtils.hashFileNames(fileNames)
|
||||
const windowsHash = cacheUtils.hashFileNames(fileNames)
|
||||
expect(posixHash).toBe(windowsHash)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
6
__tests__/samples/basic/.gitattributes
vendored
6
__tests__/samples/basic/.gitattributes
vendored
@@ -1,6 +0,0 @@
|
||||
#
|
||||
# https://help.github.com/articles/dealing-with-line-endings/
|
||||
#
|
||||
# These are explicitly windows files and should use crlf
|
||||
*.bat text eol=crlf
|
||||
|
6
__tests__/samples/kotlin-dsl/.gitattributes
vendored
6
__tests__/samples/kotlin-dsl/.gitattributes
vendored
@@ -1,6 +0,0 @@
|
||||
#
|
||||
# https://help.github.com/articles/dealing-with-line-endings/
|
||||
#
|
||||
# These are explicitly windows files and should use crlf
|
||||
*.bat text eol=crlf
|
||||
|
5
__tests__/samples/kotlin-dsl/.gitignore
vendored
5
__tests__/samples/kotlin-dsl/.gitignore
vendored
@@ -1,5 +0,0 @@
|
||||
# Ignore Gradle project-specific cache directory
|
||||
.gradle
|
||||
|
||||
# Ignore Gradle build output directory
|
||||
build
|
@@ -1,5 +1,5 @@
|
||||
plugins {
|
||||
id("com.gradle.enterprise") version("3.6.4")
|
||||
id("com.gradle.enterprise") version("3.7")
|
||||
}
|
||||
|
||||
gradleEnterprise {
|
||||
|
10
__tests__/samples/no-wrapper-gradle-4/build.gradle
Normal file
10
__tests__/samples/no-wrapper-gradle-4/build.gradle
Normal file
@@ -0,0 +1,10 @@
|
||||
plugins {
|
||||
id "com.gradle.build-scan" version "1.16"
|
||||
}
|
||||
|
||||
buildScan {
|
||||
termsOfServiceUrl = "https://gradle.com/terms-of-service"
|
||||
termsOfServiceAgree = "yes"
|
||||
publishAlways()
|
||||
}
|
||||
|
8
__tests__/samples/no-wrapper-gradle-4/settings.gradle
Normal file
8
__tests__/samples/no-wrapper-gradle-4/settings.gradle
Normal file
@@ -0,0 +1,8 @@
|
||||
rootProject.name = 'no-wrapper'
|
||||
|
||||
println "Using Gradle version: ${gradle.gradleVersion}"
|
||||
|
||||
def gradleVersionCheck = System.properties.gradleVersionCheck
|
||||
if (gradleVersionCheck && gradle.gradleVersion != gradleVersionCheck) {
|
||||
throw new RuntimeException("Got the wrong version: expected ${gradleVersionCheck} but was ${gradle.gradleVersion}")
|
||||
}
|
12
__tests__/samples/no-wrapper-gradle-5/build.gradle
Normal file
12
__tests__/samples/no-wrapper-gradle-5/build.gradle
Normal file
@@ -0,0 +1,12 @@
|
||||
plugins {
|
||||
id("com.gradle.build-scan") version("3.7")
|
||||
}
|
||||
|
||||
gradleEnterprise {
|
||||
buildScan {
|
||||
termsOfServiceUrl = "https://gradle.com/terms-of-service"
|
||||
termsOfServiceAgree = "yes"
|
||||
publishAlways()
|
||||
uploadInBackground = false
|
||||
}
|
||||
}
|
8
__tests__/samples/no-wrapper-gradle-5/settings.gradle
Normal file
8
__tests__/samples/no-wrapper-gradle-5/settings.gradle
Normal file
@@ -0,0 +1,8 @@
|
||||
rootProject.name = 'no-wrapper'
|
||||
|
||||
println "Using Gradle version: ${gradle.gradleVersion}"
|
||||
|
||||
def gradleVersionCheck = System.properties.gradleVersionCheck
|
||||
if (gradleVersionCheck && gradle.gradleVersion != gradleVersionCheck) {
|
||||
throw new RuntimeException("Got the wrong version: expected ${gradleVersionCheck} but was ${gradle.gradleVersion}")
|
||||
}
|
6
__tests__/samples/no-wrapper/.gitattributes
vendored
6
__tests__/samples/no-wrapper/.gitattributes
vendored
@@ -1,6 +0,0 @@
|
||||
#
|
||||
# https://help.github.com/articles/dealing-with-line-endings/
|
||||
#
|
||||
# These are explicitly windows files and should use crlf
|
||||
*.bat text eol=crlf
|
||||
|
5
__tests__/samples/no-wrapper/.gitignore
vendored
5
__tests__/samples/no-wrapper/.gitignore
vendored
@@ -1,5 +0,0 @@
|
||||
# Ignore Gradle project-specific cache directory
|
||||
.gradle
|
||||
|
||||
# Ignore Gradle build output directory
|
||||
build
|
@@ -1,3 +1,16 @@
|
||||
plugins {
|
||||
id("com.gradle.enterprise") version("3.7")
|
||||
}
|
||||
|
||||
gradleEnterprise {
|
||||
buildScan {
|
||||
termsOfServiceUrl = "https://gradle.com/terms-of-service"
|
||||
termsOfServiceAgree = "yes"
|
||||
publishAlways()
|
||||
uploadInBackground = false
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.name = 'no-wrapper'
|
||||
|
||||
println "Using Gradle version: ${gradle.gradleVersion}"
|
||||
|
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
12
package-lock.json
generated
12
package-lock.json
generated
@@ -1642,9 +1642,9 @@
|
||||
}
|
||||
},
|
||||
"ansi-regex": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
|
||||
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
||||
"dev": true
|
||||
},
|
||||
"ansi-styles": {
|
||||
@@ -6456,9 +6456,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"tmpl": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz",
|
||||
"integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=",
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
|
||||
"integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
|
||||
"dev": true
|
||||
},
|
||||
"to-fast-properties": {
|
||||
|
50
src/build-scan-capture.ts
Normal file
50
src/build-scan-capture.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import * as core from '@actions/core'
|
||||
|
||||
export function writeInitScript(): string {
|
||||
const tmpDir = process.env['RUNNER_TEMP'] || ''
|
||||
const initScript = path.resolve(tmpDir, 'build-scan-capture.init.gradle')
|
||||
core.info(`Writing init script: ${initScript}`)
|
||||
if (fs.existsSync(initScript)) {
|
||||
return initScript
|
||||
}
|
||||
fs.writeFileSync(
|
||||
initScript,
|
||||
`
|
||||
import org.gradle.util.GradleVersion
|
||||
|
||||
// Don't run against the included builds (if the main build has any).
|
||||
def isTopLevelBuild = gradle.getParent() == null
|
||||
if (isTopLevelBuild) {
|
||||
def version = GradleVersion.current().baseVersion
|
||||
def atLeastGradle4 = version >= GradleVersion.version("4.0")
|
||||
def atLeastGradle6 = version >= GradleVersion.version("6.0")
|
||||
|
||||
if (atLeastGradle6) {
|
||||
settingsEvaluated { settings ->
|
||||
if (settings.pluginManager.hasPlugin("com.gradle.enterprise")) {
|
||||
registerCallbacks(settings.extensions["gradleEnterprise"].buildScan, settings.rootProject.name)
|
||||
}
|
||||
}
|
||||
} else if (atLeastGradle4) {
|
||||
projectsEvaluated { gradle ->
|
||||
if (gradle.rootProject.pluginManager.hasPlugin("com.gradle.build-scan")) {
|
||||
registerCallbacks(gradle.rootProject.extensions["buildScan"], gradle.rootProject.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def registerCallbacks(buildScanExtension, rootProjectName) {
|
||||
buildScanExtension.with {
|
||||
def scanFile = new File("gradle-build-scan.txt")
|
||||
buildScanPublished { buildScan ->
|
||||
scanFile.text = buildScan.buildScanUri
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
)
|
||||
return initScript
|
||||
}
|
@@ -5,23 +5,24 @@ import * as core from '@actions/core'
|
||||
import * as glob from '@actions/glob'
|
||||
import * as exec from '@actions/exec'
|
||||
|
||||
import {AbstractCache, hashStrings} from './cache-utils'
|
||||
import {AbstractCache, hashFileNames} from './cache-utils'
|
||||
|
||||
// Which paths under Gradle User Home should be cached
|
||||
// TODO: This should adapt for the `GRADLE_USER_HOME` environment variable
|
||||
// TODO: Allow the user to override / tweak this set
|
||||
const CACHE_PATH = ['~/.gradle/caches', '~/.gradle/notifications']
|
||||
const CACHE_PATH = ['caches', 'notifications']
|
||||
|
||||
const COMMON_ARTIFACT_CACHES = new Map([
|
||||
['generated-gradle-jars', '~/.gradle/caches/*/generated-gradle-jars/*.jar'],
|
||||
['wrapper-zips', '~/.gradle/wrapper/dists/*/*/*.zip'],
|
||||
['dependency-jars', '~/.gradle/caches/modules-*/files-*/**/*.jar'],
|
||||
['instrumented-jars', '~/.gradle/caches/jars-*/*/*.jar']
|
||||
['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 {
|
||||
constructor() {
|
||||
private gradleUserHome: string
|
||||
|
||||
constructor(rootDir: string) {
|
||||
super('gradle', 'Gradle User Home')
|
||||
this.gradleUserHome = this.determineGradleUserHome(rootDir)
|
||||
}
|
||||
|
||||
async afterRestore(): Promise<void> {
|
||||
@@ -32,7 +33,7 @@ export class GradleUserHomeCache extends AbstractCache {
|
||||
|
||||
private async restoreCommonArtifacts(): Promise<void> {
|
||||
const processes: Promise<void>[] = []
|
||||
for (const [bundle, pattern] of COMMON_ARTIFACT_CACHES) {
|
||||
for (const [bundle, pattern] of this.getCommonArtifactPaths()) {
|
||||
const p = this.restoreCommonArtifactBundle(bundle, pattern)
|
||||
// Run sequentially when debugging enabled
|
||||
if (this.cacheDebuggingEnabled) {
|
||||
@@ -46,19 +47,19 @@ export class GradleUserHomeCache extends AbstractCache {
|
||||
|
||||
private async restoreCommonArtifactBundle(
|
||||
bundle: string,
|
||||
pattern: string
|
||||
artifactPath: string
|
||||
): Promise<void> {
|
||||
const cacheMetaFile = this.getCacheMetaFile(bundle)
|
||||
if (fs.existsSync(cacheMetaFile)) {
|
||||
const cacheKey = fs.readFileSync(cacheMetaFile, 'utf-8').trim()
|
||||
const restoreKey = await this.restoreCache([pattern], cacheKey)
|
||||
const restoreKey = await this.restoreCache([artifactPath], cacheKey)
|
||||
if (restoreKey) {
|
||||
core.info(
|
||||
`Restored ${bundle} with key ${cacheKey} to ${pattern}`
|
||||
`Restored ${bundle} with key ${cacheKey} to ${artifactPath}`
|
||||
)
|
||||
} else {
|
||||
this.debug(
|
||||
`Failed to restore ${bundle} with key ${cacheKey} to ${pattern}`
|
||||
`Failed to restore ${bundle} with key ${cacheKey} to ${artifactPath}`
|
||||
)
|
||||
}
|
||||
} else {
|
||||
@@ -70,7 +71,7 @@ export class GradleUserHomeCache extends AbstractCache {
|
||||
|
||||
private getCacheMetaFile(name: string): string {
|
||||
return path.resolve(
|
||||
this.getGradleUserHome(),
|
||||
this.gradleUserHome,
|
||||
'caches',
|
||||
`.gradle-build-action.${name}.cache`
|
||||
)
|
||||
@@ -80,15 +81,14 @@ export class GradleUserHomeCache extends AbstractCache {
|
||||
if (!this.cacheDebuggingEnabled) {
|
||||
return
|
||||
}
|
||||
const gradleUserHome = path.resolve(os.homedir(), '.gradle')
|
||||
if (!fs.existsSync(gradleUserHome)) {
|
||||
if (!fs.existsSync(this.gradleUserHome)) {
|
||||
return
|
||||
}
|
||||
const result = await exec.getExecOutput(
|
||||
'du',
|
||||
['-h', '-c', '-t', '5M'],
|
||||
{
|
||||
cwd: gradleUserHome,
|
||||
cwd: this.gradleUserHome,
|
||||
silent: true,
|
||||
ignoreReturnCode: true
|
||||
}
|
||||
@@ -116,7 +116,7 @@ export class GradleUserHomeCache extends AbstractCache {
|
||||
|
||||
private async saveCommonArtifacts(): Promise<void> {
|
||||
const processes: Promise<void>[] = []
|
||||
for (const [bundle, pattern] of COMMON_ARTIFACT_CACHES) {
|
||||
for (const [bundle, pattern] of this.getCommonArtifactPaths()) {
|
||||
const p = this.saveCommonArtifactBundle(bundle, pattern)
|
||||
// Run sequentially when debugging enabled
|
||||
if (this.cacheDebuggingEnabled) {
|
||||
@@ -130,11 +130,11 @@ export class GradleUserHomeCache extends AbstractCache {
|
||||
|
||||
private async saveCommonArtifactBundle(
|
||||
bundle: string,
|
||||
pattern: string
|
||||
artifactPath: string
|
||||
): Promise<void> {
|
||||
const cacheMetaFile = this.getCacheMetaFile(bundle)
|
||||
|
||||
const globber = await glob.create(pattern)
|
||||
const globber = await glob.create(artifactPath)
|
||||
const commonArtifactFiles = await globber.glob()
|
||||
|
||||
// Handle no matching files
|
||||
@@ -149,10 +149,7 @@ export class GradleUserHomeCache extends AbstractCache {
|
||||
const previouslyRestoredKey = fs.existsSync(cacheMetaFile)
|
||||
? fs.readFileSync(cacheMetaFile, 'utf-8').trim()
|
||||
: ''
|
||||
const cacheKey = this.createCacheKey(
|
||||
bundle,
|
||||
hashStrings(commonArtifactFiles)
|
||||
)
|
||||
const cacheKey = this.createCacheKey(bundle, commonArtifactFiles)
|
||||
|
||||
if (previouslyRestoredKey === cacheKey) {
|
||||
this.debug(
|
||||
@@ -160,7 +157,7 @@ export class GradleUserHomeCache extends AbstractCache {
|
||||
)
|
||||
} else {
|
||||
core.info(`Caching ${bundle} with cache key: ${cacheKey}`)
|
||||
await this.saveCache([pattern], cacheKey)
|
||||
await this.saveCache([artifactPath], cacheKey)
|
||||
|
||||
this.debug(`Writing cache metafile: ${cacheMetaFile}`)
|
||||
fs.writeFileSync(cacheMetaFile, cacheKey)
|
||||
@@ -171,22 +168,41 @@ export class GradleUserHomeCache extends AbstractCache {
|
||||
}
|
||||
}
|
||||
|
||||
protected createCacheKey(bundle: string, key: string): string {
|
||||
protected createCacheKey(bundle: string, files: string[]): string {
|
||||
const cacheKeyPrefix = process.env['CACHE_KEY_PREFIX'] || ''
|
||||
const relativeFiles = files.map(x =>
|
||||
path.relative(this.gradleUserHome, x)
|
||||
)
|
||||
const key = hashFileNames(relativeFiles)
|
||||
|
||||
return `${cacheKeyPrefix}${bundle}-${key}`
|
||||
}
|
||||
|
||||
protected getGradleUserHome(): string {
|
||||
protected determineGradleUserHome(rootDir: string): string {
|
||||
const customGradleUserHome = process.env['GRADLE_USER_HOME']
|
||||
if (customGradleUserHome) {
|
||||
return path.resolve(rootDir, customGradleUserHome)
|
||||
}
|
||||
|
||||
return path.resolve(os.homedir(), '.gradle')
|
||||
}
|
||||
|
||||
protected cacheOutputExists(): boolean {
|
||||
// Need to check for 'caches' directory to avoid incorrect detection on MacOS agents
|
||||
const dir = path.resolve(this.getGradleUserHome(), 'caches')
|
||||
const dir = path.resolve(this.gradleUserHome, 'caches')
|
||||
return fs.existsSync(dir)
|
||||
}
|
||||
|
||||
protected getCachePath(): string[] {
|
||||
return CACHE_PATH
|
||||
return CACHE_PATH.map(x => path.resolve(this.gradleUserHome, x))
|
||||
}
|
||||
|
||||
private getCommonArtifactPaths(): Map<string, string> {
|
||||
return new Map(
|
||||
Array.from(COMMON_ARTIFACT_CACHES, ([key, value]) => [
|
||||
key,
|
||||
path.resolve(this.gradleUserHome, value)
|
||||
])
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@ import * as core from '@actions/core'
|
||||
import * as cache from '@actions/cache'
|
||||
import * as github from '@actions/github'
|
||||
import * as crypto from 'crypto'
|
||||
import * as path from 'path'
|
||||
|
||||
export function isCacheDisabled(): boolean {
|
||||
return core.getBooleanInput('cache-disabled')
|
||||
@@ -53,6 +54,12 @@ export function hashStrings(values: string[]): string {
|
||||
return hash.digest('hex')
|
||||
}
|
||||
|
||||
export function hashFileNames(fileNames: string[]): string {
|
||||
return hashStrings(
|
||||
fileNames.map(x => x.replace(new RegExp(`\\${path.sep}`, 'g'), '/'))
|
||||
)
|
||||
}
|
||||
|
||||
class CacheKey {
|
||||
key: string
|
||||
restoreKeys: string[]
|
||||
|
@@ -14,7 +14,7 @@ export async function restore(buildRootDirectory: string): Promise<void> {
|
||||
await core.group('Restore Gradle state from cache', async () => {
|
||||
core.saveState(BUILD_ROOT_DIR, buildRootDirectory)
|
||||
return Promise.all([
|
||||
new GradleUserHomeCache().restore(),
|
||||
new GradleUserHomeCache(buildRootDirectory).restore(),
|
||||
new ProjectDotGradleCache(buildRootDirectory).restore()
|
||||
])
|
||||
})
|
||||
@@ -29,7 +29,7 @@ export async function save(): Promise<void> {
|
||||
await core.group('Caching Gradle state', async () => {
|
||||
const buildRootDirectory = core.getState(BUILD_ROOT_DIR)
|
||||
return Promise.all([
|
||||
new GradleUserHomeCache().save(),
|
||||
new GradleUserHomeCache(buildRootDirectory).save(),
|
||||
new ProjectDotGradleCache(buildRootDirectory).save()
|
||||
])
|
||||
})
|
||||
|
@@ -1,29 +1,36 @@
|
||||
import * as exec from '@actions/exec'
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import {writeInitScript} from './build-scan-capture'
|
||||
|
||||
export async function execute(
|
||||
executable: string,
|
||||
root: string,
|
||||
argv: string[]
|
||||
args: string[]
|
||||
): Promise<BuildResult> {
|
||||
let publishing = false
|
||||
let buildScanUrl: string | undefined
|
||||
|
||||
const status: number = await exec.exec(executable, argv, {
|
||||
// TODO: instead of running with no-daemon, run `--stop` in post action.
|
||||
args.push('--no-daemon')
|
||||
|
||||
const initScript = writeInitScript()
|
||||
args.push('--init-script')
|
||||
args.push(initScript)
|
||||
|
||||
const buildScanFile = path.resolve(root, 'gradle-build-scan.txt')
|
||||
if (fs.existsSync(buildScanFile)) {
|
||||
fs.unlinkSync(buildScanFile)
|
||||
}
|
||||
|
||||
const status: number = await exec.exec(executable, args, {
|
||||
cwd: root,
|
||||
ignoreReturnCode: true,
|
||||
listeners: {
|
||||
stdline: (line: string) => {
|
||||
if (line.includes('Publishing build scan...')) {
|
||||
publishing = true
|
||||
}
|
||||
if (publishing && line.startsWith('http')) {
|
||||
buildScanUrl = line.trim()
|
||||
publishing = false
|
||||
}
|
||||
}
|
||||
}
|
||||
ignoreReturnCode: true
|
||||
})
|
||||
|
||||
if (fs.existsSync(buildScanFile)) {
|
||||
buildScanUrl = fs.readFileSync(buildScanFile, 'utf-8')
|
||||
}
|
||||
|
||||
return new BuildResultImpl(status, buildScanUrl)
|
||||
}
|
||||
|
||||
|
@@ -16,8 +16,6 @@ export async function run(): Promise<void> {
|
||||
await caches.restore(buildRootDirectory)
|
||||
|
||||
const args: string[] = parseCommandLineArguments()
|
||||
// TODO: instead of running with no-daemon, run `--stop` in post action.
|
||||
args.push('--no-daemon')
|
||||
|
||||
const result = await execution.execute(
|
||||
await resolveGradleExecutable(
|
||||
|
Reference in New Issue
Block a user