mirror of
https://github.com/gradle/actions.git
synced 2025-11-26 17:09:10 +08:00
Compare commits
60 Commits
v3.5.0
...
v4.0.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6c9e547314 | ||
|
|
1a11891cfe | ||
|
|
fae6382622 | ||
|
|
81b4ac7741 | ||
|
|
c9872874b0 | ||
|
|
561dcd8516 | ||
|
|
7bb45b1dbd | ||
|
|
dc97151e55 | ||
|
|
2289da045c | ||
|
|
40a3605597 | ||
|
|
e6688f31b8 | ||
|
|
46308b920a | ||
|
|
7387edbbb3 | ||
|
|
9e459adb11 | ||
|
|
1371d49f1d | ||
|
|
8e4868ab4a | ||
|
|
5acdee61f0 | ||
|
|
32f9239e2c | ||
|
|
12cb23c359 | ||
|
|
238a3da6f4 | ||
|
|
2041ce6ab1 | ||
|
|
ded8009fcf | ||
|
|
db8e69bc03 | ||
|
|
4b56f19bda | ||
|
|
4576973cce | ||
|
|
5d7c18409c | ||
|
|
7da993afd5 | ||
|
|
de6862d826 | ||
|
|
4c453aec59 | ||
|
|
917439d87d | ||
|
|
77266ec345 | ||
|
|
514ac344fc | ||
|
|
f8aa3ed8b4 | ||
|
|
b175189376 | ||
|
|
20e923b8cb | ||
|
|
e7f9f25d86 | ||
|
|
f8f7d3e704 | ||
|
|
7a630bc41b | ||
|
|
a77cb2b0f8 | ||
|
|
54f7dc55a5 | ||
|
|
579a013225 | ||
|
|
94355bbb2f | ||
|
|
6d20c16462 | ||
|
|
b7e399239c | ||
|
|
723ca4de01 | ||
|
|
72dde7ef1e | ||
|
|
3083f01451 | ||
|
|
27dea2df09 | ||
|
|
91a526b647 | ||
|
|
d92de28b80 | ||
|
|
8d318190ad | ||
|
|
a025cbe7ec | ||
|
|
23dad2b1c7 | ||
|
|
4a315dceb2 | ||
|
|
bb7a843511 | ||
|
|
9a57bcca96 | ||
|
|
22818445b3 | ||
|
|
36c24e793d | ||
|
|
dff3ef9b8d | ||
|
|
01254b3eaa |
26
.github/workflows/ci-integ-test.yml
vendored
26
.github/workflows/ci-integ-test.yml
vendored
@@ -53,14 +53,6 @@ jobs:
|
||||
if: ${{ needs.determine-suite.outputs.suite != 'full' }}
|
||||
uses: ./.github/actions/build-dist
|
||||
|
||||
action-inputs:
|
||||
needs: [determine-suite, build-distribution]
|
||||
uses: ./.github/workflows/integ-test-action-inputs.yml
|
||||
with:
|
||||
runner-os: '${{ needs.determine-suite.outputs.runner-os }}'
|
||||
cache-key-prefix: '${{ needs.determine-suite.outputs.cache-key-prefix }}-'
|
||||
skip-dist: ${{ needs.determine-suite.outputs.suite == 'full' }}
|
||||
|
||||
build-scan-publish:
|
||||
needs: [determine-suite, build-distribution]
|
||||
uses: ./.github/workflows/integ-test-build-scan-publish.yml
|
||||
@@ -74,7 +66,7 @@ jobs:
|
||||
uses: ./.github/workflows/integ-test-cache-cleanup.yml
|
||||
with:
|
||||
runner-os: '${{ needs.determine-suite.outputs.runner-os }}'
|
||||
cache-key-prefix: '${{github.run_number}}-' # Requires a fresh cache entry each run
|
||||
cache-key-prefix: '${{ needs.determine-suite.outputs.suite}}-${{github.run_number}}-' # Requires a fresh cache entry each run
|
||||
skip-dist: ${{ needs.determine-suite.outputs.suite == 'full' }}
|
||||
|
||||
caching-config:
|
||||
@@ -118,22 +110,6 @@ jobs:
|
||||
cache-key-prefix: '${{ needs.determine-suite.outputs.cache-key-prefix }}-'
|
||||
skip-dist: ${{ needs.determine-suite.outputs.suite == 'full' }}
|
||||
|
||||
execution-with-caching:
|
||||
needs: [determine-suite, build-distribution]
|
||||
uses: ./.github/workflows/integ-test-execution-with-caching.yml
|
||||
with:
|
||||
runner-os: '${{ needs.determine-suite.outputs.runner-os }}'
|
||||
cache-key-prefix: '${{ needs.determine-suite.outputs.cache-key-prefix }}-'
|
||||
skip-dist: ${{ needs.determine-suite.outputs.suite == 'full' }}
|
||||
|
||||
execution:
|
||||
needs: [determine-suite, build-distribution]
|
||||
uses: ./.github/workflows/integ-test-execution.yml
|
||||
with:
|
||||
runner-os: '${{ needs.determine-suite.outputs.runner-os }}'
|
||||
cache-key-prefix: '${{ needs.determine-suite.outputs.cache-key-prefix }}-'
|
||||
skip-dist: ${{ needs.determine-suite.outputs.suite == 'full' }}
|
||||
|
||||
develocity-injection:
|
||||
if: ${{ ! github.event.pull_request.head.repo.fork }}
|
||||
needs: [determine-suite, build-distribution]
|
||||
|
||||
62
.github/workflows/demo-failure-cases.yml
vendored
62
.github/workflows/demo-failure-cases.yml
vendored
@@ -1,62 +0,0 @@
|
||||
name: demo-failure-cases
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-distribution:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v4
|
||||
- name: Build and upload distribution
|
||||
uses: ./.github/actions/build-dist
|
||||
|
||||
failing-build:
|
||||
needs: build-distribution
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v4
|
||||
- name: Initialize integ-test
|
||||
uses: ./.github/actions/init-integ-test
|
||||
|
||||
- name: Test build failure
|
||||
uses: ./setup-gradle
|
||||
continue-on-error: true
|
||||
with:
|
||||
build-root-directory: .github/workflow-samples/kotlin-dsl
|
||||
arguments: not-a-valid-task
|
||||
|
||||
wrapper-missing:
|
||||
needs: build-distribution
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v4
|
||||
- name: Initialize integ-test
|
||||
uses: ./.github/actions/init-integ-test
|
||||
|
||||
- name: Test wrapper missing
|
||||
uses: ./setup-gradle
|
||||
continue-on-error: true
|
||||
with:
|
||||
build-root-directory: .github/workflow-samples/no-wrapper
|
||||
arguments: help
|
||||
|
||||
bad-configuration:
|
||||
needs: build-distribution
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v4
|
||||
- name: Initialize integ-test
|
||||
uses: ./.github/actions/init-integ-test
|
||||
|
||||
- name: Test bad config value
|
||||
uses: ./setup-gradle
|
||||
continue-on-error: true
|
||||
with:
|
||||
build-root-directory: .github/workflow-samples/no-wrapper
|
||||
arguments: help
|
||||
cache-disabled: yes
|
||||
3
.github/workflows/demo-job-summary.yml
vendored
3
.github/workflows/demo-job-summary.yml
vendored
@@ -23,6 +23,9 @@ jobs:
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: ./setup-gradle
|
||||
with:
|
||||
cache-read-only: false
|
||||
cache-cleanup: 'on-success'
|
||||
- name: Build kotlin-dsl project
|
||||
working-directory: .github/workflow-samples/kotlin-dsl
|
||||
run: ./gradlew assemble
|
||||
|
||||
42
.github/workflows/integ-test-action-inputs.yml
vendored
42
.github/workflows/integ-test-action-inputs.yml
vendored
@@ -1,42 +0,0 @@
|
||||
name: Test action inputs
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
cache-key-prefix:
|
||||
type: string
|
||||
runner-os:
|
||||
type: string
|
||||
default: '["ubuntu-latest", "windows-latest", "macos-latest"]'
|
||||
skip-dist:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
env:
|
||||
SKIP_DIST: ${{ inputs.skip-dist }}
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: action-inputs-${{ inputs.cache-key-prefix }}
|
||||
|
||||
jobs:
|
||||
action-inputs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: ${{fromJSON(inputs.runner-os)}}
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v4
|
||||
- name: Initialize integ-test
|
||||
uses: ./.github/actions/init-integ-test
|
||||
|
||||
- name: Invoke with multi-line arguments
|
||||
uses: ./setup-gradle
|
||||
with:
|
||||
build-root-directory: .github/workflow-samples/groovy-dsl
|
||||
arguments: |
|
||||
--configuration-cache
|
||||
--build-cache
|
||||
-DsystemProperty=FOO
|
||||
-PgradleProperty=BAR
|
||||
test
|
||||
jar
|
||||
13
.github/workflows/integ-test-cache-cleanup.yml
vendored
13
.github/workflows/integ-test-cache-cleanup.yml
vendored
@@ -55,7 +55,7 @@ jobs:
|
||||
uses: ./setup-gradle
|
||||
with:
|
||||
cache-read-only: false
|
||||
gradle-home-cache-cleanup: true
|
||||
cache-cleanup: 'on-success'
|
||||
- name: Build with 3.1.1
|
||||
working-directory: sources/test/jest/resources/cache-cleanup
|
||||
run: ./gradlew --no-daemon --build-cache -Dcommons_math3_version="3.1.1" build
|
||||
@@ -78,21 +78,22 @@ jobs:
|
||||
with:
|
||||
cache-read-only: true
|
||||
- name: Report Gradle User Home
|
||||
shell: bash
|
||||
run: |
|
||||
du -hc ~/.gradle/caches/modules-2
|
||||
du -hc ~/.gradle/wrapper/dists
|
||||
du -hc $GRADLE_USER_HOME/caches/modules-2
|
||||
du -hc $GRADLE_USER_HOME/wrapper/dists
|
||||
- name: Verify cleaned cache
|
||||
shell: bash
|
||||
run: |
|
||||
if [ ! -e ~/.gradle/caches/modules-2/files-2.1/org.apache.commons/commons-math3/3.1.1 ]; then
|
||||
if [ ! -e $GRADLE_USER_HOME/caches/modules-2/files-2.1/org.apache.commons/commons-math3/3.1.1 ]; then
|
||||
echo "::error ::Should find commons-math3 3.1.1 in cache"
|
||||
exit 1
|
||||
fi
|
||||
if [ -e ~/.gradle/caches/modules-2/files-2.1/org.apache.commons/commons-math3/3.1 ]; then
|
||||
if [ -e $GRADLE_USER_HOME/caches/modules-2/files-2.1/org.apache.commons/commons-math3/3.1 ]; then
|
||||
echo "::error ::Should NOT find commons-math3 3.1 in cache"
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -e ~/.gradle/wrapper/dists/gradle-8.0.2-bin ]; then
|
||||
if [ ! -e $GRADLE_USER_HOME/wrapper/dists/gradle-8.0.2-bin ]; then
|
||||
echo "::error ::Should find gradle-8.0.2 in wrapper/dists"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -21,7 +21,7 @@ env:
|
||||
GITHUB_DEPENDENCY_GRAPH_REF: 'refs/tags/v0.0.1' # Use a different ref to avoid updating the real dependency graph for the repository
|
||||
|
||||
jobs:
|
||||
groovy-generate:
|
||||
groovy-upload:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -42,7 +42,7 @@ jobs:
|
||||
working-directory: .github/workflow-samples/groovy-dsl
|
||||
|
||||
groovy-submit:
|
||||
needs: [groovy-generate]
|
||||
needs: [groovy-upload]
|
||||
runs-on: "ubuntu-latest"
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
@@ -54,6 +54,8 @@ jobs:
|
||||
uses: ./setup-gradle
|
||||
with:
|
||||
dependency-graph: download-and-submit
|
||||
env:
|
||||
DEPENDENCY_GRAPH_DOWNLOAD_ARTIFACT_NAME: groovy-upload
|
||||
|
||||
kotlin-generate-and-submit:
|
||||
strategy:
|
||||
|
||||
@@ -80,6 +80,8 @@ jobs:
|
||||
uses: ./dependency-submission
|
||||
with:
|
||||
dependency-graph: download-and-submit
|
||||
env:
|
||||
DEPENDENCY_GRAPH_DOWNLOAD_ARTIFACT_NAME: groovy-generate-and-upload-${{ matrix.os }}
|
||||
|
||||
kotlin-generate-and-submit:
|
||||
strategy:
|
||||
@@ -225,12 +227,8 @@ jobs:
|
||||
gradle-version: ${{ matrix.gradle }}
|
||||
build-root-directory: .github/workflow-samples/no-wrapper${{ matrix.build-root-suffix }}
|
||||
|
||||
after-setup-gradle:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: ${{fromJSON(inputs.runner-os)}}
|
||||
runs-on: ${{ matrix.os }}
|
||||
with-setup-gradle:
|
||||
runs-on: ubuntu-latest # Test is not compatible with Windows
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v4
|
||||
@@ -244,6 +242,59 @@ jobs:
|
||||
uses: ./dependency-submission
|
||||
with:
|
||||
build-root-directory: .github/workflow-samples/groovy-dsl
|
||||
- name: Check and delete generated dependency graph
|
||||
shell: bash
|
||||
run: |
|
||||
if [ ! -e "${{ steps.dependency-submission.outputs.dependency-graph-file }}" ]; then
|
||||
echo "Did not find generated dependency graph files"
|
||||
exit 1
|
||||
fi
|
||||
rm ${{ steps.dependency-submission.outputs.dependency-graph-file }}*
|
||||
- name: Run Gradle build
|
||||
run: ./gradlew build
|
||||
working-directory: .github/workflow-samples/groovy-dsl
|
||||
- name: Check no dependency graph is generated
|
||||
shell: bash
|
||||
run: |
|
||||
if [ ! -z "$(ls -A dependency-graph-reports)" ]; then
|
||||
echo "Expected no dependency graph files to be generated"
|
||||
ls -l dependency-graph-reports
|
||||
exit 1
|
||||
fi
|
||||
|
||||
with-includes-and-excludes:
|
||||
runs-on: ubuntu-latest # Test is not compatible with Windows
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v4
|
||||
- name: Initialize integ-test
|
||||
uses: ./.github/actions/init-integ-test
|
||||
|
||||
- name: Generate and submit dependencies
|
||||
id: dependency-submission
|
||||
uses: ./dependency-submission
|
||||
with:
|
||||
build-root-directory: .github/workflow-samples/groovy-dsl
|
||||
dependency-graph-exclude-projects: excluded-project
|
||||
dependency-graph-include-projects: included-project
|
||||
dependency-graph-exclude-configurations: excluded-configuration
|
||||
dependency-graph-include-configurations: included-configuration
|
||||
- name: Check generated dependency graph and env vars
|
||||
shell: bash
|
||||
run: |
|
||||
if [ ! -e "${{ steps.dependency-submission.outputs.dependency-graph-file }}" ]; then
|
||||
echo "Did not find generated dependency graph file"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$DEPENDENCY_GRAPH_EXCLUDE_PROJECTS" != "excluded-project" ] ||
|
||||
[ "$DEPENDENCY_GRAPH_INCLUDE_PROJECTS" != "included-project" ] ||
|
||||
[ "$DEPENDENCY_GRAPH_EXCLUDE_CONFIGURATIONS" != "excluded-configuration" ] ||
|
||||
[ "$DEPENDENCY_GRAPH_INCLUDE_CONFIGURATIONS" != "included-configuration" ]; then
|
||||
echo "Did not set expected environment variables"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
custom-report-dir-submit:
|
||||
strategy:
|
||||
@@ -262,9 +313,8 @@ jobs:
|
||||
uses: ./dependency-submission
|
||||
with:
|
||||
dependency-graph: generate-and-submit
|
||||
dependency-graph-report-dir: '${{ github.workspace }}/custom/report-dir'
|
||||
build-root-directory: .github/workflow-samples/groovy-dsl
|
||||
env:
|
||||
DEPENDENCY_GRAPH_REPORT_DIR: '${{ github.workspace }}/custom/report-dir'
|
||||
- name: Check generated dependency graphs
|
||||
shell: bash
|
||||
run: |
|
||||
@@ -293,9 +343,8 @@ jobs:
|
||||
uses: ./dependency-submission
|
||||
with:
|
||||
dependency-graph: generate-and-upload
|
||||
dependency-graph-report-dir: '${{ github.workspace }}/custom/report-dir'
|
||||
build-root-directory: .github/workflow-samples/groovy-dsl
|
||||
env:
|
||||
DEPENDENCY_GRAPH_REPORT_DIR: '${{ github.workspace }}/custom/report-dir'
|
||||
|
||||
custom-report-dir-download-and-submit:
|
||||
needs: custom-report-dir-upload
|
||||
@@ -310,9 +359,11 @@ jobs:
|
||||
uses: ./dependency-submission
|
||||
with:
|
||||
dependency-graph: download-and-submit
|
||||
dependency-graph-report-dir: '${{ github.workspace }}/custom/report-dir'
|
||||
build-root-directory: .github/workflow-samples/groovy-dsl
|
||||
env:
|
||||
DEPENDENCY_GRAPH_REPORT_DIR: '${{ github.workspace }}/custom/report-dir'
|
||||
DEPENDENCY_GRAPH_DOWNLOAD_ARTIFACT_NAME: custom-report-dir-upload # For testing, to avoid downloading artifacts from other worklfows
|
||||
|
||||
- name: Check downloaded dependency graph
|
||||
shell: bash
|
||||
run: |
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
name: Test execution with caching
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
cache-key-prefix:
|
||||
type: string
|
||||
runner-os:
|
||||
type: string
|
||||
default: '["ubuntu-latest", "windows-latest", "macos-latest"]'
|
||||
skip-dist:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
env:
|
||||
SKIP_DIST: ${{ inputs.skip-dist }}
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: execution-with-caching-${{ inputs.cache-key-prefix }}
|
||||
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
||||
|
||||
jobs:
|
||||
seed-build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: ${{fromJSON(inputs.runner-os)}}
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v4
|
||||
- name: Initialize integ-test
|
||||
uses: ./.github/actions/init-integ-test
|
||||
|
||||
- name: Execute Gradle build
|
||||
uses: ./setup-gradle
|
||||
with:
|
||||
cache-read-only: false # For testing, allow writing cache entries on non-default branches
|
||||
build-root-directory: .github/workflow-samples/groovy-dsl
|
||||
arguments: test
|
||||
|
||||
# Test that the gradle-user-home is restored
|
||||
verify-build:
|
||||
needs: seed-build
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: ${{fromJSON(inputs.runner-os)}}
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v4
|
||||
- name: Initialize integ-test
|
||||
uses: ./.github/actions/init-integ-test
|
||||
|
||||
- name: Execute Gradle build
|
||||
uses: ./setup-gradle
|
||||
with:
|
||||
cache-read-only: true
|
||||
build-root-directory: .github/workflow-samples/groovy-dsl
|
||||
arguments: test --offline -DverifyCachedBuild=true
|
||||
|
||||
102
.github/workflows/integ-test-execution.yml
vendored
102
.github/workflows/integ-test-execution.yml
vendored
@@ -1,102 +0,0 @@
|
||||
name: Test execution
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
cache-key-prefix:
|
||||
type: string
|
||||
runner-os:
|
||||
type: string
|
||||
default: '["ubuntu-latest", "windows-latest", "macos-latest"]'
|
||||
skip-dist:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
env:
|
||||
SKIP_DIST: ${{ inputs.skip-dist }}
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: execution-${{ inputs.cache-key-prefix }}
|
||||
|
||||
jobs:
|
||||
# Tests for executing with different Gradle versions.
|
||||
# Each build verifies that it is executed with the expected Gradle version.
|
||||
gradle-execution:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: ${{fromJSON(inputs.runner-os)}}
|
||||
include:
|
||||
- os: windows-latest
|
||||
script-suffix: '.bat'
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v4
|
||||
- name: Initialize integ-test
|
||||
uses: ./.github/actions/init-integ-test
|
||||
|
||||
- name: Test use defined Gradle version
|
||||
uses: ./setup-gradle
|
||||
with:
|
||||
cache-read-only: false # For testing, allow writing cache entries on non-default branches
|
||||
gradle-version: 6.9
|
||||
build-root-directory: .github/workflow-samples/no-wrapper
|
||||
arguments: help -DgradleVersionCheck=6.9
|
||||
- name: Test use Gradle version alias
|
||||
uses: ./setup-gradle
|
||||
with:
|
||||
gradle-version: release-candidate
|
||||
build-root-directory: .github/workflow-samples/no-wrapper
|
||||
arguments: help
|
||||
- name: Test with non-executable wrapper
|
||||
uses: ./setup-gradle
|
||||
with:
|
||||
gradle-version: wrapper
|
||||
build-root-directory: .github/workflow-samples/non-executable-wrapper
|
||||
arguments: help
|
||||
|
||||
gradle-versions:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
gradle: [7.5.1, 6.9.2, 5.6.4, 4.10.3, 3.5.1]
|
||||
os: ${{fromJSON(inputs.runner-os)}}
|
||||
include:
|
||||
- java-version: 11
|
||||
- gradle: 5.6.4
|
||||
build-root-suffix: -gradle-5
|
||||
- gradle: 4.10.3
|
||||
build-root-suffix: -gradle-4
|
||||
- gradle: 3.5.1
|
||||
build-root-suffix: -gradle-4
|
||||
java-version: 8
|
||||
exclude:
|
||||
- os: macos-latest # Java 8 is not supported on macos-latest, so we cannot test Gradle 3.5.1
|
||||
gradle: 3.5.1
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v4
|
||||
- name: Initialize integ-test
|
||||
uses: ./.github/actions/init-integ-test
|
||||
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: ${{ matrix.java-version }}
|
||||
- name: Run Gradle build
|
||||
uses: ./setup-gradle
|
||||
id: gradle
|
||||
with:
|
||||
cache-read-only: false # For testing, allow writing cache entries on non-default branches
|
||||
gradle-version: ${{matrix.gradle}}
|
||||
build-root-directory: .github/workflow-samples/no-wrapper${{ matrix.build-root-suffix }}
|
||||
arguments: help -DgradleVersionCheck=${{matrix.gradle}}
|
||||
- name: Check Build Scan url
|
||||
if: ${{ !steps.gradle.outputs.build-scan-url }}
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
core.setFailed('No Build Scan detected')
|
||||
|
||||
|
||||
@@ -25,9 +25,6 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: ${{fromJSON(inputs.runner-os)}}
|
||||
include:
|
||||
- os: windows-latest
|
||||
script-suffix: '.bat'
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
@@ -62,6 +59,9 @@ jobs:
|
||||
uses: ./setup-gradle
|
||||
with:
|
||||
gradle-version: current
|
||||
- name: Test use current
|
||||
working-directory: .github/workflow-samples/no-wrapper
|
||||
run: gradle help
|
||||
- name: Check current version output parameter
|
||||
if: ${{ !startsWith(steps.gradle-current.outputs.gradle-version , '8.') }}
|
||||
uses: actions/github-script@v7
|
||||
@@ -73,7 +73,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
gradle: [7.3, 6.9, 5.6.4, 4.10.3, 3.5.1]
|
||||
gradle: [8.9, 8.8, 7.6.4, 6.9.4, 5.6.4, 4.10.3, 3.5.1] # 8.8 is the latest installed on windows runners
|
||||
os: ${{fromJSON(inputs.runner-os)}}
|
||||
include:
|
||||
- java-version: 11
|
||||
|
||||
@@ -43,6 +43,7 @@ jobs:
|
||||
uses: ./setup-gradle
|
||||
with:
|
||||
cache-read-only: false # For testing, allow writing cache entries on non-default branches
|
||||
cache-write-only: true # Ensure we start with a clean cache entry
|
||||
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
|
||||
gradle-version: 8.6
|
||||
- name: Groovy build with configuration-cache enabled
|
||||
@@ -52,6 +53,7 @@ jobs:
|
||||
verify-build-groovy:
|
||||
env:
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_JOB: restore-cc-groovy
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_JOB_EXECUTION: ${{github.sha}}_1
|
||||
needs: seed-build-groovy
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -64,6 +66,47 @@ jobs:
|
||||
- name: Initialize integ-test
|
||||
uses: ./.github/actions/init-integ-test
|
||||
|
||||
- name: Setup Java to ensure consistency
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'liberica'
|
||||
java-version: 17
|
||||
- name: Setup Gradle
|
||||
uses: ./setup-gradle
|
||||
with:
|
||||
cache-read-only: false
|
||||
cache-cleanup: on-success
|
||||
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
|
||||
gradle-version: 8.6
|
||||
- name: Groovy build with configuration-cache enabled
|
||||
id: execute
|
||||
working-directory: .github/workflow-samples/groovy-dsl
|
||||
run: gradle test --configuration-cache
|
||||
- name: Verify configuration-cache hit
|
||||
shell: bash
|
||||
run: |
|
||||
if [ -e ".github/workflow-samples/groovy-dsl/task-configured.txt" ]; then
|
||||
echo "Configuration cache was not used - task was configured unexpectedly"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Ensure that cache-cleanup doesn't remove all necessary files
|
||||
verify-no-cache-cleanup-groovy:
|
||||
env:
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_JOB: restore-cc-groovy
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_JOB_EXECUTION: ${{github.sha}}_2
|
||||
needs: verify-build-groovy
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: ${{fromJSON(inputs.runner-os)}}
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v4
|
||||
- name: Initialize integ-test
|
||||
uses: ./.github/actions/init-integ-test
|
||||
|
||||
- name: Setup Java to ensure consistency
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
@@ -79,19 +122,19 @@ jobs:
|
||||
id: execute
|
||||
working-directory: .github/workflow-samples/groovy-dsl
|
||||
run: gradle test --configuration-cache
|
||||
- name: Check that configuration-cache was used
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs')
|
||||
if (fs.existsSync('.github/workflow-samples/groovy-dsl/task-configured.txt')) {
|
||||
core.setFailed('Configuration cache was not used - task was configured unexpectedly')
|
||||
}
|
||||
- name: Verify configuration-cache hit
|
||||
shell: bash
|
||||
run: |
|
||||
if [ -e ".github/workflow-samples/groovy-dsl/task-configured.txt" ]; then
|
||||
echo "Configuration cache was not used - task was configured unexpectedly"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check that the build can run when no extracted cache entries are restored
|
||||
gradle-user-home-not-fully-restored:
|
||||
env:
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_JOB: restore-cc-groovy
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_JOB_EXECUTION: ${{github.sha}}_x
|
||||
needs: seed-build-groovy
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -144,6 +187,7 @@ jobs:
|
||||
uses: ./setup-gradle
|
||||
with:
|
||||
cache-read-only: false # For testing, allow writing cache entries on non-default branches
|
||||
cache-write-only: true # Ensure we start with a clean cache entry
|
||||
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
|
||||
gradle-version: 8.6
|
||||
- name: Execute 'help' with configuration-cache enabled
|
||||
@@ -152,7 +196,8 @@ jobs:
|
||||
|
||||
modify-build-kotlin:
|
||||
env:
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_JOB: restore-cc-kotlin-modified
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_JOB: restore-cc-kotlin
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_JOB_EXECUTION: ${{github.sha}}_1
|
||||
needs: seed-build-kotlin
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -183,7 +228,8 @@ jobs:
|
||||
# Test restore configuration-cache from the third build invocation
|
||||
verify-build-kotlin:
|
||||
env:
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_JOB: restore-cc-kotlin-modified
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_JOB: restore-cc-kotlin
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_JOB_EXECUTION: ${{github.sha}}_2
|
||||
needs: modify-build-kotlin
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -211,12 +257,10 @@ jobs:
|
||||
id: execute
|
||||
working-directory: .github/workflow-samples/kotlin-dsl
|
||||
run: gradle test --configuration-cache
|
||||
- name: Check that configuration-cache was used
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs')
|
||||
if (fs.existsSync('.github/workflow-samples/kotlin-dsl/task-configured.txt')) {
|
||||
core.setFailed('Configuration cache was not used - task was configured unexpectedly')
|
||||
}
|
||||
|
||||
- name: Verify configuration-cache hit
|
||||
shell: bash
|
||||
run: |
|
||||
if [ -e ".github/workflow-samples/kotlin-dsl/task-configured.txt" ]; then
|
||||
echo "Configuration cache was not used - task was configured unexpectedly"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -57,6 +57,19 @@ inputs:
|
||||
Configuration-cache data will not be saved/restored without an encryption key being provided.
|
||||
required: false
|
||||
|
||||
cache-cleanup:
|
||||
description: |
|
||||
Specifies if the action should attempt to remove any stale/unused entries from the Gradle User Home prior to saving to the GitHub Actions cache.
|
||||
By default, no cleanup is performed. It can be configured to run every time, or only when all Gradle builds succeed for the Job.
|
||||
Valid values are 'never', 'on-success' and 'always'.
|
||||
required: false
|
||||
default: 'on-success'
|
||||
|
||||
gradle-home-cache-cleanup:
|
||||
description: When 'true', the action will attempt to remove any stale/unused entries from the Gradle User Home prior to saving to the GitHub Actions cache.
|
||||
required: false
|
||||
deprecation-message: This input has been superceded by the 'cache-cleanup' input parameter.
|
||||
|
||||
gradle-home-cache-includes:
|
||||
description: Paths within Gradle User Home to cache.
|
||||
required: false
|
||||
@@ -68,11 +81,6 @@ inputs:
|
||||
description: Paths within Gradle User Home to exclude from cache.
|
||||
required: false
|
||||
|
||||
gradle-home-cache-cleanup:
|
||||
description: When 'true', the action will attempt to remove any stale/unused entries from the Gradle User Home prior to saving to the GitHub Actions cache.
|
||||
required: false
|
||||
default: false
|
||||
|
||||
# Job summary configuration
|
||||
add-job-summary:
|
||||
description: Specifies when a Job Summary should be inluded in the action results. Valid values are 'never', 'always' (default), and 'on-failure'.
|
||||
@@ -99,11 +107,42 @@ inputs:
|
||||
required: false
|
||||
default: 'generate-and-submit'
|
||||
|
||||
dependency-graph-report-dir:
|
||||
description: |
|
||||
Specifies where the dependency graph report will be generated.
|
||||
Paths can relative or absolute. Relative paths are resolved relative to the workspace directory.
|
||||
required: false
|
||||
default: 'dependency-graph-reports'
|
||||
|
||||
dependency-graph-continue-on-failure:
|
||||
description: When 'false' a failure to generate or submit a dependency graph will fail the Step or Job. When 'true' a warning will be emitted but no failure will result.
|
||||
required: false
|
||||
default: false
|
||||
|
||||
dependency-graph-exclude-projects:
|
||||
description: |
|
||||
Gradle projects that should be excluded from dependency graph (regular expression).
|
||||
When set, any matching project will be excluded.
|
||||
required: false
|
||||
|
||||
dependency-graph-include-projects:
|
||||
description: |
|
||||
Gradle projects that should be included in dependency graph (regular expression).
|
||||
When set, only matching projects will be included.
|
||||
required: false
|
||||
|
||||
dependency-graph-exclude-configurations:
|
||||
description: |
|
||||
Gradle configurations that should be included in dependency graph (regular expression).
|
||||
When set, anymatching configurations will be excluded.
|
||||
required: false
|
||||
|
||||
dependency-graph-include-configurations:
|
||||
description: |
|
||||
Gradle configurations that should be included in dependency graph (regular expression).
|
||||
When set, only matching configurations will be included.
|
||||
required: false
|
||||
|
||||
artifact-retention-days:
|
||||
description: Specifies the number of days to retain any artifacts generated by the action. If not set, the default retention settings for the repository will apply.
|
||||
required: false
|
||||
@@ -134,21 +173,6 @@ inputs:
|
||||
required: false
|
||||
|
||||
# DEPRECATED ACTION INPUTS
|
||||
build-scan-terms-of-service-url:
|
||||
description: The URL to the Build Scan® terms of use. This input must be set to 'https://gradle.com/terms-of-service'.
|
||||
required: false
|
||||
deprecation-message: The input has been renamed to align with the Develocity API. Use 'build-scan-terms-of-use-url' instead.
|
||||
|
||||
build-scan-terms-of-service-agree:
|
||||
description: Indicate that you agree to the Build Scan® terms of use. This input value must be "yes".
|
||||
required: false
|
||||
deprecation-message: The input has been renamed to align with the Develocity API. Use 'build-scan-terms-of-use-agree' instead.
|
||||
|
||||
generate-job-summary:
|
||||
description: When 'false', no Job Summary will be generated for the Job.
|
||||
required: false
|
||||
default: true
|
||||
deprecation-message: Superceded by the new 'add-job-summary' and 'add-job-summary-as-pr-comment' parameters.
|
||||
|
||||
# EXPERIMENTAL ACTION INPUTS
|
||||
# The following action properties allow fine-grained tweaking of the action caching behaviour.
|
||||
|
||||
892
dist/dependency-submission/main/index.js
vendored
892
dist/dependency-submission/main/index.js
vendored
File diff suppressed because it is too large
Load Diff
2
dist/dependency-submission/main/index.js.map
vendored
2
dist/dependency-submission/main/index.js.map
vendored
File diff suppressed because one or more lines are too long
868
dist/dependency-submission/post/index.js
vendored
868
dist/dependency-submission/post/index.js
vendored
File diff suppressed because it is too large
Load Diff
2
dist/dependency-submission/post/index.js.map
vendored
2
dist/dependency-submission/post/index.js.map
vendored
File diff suppressed because one or more lines are too long
909
dist/setup-gradle/main/index.js
vendored
909
dist/setup-gradle/main/index.js
vendored
File diff suppressed because it is too large
Load Diff
2
dist/setup-gradle/main/index.js.map
vendored
2
dist/setup-gradle/main/index.js.map
vendored
File diff suppressed because one or more lines are too long
892
dist/setup-gradle/post/index.js
vendored
892
dist/setup-gradle/post/index.js
vendored
File diff suppressed because it is too large
Load Diff
2
dist/setup-gradle/post/index.js.map
vendored
2
dist/setup-gradle/post/index.js.map
vendored
File diff suppressed because one or more lines are too long
373
dist/wrapper-validation/main/index.js
vendored
373
dist/wrapper-validation/main/index.js
vendored
@@ -89853,6 +89853,70 @@ function wrappy (fn, cb) {
|
||||
}).call(this);
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 2401:
|
||||
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
||||
|
||||
"use strict";
|
||||
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.run = void 0;
|
||||
const path = __importStar(__nccwpck_require__(1017));
|
||||
const core = __importStar(__nccwpck_require__(2186));
|
||||
const validate = __importStar(__nccwpck_require__(8568));
|
||||
const configuration_1 = __nccwpck_require__(5778);
|
||||
const deprecation_collector_1 = __nccwpck_require__(2572);
|
||||
const errors_1 = __nccwpck_require__(6976);
|
||||
async function run() {
|
||||
try {
|
||||
if ((0, configuration_1.getActionId)() === 'gradle/wrapper-validation-action') {
|
||||
(0, deprecation_collector_1.failOnUseOfRemovedFeature)('The action `gradle/wrapper-validation-action` has been replaced by `gradle/actions/wrapper-validation`');
|
||||
}
|
||||
(0, configuration_1.setActionId)('gradle/actions/wrapper-validation');
|
||||
const result = await validate.findInvalidWrapperJars(path.resolve('.'), +core.getInput('min-wrapper-count'), core.getInput('allow-snapshots') === 'true', core.getInput('allow-checksums').split(','));
|
||||
if (result.isValid()) {
|
||||
core.info(result.toDisplayString());
|
||||
}
|
||||
else {
|
||||
core.setFailed(`Gradle Wrapper Validation Failed!\n See https://github.com/gradle/actions/blob/main/docs/wrapper-validation.md#reporting-failures\n${result.toDisplayString()}`);
|
||||
if (result.invalid.length > 0) {
|
||||
core.setOutput('failed-wrapper', `${result.invalid.map(w => w.path).join('|')}`);
|
||||
}
|
||||
}
|
||||
(0, deprecation_collector_1.emitDeprecationWarnings)(false);
|
||||
}
|
||||
catch (error) {
|
||||
(0, errors_1.handleMainActionError)(error);
|
||||
}
|
||||
}
|
||||
exports.run = run;
|
||||
run();
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 5778:
|
||||
@@ -89887,13 +89951,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.parseNumericInput = exports.setActionId = exports.getActionId = exports.getWorkspaceDirectory = exports.getGithubToken = exports.getJobMatrix = exports.doValidateWrappers = exports.GradleExecutionConfig = exports.BuildScanConfig = exports.JobSummaryOption = exports.SummaryConfig = exports.CacheConfig = exports.DependencyGraphOption = exports.DependencyGraphConfig = void 0;
|
||||
exports.parseNumericInput = exports.setActionId = exports.getActionId = exports.getWorkspaceDirectory = exports.getGithubToken = exports.getJobMatrix = exports.doValidateWrappers = exports.GradleExecutionConfig = exports.BuildScanConfig = exports.JobSummaryOption = exports.SummaryConfig = exports.CacheCleanupOption = exports.CacheConfig = exports.DependencyGraphOption = exports.DependencyGraphConfig = void 0;
|
||||
const core = __importStar(__nccwpck_require__(2186));
|
||||
const github = __importStar(__nccwpck_require__(5438));
|
||||
const cache = __importStar(__nccwpck_require__(7799));
|
||||
const deprecator = __importStar(__nccwpck_require__(2572));
|
||||
const summary_1 = __nccwpck_require__(1327);
|
||||
const string_argv_1 = __nccwpck_require__(9663);
|
||||
const path_1 = __importDefault(__nccwpck_require__(1017));
|
||||
const ACTION_ID_VAR = 'GRADLE_ACTION_ID';
|
||||
class DependencyGraphConfig {
|
||||
@@ -89910,10 +89973,8 @@ class DependencyGraphConfig {
|
||||
return DependencyGraphOption.GenerateAndUpload;
|
||||
case 'download-and-submit':
|
||||
return DependencyGraphOption.DownloadAndSubmit;
|
||||
case 'clear':
|
||||
return DependencyGraphOption.Clear;
|
||||
}
|
||||
throw TypeError(`The value '${val}' is not valid for 'dependency-graph'. Valid values are: [disabled, generate, generate-and-submit, generate-and-upload, download-and-submit, clear]. The default value is 'disabled'.`);
|
||||
throw TypeError(`The value '${val}' is not valid for 'dependency-graph'. Valid values are: [disabled, generate, generate-and-submit, generate-and-upload, download-and-submit]. The default value is 'disabled'.`);
|
||||
}
|
||||
getDependencyGraphContinueOnFailure() {
|
||||
return getBooleanInput('dependency-graph-continue-on-failure', true);
|
||||
@@ -89926,7 +89987,23 @@ class DependencyGraphConfig {
|
||||
return DependencyGraphConfig.constructJobCorrelator(github.context.workflow, github.context.job, getJobMatrix());
|
||||
}
|
||||
getReportDirectory() {
|
||||
return path_1.default.resolve(getWorkspaceDirectory(), 'dependency-graph-reports');
|
||||
const param = core.getInput('dependency-graph-report-dir');
|
||||
return path_1.default.resolve(getWorkspaceDirectory(), param);
|
||||
}
|
||||
getDownloadArtifactName() {
|
||||
return process.env['DEPENDENCY_GRAPH_DOWNLOAD_ARTIFACT_NAME'];
|
||||
}
|
||||
getExcludeProjects() {
|
||||
return getOptionalInput('dependency-graph-exclude-projects');
|
||||
}
|
||||
getIncludeProjects() {
|
||||
return getOptionalInput('dependency-graph-include-projects');
|
||||
}
|
||||
getExcludeConfigurations() {
|
||||
return getOptionalInput('dependency-graph-exclude-configurations');
|
||||
}
|
||||
getIncludeConfigurations() {
|
||||
return getOptionalInput('dependency-graph-include-configurations');
|
||||
}
|
||||
static constructJobCorrelator(workflow, jobId, matrixJson) {
|
||||
const matrixString = this.describeMatrix(matrixJson);
|
||||
@@ -89956,7 +90033,6 @@ var DependencyGraphOption;
|
||||
DependencyGraphOption["GenerateAndSubmit"] = "generate-and-submit";
|
||||
DependencyGraphOption["GenerateAndUpload"] = "generate-and-upload";
|
||||
DependencyGraphOption["DownloadAndSubmit"] = "download-and-submit";
|
||||
DependencyGraphOption["Clear"] = "clear";
|
||||
})(DependencyGraphOption || (exports.DependencyGraphOption = DependencyGraphOption = {}));
|
||||
class CacheConfig {
|
||||
isCacheDisabled() {
|
||||
@@ -89978,7 +90054,38 @@ class CacheConfig {
|
||||
return getBooleanInput('gradle-home-cache-strict-match');
|
||||
}
|
||||
isCacheCleanupEnabled() {
|
||||
return getBooleanInput('gradle-home-cache-cleanup') && !this.isCacheReadOnly();
|
||||
if (this.isCacheReadOnly()) {
|
||||
return false;
|
||||
}
|
||||
const cleanupOption = this.getCacheCleanupOption();
|
||||
return cleanupOption === CacheCleanupOption.Always || cleanupOption === CacheCleanupOption.OnSuccess;
|
||||
}
|
||||
shouldPerformCacheCleanup(hasFailure) {
|
||||
const cleanupOption = this.getCacheCleanupOption();
|
||||
if (cleanupOption === CacheCleanupOption.Always) {
|
||||
return true;
|
||||
}
|
||||
if (cleanupOption === CacheCleanupOption.OnSuccess) {
|
||||
return !hasFailure;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
getCacheCleanupOption() {
|
||||
const legacyVal = getOptionalBooleanInput('gradle-home-cache-cleanup');
|
||||
if (legacyVal !== undefined) {
|
||||
deprecator.recordDeprecation('The `gradle-home-cache-cleanup` input parameter has been replaced by `cache-cleanup`');
|
||||
return legacyVal ? CacheCleanupOption.Always : CacheCleanupOption.Never;
|
||||
}
|
||||
const val = core.getInput('cache-cleanup');
|
||||
switch (val.toLowerCase().trim()) {
|
||||
case 'always':
|
||||
return CacheCleanupOption.Always;
|
||||
case 'on-success':
|
||||
return CacheCleanupOption.OnSuccess;
|
||||
case 'never':
|
||||
return CacheCleanupOption.Never;
|
||||
}
|
||||
throw TypeError(`The value '${val}' is not valid for cache-cleanup. Valid values are: [never, always, on-success].`);
|
||||
}
|
||||
getCacheEncryptionKey() {
|
||||
return core.getInput('cache-encryption-key');
|
||||
@@ -89991,14 +90098,17 @@ class CacheConfig {
|
||||
}
|
||||
}
|
||||
exports.CacheConfig = CacheConfig;
|
||||
var CacheCleanupOption;
|
||||
(function (CacheCleanupOption) {
|
||||
CacheCleanupOption["Never"] = "never";
|
||||
CacheCleanupOption["OnSuccess"] = "on-success";
|
||||
CacheCleanupOption["Always"] = "always";
|
||||
})(CacheCleanupOption || (exports.CacheCleanupOption = CacheCleanupOption = {}));
|
||||
class SummaryConfig {
|
||||
shouldGenerateJobSummary(hasFailure) {
|
||||
if (!process.env[summary_1.SUMMARY_ENV_VAR]) {
|
||||
return false;
|
||||
}
|
||||
if (!this.isJobSummaryEnabled()) {
|
||||
return false;
|
||||
}
|
||||
return this.shouldAddJobSummary(this.getJobSummaryOption(), hasFailure);
|
||||
}
|
||||
shouldAddPRComment(hasFailure) {
|
||||
@@ -90014,9 +90124,6 @@ class SummaryConfig {
|
||||
return hasFailure;
|
||||
}
|
||||
}
|
||||
isJobSummaryEnabled() {
|
||||
return getBooleanInput('generate-job-summary', true);
|
||||
}
|
||||
getJobSummaryOption() {
|
||||
return this.parseJobSummaryOption('add-job-summary');
|
||||
}
|
||||
@@ -90048,10 +90155,10 @@ class BuildScanConfig {
|
||||
return getBooleanInput('build-scan-publish') && this.verifyTermsOfUseAgreement();
|
||||
}
|
||||
getBuildScanTermsOfUseUrl() {
|
||||
return this.getTermsOfUseProp('build-scan-terms-of-use-url', 'build-scan-terms-of-service-url');
|
||||
return core.getInput('build-scan-terms-of-use-url');
|
||||
}
|
||||
getBuildScanTermsOfUseAgree() {
|
||||
return this.getTermsOfUseProp('build-scan-terms-of-use-agree', 'build-scan-terms-of-service-agree');
|
||||
return core.getInput('build-scan-terms-of-use-agree');
|
||||
}
|
||||
getDevelocityAccessKey() {
|
||||
return (core.getInput('develocity-access-key') ||
|
||||
@@ -90101,18 +90208,6 @@ class BuildScanConfig {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
getTermsOfUseProp(newPropName, oldPropName) {
|
||||
const newProp = core.getInput(newPropName);
|
||||
if (newProp !== '') {
|
||||
return newProp;
|
||||
}
|
||||
const oldProp = core.getInput(oldPropName);
|
||||
if (oldProp !== '') {
|
||||
deprecator.recordDeprecation('The `build-scan-terms-of-service` input parameters have been renamed');
|
||||
return oldProp;
|
||||
}
|
||||
return core.getInput(oldPropName);
|
||||
}
|
||||
}
|
||||
exports.BuildScanConfig = BuildScanConfig;
|
||||
BuildScanConfig.DevelocityAccessKeyEnvVar = 'DEVELOCITY_ACCESS_KEY';
|
||||
@@ -90129,19 +90224,18 @@ class GradleExecutionConfig {
|
||||
: path_1.default.resolve(baseDirectory, buildRootDirectoryInput);
|
||||
return resolvedBuildRootDirectory;
|
||||
}
|
||||
getArguments() {
|
||||
const input = core.getInput('arguments');
|
||||
if (input.length !== 0) {
|
||||
deprecator.recordDeprecation('Using the action to execute Gradle via the `arguments` parameter is deprecated');
|
||||
}
|
||||
return (0, string_argv_1.parseArgsStringToArgv)(input);
|
||||
}
|
||||
getDependencyResolutionTask() {
|
||||
return core.getInput('dependency-resolution-task') || ':ForceDependencyResolutionPlugin_resolveAllDependencies';
|
||||
}
|
||||
getAdditionalArguments() {
|
||||
return core.getInput('additional-arguments');
|
||||
}
|
||||
verifyNoArguments() {
|
||||
const input = core.getInput('arguments');
|
||||
if (input.length !== 0) {
|
||||
deprecator.failOnUseOfRemovedFeature(`The 'arguments' parameter is no longer supported for ${getActionId()}`, 'Using the action to execute Gradle via the `arguments` parameter is deprecated');
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.GradleExecutionConfig = GradleExecutionConfig;
|
||||
function doValidateWrappers() {
|
||||
@@ -90179,6 +90273,13 @@ function parseNumericInput(paramName, paramValue, paramDefault) {
|
||||
return numericValue;
|
||||
}
|
||||
exports.parseNumericInput = parseNumericInput;
|
||||
function getOptionalInput(paramName) {
|
||||
const paramValue = core.getInput(paramName);
|
||||
if (paramValue.length > 0) {
|
||||
return paramValue;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
function getBooleanInput(paramName, paramDefault = false) {
|
||||
const paramValue = core.getInput(paramName);
|
||||
switch (paramValue.toLowerCase().trim()) {
|
||||
@@ -90231,11 +90332,12 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.restoreDeprecationState = exports.saveDeprecationState = exports.emitDeprecationWarnings = exports.getDeprecations = exports.recordDeprecation = exports.Deprecation = void 0;
|
||||
exports.restoreDeprecationState = exports.saveDeprecationState = exports.emitDeprecationWarnings = exports.getErrors = exports.getDeprecations = exports.failOnUseOfRemovedFeature = exports.recordDeprecation = exports.Deprecation = void 0;
|
||||
const core = __importStar(__nccwpck_require__(2186));
|
||||
const configuration_1 = __nccwpck_require__(5778);
|
||||
const DEPRECATION_UPGRADE_PAGE = 'https://github.com/gradle/actions/blob/main/docs/deprecation-upgrade-guide.md';
|
||||
const recordedDeprecations = [];
|
||||
const recordedErrors = [];
|
||||
class Deprecation {
|
||||
constructor(message) {
|
||||
this.message = message;
|
||||
@@ -90255,10 +90357,21 @@ function recordDeprecation(message) {
|
||||
}
|
||||
}
|
||||
exports.recordDeprecation = recordDeprecation;
|
||||
function failOnUseOfRemovedFeature(removalMessage, deprecationMessage = removalMessage) {
|
||||
const deprecation = new Deprecation(deprecationMessage);
|
||||
const errorMessage = `${removalMessage}. See ${deprecation.getDocumentationLink()}`;
|
||||
recordedErrors.push(errorMessage);
|
||||
core.setFailed(errorMessage);
|
||||
}
|
||||
exports.failOnUseOfRemovedFeature = failOnUseOfRemovedFeature;
|
||||
function getDeprecations() {
|
||||
return recordedDeprecations;
|
||||
}
|
||||
exports.getDeprecations = getDeprecations;
|
||||
function getErrors() {
|
||||
return recordedErrors;
|
||||
}
|
||||
exports.getErrors = getErrors;
|
||||
function emitDeprecationWarnings(hasJobSummary = true) {
|
||||
if (recordedDeprecations.length > 0) {
|
||||
core.warning(`This job uses deprecated functionality from the '${(0, configuration_1.getActionId)()}' action. Consult the ${hasJobSummary ? 'Job Summary' : 'logs'} for more details.`);
|
||||
@@ -90269,17 +90382,21 @@ function emitDeprecationWarnings(hasJobSummary = true) {
|
||||
}
|
||||
exports.emitDeprecationWarnings = emitDeprecationWarnings;
|
||||
function saveDeprecationState() {
|
||||
core.saveState('deprecations', JSON.stringify(recordedDeprecations));
|
||||
core.saveState('deprecation-collector_deprecations', JSON.stringify(recordedDeprecations));
|
||||
core.saveState('deprecation-collector_errors', JSON.stringify(recordedErrors));
|
||||
}
|
||||
exports.saveDeprecationState = saveDeprecationState;
|
||||
function restoreDeprecationState() {
|
||||
const stringRep = core.getState('deprecations');
|
||||
if (stringRep === '') {
|
||||
return;
|
||||
const savedDeprecations = core.getState('deprecation-collector_deprecations');
|
||||
if (savedDeprecations) {
|
||||
JSON.parse(savedDeprecations).forEach((obj) => {
|
||||
recordedDeprecations.push(new Deprecation(obj.message));
|
||||
});
|
||||
}
|
||||
const savedErrors = core.getState('deprecation-collector_errors');
|
||||
if (savedErrors) {
|
||||
recordedErrors.push(...JSON.parse(savedErrors));
|
||||
}
|
||||
JSON.parse(stringRep).forEach((obj) => {
|
||||
recordedDeprecations.push(new Deprecation(obj.message));
|
||||
});
|
||||
}
|
||||
exports.restoreDeprecationState = restoreDeprecationState;
|
||||
|
||||
@@ -90405,33 +90522,44 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.fetchValidChecksums = exports.KNOWN_VALID_CHECKSUMS = void 0;
|
||||
exports.fetchUnknownChecksums = exports.KNOWN_CHECKSUMS = exports.WrapperChecksums = void 0;
|
||||
const httpm = __importStar(__nccwpck_require__(5538));
|
||||
const wrapper_checksums_json_1 = __importDefault(__nccwpck_require__(3802));
|
||||
const httpc = new httpm.HttpClient('gradle/wrapper-validation-action', undefined, { allowRetries: true, maxRetries: 3 });
|
||||
function getKnownValidChecksums() {
|
||||
const versionsMap = new Map();
|
||||
for (const entry of wrapper_checksums_json_1.default) {
|
||||
const checksum = entry.checksum;
|
||||
let versionNames = versionsMap.get(checksum);
|
||||
if (versionNames === undefined) {
|
||||
versionNames = new Set();
|
||||
versionsMap.set(checksum, versionNames);
|
||||
}
|
||||
versionNames.add(entry.version);
|
||||
class WrapperChecksums {
|
||||
constructor() {
|
||||
this.checksums = new Map();
|
||||
this.versions = new Set();
|
||||
}
|
||||
add(version, checksum) {
|
||||
if (this.checksums.has(checksum)) {
|
||||
this.checksums.get(checksum).add(version);
|
||||
}
|
||||
else {
|
||||
this.checksums.set(checksum, new Set([version]));
|
||||
}
|
||||
this.versions.add(version);
|
||||
}
|
||||
return versionsMap;
|
||||
}
|
||||
exports.KNOWN_VALID_CHECKSUMS = getKnownValidChecksums();
|
||||
async function fetchValidChecksums(allowSnapshots) {
|
||||
exports.WrapperChecksums = WrapperChecksums;
|
||||
function loadKnownChecksums() {
|
||||
const checksums = new WrapperChecksums();
|
||||
for (const entry of wrapper_checksums_json_1.default) {
|
||||
checksums.add(entry.version, entry.checksum);
|
||||
}
|
||||
return checksums;
|
||||
}
|
||||
exports.KNOWN_CHECKSUMS = loadKnownChecksums();
|
||||
async function fetchUnknownChecksums(allowSnapshots, knownChecksums) {
|
||||
const all = await httpGetJsonArray('https://services.gradle.org/versions/all');
|
||||
const withChecksum = all.filter(entry => typeof entry === 'object' && entry != null && entry.hasOwnProperty('wrapperChecksumUrl'));
|
||||
const allowed = withChecksum.filter((entry) => allowSnapshots || !entry.snapshot);
|
||||
const checksumUrls = allowed.map((entry) => entry.wrapperChecksumUrl);
|
||||
const notKnown = allowed.filter((entry) => !knownChecksums.versions.has(entry.version));
|
||||
const checksumUrls = notKnown.map((entry) => entry.wrapperChecksumUrl);
|
||||
const checksums = await Promise.all(checksumUrls.map(async (url) => httpGetText(url)));
|
||||
return new Set(checksums);
|
||||
}
|
||||
exports.fetchValidChecksums = fetchValidChecksums;
|
||||
exports.fetchUnknownChecksums = fetchUnknownChecksums;
|
||||
async function httpGetJsonArray(url) {
|
||||
return JSON.parse(await httpGetText(url));
|
||||
}
|
||||
@@ -90553,72 +90681,6 @@ async function sha256File(path) {
|
||||
exports.sha256File = sha256File;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 8095:
|
||||
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
||||
|
||||
"use strict";
|
||||
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.run = void 0;
|
||||
const path = __importStar(__nccwpck_require__(1017));
|
||||
const core = __importStar(__nccwpck_require__(2186));
|
||||
const validate = __importStar(__nccwpck_require__(8568));
|
||||
const configuration_1 = __nccwpck_require__(5778);
|
||||
const deprecation_collector_1 = __nccwpck_require__(2572);
|
||||
const errors_1 = __nccwpck_require__(6976);
|
||||
async function run() {
|
||||
try {
|
||||
if ((0, configuration_1.getActionId)() === 'gradle/wrapper-validation-action') {
|
||||
(0, deprecation_collector_1.recordDeprecation)('The action `gradle/wrapper-validation-action` has been replaced by `gradle/actions/wrapper-validation`');
|
||||
}
|
||||
else {
|
||||
(0, configuration_1.setActionId)('gradle/actions/wrapper-validation');
|
||||
}
|
||||
const result = await validate.findInvalidWrapperJars(path.resolve('.'), +core.getInput('min-wrapper-count'), core.getInput('allow-snapshots') === 'true', core.getInput('allow-checksums').split(','));
|
||||
if (result.isValid()) {
|
||||
core.info(result.toDisplayString());
|
||||
}
|
||||
else {
|
||||
core.setFailed(`Gradle Wrapper Validation Failed!\n See https://github.com/gradle/actions/blob/main/docs/wrapper-validation.md#reporting-failures\n${result.toDisplayString()}`);
|
||||
if (result.invalid.length > 0) {
|
||||
core.setOutput('failed-wrapper', `${result.invalid.map(w => w.path).join('|')}`);
|
||||
}
|
||||
}
|
||||
(0, deprecation_collector_1.emitDeprecationWarnings)(false);
|
||||
}
|
||||
catch (error) {
|
||||
(0, errors_1.handleMainActionError)(error);
|
||||
}
|
||||
}
|
||||
exports.run = run;
|
||||
run();
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 8568:
|
||||
@@ -90655,7 +90717,7 @@ const find = __importStar(__nccwpck_require__(849));
|
||||
const checksums = __importStar(__nccwpck_require__(907));
|
||||
const hash = __importStar(__nccwpck_require__(79));
|
||||
const path_1 = __nccwpck_require__(1017);
|
||||
async function findInvalidWrapperJars(gitRepoRoot, minWrapperCount, allowSnapshots, allowedChecksums, knownValidChecksums = checksums.KNOWN_VALID_CHECKSUMS) {
|
||||
async function findInvalidWrapperJars(gitRepoRoot, minWrapperCount, allowSnapshots, allowedChecksums, knownValidChecksums = checksums.KNOWN_CHECKSUMS) {
|
||||
const wrapperJars = await find.findWrapperJars(gitRepoRoot);
|
||||
const result = new ValidationResult([], []);
|
||||
if (wrapperJars.length < minWrapperCount) {
|
||||
@@ -90665,7 +90727,7 @@ async function findInvalidWrapperJars(gitRepoRoot, minWrapperCount, allowSnapsho
|
||||
const notYetValidatedWrappers = [];
|
||||
for (const wrapperJar of wrapperJars) {
|
||||
const sha = await hash.sha256File((0, path_1.resolve)(gitRepoRoot, wrapperJar));
|
||||
if (allowedChecksums.includes(sha) || knownValidChecksums.has(sha)) {
|
||||
if (allowedChecksums.includes(sha) || knownValidChecksums.checksums.has(sha)) {
|
||||
result.valid.push(new WrapperJar(wrapperJar, sha));
|
||||
}
|
||||
else {
|
||||
@@ -90674,7 +90736,7 @@ async function findInvalidWrapperJars(gitRepoRoot, minWrapperCount, allowSnapsho
|
||||
}
|
||||
if (notYetValidatedWrappers.length > 0) {
|
||||
result.fetchedChecksums = true;
|
||||
const fetchedValidChecksums = await checksums.fetchValidChecksums(allowSnapshots);
|
||||
const fetchedValidChecksums = await checksums.fetchUnknownChecksums(allowSnapshots, knownValidChecksums);
|
||||
for (const wrapperJar of notYetValidatedWrappers) {
|
||||
if (!fetchedValidChecksums.has(wrapperJar.checksum)) {
|
||||
result.invalid.push(wrapperJar);
|
||||
@@ -90988,59 +91050,6 @@ module.exports = require("worker_threads");
|
||||
"use strict";
|
||||
module.exports = require("zlib");
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 9663:
|
||||
/***/ ((__unused_webpack_module, exports) => {
|
||||
|
||||
"use strict";
|
||||
|
||||
exports.__esModule = true;
|
||||
exports.parseArgsStringToArgv = void 0;
|
||||
function parseArgsStringToArgv(value, env, file) {
|
||||
// ([^\s'"]([^\s'"]*(['"])([^\3]*?)\3)+[^\s'"]*) Matches nested quotes until the first space outside of quotes
|
||||
// [^\s'"]+ or Match if not a space ' or "
|
||||
// (['"])([^\5]*?)\5 or Match "quoted text" without quotes
|
||||
// `\3` and `\5` are a backreference to the quote style (' or ") captured
|
||||
var myRegexp = /([^\s'"]([^\s'"]*(['"])([^\3]*?)\3)+[^\s'"]*)|[^\s'"]+|(['"])([^\5]*?)\5/gi;
|
||||
var myString = value;
|
||||
var myArray = [];
|
||||
if (env) {
|
||||
myArray.push(env);
|
||||
}
|
||||
if (file) {
|
||||
myArray.push(file);
|
||||
}
|
||||
var match;
|
||||
do {
|
||||
// Each call to exec returns the next regex match as an array
|
||||
match = myRegexp.exec(myString);
|
||||
if (match !== null) {
|
||||
// Index 1 in the array is the captured group if it exists
|
||||
// Index 0 is the matched text, which we use if no captured group exists
|
||||
myArray.push(firstString(match[1], match[6], match[0]));
|
||||
}
|
||||
} while (match !== null);
|
||||
return myArray;
|
||||
}
|
||||
exports["default"] = parseArgsStringToArgv;
|
||||
exports.parseArgsStringToArgv = parseArgsStringToArgv;
|
||||
// Accepts any number of arguments, and returns the first one that is a string
|
||||
// (even an empty string)
|
||||
function firstString() {
|
||||
var args = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
args[_i] = arguments[_i];
|
||||
}
|
||||
for (var i = 0; i < args.length; i++) {
|
||||
var arg = args[i];
|
||||
if (typeof arg === "string") {
|
||||
return arg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 3765:
|
||||
@@ -91117,7 +91126,7 @@ module.exports = JSON.parse('[{"version":"8.9","checksum":"498495120a03b9a6ab5d1
|
||||
/******/ // startup
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ // This entry module is referenced by other modules so it can't be inlined
|
||||
/******/ var __webpack_exports__ = __nccwpck_require__(8095);
|
||||
/******/ var __webpack_exports__ = __nccwpck_require__(2401);
|
||||
/******/ module.exports = __webpack_exports__;
|
||||
/******/
|
||||
/******/ })()
|
||||
|
||||
2
dist/wrapper-validation/main/index.js.map
vendored
2
dist/wrapper-validation/main/index.js.map
vendored
File diff suppressed because one or more lines are too long
@@ -102,6 +102,13 @@ In some cases, the default action configuration will not be sufficient, and addi
|
||||
|
||||
# Do not attempt to submit the dependency-graph. Save it as a workflow artifact.
|
||||
dependency-graph: generate-and-upload
|
||||
|
||||
# Specify the location where dependency graph files will be generated.
|
||||
dependency-graph-report-dir: custom-report-dir
|
||||
|
||||
# By default, failure to generate a dependency graph will cause the workflow to fail
|
||||
dependency-graph-continue-on-failure: true
|
||||
|
||||
```
|
||||
|
||||
See the [Action Metadata file](../dependency-submission/action.yml) for a more detailed description of each input parameter.
|
||||
@@ -235,26 +242,26 @@ contribute to the dependency graph.
|
||||
> These dependencies would be assigned to different scopes (eg development, runtime, testing) and the GitHub UI would make it easy to opt-in to security alerts for different dependency scopes.
|
||||
> However, this functionality does not yet exist.
|
||||
|
||||
### Excluding certain Gradle projects from the dependency graph
|
||||
### Selecting Gradle projects that will contribute to the dependency graph
|
||||
|
||||
If you do not want the dependency graph to include dependencies from every project in your build,
|
||||
you can easily exclude certain projects from the dependency extraction process.
|
||||
you can easily exclude or include certain projects from the dependency extraction process.
|
||||
|
||||
To restrict which Gradle subprojects contribute to the report, specify which projects to exclude via a regular expression.
|
||||
You can provide this value via the `DEPENDENCY_GRAPH_EXCLUDE_PROJECTS` environment variable or system property.
|
||||
To restrict which Gradle subprojects contribute to the report, specify which projects to exclude or include via a regular expression.
|
||||
You can use the `dependency-graph-exclude-projects` and `dependency-graph-include-projects` input parameters for this purpose.
|
||||
|
||||
Note that excluding a project in this way only removes dependencies that are _resolved_ as part of that project, and may
|
||||
not necessarily remove all dependencies _declared_ in that project. If another project depends on the excluded project
|
||||
then it may transitively resolve dependencies declared in the excluded project: these dependencies will still be included
|
||||
in the generated dependency graph.
|
||||
|
||||
### Excluding certain Gradle configurations from the dependency graph
|
||||
### Selecting Gradle configurations that will contribute to the dependency graph
|
||||
|
||||
Similarly to Gradle projects, it is possible to exclude a set of configuration instances from dependency graph generation,
|
||||
so that dependencies resolved by those configurations are not included.
|
||||
Similarly to Gradle projects, it is possible to exclude or include a set of dependency configurations from dependency graph generation,
|
||||
so that only dependencies resolved by the included configurations are reported.
|
||||
|
||||
To restrict which Gradle configurations contribute to the report, specify which configurations to exclude via a regular expression.
|
||||
You can provide this value via the `DEPENDENCY_GRAPH_EXCLUDE_CONFIGURATIONS` environment variable or system property.
|
||||
To restrict which Gradle configurations contribute to the report, specify which configurations to exclude or include via a regular expression.
|
||||
You can use the `dependency-graph-exclude-configurations` and `dependency-graph-include-configurations` input parameters for this purpose.
|
||||
|
||||
Note that configuration exclusion applies to the configuration in which the dependency is _resolved_ which is not necessarily
|
||||
the configuration where the dependency is _declared_. For example if you decare a dependency as `implementation` in
|
||||
@@ -262,24 +269,18 @@ a Java project, that dependency will be resolved in `compileClasspath`, `runtime
|
||||
|
||||
### Example of project and configuration filtering
|
||||
|
||||
For example, if you want to exclude dependencies in the `buildSrc` project, and exclude dependencies from the `testCompileClasspath` and `testRuntimeClasspath` configurations, you would use the following configuration:
|
||||
For example, if you want to exclude dependencies resolved by the `buildSrc` project, and exclude dependencies from the `testCompileClasspath` and `testRuntimeClasspath` configurations, you would use the following configuration:
|
||||
|
||||
```yaml
|
||||
- name: Generate and submit dependency graph
|
||||
uses: gradle/actions/dependency-submission@v3
|
||||
env:
|
||||
with:
|
||||
# Exclude all dependencies that originate solely in the 'buildSrc' project
|
||||
DEPENDENCY_GRAPH_EXCLUDE_PROJECTS: ':buildSrc'
|
||||
dependency-graph-exclude-projets: ':buildSrc'
|
||||
# Exclude dependencies that are only resolved in test classpaths
|
||||
DEPENDENCY_GRAPH_EXCLUDE_CONFIGURATIONS: '.*[Tt]est(Compile|Runtime)Classpath'
|
||||
dependency-graph-exclude-configurations: '.*[Tt]est(Compile|Runtime)Classpath'
|
||||
```
|
||||
|
||||
### Other filtering options
|
||||
|
||||
The [GitHub Dependency Graph Gradle Plugin](https://plugins.gradle.org/plugin/org.gradle.github-dependency-graph-gradle-plugin)
|
||||
has other filtering options that may be useful.
|
||||
See [the docs](https://github.com/gradle/github-dependency-graph-gradle-plugin?tab=readme-ov-file#filtering-which-gradle-configurations-contribute-to-the-dependency-graph) for details.
|
||||
|
||||
# Advance usage scenarios
|
||||
|
||||
## Using a custom plugin repository
|
||||
@@ -418,3 +419,10 @@ Gradle versions `5.2.1`, `5.6.4`, `6.0.1`, `6.9.4`, `7.1.1` and `7.6.3`, as well
|
||||
A known exception to this is that Gradle `7.0`, `7.0.1` and `7.0.2` are not supported.
|
||||
|
||||
See [here](https://github.com/gradle/github-dependency-graph-gradle-plugin?tab=readme-ov-file#gradle-compatibility) for complete compatibility information.
|
||||
|
||||
# Additional references
|
||||
|
||||
- Dependency Submission Demo repository: https://github.com/gradle/github-dependency-submission-demo
|
||||
- GitHub Dependency Graph Gradle Plugin: https://github.com/gradle/github-dependency-graph-gradle-plugin
|
||||
- Webinar - Gradle at Scale with GitHub and GitHub Actions at Allegro: https://www.youtube.com/watch?v=gV94I28FPos
|
||||
|
||||
|
||||
@@ -148,3 +148,15 @@ These deprecated build-scan parameters are scheduled to be removed in `setup-gra
|
||||
Gradle Enterprise has been renamed to Develocity starting from Gradle plugin 3.17 and Develocity server 2024.1.
|
||||
In v4 release of the action, it will require setting the access key with the `develocity-access-key` input and Develocity 2024.1 at least to generate short-lived tokens.
|
||||
If those requirements are not met, the `GRADLE_ENTERPRISE_ACCESS_KEY` env var will be cleared out and build scan publication or other authenticated Develocity operations won't be possible.
|
||||
|
||||
## The `gradle-home-cache-cleanup` input parameter has been replaced by `cache-cleanup`
|
||||
|
||||
In versions of the action prior to `v4`, the boolean `gradle-home-cache-cleanup` parameter allows users to opt-in
|
||||
to cache cleanup, removing unused files in Gradle User Home prior to saving to the cache.
|
||||
|
||||
With `v4`, cache-cleanup is enabled by default, and controlled by the `cache-cleanup` input parameter.
|
||||
|
||||
To remove this deprecation:
|
||||
- If you are using `gradle-home-cache-cleanup: true` in your workflow, you can remove this option as this is now enabled by default.
|
||||
- If you want cache-cleanup to run even when a Gradle build fails, then add the `cache-cleanup: always` input.
|
||||
- If cache-cleanup is causing problems with your workflow, you can disable it with `cache-cleanup: never`.
|
||||
|
||||
@@ -153,9 +153,32 @@ In certain circumstances it may be desirable to start with a clean Gradle User H
|
||||
cache-write-only: true
|
||||
```
|
||||
|
||||
### Configuring cache cleanup
|
||||
|
||||
The Gradle User Home directory tends to grow over time. When you switch to a new Gradle wrapper version
|
||||
or upgrade a dependency version the old files are not automatically and immediately removed.
|
||||
While this can make sense in a local environment, in a GitHub Actions environment
|
||||
it can lead to ever-larger Gradle User Home cache entries being saved and restored.
|
||||
|
||||
To avoid this situation, the `setup-gradle` and `dependency-submission` actions will perform "cache-cleanup",
|
||||
purging any unused files from the Gradle User Home before saving it to the GitHub Actions cache.
|
||||
Cache cleanup will attempt to remove any files that are initially restored to the Gradle User Home directory
|
||||
but that are not used used by Gradle during the GitHub Actions Workflow.
|
||||
|
||||
If a Gradle build fails when running the Job, then it is possible that some required files and dependencies
|
||||
will not be touched during the Job. To prevent these files from being purged, the default behavior is for
|
||||
cache cleanup to run only when all Gradle builds in the Job are successful.
|
||||
|
||||
Gradle Home cache cleanup is enabled by default, and can be controlled by the `cache-cleanup` parameter as follows:
|
||||
- `cache-cleanup: always`: Always run cache cleanup, even when a Gradle build fails in the Job.
|
||||
- `cache-cleanup: on-success` (default): Run cache cleanup when the Job contains no failing Gradle builds.
|
||||
- `cache-cleanup: never`: Disable cache cleanup for the Job.
|
||||
|
||||
Cache cleanup will never run when the cache is configured as read-only or disabled.
|
||||
|
||||
### Overwriting an existing Gradle User Home
|
||||
|
||||
When the action detects that the Gradle User Home caches directory already exists (`~/.gradle/caches`), then by default it will not overwrite the existing content of this directory.
|
||||
When the action detects that the Gradle User Home caches directory already exists (`$GRADLE_USER_HOME/caches`), then by default it will not overwrite the existing content of this directory.
|
||||
This can occur when a prior action initializes this directory, or when using a self-hosted runner that retains this directory between uses.
|
||||
|
||||
In this case, the Job Summary will display a message like:
|
||||
@@ -356,20 +379,6 @@ gradle-home-cache-excludes: |
|
||||
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.
|
||||
|
||||
### Remove unused files from Gradle User Home before saving to the cache
|
||||
|
||||
The Gradle User Home directory tends to grow over time. When you switch to a new Gradle wrapper version or upgrade a dependency version
|
||||
the old files are not automatically and immediately removed. While this can make sense in a local environment, in a GitHub Actions environment
|
||||
it can lead to ever-larger Gradle User Home cache entries being saved and restored.
|
||||
|
||||
To avoid this situation, The `setup-gradle` action supports the `gradle-home-cache-cleanup` parameter.
|
||||
When enabled, this feature will attempt to delete any files in the Gradle User Home that were not used by Gradle during the GitHub Actions Workflow, before saving the Gradle User Home to the GitHub Actions cache.
|
||||
|
||||
Gradle Home cache cleanup is considered experimental and is disabled by default. You can enable this feature for the action as follows:
|
||||
```yaml
|
||||
gradle-home-cache-cleanup: true
|
||||
```
|
||||
|
||||
### Disable local build-cache when remote build-cache is available
|
||||
|
||||
If you have a remote build-cache available for your build, then it is recommended to do the following:
|
||||
@@ -817,3 +826,21 @@ To publish to https://scans.gradle.com, you must specify in your workflow that y
|
||||
- name: Run a Gradle build - a build scan will be published automatically
|
||||
run: ./gradlew build
|
||||
```
|
||||
|
||||
# Dependency verification
|
||||
|
||||
Develocity injection, Build Scan publishing and Dependency Graph generation all work by applying external plugins to your build.
|
||||
If you project has [dependency verification enabled](https://docs.gradle.org/current/userguide/dependency_verification.html#sec:signature-verification),
|
||||
then you'll need to update your verification metadata to trust these plugins.
|
||||
|
||||
Each of the plugins is signed by Gradle, and you can simply add the following snippet to your `dependency-verificaton.xml` file:
|
||||
|
||||
```xml
|
||||
<trusted-keys>
|
||||
<trusted-key id="7B79ADD11F8A779FE90FD3D0893A028475557671">
|
||||
<trusting group="com.gradle"/>
|
||||
<trusting group="org.gradle"/>
|
||||
</trusted-key>
|
||||
</trusted-keys>
|
||||
```
|
||||
|
||||
|
||||
@@ -40,6 +40,19 @@ inputs:
|
||||
Configuration-cache data will not be saved/restored without an encryption key being provided.
|
||||
required: false
|
||||
|
||||
cache-cleanup:
|
||||
description: |
|
||||
Specifies if the action should attempt to remove any stale/unused entries from the Gradle User Home prior to saving to the GitHub Actions cache.
|
||||
By default, no cleanup is performed. It can be configured to run every time, or only when all Gradle builds succeed for the Job.
|
||||
Valid values are 'never', 'on-success' and 'always'.
|
||||
required: false
|
||||
default: 'on-success'
|
||||
|
||||
gradle-home-cache-cleanup:
|
||||
description: When 'true', the action will attempt to remove any stale/unused entries from the Gradle User Home prior to saving to the GitHub Actions cache.
|
||||
required: false
|
||||
deprecation-message: This input has been superceded by the 'cache-cleanup' input parameter.
|
||||
|
||||
gradle-home-cache-includes:
|
||||
description: Paths within Gradle User Home to cache.
|
||||
required: false
|
||||
@@ -51,11 +64,6 @@ inputs:
|
||||
description: Paths within Gradle User Home to exclude from cache.
|
||||
required: false
|
||||
|
||||
gradle-home-cache-cleanup:
|
||||
description: When 'true', the action will attempt to remove any stale/unused entries from the Gradle User Home prior to saving to the GitHub Actions cache.
|
||||
required: false
|
||||
default: false
|
||||
|
||||
# Job summary configuration
|
||||
add-job-summary:
|
||||
description: Specifies when a Job Summary should be inluded in the action results. Valid values are 'never', 'always' (default), and 'on-failure'.
|
||||
@@ -71,15 +79,46 @@ inputs:
|
||||
dependency-graph:
|
||||
description: |
|
||||
Specifies if a GitHub dependency snapshot should be generated for each Gradle build, and if so, how.
|
||||
Valid values are 'disabled' (default), 'generate', 'generate-and-submit', 'generate-and-upload', 'download-and-submit' and 'clear'.
|
||||
Valid values are 'disabled' (default), 'generate', 'generate-and-submit', 'generate-and-upload', and 'download-and-submit'.
|
||||
required: false
|
||||
default: 'disabled'
|
||||
|
||||
dependency-graph-report-dir:
|
||||
description: |
|
||||
Specifies where the dependency graph report will be generated.
|
||||
Paths can relative or absolute. Relative paths are resolved relative to the workspace directory.
|
||||
required: false
|
||||
default: 'dependency-graph-reports'
|
||||
|
||||
dependency-graph-continue-on-failure:
|
||||
description: When 'false' a failure to generate or submit a dependency graph will fail the Step or Job. When 'true' a warning will be emitted but no failure will result.
|
||||
required: false
|
||||
default: true
|
||||
|
||||
dependency-graph-exclude-projects:
|
||||
description: |
|
||||
Gradle projects that should be excluded from dependency graph (regular expression).
|
||||
When set, any matching project will be excluded.
|
||||
required: false
|
||||
|
||||
dependency-graph-include-projects:
|
||||
description: |
|
||||
Gradle projects that should be included in dependency graph (regular expression).
|
||||
When set, only matching projects will be included.
|
||||
required: false
|
||||
|
||||
dependency-graph-exclude-configurations:
|
||||
description: |
|
||||
Gradle configurations that should be included in dependency graph (regular expression).
|
||||
When set, anymatching configurations will be excluded.
|
||||
required: false
|
||||
|
||||
dependency-graph-include-configurations:
|
||||
description: |
|
||||
Gradle configurations that should be included in dependency graph (regular expression).
|
||||
When set, only matching configurations will be included.
|
||||
required: false
|
||||
|
||||
artifact-retention-days:
|
||||
description: Specifies the number of days to retain any artifacts generated by the action. If not set, the default retention settings for the repository will apply.
|
||||
required: false
|
||||
@@ -157,31 +196,10 @@ inputs:
|
||||
default: false
|
||||
|
||||
# DEPRECATED ACTION INPUTS
|
||||
build-scan-terms-of-service-url:
|
||||
description: The URL to the Build Scan® terms of use. This input must be set to 'https://gradle.com/terms-of-service'.
|
||||
required: false
|
||||
deprecation-message: The input has been renamed to align with the Develocity API. Use 'build-scan-terms-of-use-url' instead.
|
||||
|
||||
build-scan-terms-of-service-agree:
|
||||
description: Indicate that you agree to the Build Scan® terms of use. This input value must be "yes".
|
||||
required: false
|
||||
deprecation-message: The input has been renamed to align with the Develocity API. Use 'build-scan-terms-of-use-agree' instead.
|
||||
|
||||
generate-job-summary:
|
||||
description: When 'false', no Job Summary will be generated for the Job.
|
||||
required: false
|
||||
default: true
|
||||
deprecation-message: Superceded by the new 'add-job-summary' and 'add-job-summary-as-pr-comment' parameters.
|
||||
|
||||
arguments:
|
||||
description: Gradle command line arguments (supports multi-line input)
|
||||
required: false
|
||||
deprecation-message: Using the action to execute Gradle directly is deprecated in favor of using the action to setup Gradle, and executing Gradle in a subsequent Step.
|
||||
|
||||
build-root-directory:
|
||||
description: Path to the root directory of the build. Default is the root of the GitHub workspace.
|
||||
required: false
|
||||
deprecation-message: Using the action to execute Gradle directly is deprecated in favor of using the action to setup Gradle, and executing Gradle in a subsequent Step.
|
||||
deprecation-message: This parameter has been deprecated and removed. It is only left here to allow for better reporting to assist users to migrate.
|
||||
|
||||
# EXPERIMENTAL ACTION INPUTS
|
||||
# The following action properties allow fine-grained tweaking of the action caching behaviour.
|
||||
|
||||
79
sources/package-lock.json
generated
79
sources/package-lock.json
generated
@@ -23,12 +23,14 @@
|
||||
"semver": "7.6.0",
|
||||
"string-argv": "0.3.2",
|
||||
"typed-rest-client": "1.8.11",
|
||||
"unhomoglyph": "1.0.6"
|
||||
"unhomoglyph": "1.0.6",
|
||||
"which": "4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "29.5.12",
|
||||
"@types/node": "20.12.4",
|
||||
"@types/unzipper": "0.10.9",
|
||||
"@types/which": "3.0.4",
|
||||
"@typescript-eslint/parser": "7.5.0",
|
||||
"@vercel/ncc": "0.38.1",
|
||||
"eslint": "8.57.0",
|
||||
@@ -2215,6 +2217,12 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/which": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/which/-/which-3.0.4.tgz",
|
||||
"integrity": "sha512-liyfuo/106JdlgSchJzXEQCVArk0CvevqPote8F8HgWgJ3dRCcTHgJIsLDuee0kxk/mhbInzIZk3QWSZJ8R+2w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/yargs": {
|
||||
"version": "17.0.23",
|
||||
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.23.tgz",
|
||||
@@ -3694,6 +3702,21 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/cross-spawn/node_modules/which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"isexe": "^2.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"node-which": "bin/node-which"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/crypto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz",
|
||||
@@ -8885,18 +8908,17 @@
|
||||
}
|
||||
},
|
||||
"node_modules/which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||
"dev": true,
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz",
|
||||
"integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==",
|
||||
"dependencies": {
|
||||
"isexe": "^2.0.0"
|
||||
"isexe": "^3.1.1"
|
||||
},
|
||||
"bin": {
|
||||
"node-which": "bin/node-which"
|
||||
"node-which": "bin/which.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
"node": "^16.13.0 || >=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/which-boxed-primitive": {
|
||||
@@ -8949,6 +8971,14 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/which/node_modules/isexe": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz",
|
||||
"integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==",
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/wrap-ansi": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
||||
@@ -10875,6 +10905,12 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/which": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/which/-/which-3.0.4.tgz",
|
||||
"integrity": "sha512-liyfuo/106JdlgSchJzXEQCVArk0CvevqPote8F8HgWgJ3dRCcTHgJIsLDuee0kxk/mhbInzIZk3QWSZJ8R+2w==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/yargs": {
|
||||
"version": "17.0.23",
|
||||
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.23.tgz",
|
||||
@@ -11882,6 +11918,17 @@
|
||||
"path-key": "^3.1.0",
|
||||
"shebang-command": "^2.0.0",
|
||||
"which": "^2.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"isexe": "^2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"crypto": {
|
||||
@@ -15700,12 +15747,18 @@
|
||||
}
|
||||
},
|
||||
"which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||
"dev": true,
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz",
|
||||
"integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==",
|
||||
"requires": {
|
||||
"isexe": "^2.0.0"
|
||||
"isexe": "^3.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"isexe": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz",
|
||||
"integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"which-boxed-primitive": {
|
||||
|
||||
@@ -8,11 +8,11 @@
|
||||
"prettier-write": "prettier --write 'src/**/*.ts'",
|
||||
"prettier-check": "prettier --check 'src/**/*.ts'",
|
||||
"lint": "eslint 'src/**/*.ts'",
|
||||
"compile-dependency-submission-main": "ncc build src/dependency-submission/main.ts --out dist/dependency-submission/main --source-map --no-source-map-register",
|
||||
"compile-dependency-submission-post": "ncc build src/dependency-submission/post.ts --out dist/dependency-submission/post --source-map --no-source-map-register",
|
||||
"compile-setup-gradle-main": "ncc build src/setup-gradle/main.ts --out dist/setup-gradle/main --source-map --no-source-map-register",
|
||||
"compile-setup-gradle-post": "ncc build src/setup-gradle/post.ts --out dist/setup-gradle/post --source-map --no-source-map-register",
|
||||
"compile-wrapper-validation-main": "ncc build src/wrapper-validation/main.ts --out dist/wrapper-validation/main --source-map --no-source-map-register",
|
||||
"compile-dependency-submission-main": "ncc build src/actions/dependency-submission/main.ts --out dist/dependency-submission/main --source-map --no-source-map-register",
|
||||
"compile-dependency-submission-post": "ncc build src/actions/dependency-submission/post.ts --out dist/dependency-submission/post --source-map --no-source-map-register",
|
||||
"compile-setup-gradle-main": "ncc build src/actions/setup-gradle/main.ts --out dist/setup-gradle/main --source-map --no-source-map-register",
|
||||
"compile-setup-gradle-post": "ncc build src/actions/setup-gradle/post.ts --out dist/setup-gradle/post --source-map --no-source-map-register",
|
||||
"compile-wrapper-validation-main": "ncc build src/actions/wrapper-validation/main.ts --out dist/wrapper-validation/main --source-map --no-source-map-register",
|
||||
"compile": "npm-run-all --parallel compile-*",
|
||||
"check": "npm-run-all --parallel prettier-check lint",
|
||||
"format": "npm-run-all --parallel prettier-write lint",
|
||||
@@ -45,12 +45,14 @@
|
||||
"semver": "7.6.0",
|
||||
"string-argv": "0.3.2",
|
||||
"typed-rest-client": "1.8.11",
|
||||
"unhomoglyph": "1.0.6"
|
||||
},
|
||||
"unhomoglyph": "1.0.6",
|
||||
"which": "4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "29.5.12",
|
||||
"@types/node": "20.12.4",
|
||||
"@types/unzipper": "0.10.9",
|
||||
"@types/which": "3.0.4",
|
||||
"@typescript-eslint/parser": "7.5.0",
|
||||
"@vercel/ncc": "0.38.1",
|
||||
"eslint": "8.57.0",
|
||||
@@ -59,11 +61,11 @@
|
||||
"eslint-plugin-prettier": "5.1.3",
|
||||
"jest": "29.7.0",
|
||||
"js-yaml": "4.1.0",
|
||||
"nock": "13.5.4",
|
||||
"npm-run-all": "4.1.5",
|
||||
"patch-package": "8.0.0",
|
||||
"prettier": "3.2.5",
|
||||
"ts-jest": "29.1.2",
|
||||
"typescript": "5.4.3",
|
||||
"nock": "13.5.4"
|
||||
"typescript": "5.4.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import * as setupGradle from '../setup-gradle'
|
||||
import * as gradle from '../execution/gradle'
|
||||
import * as dependencyGraph from '../dependency-graph'
|
||||
import * as core from '@actions/core'
|
||||
import * as setupGradle from '../../setup-gradle'
|
||||
import * as gradle from '../../execution/gradle'
|
||||
import * as dependencyGraph from '../../dependency-graph'
|
||||
|
||||
import {parseArgsStringToArgv} from 'string-argv'
|
||||
import {
|
||||
@@ -10,9 +11,9 @@ import {
|
||||
DependencyGraphOption,
|
||||
GradleExecutionConfig,
|
||||
setActionId
|
||||
} from '../configuration'
|
||||
import {saveDeprecationState} from '../deprecation-collector'
|
||||
import {handleMainActionError} from '../errors'
|
||||
} from '../../configuration'
|
||||
import {saveDeprecationState} from '../../deprecation-collector'
|
||||
import {handleMainActionError} from '../../errors'
|
||||
|
||||
/**
|
||||
* The main entry point for the action, called by Github Actions for the step.
|
||||
@@ -24,6 +25,9 @@ export async function run(): Promise<void> {
|
||||
// Configure Gradle environment (Gradle User Home)
|
||||
await setupGradle.setup(new CacheConfig(), new BuildScanConfig())
|
||||
|
||||
// Capture the enabled state of dependency-graph
|
||||
const originallyEnabled = process.env['GITHUB_DEPENDENCY_GRAPH_ENABLED']
|
||||
|
||||
// Configure the dependency graph submission
|
||||
const config = new DependencyGraphConfig()
|
||||
await dependencyGraph.setup(config)
|
||||
@@ -53,6 +57,9 @@ export async function run(): Promise<void> {
|
||||
|
||||
await dependencyGraph.complete(config)
|
||||
|
||||
// Reset the enabled state of dependency graph
|
||||
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_ENABLED', originallyEnabled)
|
||||
|
||||
saveDeprecationState()
|
||||
} catch (error) {
|
||||
handleMainActionError(error)
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as setupGradle from '../setup-gradle'
|
||||
import * as setupGradle from '../../setup-gradle'
|
||||
|
||||
import {CacheConfig, SummaryConfig} from '../configuration'
|
||||
import {handlePostActionError} from '../errors'
|
||||
import {CacheConfig, SummaryConfig} from '../../configuration'
|
||||
import {handlePostActionError} from '../../errors'
|
||||
|
||||
// Catch and log any unhandled exceptions. These exceptions can leak out of the uploadChunk method in
|
||||
// @actions/toolkit when a failed upload closes the file descriptor causing any in-process reads to
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as setupGradle from '../setup-gradle'
|
||||
import * as gradle from '../execution/gradle'
|
||||
import * as dependencyGraph from '../dependency-graph'
|
||||
import * as setupGradle from '../../setup-gradle'
|
||||
import * as provisioner from '../../execution/provision'
|
||||
import * as dependencyGraph from '../../dependency-graph'
|
||||
import {
|
||||
BuildScanConfig,
|
||||
CacheConfig,
|
||||
@@ -9,9 +9,9 @@ import {
|
||||
doValidateWrappers,
|
||||
getActionId,
|
||||
setActionId
|
||||
} from '../configuration'
|
||||
import {recordDeprecation, saveDeprecationState} from '../deprecation-collector'
|
||||
import {handleMainActionError} from '../errors'
|
||||
} from '../../configuration'
|
||||
import {failOnUseOfRemovedFeature, saveDeprecationState} from '../../deprecation-collector'
|
||||
import {handleMainActionError} from '../../errors'
|
||||
|
||||
/**
|
||||
* The main entry point for the action, called by Github Actions for the step.
|
||||
@@ -19,13 +19,13 @@ import {handleMainActionError} from '../errors'
|
||||
export async function run(): Promise<void> {
|
||||
try {
|
||||
if (getActionId() === 'gradle/gradle-build-action') {
|
||||
recordDeprecation(
|
||||
failOnUseOfRemovedFeature(
|
||||
'The action `gradle/gradle-build-action` has been replaced by `gradle/actions/setup-gradle`'
|
||||
)
|
||||
} else {
|
||||
setActionId('gradle/actions/setup-gradle')
|
||||
}
|
||||
|
||||
setActionId('gradle/actions/setup-gradle')
|
||||
|
||||
// Check for invalid wrapper JARs if requested
|
||||
if (doValidateWrappers()) {
|
||||
await setupGradle.checkNoInvalidWrapperJars()
|
||||
@@ -38,11 +38,8 @@ export async function run(): Promise<void> {
|
||||
await dependencyGraph.setup(new DependencyGraphConfig())
|
||||
|
||||
const config = new GradleExecutionConfig()
|
||||
await gradle.provisionAndMaybeExecute(
|
||||
config.getGradleVersion(),
|
||||
config.getBuildRootDirectory(),
|
||||
config.getArguments()
|
||||
)
|
||||
config.verifyNoArguments()
|
||||
await provisioner.provisionGradle(config.getGradleVersion())
|
||||
|
||||
saveDeprecationState()
|
||||
} catch (error) {
|
||||
@@ -1,9 +1,9 @@
|
||||
import * as setupGradle from '../setup-gradle'
|
||||
import * as dependencyGraph from '../dependency-graph'
|
||||
import * as setupGradle from '../../setup-gradle'
|
||||
import * as dependencyGraph from '../../dependency-graph'
|
||||
|
||||
import {CacheConfig, DependencyGraphConfig, SummaryConfig} from '../configuration'
|
||||
import {handlePostActionError} from '../errors'
|
||||
import {emitDeprecationWarnings, restoreDeprecationState} from '../deprecation-collector'
|
||||
import {CacheConfig, DependencyGraphConfig, SummaryConfig} from '../../configuration'
|
||||
import {handlePostActionError} from '../../errors'
|
||||
import {emitDeprecationWarnings, restoreDeprecationState} from '../../deprecation-collector'
|
||||
|
||||
// Catch and log any unhandled exceptions. These exceptions can leak out of the uploadChunk method in
|
||||
// @actions/toolkit when a failed upload closes the file descriptor causing any in-process reads to
|
||||
@@ -1,21 +1,21 @@
|
||||
import * as path from 'path'
|
||||
import * as core from '@actions/core'
|
||||
|
||||
import * as validate from './validate'
|
||||
import {getActionId, setActionId} from '../configuration'
|
||||
import {recordDeprecation, emitDeprecationWarnings} from '../deprecation-collector'
|
||||
import {handleMainActionError} from '../errors'
|
||||
import * as validate from '../../wrapper-validation/validate'
|
||||
import {getActionId, setActionId} from '../../configuration'
|
||||
import {failOnUseOfRemovedFeature, emitDeprecationWarnings} from '../../deprecation-collector'
|
||||
import {handleMainActionError} from '../../errors'
|
||||
|
||||
export async function run(): Promise<void> {
|
||||
try {
|
||||
if (getActionId() === 'gradle/wrapper-validation-action') {
|
||||
recordDeprecation(
|
||||
failOnUseOfRemovedFeature(
|
||||
'The action `gradle/wrapper-validation-action` has been replaced by `gradle/actions/wrapper-validation`'
|
||||
)
|
||||
} else {
|
||||
setActionId('gradle/actions/wrapper-validation')
|
||||
}
|
||||
|
||||
setActionId('gradle/actions/wrapper-validation')
|
||||
|
||||
const result = await validate.findInvalidWrapperJars(
|
||||
path.resolve('.'),
|
||||
+core.getInput('min-wrapper-count'),
|
||||
@@ -8,15 +8,40 @@ export interface BuildResult {
|
||||
get gradleVersion(): string
|
||||
get gradleHomeDir(): string
|
||||
get buildFailed(): boolean
|
||||
get configCacheHit(): boolean
|
||||
get buildScanUri(): string
|
||||
get buildScanFailed(): boolean
|
||||
}
|
||||
|
||||
export function loadBuildResults(): BuildResult[] {
|
||||
return getUnprocessedResults().map(filePath => {
|
||||
export class BuildResults {
|
||||
results: BuildResult[]
|
||||
|
||||
constructor(results: BuildResult[]) {
|
||||
this.results = results
|
||||
}
|
||||
|
||||
anyFailed(): boolean {
|
||||
return this.results.some(result => result.buildFailed)
|
||||
}
|
||||
|
||||
anyConfigCacheHit(): boolean {
|
||||
return this.results.some(result => result.configCacheHit)
|
||||
}
|
||||
|
||||
uniqueGradleHomes(): string[] {
|
||||
const allHomes = this.results.map(buildResult => buildResult.gradleHomeDir)
|
||||
return Array.from(new Set(allHomes))
|
||||
}
|
||||
}
|
||||
|
||||
export function loadBuildResults(): BuildResults {
|
||||
const results = getUnprocessedResults().map(filePath => {
|
||||
const content = fs.readFileSync(filePath, 'utf8')
|
||||
return JSON.parse(content) as BuildResult
|
||||
const buildResult = JSON.parse(content) as BuildResult
|
||||
addScanResults(filePath, buildResult)
|
||||
return buildResult
|
||||
})
|
||||
return new BuildResults(results)
|
||||
}
|
||||
|
||||
export function markBuildResultsProcessed(): void {
|
||||
@@ -24,7 +49,7 @@ export function markBuildResultsProcessed(): void {
|
||||
}
|
||||
|
||||
function getUnprocessedResults(): string[] {
|
||||
const buildResultsDir = path.resolve(process.env['RUNNER_TEMP']!, '.build-results')
|
||||
const buildResultsDir = path.resolve(process.env['RUNNER_TEMP']!, '.gradle-actions', 'build-results')
|
||||
if (!fs.existsSync(buildResultsDir)) {
|
||||
return []
|
||||
}
|
||||
@@ -39,6 +64,22 @@ function getUnprocessedResults(): string[] {
|
||||
})
|
||||
}
|
||||
|
||||
function addScanResults(buildResultsFile: string, buildResult: BuildResult): void {
|
||||
const buildScansDir = path.resolve(process.env['RUNNER_TEMP']!, '.gradle-actions', 'build-scans')
|
||||
if (!fs.existsSync(buildScansDir)) {
|
||||
return
|
||||
}
|
||||
|
||||
const buildScanResults = path.resolve(buildScansDir, path.basename(buildResultsFile))
|
||||
if (fs.existsSync(buildScanResults)) {
|
||||
const content = fs.readFileSync(buildScanResults, 'utf8')
|
||||
const scanResults = JSON.parse(content)
|
||||
Object.assign(buildResult, scanResults)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
function isProcessed(resultFile: string): boolean {
|
||||
const markerFile = `${resultFile}.processed`
|
||||
return fs.existsSync(markerFile)
|
||||
|
||||
@@ -73,7 +73,8 @@ export function getCacheKeyBase(cacheName: string, cacheProtocolVersion: string)
|
||||
|
||||
function getCacheKeyEnvironment(): string {
|
||||
const runnerOs = process.env['RUNNER_OS'] || ''
|
||||
return process.env[CACHE_KEY_OS_VAR] || runnerOs
|
||||
const runnerArch = process.env['RUNNER_ARCH'] || ''
|
||||
return process.env[CACHE_KEY_OS_VAR] || `${runnerOs}-${runnerArch}`
|
||||
}
|
||||
|
||||
function getCacheKeyJob(): string {
|
||||
|
||||
@@ -1,5 +1,27 @@
|
||||
import * as cache from '@actions/cache'
|
||||
|
||||
export const DEFAULT_CACHE_ENABLED_REASON = `[Cache was enabled](https://github.com/gradle/actions/blob/main/docs/setup-gradle.md#caching-build-state-between-jobs). Action attempted to both restore and save the Gradle User Home.`
|
||||
|
||||
export const DEFAULT_READONLY_REASON = `[Cache was read-only](https://github.com/gradle/actions/blob/main/docs/setup-gradle.md#using-the-cache-read-only). By default, the action will only write to the cache for Jobs running on the default branch.`
|
||||
|
||||
export const DEFAULT_DISABLED_REASON = `[Cache was disabled](https://github.com/gradle/actions/blob/main/docs/setup-gradle.md#disabling-caching) via action confiugration. Gradle User Home was not restored from or saved to the cache.`
|
||||
|
||||
export const DEFAULT_WRITEONLY_REASON = `[Cache was set to write-only](https://github.com/gradle/actions/blob/main/docs/setup-gradle.md#using-the-cache-write-only) via action configuration. Gradle User Home was not restored from cache.`
|
||||
|
||||
export const EXISTING_GRADLE_HOME = `[Cache was disabled to avoid overwriting a pre-existing Gradle User Home](https://github.com/gradle/actions/blob/main/docs/setup-gradle.md#overwriting-an-existing-gradle-user-home). Gradle User Home was not restored from or saved to the cache.`
|
||||
|
||||
export const CLEANUP_DISABLED_READONLY = `[Cache cleanup](https://github.com/gradle/actions/blob/main/docs/setup-gradle.md#configuring-cache-cleanup) is always disabled when cache is read-only or disabled.`
|
||||
|
||||
export const DEFAULT_CLEANUP_ENABLED_REASON = `[Cache cleanup](https://github.com/gradle/actions/blob/main/docs/setup-gradle.md#configuring-cache-cleanup) was enabled. Stale files in Gradle User Home were purged before saving to the cache.`
|
||||
|
||||
export const DEFAULT_CLEANUP_DISABLED_REASON = `[Cache cleanup](https://github.com/gradle/actions/blob/main/docs/setup-gradle.md#configuring-cache-cleanup) was disabled via action parameter. No cleanup of Gradle User Home was performed.`
|
||||
|
||||
export const CLEANUP_DISABLED_DUE_TO_FAILURE =
|
||||
'[Cache cleanup was disabled due to build failure](https://github.com/gradle/actions/blob/main/docs/setup-gradle.md#configuring-cache-cleanup). Use `cache-cleanup: always` to override this behavior.'
|
||||
|
||||
export const CLEANUP_DISABLED_DUE_TO_CONFIG_CACHE_HIT =
|
||||
'[Cache cleanup was disabled due to configuration-cache reuse](https://github.com/gradle/actions/blob/main/docs/setup-gradle.md#configuring-cache-cleanup). This is expected.'
|
||||
|
||||
/**
|
||||
* Collects information on what entries were saved and restored during the action.
|
||||
* This information is used to generate a summary of the cache usage.
|
||||
@@ -9,7 +31,8 @@ export class CacheListener {
|
||||
cacheReadOnly = false
|
||||
cacheWriteOnly = false
|
||||
cacheDisabled = false
|
||||
cacheDisabledReason = 'disabled'
|
||||
cacheStatusReason: string = DEFAULT_CACHE_ENABLED_REASON
|
||||
cacheCleanupMessage: string = DEFAULT_CLEANUP_DISABLED_REASON
|
||||
|
||||
get fullyRestored(): boolean {
|
||||
return this.cacheEntries.every(x => !x.wasRequestedButNotRestored())
|
||||
@@ -17,12 +40,37 @@ export class CacheListener {
|
||||
|
||||
get cacheStatus(): string {
|
||||
if (!cache.isFeatureAvailable()) return 'not available'
|
||||
if (this.cacheDisabled) return this.cacheDisabledReason
|
||||
if (this.cacheDisabled) return 'disabled'
|
||||
if (this.cacheWriteOnly) return 'write-only'
|
||||
if (this.cacheReadOnly) return 'read-only'
|
||||
return 'enabled'
|
||||
}
|
||||
|
||||
setReadOnly(reason: string = DEFAULT_READONLY_REASON): void {
|
||||
this.cacheReadOnly = true
|
||||
this.cacheStatusReason = reason
|
||||
this.cacheCleanupMessage = CLEANUP_DISABLED_READONLY
|
||||
}
|
||||
|
||||
setDisabled(reason: string = DEFAULT_DISABLED_REASON): void {
|
||||
this.cacheDisabled = true
|
||||
this.cacheStatusReason = reason
|
||||
this.cacheCleanupMessage = CLEANUP_DISABLED_READONLY
|
||||
}
|
||||
|
||||
setWriteOnly(reason: string = DEFAULT_WRITEONLY_REASON): void {
|
||||
this.cacheWriteOnly = true
|
||||
this.cacheStatusReason = reason
|
||||
}
|
||||
|
||||
setCacheCleanupEnabled(): void {
|
||||
this.cacheCleanupMessage = DEFAULT_CLEANUP_ENABLED_REASON
|
||||
}
|
||||
|
||||
setCacheCleanupDisabled(reason: string = DEFAULT_CLEANUP_DISABLED_REASON): void {
|
||||
this.cacheCleanupMessage = reason
|
||||
}
|
||||
|
||||
entry(name: string): CacheEntryListener {
|
||||
for (const entry of this.cacheEntries) {
|
||||
if (entry.entryName === name) {
|
||||
@@ -117,6 +165,10 @@ export function generateCachingReport(listener: CacheListener): string {
|
||||
return `
|
||||
<details>
|
||||
<summary><h4>Caching for Gradle actions was ${listener.cacheStatus} - expand for details</h4></summary>
|
||||
|
||||
- ${listener.cacheStatusReason}
|
||||
- ${listener.cacheCleanupMessage}
|
||||
|
||||
${renderEntryTable(entries)}
|
||||
|
||||
<h5>Cache Entry Details</h5>
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
import * as core from '@actions/core'
|
||||
import {CacheListener} from './cache-reporting'
|
||||
import {
|
||||
CacheListener,
|
||||
EXISTING_GRADLE_HOME,
|
||||
CLEANUP_DISABLED_DUE_TO_FAILURE,
|
||||
CLEANUP_DISABLED_DUE_TO_CONFIG_CACHE_HIT
|
||||
} from './cache-reporting'
|
||||
import {GradleUserHomeCache} from './gradle-user-home-cache'
|
||||
import {CacheCleaner} from './cache-cleaner'
|
||||
import {DaemonController} from '../daemon-controller'
|
||||
import {CacheConfig} from '../configuration'
|
||||
import {BuildResults} from '../build-results'
|
||||
|
||||
const CACHE_RESTORED_VAR = 'GRADLE_BUILD_ACTION_CACHE_RESTORED'
|
||||
|
||||
@@ -26,7 +32,7 @@ export async function restore(
|
||||
core.info('Cache is disabled: will not restore state from previous builds.')
|
||||
// Initialize the Gradle User Home even when caching is disabled.
|
||||
gradleStateCache.init()
|
||||
cacheListener.cacheDisabled = true
|
||||
cacheListener.setDisabled()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -35,8 +41,7 @@ export async function restore(
|
||||
core.info('Gradle User Home already exists: will not restore from cache.')
|
||||
// Initialize pre-existing Gradle User Home.
|
||||
gradleStateCache.init()
|
||||
cacheListener.cacheDisabled = true
|
||||
cacheListener.cacheDisabledReason = 'disabled due to pre-existing Gradle User Home'
|
||||
cacheListener.setDisabled(EXISTING_GRADLE_HOME)
|
||||
return
|
||||
}
|
||||
core.info('Gradle User Home already exists: will overwrite with cached contents.')
|
||||
@@ -46,21 +51,21 @@ export async function restore(
|
||||
// Mark the state as restored so that post-action will perform save.
|
||||
core.saveState(CACHE_RESTORED_VAR, true)
|
||||
|
||||
if (cacheConfig.isCacheCleanupEnabled()) {
|
||||
core.info('Preparing cache for cleanup.')
|
||||
const cacheCleaner = new CacheCleaner(gradleUserHome, process.env['RUNNER_TEMP']!)
|
||||
await cacheCleaner.prepare()
|
||||
}
|
||||
|
||||
if (cacheConfig.isCacheWriteOnly()) {
|
||||
core.info('Cache is write-only: will not restore from cache.')
|
||||
cacheListener.cacheWriteOnly = true
|
||||
cacheListener.setWriteOnly()
|
||||
return
|
||||
}
|
||||
|
||||
await core.group('Restore Gradle state from cache', async () => {
|
||||
await gradleStateCache.restore(cacheListener)
|
||||
})
|
||||
|
||||
if (cacheConfig.isCacheCleanupEnabled()) {
|
||||
core.info('Preparing cache for cleanup.')
|
||||
const cacheCleaner = new CacheCleaner(gradleUserHome, process.env['RUNNER_TEMP']!)
|
||||
await cacheCleaner.prepare()
|
||||
}
|
||||
}
|
||||
|
||||
export async function save(
|
||||
@@ -68,6 +73,7 @@ export async function save(
|
||||
gradleUserHome: string,
|
||||
cacheListener: CacheListener,
|
||||
daemonController: DaemonController,
|
||||
buildResults: BuildResults,
|
||||
cacheConfig: CacheConfig
|
||||
): Promise<void> {
|
||||
if (cacheConfig.isCacheDisabled()) {
|
||||
@@ -82,19 +88,22 @@ export async function save(
|
||||
|
||||
if (cacheConfig.isCacheReadOnly()) {
|
||||
core.info('Cache is read-only: will not save state for use in subsequent builds.')
|
||||
cacheListener.cacheReadOnly = true
|
||||
cacheListener.setReadOnly()
|
||||
return
|
||||
}
|
||||
|
||||
await daemonController.stopAllDaemons()
|
||||
|
||||
if (cacheConfig.isCacheCleanupEnabled()) {
|
||||
core.info('Forcing cache cleanup.')
|
||||
const cacheCleaner = new CacheCleaner(gradleUserHome, process.env['RUNNER_TEMP']!)
|
||||
try {
|
||||
await cacheCleaner.forceCleanup()
|
||||
} catch (e) {
|
||||
core.warning(`Cache cleanup failed. Will continue. ${String(e)}`)
|
||||
if (buildResults.anyConfigCacheHit()) {
|
||||
core.info('Not performing cache-cleanup due to config-cache reuse')
|
||||
cacheListener.setCacheCleanupDisabled(CLEANUP_DISABLED_DUE_TO_CONFIG_CACHE_HIT)
|
||||
} else if (cacheConfig.shouldPerformCacheCleanup(buildResults.anyFailed())) {
|
||||
cacheListener.setCacheCleanupEnabled()
|
||||
await performCacheCleanup(gradleUserHome)
|
||||
} else {
|
||||
core.info('Not performing cache-cleanup due to build failure')
|
||||
cacheListener.setCacheCleanupDisabled(CLEANUP_DISABLED_DUE_TO_FAILURE)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,3 +111,13 @@ export async function save(
|
||||
return new GradleUserHomeCache(userHome, gradleUserHome, cacheConfig).save(cacheListener)
|
||||
})
|
||||
}
|
||||
|
||||
async function performCacheCleanup(gradleUserHome: string): Promise<void> {
|
||||
core.info('Forcing cache cleanup.')
|
||||
const cacheCleaner = new CacheCleaner(gradleUserHome, process.env['RUNNER_TEMP']!)
|
||||
try {
|
||||
await cacheCleaner.forceCleanup()
|
||||
} catch (e) {
|
||||
core.warning(`Cache cleanup failed. Will continue. ${String(e)}`)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -449,7 +449,7 @@ export class ConfigurationCacheEntryExtractor extends AbstractEntryExtractor {
|
||||
}
|
||||
|
||||
private getConfigCacheDirectoriesWithAssociatedBuildResults(): Record<string, BuildResult[]> {
|
||||
return loadBuildResults().reduce(
|
||||
return loadBuildResults().results.reduce(
|
||||
(acc, buildResult) => {
|
||||
// For each build result, find the config-cache dir
|
||||
const configCachePath = path.resolve(buildResult.rootProjectDir, '.gradle/configuration-cache')
|
||||
|
||||
@@ -86,6 +86,7 @@ export class GradleUserHomeCache {
|
||||
await this.debugReportGradleUserHomeSize('as restored from cache')
|
||||
await new GradleHomeEntryExtractor(this.gradleUserHome, this.cacheConfig).restore(listener)
|
||||
await new ConfigurationCacheEntryExtractor(this.gradleUserHome, this.cacheConfig).restore(listener)
|
||||
await this.deleteExcludedPaths()
|
||||
await this.debugReportGradleUserHomeSize('after restoring common artifacts')
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ import * as cache from '@actions/cache'
|
||||
import * as deprecator from './deprecation-collector'
|
||||
import {SUMMARY_ENV_VAR} from '@actions/core/lib/summary'
|
||||
|
||||
import {parseArgsStringToArgv} from 'string-argv'
|
||||
import path from 'path'
|
||||
|
||||
const ACTION_ID_VAR = 'GRADLE_ACTION_ID'
|
||||
@@ -23,11 +22,9 @@ export class DependencyGraphConfig {
|
||||
return DependencyGraphOption.GenerateAndUpload
|
||||
case 'download-and-submit':
|
||||
return DependencyGraphOption.DownloadAndSubmit
|
||||
case 'clear':
|
||||
return DependencyGraphOption.Clear
|
||||
}
|
||||
throw TypeError(
|
||||
`The value '${val}' is not valid for 'dependency-graph'. Valid values are: [disabled, generate, generate-and-submit, generate-and-upload, download-and-submit, clear]. The default value is 'disabled'.`
|
||||
`The value '${val}' is not valid for 'dependency-graph'. Valid values are: [disabled, generate, generate-and-submit, generate-and-upload, download-and-submit]. The default value is 'disabled'.`
|
||||
)
|
||||
}
|
||||
|
||||
@@ -46,7 +43,28 @@ export class DependencyGraphConfig {
|
||||
}
|
||||
|
||||
getReportDirectory(): string {
|
||||
return path.resolve(getWorkspaceDirectory(), 'dependency-graph-reports')
|
||||
const param = core.getInput('dependency-graph-report-dir')
|
||||
return path.resolve(getWorkspaceDirectory(), param)
|
||||
}
|
||||
|
||||
getDownloadArtifactName(): string | undefined {
|
||||
return process.env['DEPENDENCY_GRAPH_DOWNLOAD_ARTIFACT_NAME']
|
||||
}
|
||||
|
||||
getExcludeProjects(): string | undefined {
|
||||
return getOptionalInput('dependency-graph-exclude-projects')
|
||||
}
|
||||
|
||||
getIncludeProjects(): string | undefined {
|
||||
return getOptionalInput('dependency-graph-include-projects')
|
||||
}
|
||||
|
||||
getExcludeConfigurations(): string | undefined {
|
||||
return getOptionalInput('dependency-graph-exclude-configurations')
|
||||
}
|
||||
|
||||
getIncludeConfigurations(): string | undefined {
|
||||
return getOptionalInput('dependency-graph-include-configurations')
|
||||
}
|
||||
|
||||
static constructJobCorrelator(workflow: string, jobId: string, matrixJson: string): string {
|
||||
@@ -77,8 +95,7 @@ export enum DependencyGraphOption {
|
||||
Generate = 'generate',
|
||||
GenerateAndSubmit = 'generate-and-submit',
|
||||
GenerateAndUpload = 'generate-and-upload',
|
||||
DownloadAndSubmit = 'download-and-submit',
|
||||
Clear = 'clear'
|
||||
DownloadAndSubmit = 'download-and-submit'
|
||||
}
|
||||
|
||||
export class CacheConfig {
|
||||
@@ -107,7 +124,45 @@ export class CacheConfig {
|
||||
}
|
||||
|
||||
isCacheCleanupEnabled(): boolean {
|
||||
return getBooleanInput('gradle-home-cache-cleanup') && !this.isCacheReadOnly()
|
||||
if (this.isCacheReadOnly()) {
|
||||
return false
|
||||
}
|
||||
const cleanupOption = this.getCacheCleanupOption()
|
||||
return cleanupOption === CacheCleanupOption.Always || cleanupOption === CacheCleanupOption.OnSuccess
|
||||
}
|
||||
|
||||
shouldPerformCacheCleanup(hasFailure: boolean): boolean {
|
||||
const cleanupOption = this.getCacheCleanupOption()
|
||||
if (cleanupOption === CacheCleanupOption.Always) {
|
||||
return true
|
||||
}
|
||||
if (cleanupOption === CacheCleanupOption.OnSuccess) {
|
||||
return !hasFailure
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private getCacheCleanupOption(): CacheCleanupOption {
|
||||
const legacyVal = getOptionalBooleanInput('gradle-home-cache-cleanup')
|
||||
if (legacyVal !== undefined) {
|
||||
deprecator.recordDeprecation(
|
||||
'The `gradle-home-cache-cleanup` input parameter has been replaced by `cache-cleanup`'
|
||||
)
|
||||
return legacyVal ? CacheCleanupOption.Always : CacheCleanupOption.Never
|
||||
}
|
||||
|
||||
const val = core.getInput('cache-cleanup')
|
||||
switch (val.toLowerCase().trim()) {
|
||||
case 'always':
|
||||
return CacheCleanupOption.Always
|
||||
case 'on-success':
|
||||
return CacheCleanupOption.OnSuccess
|
||||
case 'never':
|
||||
return CacheCleanupOption.Never
|
||||
}
|
||||
throw TypeError(
|
||||
`The value '${val}' is not valid for cache-cleanup. Valid values are: [never, always, on-success].`
|
||||
)
|
||||
}
|
||||
|
||||
getCacheEncryptionKey(): string {
|
||||
@@ -123,6 +178,12 @@ export class CacheConfig {
|
||||
}
|
||||
}
|
||||
|
||||
export enum CacheCleanupOption {
|
||||
Never = 'never',
|
||||
OnSuccess = 'on-success',
|
||||
Always = 'always'
|
||||
}
|
||||
|
||||
export class SummaryConfig {
|
||||
shouldGenerateJobSummary(hasFailure: boolean): boolean {
|
||||
// Check if Job Summary is supported on this platform
|
||||
@@ -130,11 +191,6 @@ export class SummaryConfig {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check if Job Summary is disabled using the deprecated input
|
||||
if (!this.isJobSummaryEnabled()) {
|
||||
return false
|
||||
}
|
||||
|
||||
return this.shouldAddJobSummary(this.getJobSummaryOption(), hasFailure)
|
||||
}
|
||||
|
||||
@@ -153,10 +209,6 @@ export class SummaryConfig {
|
||||
}
|
||||
}
|
||||
|
||||
private isJobSummaryEnabled(): boolean {
|
||||
return getBooleanInput('generate-job-summary', true)
|
||||
}
|
||||
|
||||
private getJobSummaryOption(): JobSummaryOption {
|
||||
return this.parseJobSummaryOption('add-job-summary')
|
||||
}
|
||||
@@ -196,11 +248,11 @@ export class BuildScanConfig {
|
||||
}
|
||||
|
||||
getBuildScanTermsOfUseUrl(): string {
|
||||
return this.getTermsOfUseProp('build-scan-terms-of-use-url', 'build-scan-terms-of-service-url')
|
||||
return core.getInput('build-scan-terms-of-use-url')
|
||||
}
|
||||
|
||||
getBuildScanTermsOfUseAgree(): string {
|
||||
return this.getTermsOfUseProp('build-scan-terms-of-use-agree', 'build-scan-terms-of-service-agree')
|
||||
return core.getInput('build-scan-terms-of-use-agree')
|
||||
}
|
||||
|
||||
getDevelocityAccessKey(): string {
|
||||
@@ -269,22 +321,6 @@ export class BuildScanConfig {
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO @bigdaz: remove support for the deprecated input property in the next major release of the action
|
||||
*/
|
||||
private getTermsOfUseProp(newPropName: string, oldPropName: string): string {
|
||||
const newProp = core.getInput(newPropName)
|
||||
if (newProp !== '') {
|
||||
return newProp
|
||||
}
|
||||
const oldProp = core.getInput(oldPropName)
|
||||
if (oldProp !== '') {
|
||||
deprecator.recordDeprecation('The `build-scan-terms-of-service` input parameters have been renamed')
|
||||
return oldProp
|
||||
}
|
||||
return core.getInput(oldPropName)
|
||||
}
|
||||
}
|
||||
|
||||
export class GradleExecutionConfig {
|
||||
@@ -302,16 +338,6 @@ export class GradleExecutionConfig {
|
||||
return resolvedBuildRootDirectory
|
||||
}
|
||||
|
||||
getArguments(): string[] {
|
||||
const input = core.getInput('arguments')
|
||||
if (input.length !== 0) {
|
||||
deprecator.recordDeprecation(
|
||||
'Using the action to execute Gradle via the `arguments` parameter is deprecated'
|
||||
)
|
||||
}
|
||||
return parseArgsStringToArgv(input)
|
||||
}
|
||||
|
||||
getDependencyResolutionTask(): string {
|
||||
return core.getInput('dependency-resolution-task') || ':ForceDependencyResolutionPlugin_resolveAllDependencies'
|
||||
}
|
||||
@@ -319,6 +345,16 @@ export class GradleExecutionConfig {
|
||||
getAdditionalArguments(): string {
|
||||
return core.getInput('additional-arguments')
|
||||
}
|
||||
|
||||
verifyNoArguments(): void {
|
||||
const input = core.getInput('arguments')
|
||||
if (input.length !== 0) {
|
||||
deprecator.failOnUseOfRemovedFeature(
|
||||
`The 'arguments' parameter is no longer supported for ${getActionId()}`,
|
||||
'Using the action to execute Gradle via the `arguments` parameter is deprecated'
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function doValidateWrappers(): boolean {
|
||||
@@ -357,6 +393,14 @@ export function parseNumericInput(paramName: string, paramValue: string, paramDe
|
||||
return numericValue
|
||||
}
|
||||
|
||||
function getOptionalInput(paramName: string): string | undefined {
|
||||
const paramValue = core.getInput(paramName)
|
||||
if (paramValue.length > 0) {
|
||||
return paramValue
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
function getBooleanInput(paramName: string, paramDefault = false): boolean {
|
||||
const paramValue = core.getInput(paramName)
|
||||
switch (paramValue.toLowerCase().trim()) {
|
||||
|
||||
@@ -2,14 +2,13 @@ import * as core from '@actions/core'
|
||||
import * as exec from '@actions/exec'
|
||||
import * as fs from 'fs'
|
||||
import * as path from 'path'
|
||||
import {BuildResult} from './build-results'
|
||||
import {BuildResults} from './build-results'
|
||||
|
||||
export class DaemonController {
|
||||
private readonly gradleHomes
|
||||
|
||||
constructor(buildResults: BuildResult[]) {
|
||||
const allHomes = buildResults.map(buildResult => buildResult.gradleHomeDir)
|
||||
this.gradleHomes = Array.from(new Set(allHomes))
|
||||
constructor(buildResults: BuildResults) {
|
||||
this.gradleHomes = buildResults.uniqueGradleHomes()
|
||||
}
|
||||
|
||||
async stopAllDaemons(): Promise<void> {
|
||||
|
||||
@@ -31,22 +31,23 @@ export async function setup(config: DependencyGraphConfig): Promise<void> {
|
||||
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_ENABLED', 'true')
|
||||
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_CONTINUE_ON_FAILURE', config.getDependencyGraphContinueOnFailure())
|
||||
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_CORRELATOR', config.getJobCorrelator())
|
||||
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_ID', github.context.runId)
|
||||
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_ID', github.context.runId.toString())
|
||||
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_REF', github.context.ref)
|
||||
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_SHA', getShaFromContext())
|
||||
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_WORKSPACE', getWorkspaceDirectory())
|
||||
maybeExportVariable('DEPENDENCY_GRAPH_REPORT_DIR', config.getReportDirectory())
|
||||
|
||||
// To clear the dependency graph, we generate an empty graph by excluding all projects and configurations
|
||||
if (option === DependencyGraphOption.Clear) {
|
||||
core.exportVariable('DEPENDENCY_GRAPH_INCLUDE_PROJECTS', '')
|
||||
core.exportVariable('DEPENDENCY_GRAPH_INCLUDE_CONFIGURATIONS', '')
|
||||
}
|
||||
maybeExportVariable('DEPENDENCY_GRAPH_EXCLUDE_PROJECTS', config.getExcludeProjects())
|
||||
maybeExportVariable('DEPENDENCY_GRAPH_INCLUDE_PROJECTS', config.getIncludeProjects())
|
||||
maybeExportVariable('DEPENDENCY_GRAPH_EXCLUDE_CONFIGURATIONS', config.getExcludeConfigurations())
|
||||
maybeExportVariable('DEPENDENCY_GRAPH_INCLUDE_CONFIGURATIONS', config.getIncludeConfigurations())
|
||||
}
|
||||
|
||||
function maybeExportVariable(variableName: string, value: unknown): void {
|
||||
function maybeExportVariable(variableName: string, value: string | boolean | undefined): void {
|
||||
if (!process.env[variableName]) {
|
||||
core.exportVariable(variableName, value)
|
||||
if (value !== undefined) {
|
||||
core.exportVariable(variableName, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +60,6 @@ export async function complete(config: DependencyGraphConfig): Promise<void> {
|
||||
case DependencyGraphOption.DownloadAndSubmit: // Performed in setup
|
||||
return
|
||||
case DependencyGraphOption.GenerateAndSubmit:
|
||||
case DependencyGraphOption.Clear: // Submit the empty dependency graph
|
||||
await findAndSubmitDependencyGraphs(config)
|
||||
return
|
||||
case DependencyGraphOption.GenerateAndUpload:
|
||||
@@ -77,7 +77,7 @@ async function downloadAndSubmitDependencyGraphs(config: DependencyGraphConfig):
|
||||
}
|
||||
|
||||
try {
|
||||
await submitDependencyGraphs(await downloadDependencyGraphs())
|
||||
await submitDependencyGraphs(await downloadDependencyGraphs(config))
|
||||
} catch (e) {
|
||||
warnOrFail(config, DependencyGraphOption.DownloadAndSubmit, e)
|
||||
}
|
||||
@@ -111,7 +111,7 @@ async function findAndUploadDependencyGraphs(config: DependencyGraphConfig): Pro
|
||||
await uploadDependencyGraphs(await findDependencyGraphFiles(), config)
|
||||
}
|
||||
|
||||
async function downloadDependencyGraphs(): Promise<string[]> {
|
||||
async function downloadDependencyGraphs(config: DependencyGraphConfig): Promise<string[]> {
|
||||
const findBy = github.context.payload.workflow_run
|
||||
? {
|
||||
token: getGithubToken(),
|
||||
@@ -123,13 +123,19 @@ async function downloadDependencyGraphs(): Promise<string[]> {
|
||||
|
||||
const artifactClient = new DefaultArtifactClient()
|
||||
|
||||
const dependencyGraphArtifacts = (
|
||||
let dependencyGraphArtifacts = (
|
||||
await artifactClient.listArtifacts({
|
||||
latest: true,
|
||||
findBy
|
||||
})
|
||||
).artifacts.filter(artifact => artifact.name.startsWith(DEPENDENCY_GRAPH_PREFIX))
|
||||
|
||||
const artifactName = config.getDownloadArtifactName()
|
||||
if (artifactName) {
|
||||
core.info(`Filtering for artifacts ending with ${artifactName}`)
|
||||
dependencyGraphArtifacts = dependencyGraphArtifacts.filter(artifact => artifact.name.includes(artifactName))
|
||||
}
|
||||
|
||||
for (const artifact of dependencyGraphArtifacts) {
|
||||
const downloadedArtifact = await artifactClient.downloadArtifact(artifact.id, {
|
||||
findBy
|
||||
|
||||
@@ -3,6 +3,7 @@ import {getActionId} from './configuration'
|
||||
|
||||
const DEPRECATION_UPGRADE_PAGE = 'https://github.com/gradle/actions/blob/main/docs/deprecation-upgrade-guide.md'
|
||||
const recordedDeprecations: Deprecation[] = []
|
||||
const recordedErrors: string[] = []
|
||||
|
||||
export class Deprecation {
|
||||
constructor(readonly message: string) {}
|
||||
@@ -22,10 +23,21 @@ export function recordDeprecation(message: string): void {
|
||||
}
|
||||
}
|
||||
|
||||
export function failOnUseOfRemovedFeature(removalMessage: string, deprecationMessage: string = removalMessage): void {
|
||||
const deprecation = new Deprecation(deprecationMessage)
|
||||
const errorMessage = `${removalMessage}. See ${deprecation.getDocumentationLink()}`
|
||||
recordedErrors.push(errorMessage)
|
||||
core.setFailed(errorMessage)
|
||||
}
|
||||
|
||||
export function getDeprecations(): Deprecation[] {
|
||||
return recordedDeprecations
|
||||
}
|
||||
|
||||
export function getErrors(): string[] {
|
||||
return recordedErrors
|
||||
}
|
||||
|
||||
export function emitDeprecationWarnings(hasJobSummary = true): void {
|
||||
if (recordedDeprecations.length > 0) {
|
||||
core.warning(
|
||||
@@ -38,17 +50,21 @@ export function emitDeprecationWarnings(hasJobSummary = true): void {
|
||||
}
|
||||
|
||||
export function saveDeprecationState(): void {
|
||||
core.saveState('deprecations', JSON.stringify(recordedDeprecations))
|
||||
core.saveState('deprecation-collector_deprecations', JSON.stringify(recordedDeprecations))
|
||||
core.saveState('deprecation-collector_errors', JSON.stringify(recordedErrors))
|
||||
}
|
||||
|
||||
export function restoreDeprecationState(): void {
|
||||
const stringRep = core.getState('deprecations')
|
||||
if (stringRep === '') {
|
||||
return
|
||||
const savedDeprecations = core.getState('deprecation-collector_deprecations')
|
||||
if (savedDeprecations) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
JSON.parse(savedDeprecations).forEach((obj: any) => {
|
||||
recordedDeprecations.push(new Deprecation(obj.message))
|
||||
})
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
JSON.parse(stringRep).forEach((obj: any) => {
|
||||
recordedDeprecations.push(new Deprecation(obj.message))
|
||||
})
|
||||
const savedErrors = core.getState('deprecation-collector_errors')
|
||||
if (savedErrors) {
|
||||
recordedErrors.push(...JSON.parse(savedErrors))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import * as fs from 'fs'
|
||||
import * as os from 'os'
|
||||
import * as path from 'path'
|
||||
import which from 'which'
|
||||
import * as httpm from '@actions/http-client'
|
||||
import * as core from '@actions/core'
|
||||
import * as cache from '@actions/cache'
|
||||
import * as exec from '@actions/exec'
|
||||
import * as toolCache from '@actions/tool-cache'
|
||||
|
||||
import * as gradlew from './gradlew'
|
||||
@@ -95,12 +97,18 @@ async function findGradleVersionDeclaration(version: string): Promise<GradleVers
|
||||
|
||||
async function installGradleVersion(versionInfo: GradleVersionInfo): Promise<string> {
|
||||
return core.group(`Provision Gradle ${versionInfo.version}`, async () => {
|
||||
const preInstalledGradle = await findGradleVersionOnPath(versionInfo)
|
||||
if (preInstalledGradle !== undefined) {
|
||||
core.info(`Gradle version ${versionInfo.version} is already available on PATH. Not installing.`)
|
||||
return preInstalledGradle
|
||||
}
|
||||
|
||||
return locateGradleAndDownloadIfRequired(versionInfo)
|
||||
})
|
||||
}
|
||||
|
||||
async function locateGradleAndDownloadIfRequired(versionInfo: GradleVersionInfo): Promise<string> {
|
||||
const installsDir = path.join(os.homedir(), 'gradle-installations/installs')
|
||||
const installsDir = path.join(getProvisionDir(), 'installs')
|
||||
const installDir = path.join(installsDir, `gradle-${versionInfo.version}`)
|
||||
if (fs.existsSync(installDir)) {
|
||||
core.info(`Gradle installation already exists at ${installDir}`)
|
||||
@@ -119,7 +127,7 @@ async function locateGradleAndDownloadIfRequired(versionInfo: GradleVersionInfo)
|
||||
}
|
||||
|
||||
async function downloadAndCacheGradleDistribution(versionInfo: GradleVersionInfo): Promise<string> {
|
||||
const downloadPath = path.join(os.homedir(), `gradle-installations/downloads/gradle-${versionInfo.version}-bin.zip`)
|
||||
const downloadPath = path.join(getProvisionDir(), `downloads/gradle-${versionInfo.version}-bin.zip`)
|
||||
|
||||
// TODO: Convert this to a class and inject config
|
||||
const cacheConfig = new CacheConfig()
|
||||
@@ -152,6 +160,11 @@ async function downloadAndCacheGradleDistribution(versionInfo: GradleVersionInfo
|
||||
return downloadPath
|
||||
}
|
||||
|
||||
function getProvisionDir(): string {
|
||||
const tmpDir = process.env['RUNNER_TEMP'] ?? os.tmpdir()
|
||||
return path.join(tmpDir, `.gradle-actions/gradle-installations`)
|
||||
}
|
||||
|
||||
async function downloadGradleDistribution(versionInfo: GradleVersionInfo, downloadPath: string): Promise<void> {
|
||||
await toolCache.downloadTool(versionInfo.downloadUrl, downloadPath)
|
||||
core.info(`Downloaded ${versionInfo.downloadUrl} to ${downloadPath} (size ${fs.statSync(downloadPath).size})`)
|
||||
@@ -179,3 +192,15 @@ interface GradleVersionInfo {
|
||||
version: string
|
||||
downloadUrl: string
|
||||
}
|
||||
|
||||
async function findGradleVersionOnPath(versionInfo: GradleVersionInfo): Promise<string | undefined> {
|
||||
const gradleExecutable = await which('gradle', {nothrow: true})
|
||||
if (gradleExecutable) {
|
||||
const output = await exec.getExecOutput(gradleExecutable, ['-v'], {silent: true})
|
||||
if (output.stdout.includes(`Gradle ${versionInfo.version}`)) {
|
||||
return gradleExecutable
|
||||
}
|
||||
}
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
@@ -2,18 +2,25 @@ import * as core from '@actions/core'
|
||||
import * as github from '@actions/github'
|
||||
import {RequestError} from '@octokit/request-error'
|
||||
|
||||
import {BuildResult} from './build-results'
|
||||
import {BuildResults, BuildResult} from './build-results'
|
||||
import {SummaryConfig, getActionId, getGithubToken} from './configuration'
|
||||
import {Deprecation, getDeprecations} from './deprecation-collector'
|
||||
import {Deprecation, getDeprecations, getErrors} from './deprecation-collector'
|
||||
|
||||
export async function generateJobSummary(
|
||||
buildResults: BuildResult[],
|
||||
buildResults: BuildResults,
|
||||
cachingReport: string,
|
||||
config: SummaryConfig
|
||||
): Promise<void> {
|
||||
const summaryTable = renderSummaryTable(buildResults)
|
||||
const errors = renderErrors()
|
||||
if (errors) {
|
||||
core.summary.addRaw(errors)
|
||||
await core.summary.write()
|
||||
return
|
||||
}
|
||||
|
||||
const hasFailure = buildResults.some(result => result.buildFailed)
|
||||
const summaryTable = renderSummaryTable(buildResults.results)
|
||||
|
||||
const hasFailure = buildResults.anyFailed()
|
||||
if (config.shouldGenerateJobSummary(hasFailure)) {
|
||||
core.info('Generating Job Summary')
|
||||
|
||||
@@ -82,6 +89,14 @@ export function renderSummaryTable(results: BuildResult[]): string {
|
||||
return `${renderDeprecations()}\n${renderBuildResults(results)}`
|
||||
}
|
||||
|
||||
function renderErrors(): string | undefined {
|
||||
const errors = getErrors()
|
||||
if (errors.length === 0) {
|
||||
return undefined
|
||||
}
|
||||
return errors.map(error => `<b>:x: ${error}</b>`).join('\n')
|
||||
}
|
||||
|
||||
function renderDeprecations(): string {
|
||||
const deprecations = getDeprecations()
|
||||
if (deprecations.length === 0) {
|
||||
|
||||
@@ -1,23 +1,27 @@
|
||||
import org.gradle.tooling.events.*
|
||||
import org.gradle.tooling.events.task.*
|
||||
import org.gradle.internal.operations.*
|
||||
import org.gradle.initialization.*
|
||||
import org.gradle.api.internal.tasks.execution.*
|
||||
import org.gradle.execution.*
|
||||
import org.gradle.internal.build.event.BuildEventListenerRegistryInternal
|
||||
import org.gradle.util.GradleVersion
|
||||
|
||||
// Can't use settingsEvaluated since this script is applied inside a settingsEvaluated handler
|
||||
// But projectsEvaluated is good enough, since the build service won't catch configuration failures anyway
|
||||
projectsEvaluated {
|
||||
settingsEvaluated { settings ->
|
||||
def projectTracker = gradle.sharedServices.registerIfAbsent("gradle-action-buildResultsRecorder", BuildResultsRecorder, { spec ->
|
||||
spec.getParameters().getRootProjectName().set(gradle.rootProject.name)
|
||||
spec.getParameters().getRootProjectDir().set(gradle.rootProject.rootDir.absolutePath)
|
||||
spec.getParameters().getRootProjectName().set(settings.rootProject.name)
|
||||
spec.getParameters().getRootProjectDir().set(settings.rootDir.absolutePath)
|
||||
spec.getParameters().getRequestedTasks().set(gradle.startParameter.taskNames.join(" "))
|
||||
spec.getParameters().getGradleHomeDir().set(gradle.gradleHomeDir.absolutePath)
|
||||
spec.getParameters().getInvocationId().set(gradle.ext.invocationId)
|
||||
})
|
||||
|
||||
gradle.services.get(BuildEventsListenerRegistry).onTaskCompletion(projectTracker)
|
||||
gradle.services.get(BuildEventListenerRegistryInternal).onOperationCompletion(projectTracker)
|
||||
}
|
||||
|
||||
abstract class BuildResultsRecorder implements BuildService<BuildResultsRecorder.Params>, OperationCompletionListener, AutoCloseable {
|
||||
abstract class BuildResultsRecorder implements BuildService<BuildResultsRecorder.Params>, BuildOperationListener, AutoCloseable {
|
||||
private boolean buildFailed = false
|
||||
private boolean configCacheHit = true
|
||||
interface Params extends BuildServiceParameters {
|
||||
Property<String> getRootProjectName()
|
||||
Property<String> getRootProjectDir()
|
||||
@@ -26,9 +30,19 @@ abstract class BuildResultsRecorder implements BuildService<BuildResultsRecorder
|
||||
Property<String> getInvocationId()
|
||||
}
|
||||
|
||||
public void onFinish(FinishEvent finishEvent) {
|
||||
if (finishEvent instanceof TaskFinishEvent && finishEvent.result instanceof TaskFailureResult) {
|
||||
buildFailed = true
|
||||
void started(BuildOperationDescriptor buildOperation, OperationStartEvent startEvent) {}
|
||||
|
||||
void progress(OperationIdentifier operationIdentifier, OperationProgressEvent progressEvent) {}
|
||||
|
||||
void finished(BuildOperationDescriptor buildOperation, OperationFinishEvent finishEvent) {
|
||||
if (buildOperation.details in EvaluateSettingsBuildOperationType.Details) {
|
||||
// Got EVALUATE SETTINGS event: not a config-cache hit"
|
||||
configCacheHit = false
|
||||
}
|
||||
if (buildOperation.details in RunRootBuildWorkBuildOperationType.Details) {
|
||||
if (finishEvent.failure != null) {
|
||||
buildFailed = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,8 +55,7 @@ abstract class BuildResultsRecorder implements BuildService<BuildResultsRecorder
|
||||
gradleVersion: GradleVersion.current().version,
|
||||
gradleHomeDir: getParameters().getGradleHomeDir().get(),
|
||||
buildFailed: buildFailed,
|
||||
buildScanUri: null,
|
||||
buildScanFailed: false
|
||||
configCacheHit: configCacheHit
|
||||
]
|
||||
|
||||
def runnerTempDir = System.getProperty("RUNNER_TEMP") ?: System.getenv("RUNNER_TEMP")
|
||||
@@ -52,7 +65,7 @@ abstract class BuildResultsRecorder implements BuildService<BuildResultsRecorder
|
||||
}
|
||||
|
||||
try {
|
||||
def buildResultsDir = new File(runnerTempDir, ".build-results")
|
||||
def buildResultsDir = new File(runnerTempDir, ".gradle-actions/build-results")
|
||||
buildResultsDir.mkdirs()
|
||||
def buildResultsFile = new File(buildResultsDir, githubActionStep + getParameters().getInvocationId().get() + ".json")
|
||||
if (!buildResultsFile.exists()) {
|
||||
|
||||
@@ -13,6 +13,7 @@ def GE_EXTENSION = "gradleEnterprise"
|
||||
// Only run against root build. Do not run against included builds.
|
||||
def isTopLevelBuild = gradle.getParent() == null
|
||||
if (isTopLevelBuild) {
|
||||
def resultsWriter = new ResultsWriter()
|
||||
def version = GradleVersion.current().baseVersion
|
||||
|
||||
def atLeastGradle3 = version >= GradleVersion.version("3.0")
|
||||
@@ -21,59 +22,77 @@ if (isTopLevelBuild) {
|
||||
def invocationId = "-${System.currentTimeMillis()}"
|
||||
|
||||
if (atLeastGradle6) {
|
||||
// By default, use standard mechanisms to capture build results
|
||||
def useBuildService = version >= GradleVersion.version("6.6")
|
||||
if (useBuildService) {
|
||||
captureUsingBuildService(invocationId)
|
||||
} else {
|
||||
captureUsingBuildFinished(gradle, invocationId, resultsWriter)
|
||||
}
|
||||
|
||||
// Use the Develocity plugin to also capture build scan links, when available
|
||||
settingsEvaluated { settings ->
|
||||
// By default, use standard mechanisms to capture build results
|
||||
if (useBuildService) {
|
||||
captureUsingBuildService(settings, invocationId)
|
||||
} else {
|
||||
captureUsingBuildFinished(gradle, invocationId)
|
||||
}
|
||||
|
||||
|
||||
settings.pluginManager.withPlugin(GE_PLUGIN_ID) {
|
||||
// Only execute if develocity plugin isn't applied.
|
||||
if (!settings.extensions.findByName(DEVELOCITY_EXTENSION)) {
|
||||
captureUsingBuildScanPublished(settings.extensions[GE_EXTENSION].buildScan, settings.rootProject, invocationId)
|
||||
captureUsingBuildScanPublished(settings.extensions[GE_EXTENSION].buildScan, invocationId, resultsWriter)
|
||||
}
|
||||
}
|
||||
|
||||
settings.pluginManager.withPlugin(DEVELOCITY_PLUGIN_ID) {
|
||||
captureUsingBuildScanPublished(settings.extensions[DEVELOCITY_EXTENSION].buildScan, settings.rootProject, invocationId)
|
||||
captureUsingBuildScanPublished(settings.extensions[DEVELOCITY_EXTENSION].buildScan, invocationId, resultsWriter)
|
||||
}
|
||||
}
|
||||
} else if (atLeastGradle3) {
|
||||
projectsEvaluated { gradle ->
|
||||
// By default, use 'buildFinished' to capture build results
|
||||
captureUsingBuildFinished(gradle, invocationId)
|
||||
captureUsingBuildFinished(gradle, invocationId, resultsWriter)
|
||||
|
||||
gradle.rootProject.pluginManager.withPlugin(BUILD_SCAN_PLUGIN_ID) {
|
||||
// Only execute if develocity plugin isn't applied.
|
||||
if (!gradle.rootProject.extensions.findByName(DEVELOCITY_EXTENSION)) {
|
||||
captureUsingBuildScanPublished(gradle.rootProject.extensions[BUILD_SCAN_EXTENSION], gradle.rootProject, invocationId)
|
||||
captureUsingBuildScanPublished(gradle.rootProject.extensions[BUILD_SCAN_EXTENSION], invocationId, resultsWriter)
|
||||
}
|
||||
}
|
||||
|
||||
gradle.rootProject.pluginManager.withPlugin(DEVELOCITY_PLUGIN_ID) {
|
||||
captureUsingBuildScanPublished(gradle.rootProject.extensions[DEVELOCITY_EXTENSION].buildScan, gradle.rootProject, invocationId)
|
||||
captureUsingBuildScanPublished(gradle.rootProject.extensions[DEVELOCITY_EXTENSION].buildScan, invocationId, resultsWriter)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def captureUsingBuildService(invocationId) {
|
||||
gradle.ext.invocationId = invocationId
|
||||
apply from: 'gradle-actions.build-result-capture-service.plugin.groovy'
|
||||
}
|
||||
|
||||
void captureUsingBuildFinished(gradle, String invocationId, ResultsWriter resultsWriter) {
|
||||
gradle.buildFinished { result ->
|
||||
println "Got buildFinished: ${result}"
|
||||
def buildResults = [
|
||||
rootProjectName: rootProject.name,
|
||||
rootProjectDir: rootProject.projectDir.absolutePath,
|
||||
requestedTasks: gradle.startParameter.taskNames.join(" "),
|
||||
gradleVersion: GradleVersion.current().version,
|
||||
gradleHomeDir: gradle.gradleHomeDir.absolutePath,
|
||||
buildFailed: result.failure != null,
|
||||
configCacheHit: false
|
||||
]
|
||||
resultsWriter.writeToResultsFile("build-results", invocationId, buildResults)
|
||||
}
|
||||
}
|
||||
|
||||
// The `buildScanPublished` hook allows the capture of the Build Scan URI.
|
||||
// Results captured this way will overwrite any results from 'buildFinished'.
|
||||
def captureUsingBuildScanPublished(buildScanExtension, rootProject, invocationId) {
|
||||
void captureUsingBuildScanPublished(buildScanExtension, String invocationId, ResultsWriter resultsWriter) {
|
||||
buildScanExtension.with {
|
||||
def buildResults = new BuildResults(invocationId, gradle, rootProject)
|
||||
|
||||
buildFinished { result ->
|
||||
buildResults.setBuildResult(result)
|
||||
}
|
||||
|
||||
buildScanPublished { buildScan ->
|
||||
buildResults.setBuildScanUri(buildScan.buildScanUri.toASCIIString())
|
||||
buildResults.writeToResultsFile(true)
|
||||
def scanResults = [
|
||||
buildScanUri: buildScan.buildScanUri.toASCIIString(),
|
||||
buildScanFailed: false
|
||||
]
|
||||
resultsWriter.writeToResultsFile("build-scans", invocationId, scanResults)
|
||||
|
||||
def githubOutput = System.getenv("GITHUB_OUTPUT")
|
||||
if (githubOutput) {
|
||||
@@ -85,63 +104,17 @@ def captureUsingBuildScanPublished(buildScanExtension, rootProject, invocationId
|
||||
}
|
||||
|
||||
onError { error ->
|
||||
buildResults.setBuildScanFailed()
|
||||
buildResults.writeToResultsFile(true)
|
||||
def scanResults = [
|
||||
buildScanUri: null,
|
||||
buildScanFailed: true
|
||||
]
|
||||
resultsWriter.writeToResultsFile("build-scans", invocationId, scanResults)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def captureUsingBuildFinished(gradle, invocationId) {
|
||||
gradle.buildFinished { result ->
|
||||
println "Got buildFinished: ${result}"
|
||||
def buildResults = new BuildResults(invocationId, gradle, gradle.rootProject)
|
||||
buildResults.setBuildResult(result)
|
||||
buildResults.writeToResultsFile(false)
|
||||
}
|
||||
}
|
||||
|
||||
def captureUsingBuildService(settings, invocationId) {
|
||||
gradle.ext.invocationId = invocationId
|
||||
apply from: 'gradle-actions.build-result-capture-service.plugin.groovy'
|
||||
}
|
||||
|
||||
class BuildResults {
|
||||
def invocationId
|
||||
def buildResults
|
||||
|
||||
BuildResults(String invocationId, def gradle, def rootProject) {
|
||||
this.invocationId = invocationId
|
||||
buildResults = [
|
||||
rootProjectName: rootProject.name,
|
||||
rootProjectDir: rootProject.projectDir.absolutePath,
|
||||
requestedTasks: gradle.startParameter.taskNames.join(" "),
|
||||
gradleVersion: GradleVersion.current().version,
|
||||
gradleHomeDir: gradle.gradleHomeDir.absolutePath,
|
||||
buildFailed: false,
|
||||
buildScanUri: null,
|
||||
buildScanFailed: false
|
||||
]
|
||||
}
|
||||
|
||||
def setBuildResult(def result) {
|
||||
try {
|
||||
// Gradle and old Build Scan/Gradle Enterprise plugins report a single optional failure in the build result
|
||||
buildResults['buildFailed'] = result.failure != null
|
||||
} catch (Exception e) {
|
||||
// Develocity plugin unwraps all build failures and reports them as a mandatory array
|
||||
buildResults['buildFailed'] = !result.failures.empty
|
||||
}
|
||||
}
|
||||
|
||||
def setBuildScanUri(def buildScanUrl) {
|
||||
buildResults['buildScanUri'] = buildScanUrl
|
||||
}
|
||||
|
||||
def setBuildScanFailed() {
|
||||
buildResults['buildScanFailed'] = true
|
||||
}
|
||||
|
||||
def writeToResultsFile(boolean overwrite) {
|
||||
class ResultsWriter {
|
||||
void writeToResultsFile(String subDir, String invocationId, def content) {
|
||||
def runnerTempDir = System.getProperty("RUNNER_TEMP") ?: System.getenv("RUNNER_TEMP")
|
||||
def githubActionStep = System.getProperty("GITHUB_ACTION") ?: System.getenv("GITHUB_ACTION")
|
||||
if (!runnerTempDir || !githubActionStep) {
|
||||
@@ -149,19 +122,12 @@ class BuildResults {
|
||||
}
|
||||
|
||||
try {
|
||||
def buildResultsDir = new File(runnerTempDir, ".build-results")
|
||||
def buildResultsDir = new File(runnerTempDir, ".gradle-actions/${subDir}")
|
||||
buildResultsDir.mkdirs()
|
||||
def buildResultsFile = new File(buildResultsDir, githubActionStep + invocationId + ".json")
|
||||
|
||||
// Overwrite any contents written by buildFinished or build service, since this result is a superset.
|
||||
if (buildResultsFile.exists()) {
|
||||
if (overwrite) {
|
||||
buildResultsFile.text = groovy.json.JsonOutput.toJson(buildResults)
|
||||
}
|
||||
} else {
|
||||
buildResultsFile << groovy.json.JsonOutput.toJson(buildResults)
|
||||
if (!buildResultsFile.exists()) {
|
||||
buildResultsFile << groovy.json.JsonOutput.toJson(content)
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
println "\ngradle action failed to write build-results file. Will continue.\n> ${e.getLocalizedMessage()}"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import * as core from '@actions/core'
|
||||
import * as exec from '@actions/exec'
|
||||
import * as fs from 'fs'
|
||||
import * as path from 'path'
|
||||
import * as os from 'os'
|
||||
import * as caches from './caching/caches'
|
||||
@@ -60,7 +61,7 @@ export async function complete(cacheConfig: CacheConfig, summaryConfig: SummaryC
|
||||
const cacheListener: CacheListener = CacheListener.rehydrate(core.getState(CACHE_LISTENER))
|
||||
|
||||
const daemonController = new DaemonController(buildResults)
|
||||
await caches.save(userHome, gradleUserHome, cacheListener, daemonController, cacheConfig)
|
||||
await caches.save(userHome, gradleUserHome, cacheListener, daemonController, buildResults, cacheConfig)
|
||||
|
||||
const cachingReport = generateCachingReport(cacheListener)
|
||||
await jobSummary.generateJobSummary(buildResults, cachingReport, summaryConfig)
|
||||
@@ -79,7 +80,24 @@ async function determineGradleUserHome(): Promise<string> {
|
||||
return path.resolve(rootDir, customGradleUserHome)
|
||||
}
|
||||
|
||||
return path.resolve(await determineUserHome(), '.gradle')
|
||||
const defaultGradleUserHome = path.resolve(await determineUserHome(), '.gradle')
|
||||
// Use the default Gradle User Home if it already exists
|
||||
if (fs.existsSync(defaultGradleUserHome)) {
|
||||
core.info(`Gradle User Home already exists at ${defaultGradleUserHome}`)
|
||||
core.exportVariable('GRADLE_USER_HOME', defaultGradleUserHome)
|
||||
return defaultGradleUserHome
|
||||
}
|
||||
|
||||
// Switch Gradle User Home to faster 'D:' drive if possible
|
||||
if (os.platform() === 'win32' && defaultGradleUserHome.startsWith('C:\\') && fs.existsSync('D:\\a\\')) {
|
||||
const fasterGradleUserHome = 'D:\\a\\.gradle'
|
||||
core.info(`Setting GRADLE_USER_HOME to ${fasterGradleUserHome} to leverage (potentially) faster drive.`)
|
||||
core.exportVariable('GRADLE_USER_HOME', fasterGradleUserHome)
|
||||
return fasterGradleUserHome
|
||||
}
|
||||
|
||||
core.exportVariable('GRADLE_USER_HOME', defaultGradleUserHome)
|
||||
return defaultGradleUserHome
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,21 +4,27 @@ import fileWrapperChecksums from './wrapper-checksums.json'
|
||||
|
||||
const httpc = new httpm.HttpClient('gradle/wrapper-validation-action', undefined, {allowRetries: true, maxRetries: 3})
|
||||
|
||||
function getKnownValidChecksums(): Map<string, Set<string>> {
|
||||
const versionsMap = new Map<string, Set<string>>()
|
||||
for (const entry of fileWrapperChecksums) {
|
||||
const checksum = entry.checksum
|
||||
export class WrapperChecksums {
|
||||
checksums = new Map<string, Set<string>>()
|
||||
versions = new Set<string>()
|
||||
|
||||
let versionNames = versionsMap.get(checksum)
|
||||
if (versionNames === undefined) {
|
||||
versionNames = new Set()
|
||||
versionsMap.set(checksum, versionNames)
|
||||
add(version: string, checksum: string): void {
|
||||
if (this.checksums.has(checksum)) {
|
||||
this.checksums.get(checksum)!.add(version)
|
||||
} else {
|
||||
this.checksums.set(checksum, new Set([version]))
|
||||
}
|
||||
|
||||
versionNames.add(entry.version)
|
||||
this.versions.add(version)
|
||||
}
|
||||
}
|
||||
|
||||
return versionsMap
|
||||
function loadKnownChecksums(): WrapperChecksums {
|
||||
const checksums = new WrapperChecksums()
|
||||
for (const entry of fileWrapperChecksums) {
|
||||
checksums.add(entry.version, entry.checksum)
|
||||
}
|
||||
return checksums
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -26,9 +32,12 @@ function getKnownValidChecksums(): Map<string, Set<string>> {
|
||||
*
|
||||
* Maps from the checksum to the names of the Gradle versions whose wrapper has this checksum.
|
||||
*/
|
||||
export const KNOWN_VALID_CHECKSUMS = getKnownValidChecksums()
|
||||
export const KNOWN_CHECKSUMS = loadKnownChecksums()
|
||||
|
||||
export async function fetchValidChecksums(allowSnapshots: boolean): Promise<Set<string>> {
|
||||
export async function fetchUnknownChecksums(
|
||||
allowSnapshots: boolean,
|
||||
knownChecksums: WrapperChecksums
|
||||
): Promise<Set<string>> {
|
||||
const all = await httpGetJsonArray('https://services.gradle.org/versions/all')
|
||||
const withChecksum = all.filter(
|
||||
entry => typeof entry === 'object' && entry != null && entry.hasOwnProperty('wrapperChecksumUrl')
|
||||
@@ -37,7 +46,11 @@ export async function fetchValidChecksums(allowSnapshots: boolean): Promise<Set<
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(entry: any) => allowSnapshots || !entry.snapshot
|
||||
)
|
||||
const checksumUrls = allowed.map(
|
||||
const notKnown = allowed.filter(
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(entry: any) => !knownChecksums.versions.has(entry.version)
|
||||
)
|
||||
const checksumUrls = notKnown.map(
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(entry: any) => entry.wrapperChecksumUrl as string
|
||||
)
|
||||
|
||||
@@ -8,7 +8,7 @@ export async function findInvalidWrapperJars(
|
||||
minWrapperCount: number,
|
||||
allowSnapshots: boolean,
|
||||
allowedChecksums: string[],
|
||||
knownValidChecksums: Map<string, Set<string>> = checksums.KNOWN_VALID_CHECKSUMS
|
||||
knownValidChecksums: checksums.WrapperChecksums = checksums.KNOWN_CHECKSUMS
|
||||
): Promise<ValidationResult> {
|
||||
const wrapperJars = await find.findWrapperJars(gitRepoRoot)
|
||||
const result = new ValidationResult([], [])
|
||||
@@ -21,7 +21,7 @@ export async function findInvalidWrapperJars(
|
||||
const notYetValidatedWrappers = []
|
||||
for (const wrapperJar of wrapperJars) {
|
||||
const sha = await hash.sha256File(resolve(gitRepoRoot, wrapperJar))
|
||||
if (allowedChecksums.includes(sha) || knownValidChecksums.has(sha)) {
|
||||
if (allowedChecksums.includes(sha) || knownValidChecksums.checksums.has(sha)) {
|
||||
result.valid.push(new WrapperJar(wrapperJar, sha))
|
||||
} else {
|
||||
notYetValidatedWrappers.push(new WrapperJar(wrapperJar, sha))
|
||||
@@ -31,7 +31,7 @@ export async function findInvalidWrapperJars(
|
||||
// Otherwise fall back to fetching checksums from Gradle API and compare against them
|
||||
if (notYetValidatedWrappers.length > 0) {
|
||||
result.fetchedChecksums = true
|
||||
const fetchedValidChecksums = await checksums.fetchValidChecksums(allowSnapshots)
|
||||
const fetchedValidChecksums = await checksums.fetchUnknownChecksums(allowSnapshots, knownValidChecksums)
|
||||
|
||||
for (const wrapperJar of notYetValidatedWrappers) {
|
||||
if (!fetchedValidChecksums.has(wrapperJar.checksum)) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.gradle.gradlebuildaction
|
||||
|
||||
import groovy.json.JsonSlurper
|
||||
import org.gradle.util.GradleVersion
|
||||
|
||||
import static org.junit.Assume.assumeTrue
|
||||
|
||||
@@ -15,7 +14,7 @@ class TestBuildResultRecorder extends BaseInitScriptTest {
|
||||
run(testGradleVersion.gradleVersion)
|
||||
|
||||
then:
|
||||
assertResults('help', testGradleVersion, false, false)
|
||||
assertResults('help', testGradleVersion, false)
|
||||
|
||||
where:
|
||||
testGradleVersion << ALL_VERSIONS
|
||||
@@ -29,7 +28,7 @@ class TestBuildResultRecorder extends BaseInitScriptTest {
|
||||
runAndFail(testGradleVersion.gradleVersion)
|
||||
|
||||
then:
|
||||
assertResults('expectFailure', testGradleVersion, true, false)
|
||||
assertResults('expectFailure', testGradleVersion, true)
|
||||
|
||||
where:
|
||||
testGradleVersion << ALL_VERSIONS
|
||||
@@ -49,7 +48,7 @@ class TestBuildResultRecorder extends BaseInitScriptTest {
|
||||
run(['help', '--configuration-cache'], testGradleVersion.gradleVersion)
|
||||
|
||||
then:
|
||||
assertResults('help', testGradleVersion, false, false)
|
||||
assertResults('help', testGradleVersion, false, true)
|
||||
|
||||
where:
|
||||
testGradleVersion << CONFIGURATION_CACHE_VERSIONS
|
||||
@@ -63,7 +62,8 @@ class TestBuildResultRecorder extends BaseInitScriptTest {
|
||||
run(testGradleVersion.gradleVersion)
|
||||
|
||||
then:
|
||||
assertResults('help', testGradleVersion, false, true)
|
||||
assertResults('help', testGradleVersion, false)
|
||||
assertScanResults()
|
||||
|
||||
where:
|
||||
testGradleVersion << ALL_VERSIONS
|
||||
@@ -77,7 +77,8 @@ class TestBuildResultRecorder extends BaseInitScriptTest {
|
||||
run(testGradleVersion.gradleVersion)
|
||||
|
||||
then:
|
||||
assertResults('help', testGradleVersion, false, true)
|
||||
assertResults('help', testGradleVersion, false)
|
||||
assertScanResults()
|
||||
|
||||
where:
|
||||
testGradleVersion << ALL_VERSIONS
|
||||
@@ -91,7 +92,7 @@ class TestBuildResultRecorder extends BaseInitScriptTest {
|
||||
run(['help', '--no-scan'], testGradleVersion.gradleVersion)
|
||||
|
||||
then:
|
||||
assertResults('help', testGradleVersion, false, false)
|
||||
assertResults('help', testGradleVersion, false)
|
||||
|
||||
where:
|
||||
testGradleVersion << ALL_VERSIONS
|
||||
@@ -106,7 +107,8 @@ class TestBuildResultRecorder extends BaseInitScriptTest {
|
||||
runAndFail(testGradleVersion.gradleVersion)
|
||||
|
||||
then:
|
||||
assertResults('expectFailure', testGradleVersion, true, true)
|
||||
assertResults('expectFailure', testGradleVersion, true)
|
||||
assertScanResults()
|
||||
|
||||
where:
|
||||
testGradleVersion << ALL_VERSIONS
|
||||
@@ -120,14 +122,17 @@ class TestBuildResultRecorder extends BaseInitScriptTest {
|
||||
run(['help', '--configuration-cache'], testGradleVersion.gradleVersion)
|
||||
|
||||
then:
|
||||
assertResults('help', testGradleVersion, false, true)
|
||||
assertResults('help', testGradleVersion, false, false)
|
||||
assertScanResults()
|
||||
assert buildResultFile.delete()
|
||||
assert scanResultFile.delete()
|
||||
|
||||
when:
|
||||
run(['help', '--configuration-cache'], testGradleVersion.gradleVersion)
|
||||
|
||||
then:
|
||||
assertResults('help', testGradleVersion, false, true)
|
||||
assertScanResults()
|
||||
|
||||
where:
|
||||
testGradleVersion << CONFIGURATION_CACHE_VERSIONS
|
||||
@@ -143,7 +148,8 @@ class TestBuildResultRecorder extends BaseInitScriptTest {
|
||||
runAndFail(testGradleVersion.gradleVersion)
|
||||
|
||||
then:
|
||||
assertResults('expectFailure', testGradleVersion, true, false, true)
|
||||
assertResults('expectFailure', testGradleVersion, true)
|
||||
assertScanResults(true)
|
||||
|
||||
where:
|
||||
testGradleVersion << ALL_VERSIONS
|
||||
@@ -204,7 +210,8 @@ class TestBuildResultRecorder extends BaseInitScriptTest {
|
||||
run(testGradleVersion.gradleVersion)
|
||||
|
||||
then:
|
||||
assertResults('help', testGradleVersion, false, true)
|
||||
assertResults('help', testGradleVersion, false)
|
||||
assertScanResults()
|
||||
|
||||
where:
|
||||
testGradleVersion << SETTINGS_PLUGIN_VERSIONS
|
||||
@@ -232,7 +239,7 @@ class TestBuildResultRecorder extends BaseInitScriptTest {
|
||||
]
|
||||
}
|
||||
|
||||
void assertResults(String task, TestGradleVersion testGradleVersion, boolean hasFailure, boolean hasBuildScan, boolean scanUploadFailed = false) {
|
||||
void assertResults(String task, TestGradleVersion testGradleVersion, boolean hasFailure, boolean configCacheHit = false) {
|
||||
def results = new JsonSlurper().parse(buildResultFile)
|
||||
assert results['rootProjectName'] == ROOT_PROJECT_NAME
|
||||
assert results['rootProjectDir'] == testProjectDir.canonicalPath
|
||||
@@ -240,12 +247,17 @@ class TestBuildResultRecorder extends BaseInitScriptTest {
|
||||
assert results['gradleVersion'] == testGradleVersion.gradleVersion.version
|
||||
assert results['gradleHomeDir'] != null
|
||||
assert results['buildFailed'] == hasFailure
|
||||
assert results['buildScanUri'] == (hasBuildScan ? "${mockScansServer.address}s/${PUBLIC_BUILD_SCAN_ID}" : null)
|
||||
assert results['buildScanFailed'] == scanUploadFailed
|
||||
assert results['configCacheHit'] == configCacheHit
|
||||
}
|
||||
|
||||
void assertScanResults(boolean scanUploadFailed = false) {
|
||||
def scanResults = new JsonSlurper().parse(scanResultFile)
|
||||
assert scanResults['buildScanUri'] == (scanUploadFailed ? null : "${mockScansServer.address}s/${PUBLIC_BUILD_SCAN_ID}")
|
||||
assert scanResults['buildScanFailed'] == scanUploadFailed
|
||||
}
|
||||
|
||||
private File getBuildResultFile() {
|
||||
def buildResultsDir = new File(testProjectDir, '.build-results')
|
||||
def buildResultsDir = new File(testProjectDir, '.gradle-actions/build-results')
|
||||
assert buildResultsDir.directory
|
||||
assert buildResultsDir.listFiles().size() == 1
|
||||
def resultsFile = buildResultsDir.listFiles()[0]
|
||||
@@ -253,4 +265,14 @@ class TestBuildResultRecorder extends BaseInitScriptTest {
|
||||
assert resultsFile.text.count('rootProjectName') == 1
|
||||
return resultsFile
|
||||
}
|
||||
|
||||
private File getScanResultFile() {
|
||||
def buildResultsDir = new File(testProjectDir, '.gradle-actions/build-scans')
|
||||
assert buildResultsDir.directory
|
||||
assert buildResultsDir.listFiles().size() == 1
|
||||
def resultsFile = buildResultsDir.listFiles()[0]
|
||||
assert resultsFile.name.startsWith('github-step-id')
|
||||
assert resultsFile.text.count('buildScanUri') == 1
|
||||
return resultsFile
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ const successfulHelpBuild: BuildResult = {
|
||||
gradleVersion: '8.0',
|
||||
gradleHomeDir: '/opt/gradle',
|
||||
buildFailed: false,
|
||||
configCacheHit: false,
|
||||
buildScanUri: 'https://scans.gradle.com/s/abc123',
|
||||
buildScanFailed: false
|
||||
}
|
||||
|
||||
@@ -6,22 +6,22 @@ jest.setTimeout(30000)
|
||||
|
||||
test('has loaded hardcoded wrapper jars checksums', async () => {
|
||||
// Sanity check that generated checksums file is not empty and was properly imported
|
||||
expect(checksums.KNOWN_VALID_CHECKSUMS.size).toBeGreaterThan(10)
|
||||
expect(checksums.KNOWN_CHECKSUMS.checksums.size).toBeGreaterThan(10)
|
||||
// Verify that checksums of arbitrary versions are contained
|
||||
expect(
|
||||
checksums.KNOWN_VALID_CHECKSUMS.get(
|
||||
checksums.KNOWN_CHECKSUMS.checksums.get(
|
||||
'660ab018b8e319e9ae779fdb1b7ac47d0321bde953bf0eb4545f14952cfdcaa3'
|
||||
)
|
||||
).toEqual(new Set(['4.10.3']))
|
||||
expect(
|
||||
checksums.KNOWN_VALID_CHECKSUMS.get(
|
||||
checksums.KNOWN_CHECKSUMS.checksums.get(
|
||||
'28b330c20a9a73881dfe9702df78d4d78bf72368e8906c70080ab6932462fe9e'
|
||||
)
|
||||
).toEqual(new Set(['6.0-rc-1', '6.0-rc-2', '6.0-rc-3', '6.0', '6.0.1']))
|
||||
})
|
||||
|
||||
test('fetches wrapper jars checksums', async () => {
|
||||
const validChecksums = await checksums.fetchValidChecksums(false)
|
||||
const validChecksums = await checksums.fetchUnknownChecksums(false, new checksums.WrapperChecksums)
|
||||
expect(validChecksums.size).toBeGreaterThan(10)
|
||||
// Verify that checksum of arbitrary version is contained
|
||||
expect(
|
||||
@@ -47,7 +47,7 @@ describe('retry', () => {
|
||||
code: 'ECONNREFUSED'
|
||||
})
|
||||
|
||||
const validChecksums = await checksums.fetchValidChecksums(false)
|
||||
const validChecksums = await checksums.fetchUnknownChecksums(false, new checksums.WrapperChecksums)
|
||||
expect(validChecksums.size).toBeGreaterThan(10)
|
||||
nock.isDone()
|
||||
})
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import * as path from 'path'
|
||||
import * as validate from '../../../src/wrapper-validation/validate'
|
||||
import {expect, test, jest} from '@jest/globals'
|
||||
import { WrapperChecksums } from '../../../src/wrapper-validation/checksums'
|
||||
|
||||
jest.setTimeout(30000)
|
||||
|
||||
@@ -24,7 +25,7 @@ test('succeeds if all found wrapper jars are valid', async () => {
|
||||
})
|
||||
|
||||
test('succeeds if all found wrapper jars are valid (and checksums are fetched from Gradle API)', async () => {
|
||||
const knownValidChecksums = new Map<string, Set<string>>()
|
||||
const knownValidChecksums = new WrapperChecksums()
|
||||
const result = await validate.findInvalidWrapperJars(
|
||||
baseDir,
|
||||
1,
|
||||
@@ -32,6 +33,7 @@ test('succeeds if all found wrapper jars are valid (and checksums are fetched fr
|
||||
['e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'],
|
||||
knownValidChecksums
|
||||
)
|
||||
console.log(`fetchedChecksums = ${result.fetchedChecksums}`)
|
||||
|
||||
expect(result.isValid()).toBe(true)
|
||||
// Should have fetched checksums because no known checksums were provided
|
||||
|
||||
Reference in New Issue
Block a user