mirror of
https://github.com/gradle/gradle-build-action.git
synced 2025-10-20 15:18:56 +08:00
Compare commits
99 Commits
v2.2.0-rc.
...
v2.2.2
Author | SHA1 | Date | |
---|---|---|---|
|
cd3cedc781 | ||
|
e54bfe60d4 | ||
|
d70ff19b06 | ||
|
45417006b1 | ||
|
925e60d017 | ||
|
47a028a7f5 | ||
|
7df347a3ca | ||
|
d742f2f6db | ||
|
e4c0d1d512 | ||
|
64a1064eca | ||
|
bc57473979 | ||
|
11ea84dec5 | ||
|
5a614fb332 | ||
|
d3a8ea948b | ||
|
fba23f26a1 | ||
|
683f9d4247 | ||
|
f87d5a33c9 | ||
|
42014fb4fa | ||
|
2da06d5689 | ||
|
792a93a5e3 | ||
|
86da5e6c4e | ||
|
6daf446e27 | ||
|
8a8f74b15c | ||
|
15453523bd | ||
|
b1b0eab63d | ||
|
f580ce7b99 | ||
|
2a7ffc9c95 | ||
|
ff6b0e0388 | ||
|
71e1e1b52b | ||
|
02b67b8bfe | ||
|
5ce69a34b6 | ||
|
e7f3e4d839 | ||
|
7645d3e274 | ||
|
be13141ec7 | ||
|
db33711f5a | ||
|
84dee23dd9 | ||
|
a603ab7405 | ||
|
bc41b8f654 | ||
|
32923891b5 | ||
|
fecf3693b5 | ||
|
6965e8ed4c | ||
|
884bca012f | ||
|
7f46dbd76f | ||
|
ea4554d4d2 | ||
|
d8b58e3519 | ||
|
4cb86e9712 | ||
|
eaed5520c4 | ||
|
ec939a8c10 | ||
|
6594e9d359 | ||
|
52e6e7d89f | ||
|
2bf1894aa3 | ||
|
795895fc71 | ||
|
98376690f1 | ||
|
67421db6bd | ||
|
ce3874fec9 | ||
|
67f42d16a1 | ||
|
56036f8577 | ||
|
1903bd4674 | ||
|
df4c1902a6 | ||
|
132237ba05 | ||
|
2335d51128 | ||
|
2f7e5c0d4b | ||
|
2248b3f239 | ||
|
7d8a9a65e5 | ||
|
bc39e4abaa | ||
|
26cd1c9794 | ||
|
5ccc7fa6a6 | ||
|
badf18c0a6 | ||
|
1ee84620f9 | ||
|
f1c1269910 | ||
|
c09f41c4bd | ||
|
829c7a236d | ||
|
c1ed8b1925 | ||
|
3d091fa7a8 | ||
|
a8d44c9749 | ||
|
6125b490f2 | ||
|
f75a77b009 | ||
|
3510b43886 | ||
|
61ba2ad220 | ||
|
4b449e5b54 | ||
|
b8f0ecc408 | ||
|
c2bd86551b | ||
|
92087b6bb6 | ||
|
9355458b6c | ||
|
4ec1021d58 | ||
|
f3e4903860 | ||
|
c5d80a628f | ||
|
ee54c1fd71 | ||
|
f33d84950e | ||
|
d20c5c0356 | ||
|
c207cf448f | ||
|
a534572737 | ||
|
acf6027bd2 | ||
|
f6ab09b0bf | ||
|
55ddd21594 | ||
|
33ed11e54c | ||
|
93c31ca3b5 | ||
|
7a15005377 | ||
|
e88ed3e650 |
2
.github/dependabot.yml
vendored
2
.github/dependabot.yml
vendored
@@ -9,7 +9,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "weekly"
|
||||
open-pull-requests-limit: 10
|
||||
ignore:
|
||||
- dependency-name: "@types/node"
|
||||
|
Binary file not shown.
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionSha256Sum=29e49b10984e585d8118b7d0bc452f944e386458df27371b49b4ac1dec4b7fda
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
|
||||
distributionSha256Sum=cb87f222c5585bd46838ad4db78463a5c5f3d336e5e2b98dc7c0c586527351c2
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
@@ -205,6 +205,12 @@ set -- \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
|
@@ -14,7 +14,7 @@
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@@ -25,7 +25,7 @@
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
@@ -75,13 +75,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
Binary file not shown.
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionSha256Sum=29e49b10984e585d8118b7d0bc452f944e386458df27371b49b4ac1dec4b7fda
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
|
||||
distributionSha256Sum=cb87f222c5585bd46838ad4db78463a5c5f3d336e5e2b98dc7c0c586527351c2
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
6
.github/workflow-samples/groovy-dsl/gradlew
vendored
6
.github/workflow-samples/groovy-dsl/gradlew
vendored
@@ -205,6 +205,12 @@ set -- \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
|
14
.github/workflow-samples/groovy-dsl/gradlew.bat
vendored
14
.github/workflow-samples/groovy-dsl/gradlew.bat
vendored
@@ -14,7 +14,7 @@
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@@ -25,7 +25,7 @@
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
@@ -75,13 +75,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
@@ -1,5 +1,6 @@
|
||||
plugins {
|
||||
id "com.gradle.enterprise" version "3.10.1"
|
||||
id "com.gradle.enterprise" version "3.10.3"
|
||||
id "com.gradle.common-custom-user-data-gradle-plugin" version "1.7.2"
|
||||
}
|
||||
|
||||
gradleEnterprise {
|
||||
|
Binary file not shown.
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionSha256Sum=29e49b10984e585d8118b7d0bc452f944e386458df27371b49b4ac1dec4b7fda
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
|
||||
distributionSha256Sum=cb87f222c5585bd46838ad4db78463a5c5f3d336e5e2b98dc7c0c586527351c2
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
@@ -205,6 +205,12 @@ set -- \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
|
@@ -14,7 +14,7 @@
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@@ -25,7 +25,7 @@
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
@@ -75,13 +75,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
Binary file not shown.
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionSha256Sum=29e49b10984e585d8118b7d0bc452f944e386458df27371b49b4ac1dec4b7fda
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
|
||||
distributionSha256Sum=cb87f222c5585bd46838ad4db78463a5c5f3d336e5e2b98dc7c0c586527351c2
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
6
.github/workflow-samples/kotlin-dsl/gradlew
vendored
6
.github/workflow-samples/kotlin-dsl/gradlew
vendored
@@ -205,6 +205,12 @@ set -- \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
|
14
.github/workflow-samples/kotlin-dsl/gradlew.bat
vendored
14
.github/workflow-samples/kotlin-dsl/gradlew.bat
vendored
@@ -14,7 +14,7 @@
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@@ -25,7 +25,7 @@
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
@@ -75,13 +75,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
@@ -1,5 +1,6 @@
|
||||
plugins {
|
||||
id("com.gradle.enterprise") version "3.10.1"
|
||||
id("com.gradle.enterprise") version "3.10.3"
|
||||
id("com.gradle.common-custom-user-data-gradle-plugin") version "1.7.2"
|
||||
}
|
||||
|
||||
gradleEnterprise {
|
||||
|
@@ -1,5 +1,5 @@
|
||||
plugins {
|
||||
id "com.gradle.build-scan" version "3.10.1"
|
||||
id "com.gradle.build-scan" version "3.10.3"
|
||||
}
|
||||
|
||||
gradleEnterprise {
|
||||
|
@@ -1,5 +1,5 @@
|
||||
plugins {
|
||||
id "com.gradle.enterprise" version "3.10.1"
|
||||
id "com.gradle.enterprise" version "3.10.3"
|
||||
}
|
||||
|
||||
gradleEnterprise {
|
||||
|
7
.github/workflows/ci-init-script-check.yml
vendored
7
.github/workflows/ci-init-script-check.yml
vendored
@@ -2,6 +2,11 @@ name: CI-init-script-check
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- '.github/workflows/**'
|
||||
- 'src/resources/init-scripts/**'
|
||||
- 'test/init-script-check/**'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
test-init-scripts:
|
||||
@@ -17,5 +22,5 @@ jobs:
|
||||
- name: Setup Gradle
|
||||
uses: gradle/gradle-build-action@v2 # Use a released version to avoid breakages
|
||||
- name: Run integration tests
|
||||
working-directory: test/test-init-scripts
|
||||
working-directory: test/init-scripts
|
||||
run: ./gradlew check
|
||||
|
4
.github/workflows/ci-verify-outputs.yml
vendored
4
.github/workflows/ci-verify-outputs.yml
vendored
@@ -8,9 +8,7 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- '.github/workflows/**'
|
||||
- 'dist/**'
|
||||
- dependabot/**
|
||||
|
||||
jobs:
|
||||
check:
|
||||
|
5
.github/workflows/demo-job-summary.yml
vendored
5
.github/workflows/demo-job-summary.yml
vendored
@@ -25,7 +25,10 @@ jobs:
|
||||
run: ./gradlew assemble
|
||||
- name: Build kotlin-dsl project without build scan
|
||||
working-directory: .github/workflow-samples/kotlin-dsl
|
||||
run: ./gradlew check --no-scan
|
||||
run: ./gradlew assemble check --no-scan
|
||||
- name: Build kotlin-dsl project with build scan publish failure
|
||||
working-directory: .github/workflow-samples/kotlin-dsl
|
||||
run: ./gradlew check -Dgradle.enterprise.url=https://not.valid.server
|
||||
- name: Build groovy-dsl project
|
||||
working-directory: .github/workflow-samples/groovy-dsl
|
||||
run: ./gradlew assemble
|
||||
|
2
.github/workflows/integ-test-execution.yml
vendored
2
.github/workflows/integ-test-execution.yml
vendored
@@ -51,7 +51,7 @@ jobs:
|
||||
with:
|
||||
gradle-executable: .github/workflow-samples/groovy-dsl/gradlew${{ matrix.script-suffix }}
|
||||
build-root-directory: .github/workflow-samples/no-wrapper
|
||||
arguments: help -DgradleVersionCheck=7.4.2
|
||||
arguments: help -DgradleVersionCheck=7.5
|
||||
|
||||
gradle-versions:
|
||||
strategy:
|
||||
|
50
README.md
50
README.md
@@ -85,6 +85,7 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 11
|
||||
- uses: gradle/gradle-build-action@v2
|
||||
with:
|
||||
@@ -111,6 +112,7 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 11
|
||||
|
||||
- name: Setup and execute Gradle 'test' task
|
||||
@@ -203,7 +205,6 @@ Caching is enabled by default. You can disable caching for the action as follows
|
||||
```yaml
|
||||
cache-disabled: true
|
||||
```
|
||||
|
||||
### Cache keys
|
||||
|
||||
Distributions downloaded to satisfy a `gradle-version` parameter are stored outside of Gradle User Home and cached separately. The cache key is unique to the downloaded distribution and will not change over time.
|
||||
@@ -218,17 +219,27 @@ For example, this means that all jobs executing a particular version of the Grad
|
||||
|
||||
### Using the caches read-only
|
||||
|
||||
In some circumstances, it makes sense for a Gradle invocation to read any existing cache entries but not to write changes back.
|
||||
For example, you may want to write cache entries for builds on your `main` branch, but not for any PR build invocations.
|
||||
By default, the `gradle-build-action` will only write to the cache from Jobs on the default (`main`/`master`) branch.
|
||||
Jobs on other branches will read entries from the cache but will not write updated entries.
|
||||
See [Optimizing cache effectiveness](#optimizing-cache-effectiveness) for a more detailed explanation.
|
||||
|
||||
You can enable read-only caching for any of the caches as follows:
|
||||
In some circumstances it makes sense to change this default, and to configure a workflow Job to read existing cache entries but not to write changes back.
|
||||
|
||||
You can configure read-only caching for the `gradle-build-action` as follows:
|
||||
|
||||
```yaml
|
||||
# Only write to the cache for builds on the 'main' branch.
|
||||
# Only write to the cache for builds on the 'main' and 'release' branches. (Default is 'main' only.)
|
||||
# Builds on other branches will only read existing entries from the cache.
|
||||
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
|
||||
cache-read-only: ${{ github.ref != 'refs/heads/main' && github.ref != 'refs/heads/release' }}
|
||||
```
|
||||
|
||||
### Stopping the Gradle daemon
|
||||
|
||||
By default, the action will stop all running Gradle daemons in the post-action step, prior to saving the Gradle User Home state.
|
||||
This allows for any Gradle User Home cleanup to occur, and avoid file-locking issues on Windows.
|
||||
|
||||
If caching is unavailable or the cache is in read-only mode, the daemon will not be stopped and will continue running after the job is completed.
|
||||
|
||||
### Gradle User Home cache tuning
|
||||
|
||||
As well as any wrapper distributions, the action will attempt to save and restore the `caches` and `notifications` directories from Gradle User Home.
|
||||
@@ -253,7 +264,7 @@ File pattern support is documented at https://docs.github.com/en/actions/learn-g
|
||||
|
||||
Gradle User Home state will be restored from the cache during the first `gradle-build-action` step for any workflow job.
|
||||
This state will be saved back to the cache at the end of the job, after all Gradle executions have completed.
|
||||
A report of all cache entries restored and saved is printed to the action log when saving the cache entries.
|
||||
A report of all cache entries restored and saved is printed to the Job Summary when saving the cache entries.
|
||||
This report can provide valuable insignt into how much cache space is being used.
|
||||
|
||||
It is possible to enable additional debug logging for cache operations. You do via the `GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED` environment variable:
|
||||
@@ -267,18 +278,25 @@ Note that this setting will also prevent certain cache operations from running i
|
||||
|
||||
### Optimizing cache effectiveness
|
||||
|
||||
Cache storage space for GitHub actions is limited, and writing new cache entries can trigger the deletion of exising entries.
|
||||
Cache storage space for GitHub actions is limited, and writing new cache entries can trigger the deletion of existing entries.
|
||||
Eviction of shared cache entries can reduce cache effectiveness, slowing down your `gradle-build-action` steps.
|
||||
|
||||
There are a number of actions you can take if your cache use is less effective due to entry eviction.
|
||||
|
||||
#### Only write to the cache from the default branch
|
||||
#### Select branches that should write to the cache
|
||||
|
||||
GitHub cache entries are not shared between builds on different branches. This means that identical cache entries will be stored separately for different branches.
|
||||
The exception to the is cache entries for the default (`master`/`main`) branch can be read by actions invoked for other branches.
|
||||
GitHub cache entries are not shared between builds on different branches.
|
||||
This means that each PR branch will have it's own Gradle User Home cache, and will not benefit from cache entries written by other PR branches.
|
||||
An exception to this is that cache entries written in parent and upstream branches are visible to child branches, and cache entries for the default (`master`/`main`) branch can be read by actions invoked for any other branch.
|
||||
|
||||
An easy way to reduce cache usage when you run builds on many different branches is to only permit your default branch to write to the cache,
|
||||
with all other branch builds using `cache-read-only`. See [Using the caches read-only](#using-the-caches-read-only) for more details.
|
||||
By default, the `gradle-build-action` will only _write_ to the cache for builds run on the default (`master`/`main`) branch.
|
||||
Jobs run on other branches will only read from the cache. In most cases, this is the desired behaviour,
|
||||
because Jobs run against other branches will benefit from the cache Gradle User Home from `main`,
|
||||
without writing private cache entries that could lead to evicting shared entries.
|
||||
|
||||
If you have other long-lived development branches that would benefit from writing to the cache,
|
||||
you can configure these by overriding the `cache-read-only` action parameter.
|
||||
See [Using the caches read-only](#using-the-caches-read-only) for more details.
|
||||
|
||||
Similarly, you could use `cache-read-only` for certain jobs in the workflow, and instead have these jobs reuse the cache content from upstream jobs.
|
||||
|
||||
@@ -350,3 +368,9 @@ jobs:
|
||||
body: '❌ ${{ github.workflow }} failed: ${{ steps.gradle.outputs.build-scan-url }}'
|
||||
})
|
||||
```
|
||||
|
||||
## Support for GitHub Enterprise Server (GHES)
|
||||
|
||||
You can use the `gradle-build-action` on GitHub Enterprise Server, with some important limitations:
|
||||
- Support for GitHub Actions cache was introduced in GHES v3.5. Workflows using `gradle-build-action` on an earlier version of GHES will not benefit from save/restore of Gradle User Home.
|
||||
- Support for GitHub Actions Job Summary is not yet available in any version of GHES. Instead of producing a Job Summary, the build-results summary and caching report will be written to the workflow log, as part of the post-action step.
|
||||
|
@@ -1,5 +0,0 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
@@ -1,6 +0,0 @@
|
||||
#
|
||||
# https://help.github.com/articles/dealing-with-line-endings/
|
||||
#
|
||||
# These are explicitly windows files and should use crlf
|
||||
*.bat text eol=crlf
|
||||
|
5
__tests__/data/crypto-utils-test/.gitignore
vendored
5
__tests__/data/crypto-utils-test/.gitignore
vendored
@@ -1,5 +0,0 @@
|
||||
# Ignore Gradle project-specific cache directory
|
||||
.gradle
|
||||
|
||||
# Ignore Gradle build output directory
|
||||
build
|
@@ -1,11 +0,0 @@
|
||||
plugins {
|
||||
id 'java'
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation('junit:junit:4.12')
|
||||
}
|
Binary file not shown.
@@ -1,5 +0,0 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
185
__tests__/data/crypto-utils-test/gradlew
vendored
185
__tests__/data/crypto-utils-test/gradlew
vendored
@@ -1,185 +0,0 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#
|
||||
# Copyright 2015 the original author or authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
case $i in
|
||||
0) set -- ;;
|
||||
1) set -- "$args0" ;;
|
||||
2) set -- "$args0" "$args1" ;;
|
||||
3) set -- "$args0" "$args1" "$args2" ;;
|
||||
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=`save "$@"`
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
exec "$JAVACMD" "$@"
|
104
__tests__/data/crypto-utils-test/gradlew.bat
vendored
104
__tests__/data/crypto-utils-test/gradlew.bat
vendored
@@ -1,104 +0,0 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
@@ -1,10 +0,0 @@
|
||||
/*
|
||||
* This file was generated by the Gradle 'init' task.
|
||||
*
|
||||
* The settings file is used to specify which projects to include in your build.
|
||||
*
|
||||
* Detailed information about configuring a multi-project build in Gradle can be found
|
||||
* in the user manual at https://docs.gradle.org/6.5/userguide/multi_project_builds.html
|
||||
*/
|
||||
|
||||
rootProject.name = 'basic'
|
@@ -1,10 +0,0 @@
|
||||
package basic;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class BasicTest {
|
||||
@Test
|
||||
public void test() {
|
||||
assert true;
|
||||
}
|
||||
}
|
555
dist/main/index.js
vendored
555
dist/main/index.js
vendored
@@ -90,18 +90,19 @@ function restoreCache(paths, primaryKey, restoreKeys, options) {
|
||||
checkKey(key);
|
||||
}
|
||||
const compressionMethod = yield utils.getCompressionMethod();
|
||||
// path are needed to compute version
|
||||
const cacheEntry = yield cacheHttpClient.getCacheEntry(keys, paths, {
|
||||
compressionMethod
|
||||
});
|
||||
if (!(cacheEntry === null || cacheEntry === void 0 ? void 0 : cacheEntry.archiveLocation)) {
|
||||
// Cache not found
|
||||
return undefined;
|
||||
}
|
||||
const archivePath = path.join(yield utils.createTempDirectory(), utils.getCacheFileName(compressionMethod));
|
||||
core.debug(`Archive Path: ${archivePath}`);
|
||||
const restoredEntry = new CacheEntry(cacheEntry.cacheKey);
|
||||
let archivePath = '';
|
||||
try {
|
||||
// path are needed to compute version
|
||||
const cacheEntry = yield cacheHttpClient.getCacheEntry(keys, paths, {
|
||||
compressionMethod
|
||||
});
|
||||
if (!(cacheEntry === null || cacheEntry === void 0 ? void 0 : cacheEntry.archiveLocation)) {
|
||||
// Cache not found
|
||||
return undefined;
|
||||
}
|
||||
archivePath = path.join(yield utils.createTempDirectory(), utils.getCacheFileName(compressionMethod));
|
||||
core.debug(`Archive Path: ${archivePath}`);
|
||||
const restoredEntry = new CacheEntry(cacheEntry.cacheKey);
|
||||
// Download the cache from the cache entry
|
||||
yield cacheHttpClient.downloadCache(cacheEntry.archiveLocation, archivePath, options);
|
||||
if (core.isDebug()) {
|
||||
@@ -112,6 +113,17 @@ function restoreCache(paths, primaryKey, restoreKeys, options) {
|
||||
core.info(`Cache Size: ~${Math.round(archiveFileSize / (1024 * 1024))} MB (${archiveFileSize} B)`);
|
||||
yield tar_1.extractTar(archivePath, compressionMethod);
|
||||
core.info('Cache restored successfully');
|
||||
return restoredEntry;
|
||||
}
|
||||
catch (error) {
|
||||
const typedError = error;
|
||||
if (typedError.name === ValidationError.name) {
|
||||
throw error;
|
||||
}
|
||||
else {
|
||||
// Supress all non-validation cache related errors because caching should be optional
|
||||
core.warning(`Failed to restore: ${error.message}`);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
// Try to delete the archive to save space
|
||||
@@ -122,7 +134,7 @@ function restoreCache(paths, primaryKey, restoreKeys, options) {
|
||||
core.debug(`Failed to delete archive: ${error}`);
|
||||
}
|
||||
}
|
||||
return restoredEntry;
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
exports.restoreCache = restoreCache;
|
||||
@@ -140,7 +152,7 @@ function saveCache(paths, key, options) {
|
||||
checkPaths(paths);
|
||||
checkKey(key);
|
||||
const compressionMethod = yield utils.getCompressionMethod();
|
||||
let cacheId = null;
|
||||
let cacheId = -1;
|
||||
const cachePaths = yield utils.resolvePaths(paths);
|
||||
core.debug('Cache Paths:');
|
||||
core.debug(`${JSON.stringify(cachePaths)}`);
|
||||
@@ -181,6 +193,18 @@ function saveCache(paths, key, options) {
|
||||
core.debug(`Saving Cache (ID: ${cacheId})`);
|
||||
yield cacheHttpClient.saveCache(cacheId, archivePath, options);
|
||||
}
|
||||
catch (error) {
|
||||
const typedError = error;
|
||||
if (typedError.name === ValidationError.name) {
|
||||
throw error;
|
||||
}
|
||||
else if (typedError.name === ReserveCacheError.name) {
|
||||
core.info(`Failed to save: ${typedError.message}`);
|
||||
}
|
||||
else {
|
||||
core.warning(`Failed to save: ${typedError.message}`);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
// Try to delete the archive to save space
|
||||
try {
|
||||
@@ -1134,6 +1158,8 @@ function createTar(archiveFolder, sourceDirectories, compressionMethod) {
|
||||
...getCompressionProgram(),
|
||||
'-cf',
|
||||
cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
||||
'--exclude',
|
||||
cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
||||
'-P',
|
||||
'-C',
|
||||
workingDirectory.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
||||
@@ -2730,6 +2756,13 @@ Object.defineProperty(exports, "summary", ({ enumerable: true, get: function ()
|
||||
*/
|
||||
var summary_2 = __nccwpck_require__(1327);
|
||||
Object.defineProperty(exports, "markdownSummary", ({ enumerable: true, get: function () { return summary_2.markdownSummary; } }));
|
||||
/**
|
||||
* Path exports
|
||||
*/
|
||||
var path_utils_1 = __nccwpck_require__(2981);
|
||||
Object.defineProperty(exports, "toPosixPath", ({ enumerable: true, get: function () { return path_utils_1.toPosixPath; } }));
|
||||
Object.defineProperty(exports, "toWin32Path", ({ enumerable: true, get: function () { return path_utils_1.toWin32Path; } }));
|
||||
Object.defineProperty(exports, "toPlatformPath", ({ enumerable: true, get: function () { return path_utils_1.toPlatformPath; } }));
|
||||
//# sourceMappingURL=core.js.map
|
||||
|
||||
/***/ }),
|
||||
@@ -2867,6 +2900,71 @@ exports.OidcClient = OidcClient;
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 2981:
|
||||
/***/ (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;
|
||||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||
}) : (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.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.toPlatformPath = exports.toWin32Path = exports.toPosixPath = void 0;
|
||||
const path = __importStar(__nccwpck_require__(1017));
|
||||
/**
|
||||
* toPosixPath converts the given path to the posix form. On Windows, \\ will be
|
||||
* replaced with /.
|
||||
*
|
||||
* @param pth. Path to transform.
|
||||
* @return string Posix path.
|
||||
*/
|
||||
function toPosixPath(pth) {
|
||||
return pth.replace(/[\\]/g, '/');
|
||||
}
|
||||
exports.toPosixPath = toPosixPath;
|
||||
/**
|
||||
* toWin32Path converts the given path to the win32 form. On Linux, / will be
|
||||
* replaced with \\.
|
||||
*
|
||||
* @param pth. Path to transform.
|
||||
* @return string Win32 path.
|
||||
*/
|
||||
function toWin32Path(pth) {
|
||||
return pth.replace(/[/]/g, '\\');
|
||||
}
|
||||
exports.toWin32Path = toWin32Path;
|
||||
/**
|
||||
* toPlatformPath converts the given path to a platform-specific path. It does
|
||||
* this by replacing instances of / and \ with the platform-specific path
|
||||
* separator.
|
||||
*
|
||||
* @param pth The path to platformize.
|
||||
* @return string The platform-specific path.
|
||||
*/
|
||||
function toPlatformPath(pth) {
|
||||
return pth.replace(/[/\\]/g, path.sep);
|
||||
}
|
||||
exports.toPlatformPath = toPlatformPath;
|
||||
//# sourceMappingURL=path-utils.js.map
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 1327:
|
||||
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
||||
|
||||
@@ -64800,6 +64898,54 @@ function wrappy (fn, cb) {
|
||||
}).call(this);
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 3017:
|
||||
/***/ (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.loadBuildResults = void 0;
|
||||
const fs = __importStar(__nccwpck_require__(7147));
|
||||
const path = __importStar(__nccwpck_require__(1017));
|
||||
function loadBuildResults() {
|
||||
const buildResultsDir = path.resolve(process.env['RUNNER_TEMP'], '.build-results');
|
||||
if (!fs.existsSync(buildResultsDir)) {
|
||||
return [];
|
||||
}
|
||||
return fs.readdirSync(buildResultsDir).map(file => {
|
||||
const filePath = path.join(buildResultsDir, file);
|
||||
const content = fs.readFileSync(filePath, 'utf8');
|
||||
return JSON.parse(content);
|
||||
});
|
||||
}
|
||||
exports.loadBuildResults = loadBuildResults;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 7591:
|
||||
@@ -64909,10 +65055,17 @@ class GradleStateCache {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const cacheKey = (0, cache_utils_1.generateCacheKey)(this.cacheName).key;
|
||||
const restoredCacheKey = core.getState(RESTORED_CACHE_KEY_KEY);
|
||||
const entryListener = listener.entry(this.cacheDescription);
|
||||
const gradleHomeEntryListener = listener.entry(this.cacheDescription);
|
||||
if (restoredCacheKey && cacheKey === restoredCacheKey) {
|
||||
core.info(`Cache hit occurred on the cache key ${cacheKey}, not saving cache.`);
|
||||
entryListener.markUnchanged('cache key not changed');
|
||||
for (const entryListener of listener.cacheEntries) {
|
||||
if (entryListener === gradleHomeEntryListener) {
|
||||
entryListener.markUnsaved('cache key not changed');
|
||||
}
|
||||
else {
|
||||
entryListener.markUnsaved(`referencing '${this.cacheDescription}' cache entry not saved`);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
try {
|
||||
@@ -64924,7 +65077,7 @@ class GradleStateCache {
|
||||
}
|
||||
core.info(`Caching ${this.cacheDescription} with cache key: ${cacheKey}`);
|
||||
const cachePath = this.getCachePath();
|
||||
yield (0, cache_utils_1.saveCache)(cachePath, cacheKey, entryListener);
|
||||
yield (0, cache_utils_1.saveCache)(cachePath, cacheKey, gradleHomeEntryListener);
|
||||
return;
|
||||
});
|
||||
}
|
||||
@@ -64964,13 +65117,13 @@ class GradleStateCache {
|
||||
initializeGradleUserHome(gradleUserHome, initScriptsDir) {
|
||||
const initScriptFilenames = ['build-result-capture.init.gradle', 'build-result-capture-service.plugin.groovy'];
|
||||
for (const initScriptFilename of initScriptFilenames) {
|
||||
const initScriptContent = this.readResourceAsString(initScriptFilename);
|
||||
const initScriptContent = this.readInitScriptAsString(initScriptFilename);
|
||||
const initScriptPath = path_1.default.resolve(initScriptsDir, initScriptFilename);
|
||||
fs_1.default.writeFileSync(initScriptPath, initScriptContent);
|
||||
}
|
||||
}
|
||||
readResourceAsString(resource) {
|
||||
const absolutePath = path_1.default.resolve(__dirname, '..', '..', 'src', 'resources', resource);
|
||||
readInitScriptAsString(resource) {
|
||||
const absolutePath = path_1.default.resolve(__dirname, '..', '..', 'src', 'resources', 'init-scripts', resource);
|
||||
return fs_1.default.readFileSync(absolutePath, 'utf8');
|
||||
}
|
||||
debugReportGradleUserHomeSize(label) {
|
||||
@@ -65052,7 +65205,7 @@ const core = __importStar(__nccwpck_require__(2186));
|
||||
const glob = __importStar(__nccwpck_require__(8090));
|
||||
const cache_base_1 = __nccwpck_require__(7591);
|
||||
const cache_utils_1 = __nccwpck_require__(1678);
|
||||
const job_summary_1 = __nccwpck_require__(7345);
|
||||
const build_results_1 = __nccwpck_require__(3017);
|
||||
const SKIP_RESTORE_VAR = 'GRADLE_BUILD_ACTION_SKIP_RESTORE';
|
||||
class ExtractedCacheEntry {
|
||||
constructor(artifactType, pattern, cacheKey) {
|
||||
@@ -65154,7 +65307,7 @@ class AbstractEntryExtractor {
|
||||
const previouslyRestoredKey = (_a = previouslyRestoredEntries.find(x => x.artifactType === artifactType && x.pattern === pattern)) === null || _a === void 0 ? void 0 : _a.cacheKey;
|
||||
if (previouslyRestoredKey === cacheKey) {
|
||||
(0, cache_utils_1.cacheDebug)(`No change to previously restored ${artifactType}. Not saving.`);
|
||||
entryListener.markUnchanged('contents unchanged');
|
||||
entryListener.markUnsaved('contents unchanged');
|
||||
}
|
||||
else {
|
||||
core.info(`Caching ${artifactType} with path '${pattern}' and cache key: ${cacheKey}`);
|
||||
@@ -65232,9 +65385,9 @@ class GradleHomeEntryExtractor extends AbstractEntryExtractor {
|
||||
implicitDescendants: false,
|
||||
followSymbolicLinks: false
|
||||
});
|
||||
for (const p of yield globber.glob()) {
|
||||
(0, cache_utils_1.cacheDebug)(`Deleting wrapper zip: ${p}`);
|
||||
(0, cache_utils_1.tryDelete)(p);
|
||||
for (const wrapperZip of yield globber.glob()) {
|
||||
(0, cache_utils_1.cacheDebug)(`Deleting wrapper zip: ${wrapperZip}`);
|
||||
yield (0, cache_utils_1.tryDelete)(wrapperZip);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -65285,7 +65438,7 @@ class ConfigurationCacheEntryExtractor extends AbstractEntryExtractor {
|
||||
});
|
||||
}
|
||||
getProjectRoots() {
|
||||
const buildResults = (0, job_summary_1.loadBuildResults)();
|
||||
const buildResults = (0, build_results_1.loadBuildResults)();
|
||||
const projectRootDirs = buildResults.map(x => x.rootProjectDir);
|
||||
return [...new Set(projectRootDirs)];
|
||||
}
|
||||
@@ -65324,24 +65477,27 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.logCachingReport = exports.CacheEntryListener = exports.CacheListener = void 0;
|
||||
exports.logCachingReport = exports.writeCachingReport = exports.CacheEntryListener = exports.CacheListener = void 0;
|
||||
const core = __importStar(__nccwpck_require__(2186));
|
||||
const cache = __importStar(__nccwpck_require__(7799));
|
||||
class CacheListener {
|
||||
constructor() {
|
||||
this.cacheEntries = [];
|
||||
this.isCacheReadOnly = false;
|
||||
this.isCacheWriteOnly = false;
|
||||
this.isCacheDisabled = false;
|
||||
this.cacheReadOnly = false;
|
||||
this.cacheWriteOnly = false;
|
||||
this.cacheDisabled = false;
|
||||
}
|
||||
get fullyRestored() {
|
||||
return this.cacheEntries.every(x => !x.wasRequestedButNotRestored());
|
||||
}
|
||||
get cacheStatus() {
|
||||
if (this.isCacheDisabled)
|
||||
if (!cache.isFeatureAvailable())
|
||||
return 'not available';
|
||||
if (this.cacheDisabled)
|
||||
return 'disabled';
|
||||
if (this.isCacheWriteOnly)
|
||||
if (this.cacheWriteOnly)
|
||||
return 'write-only';
|
||||
if (this.isCacheReadOnly)
|
||||
if (this.cacheReadOnly)
|
||||
return 'read-only';
|
||||
return 'enabled';
|
||||
}
|
||||
@@ -65399,13 +65555,13 @@ class CacheEntryListener {
|
||||
this.savedSize = 0;
|
||||
return this;
|
||||
}
|
||||
markUnchanged(message) {
|
||||
this.unchanged = message;
|
||||
markUnsaved(message) {
|
||||
this.unsaved = message;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
exports.CacheEntryListener = CacheEntryListener;
|
||||
function logCachingReport(listener) {
|
||||
function writeCachingReport(listener) {
|
||||
const entries = listener.cacheEntries;
|
||||
core.summary.addRaw(`\n<details><summary><h4>Caching for gradle-build-action was ${listener.cacheStatus} - expand for details</h4></summary>\n`);
|
||||
core.summary.addTable([
|
||||
@@ -65418,29 +65574,42 @@ function logCachingReport(listener) {
|
||||
['Entries Saved', `${getCount(entries, e => e.savedSize)}`, `${getSize(entries, e => e.savedSize)}`]
|
||||
]);
|
||||
core.summary.addHeading('Cache Entry Details', 5);
|
||||
const entryDetails = listener.cacheEntries
|
||||
.map(entry => {
|
||||
var _a, _b, _c;
|
||||
return `Entry: ${entry.entryName}
|
||||
Requested Key : ${(_a = entry.requestedKey) !== null && _a !== void 0 ? _a : ''}
|
||||
Restored Key : ${(_b = entry.restoredKey) !== null && _b !== void 0 ? _b : ''}
|
||||
Size: ${formatSize(entry.restoredSize)}
|
||||
${getRestoredMessage(entry, listener.isCacheWriteOnly)}
|
||||
Saved Key : ${(_c = entry.savedKey) !== null && _c !== void 0 ? _c : ''}
|
||||
Size: ${formatSize(entry.savedSize)}
|
||||
${getSavedMessage(entry, listener.isCacheReadOnly)}
|
||||
`;
|
||||
})
|
||||
.join('---\n');
|
||||
const entryDetails = renderEntryDetails(listener);
|
||||
core.summary.addRaw(`<pre>
|
||||
${entryDetails}
|
||||
</pre>
|
||||
</details>
|
||||
`);
|
||||
}
|
||||
exports.writeCachingReport = writeCachingReport;
|
||||
function logCachingReport(listener) {
|
||||
const entries = listener.cacheEntries;
|
||||
core.startGroup(`Caching for gradle-build-action was ${listener.cacheStatus} - expand for details`);
|
||||
core.info(`Entries Restored: ${getCount(entries, e => e.restoredSize)} (${getSize(entries, e => e.restoredSize)} Mb)`);
|
||||
core.info(`Entries Saved : ${getCount(entries, e => e.savedSize)} (${getSize(entries, e => e.savedSize)} Mb)`);
|
||||
core.info(`Cache Entry Details`);
|
||||
core.info(renderEntryDetails(listener));
|
||||
core.endGroup();
|
||||
}
|
||||
exports.logCachingReport = logCachingReport;
|
||||
function getRestoredMessage(entry, isCacheWriteOnly) {
|
||||
if (isCacheWriteOnly) {
|
||||
function renderEntryDetails(listener) {
|
||||
return listener.cacheEntries
|
||||
.map(entry => {
|
||||
var _a, _b, _c;
|
||||
return `Entry: ${entry.entryName}
|
||||
Requested Key : ${(_a = entry.requestedKey) !== null && _a !== void 0 ? _a : ''}
|
||||
Restored Key : ${(_b = entry.restoredKey) !== null && _b !== void 0 ? _b : ''}
|
||||
Size: ${formatSize(entry.restoredSize)}
|
||||
${getRestoredMessage(entry, listener.cacheWriteOnly)}
|
||||
Saved Key : ${(_c = entry.savedKey) !== null && _c !== void 0 ? _c : ''}
|
||||
Size: ${formatSize(entry.savedSize)}
|
||||
${getSavedMessage(entry, listener.cacheReadOnly)}
|
||||
`;
|
||||
})
|
||||
.join('---\n');
|
||||
}
|
||||
function getRestoredMessage(entry, cacheWriteOnly) {
|
||||
if (cacheWriteOnly) {
|
||||
return '(Entry not restored: cache is write-only)';
|
||||
}
|
||||
if (entry.restoredKey === undefined) {
|
||||
@@ -65451,12 +65620,12 @@ function getRestoredMessage(entry, isCacheWriteOnly) {
|
||||
}
|
||||
return '(Entry restored: partial match found)';
|
||||
}
|
||||
function getSavedMessage(entry, isCacheReadOnly) {
|
||||
if (entry.unchanged) {
|
||||
return `(Entry not saved: ${entry.unchanged})`;
|
||||
function getSavedMessage(entry, cacheReadOnly) {
|
||||
if (entry.unsaved) {
|
||||
return `(Entry not saved: ${entry.unsaved})`;
|
||||
}
|
||||
if (entry.savedKey === undefined) {
|
||||
if (isCacheReadOnly) {
|
||||
if (cacheReadOnly) {
|
||||
return '(Entry not saved: cache is read-only)';
|
||||
}
|
||||
return '(Entry not saved: reason unknown)';
|
||||
@@ -65474,12 +65643,9 @@ function getSize(cacheEntries, predicate) {
|
||||
return Math.round(bytes / (1024 * 1024));
|
||||
}
|
||||
function formatSize(bytes) {
|
||||
if (bytes === undefined) {
|
||||
if (bytes === undefined || bytes === 0) {
|
||||
return '';
|
||||
}
|
||||
if (bytes === 0) {
|
||||
return '0 (Entry already exists)';
|
||||
}
|
||||
return `${Math.round(bytes / (1024 * 1024))} MB (${bytes} B)`;
|
||||
}
|
||||
|
||||
@@ -65545,6 +65711,9 @@ const CACHE_KEY_JOB_VAR = 'GRADLE_BUILD_ACTION_CACHE_KEY_JOB';
|
||||
const CACHE_KEY_JOB_INSTANCE_VAR = 'GRADLE_BUILD_ACTION_CACHE_KEY_JOB_INSTANCE';
|
||||
const CACHE_KEY_JOB_EXECUTION_VAR = 'GRADLE_BUILD_ACTION_CACHE_KEY_JOB_EXECUTION';
|
||||
function isCacheDisabled() {
|
||||
if (!cache.isFeatureAvailable()) {
|
||||
return true;
|
||||
}
|
||||
return core.getBooleanInput(CACHE_DISABLED_PARAMETER);
|
||||
}
|
||||
exports.isCacheDisabled = isCacheDisabled;
|
||||
@@ -65672,9 +65841,12 @@ exports.handleCacheFailure = handleCacheFailure;
|
||||
function tryDelete(file) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const maxAttempts = 5;
|
||||
const stat = fs.lstatSync(file);
|
||||
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
||||
if (!fs.existsSync(file)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const stat = fs.lstatSync(file);
|
||||
if (stat.isDirectory()) {
|
||||
fs.rmdirSync(file, { recursive: true });
|
||||
}
|
||||
@@ -65768,7 +65940,7 @@ function restore(gradleUserHome, cacheListener) {
|
||||
if ((0, cache_utils_1.isCacheDisabled)()) {
|
||||
core.info('Cache is disabled: will not restore state from previous builds.');
|
||||
gradleStateCache.init();
|
||||
cacheListener.isCacheDisabled = true;
|
||||
cacheListener.cacheDisabled = true;
|
||||
return;
|
||||
}
|
||||
if (gradleStateCache.cacheOutputExists()) {
|
||||
@@ -65780,7 +65952,7 @@ function restore(gradleUserHome, cacheListener) {
|
||||
core.saveState(CACHE_RESTORED_VAR, true);
|
||||
if ((0, cache_utils_1.isCacheWriteOnly)()) {
|
||||
core.info('Cache is write-only: will not restore from cache.');
|
||||
cacheListener.isCacheWriteOnly = true;
|
||||
cacheListener.cacheWriteOnly = true;
|
||||
return;
|
||||
}
|
||||
yield core.group('Restore Gradle state from cache', () => __awaiter(this, void 0, void 0, function* () {
|
||||
@@ -65789,33 +65961,101 @@ function restore(gradleUserHome, cacheListener) {
|
||||
});
|
||||
}
|
||||
exports.restore = restore;
|
||||
function save(gradleUserHome, cacheListener) {
|
||||
function save(gradleUserHome, cacheListener, daemonController) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
if (!shouldSaveCaches()) {
|
||||
if ((0, cache_utils_1.isCacheDisabled)()) {
|
||||
core.info('Cache is disabled: will not save state for later builds.');
|
||||
return;
|
||||
}
|
||||
if (!core.getState(CACHE_RESTORED_VAR)) {
|
||||
core.info('Cache will not be saved: not restored in main action step.');
|
||||
return;
|
||||
}
|
||||
if ((0, cache_utils_1.isCacheReadOnly)()) {
|
||||
core.info('Cache is read-only: will not save state for use in subsequent builds.');
|
||||
cacheListener.isCacheReadOnly = true;
|
||||
cacheListener.cacheReadOnly = true;
|
||||
return;
|
||||
}
|
||||
yield daemonController.stopAllDaemons();
|
||||
yield core.group('Caching Gradle state', () => __awaiter(this, void 0, void 0, function* () {
|
||||
return new cache_base_1.GradleStateCache(gradleUserHome).save(cacheListener);
|
||||
}));
|
||||
});
|
||||
}
|
||||
exports.save = save;
|
||||
function shouldSaveCaches() {
|
||||
if ((0, cache_utils_1.isCacheDisabled)()) {
|
||||
core.info('Cache is disabled: will not save state for later builds.');
|
||||
return false;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 5146:
|
||||
/***/ (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]; } };
|
||||
}
|
||||
if (!core.getState(CACHE_RESTORED_VAR)) {
|
||||
core.info('Cache will not be saved: not restored in main action step.');
|
||||
return false;
|
||||
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;
|
||||
};
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.DaemonController = void 0;
|
||||
const core = __importStar(__nccwpck_require__(2186));
|
||||
const exec = __importStar(__nccwpck_require__(1514));
|
||||
const fs = __importStar(__nccwpck_require__(7147));
|
||||
const path = __importStar(__nccwpck_require__(1017));
|
||||
class DaemonController {
|
||||
constructor(buildResults) {
|
||||
const allHomes = buildResults.map(buildResult => buildResult.gradleHomeDir);
|
||||
this.gradleHomes = Array.from(new Set(allHomes));
|
||||
}
|
||||
stopAllDaemons() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
core.info('Stopping all Gradle daemons before saving Gradle User Home state');
|
||||
const executions = [];
|
||||
const args = ['--stop'];
|
||||
for (const gradleHome of this.gradleHomes) {
|
||||
const executable = path.resolve(gradleHome, 'bin', 'gradle');
|
||||
if (!fs.existsSync(executable)) {
|
||||
core.warning(`Gradle executable not found at ${executable}. Could not stop Gradle daemons.`);
|
||||
continue;
|
||||
}
|
||||
core.info(`Stopping Gradle daemons for ${gradleHome}`);
|
||||
executions.push(exec.exec(executable, args, {
|
||||
ignoreReturnCode: true
|
||||
}));
|
||||
}
|
||||
yield Promise.all(executions);
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
exports.DaemonController = DaemonController;
|
||||
|
||||
|
||||
/***/ }),
|
||||
@@ -65979,65 +66219,97 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.loadBuildResults = exports.writeJobSummary = void 0;
|
||||
exports.logJobSummary = exports.writeJobSummary = void 0;
|
||||
const core = __importStar(__nccwpck_require__(2186));
|
||||
const fs_1 = __importDefault(__nccwpck_require__(7147));
|
||||
const path_1 = __importDefault(__nccwpck_require__(1017));
|
||||
const cache_reporting_1 = __nccwpck_require__(6674);
|
||||
function writeJobSummary(buildResults, cacheListener) {
|
||||
core.info('Writing job summary');
|
||||
if (buildResults.length === 0) {
|
||||
core.debug('No Gradle build results found. Summary table will not be generated.');
|
||||
}
|
||||
else {
|
||||
writeSummaryTable(buildResults);
|
||||
}
|
||||
(0, cache_reporting_1.logCachingReport)(cacheListener);
|
||||
core.summary.write();
|
||||
}
|
||||
exports.writeJobSummary = writeJobSummary;
|
||||
function loadBuildResults() {
|
||||
const buildResultsDir = path_1.default.resolve(process.env['RUNNER_TEMP'], '.build-results');
|
||||
if (!fs_1.default.existsSync(buildResultsDir)) {
|
||||
return [];
|
||||
}
|
||||
return fs_1.default.readdirSync(buildResultsDir).map(file => {
|
||||
const filePath = path_1.default.join(buildResultsDir, file);
|
||||
const content = fs_1.default.readFileSync(filePath, 'utf8');
|
||||
return JSON.parse(content);
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
core.info('Writing job summary');
|
||||
if (buildResults.length === 0) {
|
||||
core.debug('No Gradle build results found. Summary table will not be generated.');
|
||||
}
|
||||
else {
|
||||
writeSummaryTable(buildResults);
|
||||
}
|
||||
(0, cache_reporting_1.writeCachingReport)(cacheListener);
|
||||
yield core.summary.write();
|
||||
});
|
||||
}
|
||||
exports.loadBuildResults = loadBuildResults;
|
||||
exports.writeJobSummary = writeJobSummary;
|
||||
function logJobSummary(buildResults, cacheListener) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
if (buildResults.length === 0) {
|
||||
core.debug('No Gradle build results found. Summary table will not be logged.');
|
||||
}
|
||||
else {
|
||||
logSummaryTable(buildResults);
|
||||
}
|
||||
(0, cache_reporting_1.logCachingReport)(cacheListener);
|
||||
});
|
||||
}
|
||||
exports.logJobSummary = logJobSummary;
|
||||
function writeSummaryTable(results) {
|
||||
core.summary.addHeading('Gradle Builds', 3);
|
||||
core.summary.addTable([
|
||||
[
|
||||
{ data: 'Root Project', header: true },
|
||||
{ data: 'Tasks', header: true },
|
||||
{ data: 'Gradle Version', header: true },
|
||||
{ data: 'Outcome', header: true }
|
||||
],
|
||||
...results.map(result => [
|
||||
result.rootProjectName,
|
||||
result.requestedTasks,
|
||||
result.gradleVersion,
|
||||
renderOutcome(result)
|
||||
])
|
||||
]);
|
||||
core.summary.addRaw('\n');
|
||||
core.summary.addRaw(`
|
||||
<table>
|
||||
<tr>
|
||||
<th>Root Project</th>
|
||||
<th>Requested Tasks</th>
|
||||
<th>Gradle Version</th>
|
||||
<th>Build Outcome</th>
|
||||
<th>Build Scan™</th>
|
||||
</tr>${results.map(result => renderBuildResultRow(result)).join('')}
|
||||
</table>
|
||||
`);
|
||||
}
|
||||
function renderBuildResultRow(result) {
|
||||
return `
|
||||
<tr>
|
||||
<td>${result.rootProjectName}</td>
|
||||
<td>${result.requestedTasks}</td>
|
||||
<td align='center'>${result.gradleVersion}</td>
|
||||
<td align='center'>${renderOutcome(result)}</td>
|
||||
<td>${renderBuildScan(result)}</td>
|
||||
</tr>`;
|
||||
}
|
||||
function renderOutcome(result) {
|
||||
const labelPart = result.buildScanUri ? 'Build%20Scan%E2%84%A2' : 'Build';
|
||||
const outcomePart = result.buildFailed ? 'FAILED-red' : 'SUCCESS-brightgreen';
|
||||
const badgeUrl = `https://img.shields.io/badge/${labelPart}-${outcomePart}?logo=Gradle`;
|
||||
const badgeHtml = `<img src="${badgeUrl}" alt="Gradle Build">`;
|
||||
const targetUrl = result.buildScanUri ? result.buildScanUri : '#';
|
||||
return result.buildFailed ? ':x:' : ':white_check_mark:';
|
||||
}
|
||||
function renderBuildScan(result) {
|
||||
if (result.buildScanFailed) {
|
||||
return renderBuildScanBadge('PUBLISH_FAILED', 'orange', 'https://docs.gradle.com/enterprise/gradle-plugin/#troubleshooting');
|
||||
}
|
||||
if (result.buildScanUri) {
|
||||
return renderBuildScanBadge('PUBLISHED', '06A0CE', result.buildScanUri);
|
||||
}
|
||||
return renderBuildScanBadge('NOT_PUBLISHED', 'lightgrey', 'https://scans.gradle.com');
|
||||
}
|
||||
function renderBuildScanBadge(outcomeText, outcomeColor, targetUrl) {
|
||||
const badgeUrl = `https://img.shields.io/badge/Build%20Scan%E2%84%A2-${outcomeText}-${outcomeColor}?logo=Gradle`;
|
||||
const badgeHtml = `<img src="${badgeUrl}" alt="Build Scan ${outcomeText}" />`;
|
||||
return `<a href="${targetUrl}" rel="nofollow">${badgeHtml}</a>`;
|
||||
}
|
||||
function logSummaryTable(results) {
|
||||
core.info('============================');
|
||||
core.info('Gradle Builds');
|
||||
core.info('----------------------------');
|
||||
core.info('Root Project | Requested Tasks | Gradle Version | Build Outcome | Build Scan™');
|
||||
core.info('----------------------------');
|
||||
for (const result of results) {
|
||||
core.info(`${result.rootProjectName} | ${result.requestedTasks} | ${result.gradleVersion} | ${result.buildFailed ? 'FAILED' : 'SUCCESS'} | ${result.buildScanFailed ? 'Publish failed' : result.buildScanUri}`);
|
||||
}
|
||||
core.info('============================');
|
||||
}
|
||||
|
||||
|
||||
/***/ }),
|
||||
@@ -66383,17 +66655,22 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.complete = exports.setup = void 0;
|
||||
const core = __importStar(__nccwpck_require__(2186));
|
||||
const exec = __importStar(__nccwpck_require__(1514));
|
||||
const fs = __importStar(__nccwpck_require__(7147));
|
||||
const summary_1 = __nccwpck_require__(1327);
|
||||
const path = __importStar(__nccwpck_require__(1017));
|
||||
const os = __importStar(__nccwpck_require__(2037));
|
||||
const caches = __importStar(__nccwpck_require__(3800));
|
||||
const cache_reporting_1 = __nccwpck_require__(6674);
|
||||
const job_summary_1 = __nccwpck_require__(7345);
|
||||
const build_results_1 = __nccwpck_require__(3017);
|
||||
const cache_reporting_1 = __nccwpck_require__(6674);
|
||||
const daemon_controller_1 = __nccwpck_require__(5146);
|
||||
const GRADLE_SETUP_VAR = 'GRADLE_BUILD_ACTION_SETUP_COMPLETED';
|
||||
const GRADLE_USER_HOME = 'GRADLE_USER_HOME';
|
||||
const CACHE_LISTENER = 'CACHE_LISTENER';
|
||||
const JOB_SUMMARY_ENABLED_PARAMETER = 'generate-job-summary';
|
||||
function shouldGenerateJobSummary() {
|
||||
if (!process.env[summary_1.SUMMARY_ENV_VAR]) {
|
||||
return false;
|
||||
}
|
||||
return core.getBooleanInput(JOB_SUMMARY_ENABLED_PARAMETER);
|
||||
}
|
||||
function setup(buildRootDirectory) {
|
||||
@@ -66418,15 +66695,17 @@ function complete() {
|
||||
core.info('Gradle setup post-action only performed for first gradle-build-action step in workflow.');
|
||||
return;
|
||||
}
|
||||
const buildResults = (0, job_summary_1.loadBuildResults)();
|
||||
core.info('Stopping all Gradle daemons');
|
||||
yield stopAllDaemons(getUniqueGradleHomes(buildResults));
|
||||
core.info('In final post-action step, saving state and writing summary');
|
||||
const cacheListener = cache_reporting_1.CacheListener.rehydrate(core.getState(CACHE_LISTENER));
|
||||
const buildResults = (0, build_results_1.loadBuildResults)();
|
||||
const gradleUserHome = core.getState(GRADLE_USER_HOME);
|
||||
yield caches.save(gradleUserHome, cacheListener);
|
||||
const cacheListener = cache_reporting_1.CacheListener.rehydrate(core.getState(CACHE_LISTENER));
|
||||
const daemonController = new daemon_controller_1.DaemonController(buildResults);
|
||||
yield caches.save(gradleUserHome, cacheListener, daemonController);
|
||||
if (shouldGenerateJobSummary()) {
|
||||
(0, job_summary_1.writeJobSummary)(buildResults, cacheListener);
|
||||
yield (0, job_summary_1.writeJobSummary)(buildResults, cacheListener);
|
||||
}
|
||||
else {
|
||||
(0, job_summary_1.logJobSummary)(buildResults, cacheListener);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -66454,28 +66733,6 @@ function determineUserHome() {
|
||||
return userHome;
|
||||
});
|
||||
}
|
||||
function getUniqueGradleHomes(buildResults) {
|
||||
const gradleHomes = buildResults.map(buildResult => buildResult.gradleHomeDir);
|
||||
return Array.from(new Set(gradleHomes));
|
||||
}
|
||||
function stopAllDaemons(gradleHomes) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const executions = [];
|
||||
const args = ['--stop'];
|
||||
for (const gradleHome of gradleHomes) {
|
||||
const executable = path.resolve(gradleHome, 'bin', 'gradle');
|
||||
if (!fs.existsSync(executable)) {
|
||||
core.warning(`Gradle executable not found at ${executable}. Could not stop Gradle daemons.`);
|
||||
continue;
|
||||
}
|
||||
core.info(`Stopping Gradle daemons in ${gradleHome}`);
|
||||
executions.push(exec.exec(executable, args, {
|
||||
ignoreReturnCode: true
|
||||
}));
|
||||
}
|
||||
yield Promise.all(executions);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
2
dist/main/index.js.map
vendored
2
dist/main/index.js.map
vendored
File diff suppressed because one or more lines are too long
555
dist/post/index.js
vendored
555
dist/post/index.js
vendored
@@ -90,18 +90,19 @@ function restoreCache(paths, primaryKey, restoreKeys, options) {
|
||||
checkKey(key);
|
||||
}
|
||||
const compressionMethod = yield utils.getCompressionMethod();
|
||||
// path are needed to compute version
|
||||
const cacheEntry = yield cacheHttpClient.getCacheEntry(keys, paths, {
|
||||
compressionMethod
|
||||
});
|
||||
if (!(cacheEntry === null || cacheEntry === void 0 ? void 0 : cacheEntry.archiveLocation)) {
|
||||
// Cache not found
|
||||
return undefined;
|
||||
}
|
||||
const archivePath = path.join(yield utils.createTempDirectory(), utils.getCacheFileName(compressionMethod));
|
||||
core.debug(`Archive Path: ${archivePath}`);
|
||||
const restoredEntry = new CacheEntry(cacheEntry.cacheKey);
|
||||
let archivePath = '';
|
||||
try {
|
||||
// path are needed to compute version
|
||||
const cacheEntry = yield cacheHttpClient.getCacheEntry(keys, paths, {
|
||||
compressionMethod
|
||||
});
|
||||
if (!(cacheEntry === null || cacheEntry === void 0 ? void 0 : cacheEntry.archiveLocation)) {
|
||||
// Cache not found
|
||||
return undefined;
|
||||
}
|
||||
archivePath = path.join(yield utils.createTempDirectory(), utils.getCacheFileName(compressionMethod));
|
||||
core.debug(`Archive Path: ${archivePath}`);
|
||||
const restoredEntry = new CacheEntry(cacheEntry.cacheKey);
|
||||
// Download the cache from the cache entry
|
||||
yield cacheHttpClient.downloadCache(cacheEntry.archiveLocation, archivePath, options);
|
||||
if (core.isDebug()) {
|
||||
@@ -112,6 +113,17 @@ function restoreCache(paths, primaryKey, restoreKeys, options) {
|
||||
core.info(`Cache Size: ~${Math.round(archiveFileSize / (1024 * 1024))} MB (${archiveFileSize} B)`);
|
||||
yield tar_1.extractTar(archivePath, compressionMethod);
|
||||
core.info('Cache restored successfully');
|
||||
return restoredEntry;
|
||||
}
|
||||
catch (error) {
|
||||
const typedError = error;
|
||||
if (typedError.name === ValidationError.name) {
|
||||
throw error;
|
||||
}
|
||||
else {
|
||||
// Supress all non-validation cache related errors because caching should be optional
|
||||
core.warning(`Failed to restore: ${error.message}`);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
// Try to delete the archive to save space
|
||||
@@ -122,7 +134,7 @@ function restoreCache(paths, primaryKey, restoreKeys, options) {
|
||||
core.debug(`Failed to delete archive: ${error}`);
|
||||
}
|
||||
}
|
||||
return restoredEntry;
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
exports.restoreCache = restoreCache;
|
||||
@@ -140,7 +152,7 @@ function saveCache(paths, key, options) {
|
||||
checkPaths(paths);
|
||||
checkKey(key);
|
||||
const compressionMethod = yield utils.getCompressionMethod();
|
||||
let cacheId = null;
|
||||
let cacheId = -1;
|
||||
const cachePaths = yield utils.resolvePaths(paths);
|
||||
core.debug('Cache Paths:');
|
||||
core.debug(`${JSON.stringify(cachePaths)}`);
|
||||
@@ -181,6 +193,18 @@ function saveCache(paths, key, options) {
|
||||
core.debug(`Saving Cache (ID: ${cacheId})`);
|
||||
yield cacheHttpClient.saveCache(cacheId, archivePath, options);
|
||||
}
|
||||
catch (error) {
|
||||
const typedError = error;
|
||||
if (typedError.name === ValidationError.name) {
|
||||
throw error;
|
||||
}
|
||||
else if (typedError.name === ReserveCacheError.name) {
|
||||
core.info(`Failed to save: ${typedError.message}`);
|
||||
}
|
||||
else {
|
||||
core.warning(`Failed to save: ${typedError.message}`);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
// Try to delete the archive to save space
|
||||
try {
|
||||
@@ -1134,6 +1158,8 @@ function createTar(archiveFolder, sourceDirectories, compressionMethod) {
|
||||
...getCompressionProgram(),
|
||||
'-cf',
|
||||
cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
||||
'--exclude',
|
||||
cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
||||
'-P',
|
||||
'-C',
|
||||
workingDirectory.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
||||
@@ -2730,6 +2756,13 @@ Object.defineProperty(exports, "summary", ({ enumerable: true, get: function ()
|
||||
*/
|
||||
var summary_2 = __nccwpck_require__(1327);
|
||||
Object.defineProperty(exports, "markdownSummary", ({ enumerable: true, get: function () { return summary_2.markdownSummary; } }));
|
||||
/**
|
||||
* Path exports
|
||||
*/
|
||||
var path_utils_1 = __nccwpck_require__(2981);
|
||||
Object.defineProperty(exports, "toPosixPath", ({ enumerable: true, get: function () { return path_utils_1.toPosixPath; } }));
|
||||
Object.defineProperty(exports, "toWin32Path", ({ enumerable: true, get: function () { return path_utils_1.toWin32Path; } }));
|
||||
Object.defineProperty(exports, "toPlatformPath", ({ enumerable: true, get: function () { return path_utils_1.toPlatformPath; } }));
|
||||
//# sourceMappingURL=core.js.map
|
||||
|
||||
/***/ }),
|
||||
@@ -2867,6 +2900,71 @@ exports.OidcClient = OidcClient;
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 2981:
|
||||
/***/ (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;
|
||||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||
}) : (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.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.toPlatformPath = exports.toWin32Path = exports.toPosixPath = void 0;
|
||||
const path = __importStar(__nccwpck_require__(1017));
|
||||
/**
|
||||
* toPosixPath converts the given path to the posix form. On Windows, \\ will be
|
||||
* replaced with /.
|
||||
*
|
||||
* @param pth. Path to transform.
|
||||
* @return string Posix path.
|
||||
*/
|
||||
function toPosixPath(pth) {
|
||||
return pth.replace(/[\\]/g, '/');
|
||||
}
|
||||
exports.toPosixPath = toPosixPath;
|
||||
/**
|
||||
* toWin32Path converts the given path to the win32 form. On Linux, / will be
|
||||
* replaced with \\.
|
||||
*
|
||||
* @param pth. Path to transform.
|
||||
* @return string Win32 path.
|
||||
*/
|
||||
function toWin32Path(pth) {
|
||||
return pth.replace(/[/]/g, '\\');
|
||||
}
|
||||
exports.toWin32Path = toWin32Path;
|
||||
/**
|
||||
* toPlatformPath converts the given path to a platform-specific path. It does
|
||||
* this by replacing instances of / and \ with the platform-specific path
|
||||
* separator.
|
||||
*
|
||||
* @param pth The path to platformize.
|
||||
* @return string The platform-specific path.
|
||||
*/
|
||||
function toPlatformPath(pth) {
|
||||
return pth.replace(/[/\\]/g, path.sep);
|
||||
}
|
||||
exports.toPlatformPath = toPlatformPath;
|
||||
//# sourceMappingURL=path-utils.js.map
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 1327:
|
||||
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
||||
|
||||
@@ -63851,6 +63949,54 @@ function wrappy (fn, cb) {
|
||||
}).call(this);
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 3017:
|
||||
/***/ (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.loadBuildResults = void 0;
|
||||
const fs = __importStar(__nccwpck_require__(7147));
|
||||
const path = __importStar(__nccwpck_require__(1017));
|
||||
function loadBuildResults() {
|
||||
const buildResultsDir = path.resolve(process.env['RUNNER_TEMP'], '.build-results');
|
||||
if (!fs.existsSync(buildResultsDir)) {
|
||||
return [];
|
||||
}
|
||||
return fs.readdirSync(buildResultsDir).map(file => {
|
||||
const filePath = path.join(buildResultsDir, file);
|
||||
const content = fs.readFileSync(filePath, 'utf8');
|
||||
return JSON.parse(content);
|
||||
});
|
||||
}
|
||||
exports.loadBuildResults = loadBuildResults;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 7591:
|
||||
@@ -63960,10 +64106,17 @@ class GradleStateCache {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const cacheKey = (0, cache_utils_1.generateCacheKey)(this.cacheName).key;
|
||||
const restoredCacheKey = core.getState(RESTORED_CACHE_KEY_KEY);
|
||||
const entryListener = listener.entry(this.cacheDescription);
|
||||
const gradleHomeEntryListener = listener.entry(this.cacheDescription);
|
||||
if (restoredCacheKey && cacheKey === restoredCacheKey) {
|
||||
core.info(`Cache hit occurred on the cache key ${cacheKey}, not saving cache.`);
|
||||
entryListener.markUnchanged('cache key not changed');
|
||||
for (const entryListener of listener.cacheEntries) {
|
||||
if (entryListener === gradleHomeEntryListener) {
|
||||
entryListener.markUnsaved('cache key not changed');
|
||||
}
|
||||
else {
|
||||
entryListener.markUnsaved(`referencing '${this.cacheDescription}' cache entry not saved`);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
try {
|
||||
@@ -63975,7 +64128,7 @@ class GradleStateCache {
|
||||
}
|
||||
core.info(`Caching ${this.cacheDescription} with cache key: ${cacheKey}`);
|
||||
const cachePath = this.getCachePath();
|
||||
yield (0, cache_utils_1.saveCache)(cachePath, cacheKey, entryListener);
|
||||
yield (0, cache_utils_1.saveCache)(cachePath, cacheKey, gradleHomeEntryListener);
|
||||
return;
|
||||
});
|
||||
}
|
||||
@@ -64015,13 +64168,13 @@ class GradleStateCache {
|
||||
initializeGradleUserHome(gradleUserHome, initScriptsDir) {
|
||||
const initScriptFilenames = ['build-result-capture.init.gradle', 'build-result-capture-service.plugin.groovy'];
|
||||
for (const initScriptFilename of initScriptFilenames) {
|
||||
const initScriptContent = this.readResourceAsString(initScriptFilename);
|
||||
const initScriptContent = this.readInitScriptAsString(initScriptFilename);
|
||||
const initScriptPath = path_1.default.resolve(initScriptsDir, initScriptFilename);
|
||||
fs_1.default.writeFileSync(initScriptPath, initScriptContent);
|
||||
}
|
||||
}
|
||||
readResourceAsString(resource) {
|
||||
const absolutePath = path_1.default.resolve(__dirname, '..', '..', 'src', 'resources', resource);
|
||||
readInitScriptAsString(resource) {
|
||||
const absolutePath = path_1.default.resolve(__dirname, '..', '..', 'src', 'resources', 'init-scripts', resource);
|
||||
return fs_1.default.readFileSync(absolutePath, 'utf8');
|
||||
}
|
||||
debugReportGradleUserHomeSize(label) {
|
||||
@@ -64103,7 +64256,7 @@ const core = __importStar(__nccwpck_require__(2186));
|
||||
const glob = __importStar(__nccwpck_require__(8090));
|
||||
const cache_base_1 = __nccwpck_require__(7591);
|
||||
const cache_utils_1 = __nccwpck_require__(1678);
|
||||
const job_summary_1 = __nccwpck_require__(7345);
|
||||
const build_results_1 = __nccwpck_require__(3017);
|
||||
const SKIP_RESTORE_VAR = 'GRADLE_BUILD_ACTION_SKIP_RESTORE';
|
||||
class ExtractedCacheEntry {
|
||||
constructor(artifactType, pattern, cacheKey) {
|
||||
@@ -64205,7 +64358,7 @@ class AbstractEntryExtractor {
|
||||
const previouslyRestoredKey = (_a = previouslyRestoredEntries.find(x => x.artifactType === artifactType && x.pattern === pattern)) === null || _a === void 0 ? void 0 : _a.cacheKey;
|
||||
if (previouslyRestoredKey === cacheKey) {
|
||||
(0, cache_utils_1.cacheDebug)(`No change to previously restored ${artifactType}. Not saving.`);
|
||||
entryListener.markUnchanged('contents unchanged');
|
||||
entryListener.markUnsaved('contents unchanged');
|
||||
}
|
||||
else {
|
||||
core.info(`Caching ${artifactType} with path '${pattern}' and cache key: ${cacheKey}`);
|
||||
@@ -64283,9 +64436,9 @@ class GradleHomeEntryExtractor extends AbstractEntryExtractor {
|
||||
implicitDescendants: false,
|
||||
followSymbolicLinks: false
|
||||
});
|
||||
for (const p of yield globber.glob()) {
|
||||
(0, cache_utils_1.cacheDebug)(`Deleting wrapper zip: ${p}`);
|
||||
(0, cache_utils_1.tryDelete)(p);
|
||||
for (const wrapperZip of yield globber.glob()) {
|
||||
(0, cache_utils_1.cacheDebug)(`Deleting wrapper zip: ${wrapperZip}`);
|
||||
yield (0, cache_utils_1.tryDelete)(wrapperZip);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -64336,7 +64489,7 @@ class ConfigurationCacheEntryExtractor extends AbstractEntryExtractor {
|
||||
});
|
||||
}
|
||||
getProjectRoots() {
|
||||
const buildResults = (0, job_summary_1.loadBuildResults)();
|
||||
const buildResults = (0, build_results_1.loadBuildResults)();
|
||||
const projectRootDirs = buildResults.map(x => x.rootProjectDir);
|
||||
return [...new Set(projectRootDirs)];
|
||||
}
|
||||
@@ -64375,24 +64528,27 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.logCachingReport = exports.CacheEntryListener = exports.CacheListener = void 0;
|
||||
exports.logCachingReport = exports.writeCachingReport = exports.CacheEntryListener = exports.CacheListener = void 0;
|
||||
const core = __importStar(__nccwpck_require__(2186));
|
||||
const cache = __importStar(__nccwpck_require__(7799));
|
||||
class CacheListener {
|
||||
constructor() {
|
||||
this.cacheEntries = [];
|
||||
this.isCacheReadOnly = false;
|
||||
this.isCacheWriteOnly = false;
|
||||
this.isCacheDisabled = false;
|
||||
this.cacheReadOnly = false;
|
||||
this.cacheWriteOnly = false;
|
||||
this.cacheDisabled = false;
|
||||
}
|
||||
get fullyRestored() {
|
||||
return this.cacheEntries.every(x => !x.wasRequestedButNotRestored());
|
||||
}
|
||||
get cacheStatus() {
|
||||
if (this.isCacheDisabled)
|
||||
if (!cache.isFeatureAvailable())
|
||||
return 'not available';
|
||||
if (this.cacheDisabled)
|
||||
return 'disabled';
|
||||
if (this.isCacheWriteOnly)
|
||||
if (this.cacheWriteOnly)
|
||||
return 'write-only';
|
||||
if (this.isCacheReadOnly)
|
||||
if (this.cacheReadOnly)
|
||||
return 'read-only';
|
||||
return 'enabled';
|
||||
}
|
||||
@@ -64450,13 +64606,13 @@ class CacheEntryListener {
|
||||
this.savedSize = 0;
|
||||
return this;
|
||||
}
|
||||
markUnchanged(message) {
|
||||
this.unchanged = message;
|
||||
markUnsaved(message) {
|
||||
this.unsaved = message;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
exports.CacheEntryListener = CacheEntryListener;
|
||||
function logCachingReport(listener) {
|
||||
function writeCachingReport(listener) {
|
||||
const entries = listener.cacheEntries;
|
||||
core.summary.addRaw(`\n<details><summary><h4>Caching for gradle-build-action was ${listener.cacheStatus} - expand for details</h4></summary>\n`);
|
||||
core.summary.addTable([
|
||||
@@ -64469,29 +64625,42 @@ function logCachingReport(listener) {
|
||||
['Entries Saved', `${getCount(entries, e => e.savedSize)}`, `${getSize(entries, e => e.savedSize)}`]
|
||||
]);
|
||||
core.summary.addHeading('Cache Entry Details', 5);
|
||||
const entryDetails = listener.cacheEntries
|
||||
.map(entry => {
|
||||
var _a, _b, _c;
|
||||
return `Entry: ${entry.entryName}
|
||||
Requested Key : ${(_a = entry.requestedKey) !== null && _a !== void 0 ? _a : ''}
|
||||
Restored Key : ${(_b = entry.restoredKey) !== null && _b !== void 0 ? _b : ''}
|
||||
Size: ${formatSize(entry.restoredSize)}
|
||||
${getRestoredMessage(entry, listener.isCacheWriteOnly)}
|
||||
Saved Key : ${(_c = entry.savedKey) !== null && _c !== void 0 ? _c : ''}
|
||||
Size: ${formatSize(entry.savedSize)}
|
||||
${getSavedMessage(entry, listener.isCacheReadOnly)}
|
||||
`;
|
||||
})
|
||||
.join('---\n');
|
||||
const entryDetails = renderEntryDetails(listener);
|
||||
core.summary.addRaw(`<pre>
|
||||
${entryDetails}
|
||||
</pre>
|
||||
</details>
|
||||
`);
|
||||
}
|
||||
exports.writeCachingReport = writeCachingReport;
|
||||
function logCachingReport(listener) {
|
||||
const entries = listener.cacheEntries;
|
||||
core.startGroup(`Caching for gradle-build-action was ${listener.cacheStatus} - expand for details`);
|
||||
core.info(`Entries Restored: ${getCount(entries, e => e.restoredSize)} (${getSize(entries, e => e.restoredSize)} Mb)`);
|
||||
core.info(`Entries Saved : ${getCount(entries, e => e.savedSize)} (${getSize(entries, e => e.savedSize)} Mb)`);
|
||||
core.info(`Cache Entry Details`);
|
||||
core.info(renderEntryDetails(listener));
|
||||
core.endGroup();
|
||||
}
|
||||
exports.logCachingReport = logCachingReport;
|
||||
function getRestoredMessage(entry, isCacheWriteOnly) {
|
||||
if (isCacheWriteOnly) {
|
||||
function renderEntryDetails(listener) {
|
||||
return listener.cacheEntries
|
||||
.map(entry => {
|
||||
var _a, _b, _c;
|
||||
return `Entry: ${entry.entryName}
|
||||
Requested Key : ${(_a = entry.requestedKey) !== null && _a !== void 0 ? _a : ''}
|
||||
Restored Key : ${(_b = entry.restoredKey) !== null && _b !== void 0 ? _b : ''}
|
||||
Size: ${formatSize(entry.restoredSize)}
|
||||
${getRestoredMessage(entry, listener.cacheWriteOnly)}
|
||||
Saved Key : ${(_c = entry.savedKey) !== null && _c !== void 0 ? _c : ''}
|
||||
Size: ${formatSize(entry.savedSize)}
|
||||
${getSavedMessage(entry, listener.cacheReadOnly)}
|
||||
`;
|
||||
})
|
||||
.join('---\n');
|
||||
}
|
||||
function getRestoredMessage(entry, cacheWriteOnly) {
|
||||
if (cacheWriteOnly) {
|
||||
return '(Entry not restored: cache is write-only)';
|
||||
}
|
||||
if (entry.restoredKey === undefined) {
|
||||
@@ -64502,12 +64671,12 @@ function getRestoredMessage(entry, isCacheWriteOnly) {
|
||||
}
|
||||
return '(Entry restored: partial match found)';
|
||||
}
|
||||
function getSavedMessage(entry, isCacheReadOnly) {
|
||||
if (entry.unchanged) {
|
||||
return `(Entry not saved: ${entry.unchanged})`;
|
||||
function getSavedMessage(entry, cacheReadOnly) {
|
||||
if (entry.unsaved) {
|
||||
return `(Entry not saved: ${entry.unsaved})`;
|
||||
}
|
||||
if (entry.savedKey === undefined) {
|
||||
if (isCacheReadOnly) {
|
||||
if (cacheReadOnly) {
|
||||
return '(Entry not saved: cache is read-only)';
|
||||
}
|
||||
return '(Entry not saved: reason unknown)';
|
||||
@@ -64525,12 +64694,9 @@ function getSize(cacheEntries, predicate) {
|
||||
return Math.round(bytes / (1024 * 1024));
|
||||
}
|
||||
function formatSize(bytes) {
|
||||
if (bytes === undefined) {
|
||||
if (bytes === undefined || bytes === 0) {
|
||||
return '';
|
||||
}
|
||||
if (bytes === 0) {
|
||||
return '0 (Entry already exists)';
|
||||
}
|
||||
return `${Math.round(bytes / (1024 * 1024))} MB (${bytes} B)`;
|
||||
}
|
||||
|
||||
@@ -64596,6 +64762,9 @@ const CACHE_KEY_JOB_VAR = 'GRADLE_BUILD_ACTION_CACHE_KEY_JOB';
|
||||
const CACHE_KEY_JOB_INSTANCE_VAR = 'GRADLE_BUILD_ACTION_CACHE_KEY_JOB_INSTANCE';
|
||||
const CACHE_KEY_JOB_EXECUTION_VAR = 'GRADLE_BUILD_ACTION_CACHE_KEY_JOB_EXECUTION';
|
||||
function isCacheDisabled() {
|
||||
if (!cache.isFeatureAvailable()) {
|
||||
return true;
|
||||
}
|
||||
return core.getBooleanInput(CACHE_DISABLED_PARAMETER);
|
||||
}
|
||||
exports.isCacheDisabled = isCacheDisabled;
|
||||
@@ -64723,9 +64892,12 @@ exports.handleCacheFailure = handleCacheFailure;
|
||||
function tryDelete(file) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const maxAttempts = 5;
|
||||
const stat = fs.lstatSync(file);
|
||||
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
||||
if (!fs.existsSync(file)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const stat = fs.lstatSync(file);
|
||||
if (stat.isDirectory()) {
|
||||
fs.rmdirSync(file, { recursive: true });
|
||||
}
|
||||
@@ -64819,7 +64991,7 @@ function restore(gradleUserHome, cacheListener) {
|
||||
if ((0, cache_utils_1.isCacheDisabled)()) {
|
||||
core.info('Cache is disabled: will not restore state from previous builds.');
|
||||
gradleStateCache.init();
|
||||
cacheListener.isCacheDisabled = true;
|
||||
cacheListener.cacheDisabled = true;
|
||||
return;
|
||||
}
|
||||
if (gradleStateCache.cacheOutputExists()) {
|
||||
@@ -64831,7 +65003,7 @@ function restore(gradleUserHome, cacheListener) {
|
||||
core.saveState(CACHE_RESTORED_VAR, true);
|
||||
if ((0, cache_utils_1.isCacheWriteOnly)()) {
|
||||
core.info('Cache is write-only: will not restore from cache.');
|
||||
cacheListener.isCacheWriteOnly = true;
|
||||
cacheListener.cacheWriteOnly = true;
|
||||
return;
|
||||
}
|
||||
yield core.group('Restore Gradle state from cache', () => __awaiter(this, void 0, void 0, function* () {
|
||||
@@ -64840,33 +65012,101 @@ function restore(gradleUserHome, cacheListener) {
|
||||
});
|
||||
}
|
||||
exports.restore = restore;
|
||||
function save(gradleUserHome, cacheListener) {
|
||||
function save(gradleUserHome, cacheListener, daemonController) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
if (!shouldSaveCaches()) {
|
||||
if ((0, cache_utils_1.isCacheDisabled)()) {
|
||||
core.info('Cache is disabled: will not save state for later builds.');
|
||||
return;
|
||||
}
|
||||
if (!core.getState(CACHE_RESTORED_VAR)) {
|
||||
core.info('Cache will not be saved: not restored in main action step.');
|
||||
return;
|
||||
}
|
||||
if ((0, cache_utils_1.isCacheReadOnly)()) {
|
||||
core.info('Cache is read-only: will not save state for use in subsequent builds.');
|
||||
cacheListener.isCacheReadOnly = true;
|
||||
cacheListener.cacheReadOnly = true;
|
||||
return;
|
||||
}
|
||||
yield daemonController.stopAllDaemons();
|
||||
yield core.group('Caching Gradle state', () => __awaiter(this, void 0, void 0, function* () {
|
||||
return new cache_base_1.GradleStateCache(gradleUserHome).save(cacheListener);
|
||||
}));
|
||||
});
|
||||
}
|
||||
exports.save = save;
|
||||
function shouldSaveCaches() {
|
||||
if ((0, cache_utils_1.isCacheDisabled)()) {
|
||||
core.info('Cache is disabled: will not save state for later builds.');
|
||||
return false;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 5146:
|
||||
/***/ (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]; } };
|
||||
}
|
||||
if (!core.getState(CACHE_RESTORED_VAR)) {
|
||||
core.info('Cache will not be saved: not restored in main action step.');
|
||||
return false;
|
||||
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;
|
||||
};
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.DaemonController = void 0;
|
||||
const core = __importStar(__nccwpck_require__(2186));
|
||||
const exec = __importStar(__nccwpck_require__(1514));
|
||||
const fs = __importStar(__nccwpck_require__(7147));
|
||||
const path = __importStar(__nccwpck_require__(1017));
|
||||
class DaemonController {
|
||||
constructor(buildResults) {
|
||||
const allHomes = buildResults.map(buildResult => buildResult.gradleHomeDir);
|
||||
this.gradleHomes = Array.from(new Set(allHomes));
|
||||
}
|
||||
stopAllDaemons() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
core.info('Stopping all Gradle daemons before saving Gradle User Home state');
|
||||
const executions = [];
|
||||
const args = ['--stop'];
|
||||
for (const gradleHome of this.gradleHomes) {
|
||||
const executable = path.resolve(gradleHome, 'bin', 'gradle');
|
||||
if (!fs.existsSync(executable)) {
|
||||
core.warning(`Gradle executable not found at ${executable}. Could not stop Gradle daemons.`);
|
||||
continue;
|
||||
}
|
||||
core.info(`Stopping Gradle daemons for ${gradleHome}`);
|
||||
executions.push(exec.exec(executable, args, {
|
||||
ignoreReturnCode: true
|
||||
}));
|
||||
}
|
||||
yield Promise.all(executions);
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
exports.DaemonController = DaemonController;
|
||||
|
||||
|
||||
/***/ }),
|
||||
@@ -64899,65 +65139,97 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.loadBuildResults = exports.writeJobSummary = void 0;
|
||||
exports.logJobSummary = exports.writeJobSummary = void 0;
|
||||
const core = __importStar(__nccwpck_require__(2186));
|
||||
const fs_1 = __importDefault(__nccwpck_require__(7147));
|
||||
const path_1 = __importDefault(__nccwpck_require__(1017));
|
||||
const cache_reporting_1 = __nccwpck_require__(6674);
|
||||
function writeJobSummary(buildResults, cacheListener) {
|
||||
core.info('Writing job summary');
|
||||
if (buildResults.length === 0) {
|
||||
core.debug('No Gradle build results found. Summary table will not be generated.');
|
||||
}
|
||||
else {
|
||||
writeSummaryTable(buildResults);
|
||||
}
|
||||
(0, cache_reporting_1.logCachingReport)(cacheListener);
|
||||
core.summary.write();
|
||||
}
|
||||
exports.writeJobSummary = writeJobSummary;
|
||||
function loadBuildResults() {
|
||||
const buildResultsDir = path_1.default.resolve(process.env['RUNNER_TEMP'], '.build-results');
|
||||
if (!fs_1.default.existsSync(buildResultsDir)) {
|
||||
return [];
|
||||
}
|
||||
return fs_1.default.readdirSync(buildResultsDir).map(file => {
|
||||
const filePath = path_1.default.join(buildResultsDir, file);
|
||||
const content = fs_1.default.readFileSync(filePath, 'utf8');
|
||||
return JSON.parse(content);
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
core.info('Writing job summary');
|
||||
if (buildResults.length === 0) {
|
||||
core.debug('No Gradle build results found. Summary table will not be generated.');
|
||||
}
|
||||
else {
|
||||
writeSummaryTable(buildResults);
|
||||
}
|
||||
(0, cache_reporting_1.writeCachingReport)(cacheListener);
|
||||
yield core.summary.write();
|
||||
});
|
||||
}
|
||||
exports.loadBuildResults = loadBuildResults;
|
||||
exports.writeJobSummary = writeJobSummary;
|
||||
function logJobSummary(buildResults, cacheListener) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
if (buildResults.length === 0) {
|
||||
core.debug('No Gradle build results found. Summary table will not be logged.');
|
||||
}
|
||||
else {
|
||||
logSummaryTable(buildResults);
|
||||
}
|
||||
(0, cache_reporting_1.logCachingReport)(cacheListener);
|
||||
});
|
||||
}
|
||||
exports.logJobSummary = logJobSummary;
|
||||
function writeSummaryTable(results) {
|
||||
core.summary.addHeading('Gradle Builds', 3);
|
||||
core.summary.addTable([
|
||||
[
|
||||
{ data: 'Root Project', header: true },
|
||||
{ data: 'Tasks', header: true },
|
||||
{ data: 'Gradle Version', header: true },
|
||||
{ data: 'Outcome', header: true }
|
||||
],
|
||||
...results.map(result => [
|
||||
result.rootProjectName,
|
||||
result.requestedTasks,
|
||||
result.gradleVersion,
|
||||
renderOutcome(result)
|
||||
])
|
||||
]);
|
||||
core.summary.addRaw('\n');
|
||||
core.summary.addRaw(`
|
||||
<table>
|
||||
<tr>
|
||||
<th>Root Project</th>
|
||||
<th>Requested Tasks</th>
|
||||
<th>Gradle Version</th>
|
||||
<th>Build Outcome</th>
|
||||
<th>Build Scan™</th>
|
||||
</tr>${results.map(result => renderBuildResultRow(result)).join('')}
|
||||
</table>
|
||||
`);
|
||||
}
|
||||
function renderBuildResultRow(result) {
|
||||
return `
|
||||
<tr>
|
||||
<td>${result.rootProjectName}</td>
|
||||
<td>${result.requestedTasks}</td>
|
||||
<td align='center'>${result.gradleVersion}</td>
|
||||
<td align='center'>${renderOutcome(result)}</td>
|
||||
<td>${renderBuildScan(result)}</td>
|
||||
</tr>`;
|
||||
}
|
||||
function renderOutcome(result) {
|
||||
const labelPart = result.buildScanUri ? 'Build%20Scan%E2%84%A2' : 'Build';
|
||||
const outcomePart = result.buildFailed ? 'FAILED-red' : 'SUCCESS-brightgreen';
|
||||
const badgeUrl = `https://img.shields.io/badge/${labelPart}-${outcomePart}?logo=Gradle`;
|
||||
const badgeHtml = `<img src="${badgeUrl}" alt="Gradle Build">`;
|
||||
const targetUrl = result.buildScanUri ? result.buildScanUri : '#';
|
||||
return result.buildFailed ? ':x:' : ':white_check_mark:';
|
||||
}
|
||||
function renderBuildScan(result) {
|
||||
if (result.buildScanFailed) {
|
||||
return renderBuildScanBadge('PUBLISH_FAILED', 'orange', 'https://docs.gradle.com/enterprise/gradle-plugin/#troubleshooting');
|
||||
}
|
||||
if (result.buildScanUri) {
|
||||
return renderBuildScanBadge('PUBLISHED', '06A0CE', result.buildScanUri);
|
||||
}
|
||||
return renderBuildScanBadge('NOT_PUBLISHED', 'lightgrey', 'https://scans.gradle.com');
|
||||
}
|
||||
function renderBuildScanBadge(outcomeText, outcomeColor, targetUrl) {
|
||||
const badgeUrl = `https://img.shields.io/badge/Build%20Scan%E2%84%A2-${outcomeText}-${outcomeColor}?logo=Gradle`;
|
||||
const badgeHtml = `<img src="${badgeUrl}" alt="Build Scan ${outcomeText}" />`;
|
||||
return `<a href="${targetUrl}" rel="nofollow">${badgeHtml}</a>`;
|
||||
}
|
||||
function logSummaryTable(results) {
|
||||
core.info('============================');
|
||||
core.info('Gradle Builds');
|
||||
core.info('----------------------------');
|
||||
core.info('Root Project | Requested Tasks | Gradle Version | Build Outcome | Build Scan™');
|
||||
core.info('----------------------------');
|
||||
for (const result of results) {
|
||||
core.info(`${result.rootProjectName} | ${result.requestedTasks} | ${result.gradleVersion} | ${result.buildFailed ? 'FAILED' : 'SUCCESS'} | ${result.buildScanFailed ? 'Publish failed' : result.buildScanUri}`);
|
||||
}
|
||||
core.info('============================');
|
||||
}
|
||||
|
||||
|
||||
/***/ }),
|
||||
@@ -65067,17 +65339,22 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.complete = exports.setup = void 0;
|
||||
const core = __importStar(__nccwpck_require__(2186));
|
||||
const exec = __importStar(__nccwpck_require__(1514));
|
||||
const fs = __importStar(__nccwpck_require__(7147));
|
||||
const summary_1 = __nccwpck_require__(1327);
|
||||
const path = __importStar(__nccwpck_require__(1017));
|
||||
const os = __importStar(__nccwpck_require__(2037));
|
||||
const caches = __importStar(__nccwpck_require__(3800));
|
||||
const cache_reporting_1 = __nccwpck_require__(6674);
|
||||
const job_summary_1 = __nccwpck_require__(7345);
|
||||
const build_results_1 = __nccwpck_require__(3017);
|
||||
const cache_reporting_1 = __nccwpck_require__(6674);
|
||||
const daemon_controller_1 = __nccwpck_require__(5146);
|
||||
const GRADLE_SETUP_VAR = 'GRADLE_BUILD_ACTION_SETUP_COMPLETED';
|
||||
const GRADLE_USER_HOME = 'GRADLE_USER_HOME';
|
||||
const CACHE_LISTENER = 'CACHE_LISTENER';
|
||||
const JOB_SUMMARY_ENABLED_PARAMETER = 'generate-job-summary';
|
||||
function shouldGenerateJobSummary() {
|
||||
if (!process.env[summary_1.SUMMARY_ENV_VAR]) {
|
||||
return false;
|
||||
}
|
||||
return core.getBooleanInput(JOB_SUMMARY_ENABLED_PARAMETER);
|
||||
}
|
||||
function setup(buildRootDirectory) {
|
||||
@@ -65102,15 +65379,17 @@ function complete() {
|
||||
core.info('Gradle setup post-action only performed for first gradle-build-action step in workflow.');
|
||||
return;
|
||||
}
|
||||
const buildResults = (0, job_summary_1.loadBuildResults)();
|
||||
core.info('Stopping all Gradle daemons');
|
||||
yield stopAllDaemons(getUniqueGradleHomes(buildResults));
|
||||
core.info('In final post-action step, saving state and writing summary');
|
||||
const cacheListener = cache_reporting_1.CacheListener.rehydrate(core.getState(CACHE_LISTENER));
|
||||
const buildResults = (0, build_results_1.loadBuildResults)();
|
||||
const gradleUserHome = core.getState(GRADLE_USER_HOME);
|
||||
yield caches.save(gradleUserHome, cacheListener);
|
||||
const cacheListener = cache_reporting_1.CacheListener.rehydrate(core.getState(CACHE_LISTENER));
|
||||
const daemonController = new daemon_controller_1.DaemonController(buildResults);
|
||||
yield caches.save(gradleUserHome, cacheListener, daemonController);
|
||||
if (shouldGenerateJobSummary()) {
|
||||
(0, job_summary_1.writeJobSummary)(buildResults, cacheListener);
|
||||
yield (0, job_summary_1.writeJobSummary)(buildResults, cacheListener);
|
||||
}
|
||||
else {
|
||||
(0, job_summary_1.logJobSummary)(buildResults, cacheListener);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -65138,28 +65417,6 @@ function determineUserHome() {
|
||||
return userHome;
|
||||
});
|
||||
}
|
||||
function getUniqueGradleHomes(buildResults) {
|
||||
const gradleHomes = buildResults.map(buildResult => buildResult.gradleHomeDir);
|
||||
return Array.from(new Set(gradleHomes));
|
||||
}
|
||||
function stopAllDaemons(gradleHomes) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const executions = [];
|
||||
const args = ['--stop'];
|
||||
for (const gradleHome of gradleHomes) {
|
||||
const executable = path.resolve(gradleHome, 'bin', 'gradle');
|
||||
if (!fs.existsSync(executable)) {
|
||||
core.warning(`Gradle executable not found at ${executable}. Could not stop Gradle daemons.`);
|
||||
continue;
|
||||
}
|
||||
core.info(`Stopping Gradle daemons in ${gradleHome}`);
|
||||
executions.push(exec.exec(executable, args, {
|
||||
ignoreReturnCode: true
|
||||
}));
|
||||
}
|
||||
yield Promise.all(executions);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
2
dist/post/index.js.map
vendored
2
dist/post/index.js.map
vendored
File diff suppressed because one or more lines are too long
2355
package-lock.json
generated
2355
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
20
package.json
20
package.json
@@ -25,8 +25,8 @@
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/cache": "2.0.5",
|
||||
"@actions/core": "1.8.2",
|
||||
"@actions/cache": "3.0.0",
|
||||
"@actions/core": "1.9.0",
|
||||
"@actions/exec": "1.1.1",
|
||||
"@actions/github": "5.0.3",
|
||||
"@actions/glob": "0.3.0",
|
||||
@@ -35,19 +35,19 @@
|
||||
"string-argv": "0.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "28.1.0",
|
||||
"@types/jest": "28.1.4",
|
||||
"@types/node": "16.11.21",
|
||||
"@types/unzipper": "0.10.5",
|
||||
"@typescript-eslint/parser": "5.27.0",
|
||||
"@typescript-eslint/parser": "5.30.6",
|
||||
"@vercel/ncc": "0.34.0",
|
||||
"eslint": "8.17.0",
|
||||
"eslint": "8.19.0",
|
||||
"eslint-plugin-github": "4.3.6",
|
||||
"eslint-plugin-jest": "26.4.6",
|
||||
"jest": "28.1.0",
|
||||
"eslint-plugin-jest": "26.5.3",
|
||||
"jest": "28.1.2",
|
||||
"js-yaml": "4.1.0",
|
||||
"patch-package": "6.4.7",
|
||||
"prettier": "2.6.2",
|
||||
"ts-jest": "28.0.4",
|
||||
"typescript": "4.7.3"
|
||||
"prettier": "2.7.1",
|
||||
"ts-jest": "28.0.5",
|
||||
"typescript": "4.7.4"
|
||||
}
|
||||
}
|
||||
|
@@ -26,18 +26,17 @@ index 16b20f7..aea77ba 100644
|
||||
+ constructor(key: string, size?: number);
|
||||
+}
|
||||
diff --git a/node_modules/@actions/cache/lib/cache.js b/node_modules/@actions/cache/lib/cache.js
|
||||
index 2dd645a..a392352 100644
|
||||
index 4dc5e88..2141dd5 100644
|
||||
--- a/node_modules/@actions/cache/lib/cache.js
|
||||
+++ b/node_modules/@actions/cache/lib/cache.js
|
||||
@@ -93,6 +93,7 @@ function restoreCache(paths, primaryKey, restoreKeys, options) {
|
||||
}
|
||||
const archivePath = path.join(yield utils.createTempDirectory(), utils.getCacheFileName(compressionMethod));
|
||||
core.debug(`Archive Path: ${archivePath}`);
|
||||
+ const restoredEntry = new CacheEntry(cacheEntry.cacheKey);
|
||||
try {
|
||||
@@ -95,16 +95,18 @@ function restoreCache(paths, primaryKey, restoreKeys, options) {
|
||||
}
|
||||
archivePath = path.join(yield utils.createTempDirectory(), utils.getCacheFileName(compressionMethod));
|
||||
core.debug(`Archive Path: ${archivePath}`);
|
||||
+ const restoredEntry = new CacheEntry(cacheEntry.cacheKey);
|
||||
// Download the cache from the cache entry
|
||||
yield cacheHttpClient.downloadCache(cacheEntry.archiveLocation, archivePath, options);
|
||||
@@ -100,6 +101,7 @@ function restoreCache(paths, primaryKey, restoreKeys, options) {
|
||||
if (core.isDebug()) {
|
||||
yield tar_1.listTar(archivePath, compressionMethod);
|
||||
}
|
||||
const archiveFileSize = utils.getArchiveFileSizeInBytes(archivePath);
|
||||
@@ -45,16 +44,12 @@ index 2dd645a..a392352 100644
|
||||
core.info(`Cache Size: ~${Math.round(archiveFileSize / (1024 * 1024))} MB (${archiveFileSize} B)`);
|
||||
yield tar_1.extractTar(archivePath, compressionMethod);
|
||||
core.info('Cache restored successfully');
|
||||
@@ -113,7 +115,7 @@ function restoreCache(paths, primaryKey, restoreKeys, options) {
|
||||
core.debug(`Failed to delete archive: ${error}`);
|
||||
}
|
||||
- return cacheEntry.cacheKey;
|
||||
+ return restoredEntry;
|
||||
}
|
||||
- return cacheEntry.cacheKey;
|
||||
+ return restoredEntry;
|
||||
});
|
||||
}
|
||||
exports.restoreCache = restoreCache;
|
||||
@@ -141,6 +143,7 @@ function saveCache(paths, key, options) {
|
||||
catch (error) {
|
||||
const typedError = error;
|
||||
@@ -153,6 +155,7 @@ function saveCache(paths, key, options) {
|
||||
const archiveFolder = yield utils.createTempDirectory();
|
||||
const archivePath = path.join(archiveFolder, utils.getCacheFileName(compressionMethod));
|
||||
core.debug(`Archive Path: ${archivePath}`);
|
||||
@@ -62,7 +57,7 @@ index 2dd645a..a392352 100644
|
||||
try {
|
||||
yield tar_1.createTar(archiveFolder, cachePaths, compressionMethod);
|
||||
if (core.isDebug()) {
|
||||
@@ -148,6 +151,7 @@ function saveCache(paths, key, options) {
|
||||
@@ -160,6 +163,7 @@ function saveCache(paths, key, options) {
|
||||
}
|
||||
const fileSizeLimit = 10 * 1024 * 1024 * 1024; // 10GB per repo limit
|
||||
const archiveFileSize = utils.getArchiveFileSizeInBytes(archivePath);
|
||||
@@ -70,7 +65,7 @@ index 2dd645a..a392352 100644
|
||||
core.debug(`File Size: ${archiveFileSize}`);
|
||||
// For GHES, this check will take place in ReserveCache API with enterprise file size limit
|
||||
if (archiveFileSize > fileSizeLimit && !utils.isGhes()) {
|
||||
@@ -179,8 +183,15 @@ function saveCache(paths, key, options) {
|
||||
@@ -203,8 +207,15 @@ function saveCache(paths, key, options) {
|
||||
core.debug(`Failed to delete archive: ${error}`);
|
||||
}
|
||||
}
|
@@ -1 +0,0 @@
|
||||
- [NEW] Use Job Summary to display build scan links, instead of GHA annotations
|
||||
|
27
src/build-results.ts
Normal file
27
src/build-results.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import * as fs from 'fs'
|
||||
import * as path from 'path'
|
||||
|
||||
export interface BuildResult {
|
||||
get rootProjectName(): string
|
||||
get rootProjectDir(): string
|
||||
get requestedTasks(): string
|
||||
get gradleVersion(): string
|
||||
get gradleHomeDir(): string
|
||||
get buildFailed(): boolean
|
||||
get buildScanUri(): string
|
||||
get buildScanFailed(): boolean
|
||||
}
|
||||
|
||||
export function loadBuildResults(): BuildResult[] {
|
||||
const buildResultsDir = path.resolve(process.env['RUNNER_TEMP']!, '.build-results')
|
||||
if (!fs.existsSync(buildResultsDir)) {
|
||||
return []
|
||||
}
|
||||
|
||||
return fs.readdirSync(buildResultsDir).map(file => {
|
||||
// Every file in the .build-results dir should be a BuildResults JSON
|
||||
const filePath = path.join(buildResultsDir, file)
|
||||
const content = fs.readFileSync(filePath, 'utf8')
|
||||
return JSON.parse(content) as BuildResult
|
||||
})
|
||||
}
|
@@ -94,11 +94,18 @@ export class GradleStateCache {
|
||||
async save(listener: CacheListener): Promise<void> {
|
||||
const cacheKey = generateCacheKey(this.cacheName).key
|
||||
const restoredCacheKey = core.getState(RESTORED_CACHE_KEY_KEY)
|
||||
const entryListener = listener.entry(this.cacheDescription)
|
||||
const gradleHomeEntryListener = listener.entry(this.cacheDescription)
|
||||
|
||||
if (restoredCacheKey && cacheKey === restoredCacheKey) {
|
||||
core.info(`Cache hit occurred on the cache key ${cacheKey}, not saving cache.`)
|
||||
entryListener.markUnchanged('cache key not changed')
|
||||
|
||||
for (const entryListener of listener.cacheEntries) {
|
||||
if (entryListener === gradleHomeEntryListener) {
|
||||
entryListener.markUnsaved('cache key not changed')
|
||||
} else {
|
||||
entryListener.markUnsaved(`referencing '${this.cacheDescription}' cache entry not saved`)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -111,7 +118,7 @@ export class GradleStateCache {
|
||||
|
||||
core.info(`Caching ${this.cacheDescription} with cache key: ${cacheKey}`)
|
||||
const cachePath = this.getCachePath()
|
||||
await saveCache(cachePath, cacheKey, entryListener)
|
||||
await saveCache(cachePath, cacheKey, gradleHomeEntryListener)
|
||||
|
||||
return
|
||||
}
|
||||
@@ -168,15 +175,15 @@ export class GradleStateCache {
|
||||
private initializeGradleUserHome(gradleUserHome: string, initScriptsDir: string): void {
|
||||
const initScriptFilenames = ['build-result-capture.init.gradle', 'build-result-capture-service.plugin.groovy']
|
||||
for (const initScriptFilename of initScriptFilenames) {
|
||||
const initScriptContent = this.readResourceAsString(initScriptFilename)
|
||||
const initScriptContent = this.readInitScriptAsString(initScriptFilename)
|
||||
const initScriptPath = path.resolve(initScriptsDir, initScriptFilename)
|
||||
fs.writeFileSync(initScriptPath, initScriptContent)
|
||||
}
|
||||
}
|
||||
|
||||
private readResourceAsString(resource: string): string {
|
||||
private readInitScriptAsString(resource: string): string {
|
||||
// Resolving relative to __dirname will allow node to find the resource at runtime
|
||||
const absolutePath = path.resolve(__dirname, '..', '..', 'src', 'resources', resource)
|
||||
const absolutePath = path.resolve(__dirname, '..', '..', 'src', 'resources', 'init-scripts', resource)
|
||||
return fs.readFileSync(absolutePath, 'utf8')
|
||||
}
|
||||
|
||||
|
@@ -14,7 +14,7 @@ import {
|
||||
saveCache,
|
||||
tryDelete
|
||||
} from './cache-utils'
|
||||
import {loadBuildResults} from './job-summary'
|
||||
import {loadBuildResults} from './build-results'
|
||||
|
||||
const SKIP_RESTORE_VAR = 'GRADLE_BUILD_ACTION_SKIP_RESTORE'
|
||||
|
||||
@@ -213,7 +213,7 @@ abstract class AbstractEntryExtractor {
|
||||
|
||||
if (previouslyRestoredKey === cacheKey) {
|
||||
cacheDebug(`No change to previously restored ${artifactType}. Not saving.`)
|
||||
entryListener.markUnchanged('contents unchanged')
|
||||
entryListener.markUnsaved('contents unchanged')
|
||||
} else {
|
||||
core.info(`Caching ${artifactType} with path '${pattern}' and cache key: ${cacheKey}`)
|
||||
await saveCache([pattern], cacheKey, entryListener)
|
||||
@@ -312,9 +312,9 @@ export class GradleHomeEntryExtractor extends AbstractEntryExtractor {
|
||||
followSymbolicLinks: false
|
||||
})
|
||||
|
||||
for (const p of await globber.glob()) {
|
||||
cacheDebug(`Deleting wrapper zip: ${p}`)
|
||||
tryDelete(p)
|
||||
for (const wrapperZip of await globber.glob()) {
|
||||
cacheDebug(`Deleting wrapper zip: ${wrapperZip}`)
|
||||
await tryDelete(wrapperZip)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import * as core from '@actions/core'
|
||||
import * as cache from '@actions/cache'
|
||||
|
||||
/**
|
||||
* Collects information on what entries were saved and restored during the action.
|
||||
@@ -6,18 +7,19 @@ import * as core from '@actions/core'
|
||||
*/
|
||||
export class CacheListener {
|
||||
cacheEntries: CacheEntryListener[] = []
|
||||
isCacheReadOnly = false
|
||||
isCacheWriteOnly = false
|
||||
isCacheDisabled = false
|
||||
cacheReadOnly = false
|
||||
cacheWriteOnly = false
|
||||
cacheDisabled = false
|
||||
|
||||
get fullyRestored(): boolean {
|
||||
return this.cacheEntries.every(x => !x.wasRequestedButNotRestored())
|
||||
}
|
||||
|
||||
get cacheStatus(): string {
|
||||
if (this.isCacheDisabled) return 'disabled'
|
||||
if (this.isCacheWriteOnly) return 'write-only'
|
||||
if (this.isCacheReadOnly) return 'read-only'
|
||||
if (!cache.isFeatureAvailable()) return 'not available'
|
||||
if (this.cacheDisabled) return 'disabled'
|
||||
if (this.cacheWriteOnly) return 'write-only'
|
||||
if (this.cacheReadOnly) return 'read-only'
|
||||
return 'enabled'
|
||||
}
|
||||
|
||||
@@ -64,7 +66,7 @@ export class CacheEntryListener {
|
||||
savedKey: string | undefined
|
||||
savedSize: number | undefined
|
||||
|
||||
unchanged: string | undefined
|
||||
unsaved: string | undefined
|
||||
|
||||
constructor(entryName: string) {
|
||||
this.entryName = entryName
|
||||
@@ -98,13 +100,13 @@ export class CacheEntryListener {
|
||||
return this
|
||||
}
|
||||
|
||||
markUnchanged(message: string): CacheEntryListener {
|
||||
this.unchanged = message
|
||||
markUnsaved(message: string): CacheEntryListener {
|
||||
this.unsaved = message
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
export function logCachingReport(listener: CacheListener): void {
|
||||
export function writeCachingReport(listener: CacheListener): void {
|
||||
const entries = listener.cacheEntries
|
||||
|
||||
core.summary.addRaw(
|
||||
@@ -123,21 +125,7 @@ export function logCachingReport(listener: CacheListener): void {
|
||||
|
||||
core.summary.addHeading('Cache Entry Details', 5)
|
||||
|
||||
const entryDetails = listener.cacheEntries
|
||||
.map(
|
||||
entry =>
|
||||
`Entry: ${entry.entryName}
|
||||
Requested Key : ${entry.requestedKey ?? ''}
|
||||
Restored Key : ${entry.restoredKey ?? ''}
|
||||
Size: ${formatSize(entry.restoredSize)}
|
||||
${getRestoredMessage(entry, listener.isCacheWriteOnly)}
|
||||
Saved Key : ${entry.savedKey ?? ''}
|
||||
Size: ${formatSize(entry.savedSize)}
|
||||
${getSavedMessage(entry, listener.isCacheReadOnly)}
|
||||
`
|
||||
)
|
||||
.join('---\n')
|
||||
|
||||
const entryDetails = renderEntryDetails(listener)
|
||||
core.summary.addRaw(`<pre>
|
||||
${entryDetails}
|
||||
</pre>
|
||||
@@ -145,8 +133,40 @@ ${entryDetails}
|
||||
`)
|
||||
}
|
||||
|
||||
function getRestoredMessage(entry: CacheEntryListener, isCacheWriteOnly: boolean): string {
|
||||
if (isCacheWriteOnly) {
|
||||
export function logCachingReport(listener: CacheListener): void {
|
||||
const entries = listener.cacheEntries
|
||||
|
||||
core.startGroup(`Caching for gradle-build-action was ${listener.cacheStatus} - expand for details`)
|
||||
|
||||
core.info(
|
||||
`Entries Restored: ${getCount(entries, e => e.restoredSize)} (${getSize(entries, e => e.restoredSize)} Mb)`
|
||||
)
|
||||
core.info(`Entries Saved : ${getCount(entries, e => e.savedSize)} (${getSize(entries, e => e.savedSize)} Mb)`)
|
||||
|
||||
core.info(`Cache Entry Details`)
|
||||
core.info(renderEntryDetails(listener))
|
||||
|
||||
core.endGroup()
|
||||
}
|
||||
|
||||
function renderEntryDetails(listener: CacheListener): string {
|
||||
return listener.cacheEntries
|
||||
.map(
|
||||
entry => `Entry: ${entry.entryName}
|
||||
Requested Key : ${entry.requestedKey ?? ''}
|
||||
Restored Key : ${entry.restoredKey ?? ''}
|
||||
Size: ${formatSize(entry.restoredSize)}
|
||||
${getRestoredMessage(entry, listener.cacheWriteOnly)}
|
||||
Saved Key : ${entry.savedKey ?? ''}
|
||||
Size: ${formatSize(entry.savedSize)}
|
||||
${getSavedMessage(entry, listener.cacheReadOnly)}
|
||||
`
|
||||
)
|
||||
.join('---\n')
|
||||
}
|
||||
|
||||
function getRestoredMessage(entry: CacheEntryListener, cacheWriteOnly: boolean): string {
|
||||
if (cacheWriteOnly) {
|
||||
return '(Entry not restored: cache is write-only)'
|
||||
}
|
||||
if (entry.restoredKey === undefined) {
|
||||
@@ -158,12 +178,12 @@ function getRestoredMessage(entry: CacheEntryListener, isCacheWriteOnly: boolean
|
||||
return '(Entry restored: partial match found)'
|
||||
}
|
||||
|
||||
function getSavedMessage(entry: CacheEntryListener, isCacheReadOnly: boolean): string {
|
||||
if (entry.unchanged) {
|
||||
return `(Entry not saved: ${entry.unchanged})`
|
||||
function getSavedMessage(entry: CacheEntryListener, cacheReadOnly: boolean): string {
|
||||
if (entry.unsaved) {
|
||||
return `(Entry not saved: ${entry.unsaved})`
|
||||
}
|
||||
if (entry.savedKey === undefined) {
|
||||
if (isCacheReadOnly) {
|
||||
if (cacheReadOnly) {
|
||||
return '(Entry not saved: cache is read-only)'
|
||||
}
|
||||
return '(Entry not saved: reason unknown)'
|
||||
@@ -190,11 +210,8 @@ function getSize(
|
||||
}
|
||||
|
||||
function formatSize(bytes: number | undefined): string {
|
||||
if (bytes === undefined) {
|
||||
if (bytes === undefined || bytes === 0) {
|
||||
return ''
|
||||
}
|
||||
if (bytes === 0) {
|
||||
return '0 (Entry already exists)'
|
||||
}
|
||||
return `${Math.round(bytes / (1024 * 1024))} MB (${bytes} B)`
|
||||
}
|
||||
|
@@ -25,6 +25,9 @@ const CACHE_KEY_JOB_INSTANCE_VAR = 'GRADLE_BUILD_ACTION_CACHE_KEY_JOB_INSTANCE'
|
||||
const CACHE_KEY_JOB_EXECUTION_VAR = 'GRADLE_BUILD_ACTION_CACHE_KEY_JOB_EXECUTION'
|
||||
|
||||
export function isCacheDisabled(): boolean {
|
||||
if (!cache.isFeatureAvailable()) {
|
||||
return true
|
||||
}
|
||||
return core.getBooleanInput(CACHE_DISABLED_PARAMETER)
|
||||
}
|
||||
|
||||
@@ -198,9 +201,12 @@ export function handleCacheFailure(error: unknown, message: string): void {
|
||||
*/
|
||||
export async function tryDelete(file: string): Promise<void> {
|
||||
const maxAttempts = 5
|
||||
const stat = fs.lstatSync(file)
|
||||
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
||||
if (!fs.existsSync(file)) {
|
||||
return
|
||||
}
|
||||
try {
|
||||
const stat = fs.lstatSync(file)
|
||||
if (stat.isDirectory()) {
|
||||
fs.rmdirSync(file, {recursive: true})
|
||||
} else {
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import * as core from '@actions/core'
|
||||
import {isCacheDisabled, isCacheReadOnly, isCacheWriteOnly} from './cache-utils'
|
||||
import {CacheListener} from './cache-reporting'
|
||||
import {DaemonController} from './daemon-controller'
|
||||
import {GradleStateCache} from './cache-base'
|
||||
|
||||
const CACHE_RESTORED_VAR = 'GRADLE_BUILD_ACTION_CACHE_RESTORED'
|
||||
@@ -19,7 +20,7 @@ export async function restore(gradleUserHome: string, cacheListener: CacheListen
|
||||
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.isCacheDisabled = true
|
||||
cacheListener.cacheDisabled = true
|
||||
return
|
||||
}
|
||||
|
||||
@@ -36,7 +37,7 @@ export async function restore(gradleUserHome: string, cacheListener: CacheListen
|
||||
|
||||
if (isCacheWriteOnly()) {
|
||||
core.info('Cache is write-only: will not restore from cache.')
|
||||
cacheListener.isCacheWriteOnly = true
|
||||
cacheListener.cacheWriteOnly = true
|
||||
return
|
||||
}
|
||||
|
||||
@@ -45,32 +46,30 @@ export async function restore(gradleUserHome: string, cacheListener: CacheListen
|
||||
})
|
||||
}
|
||||
|
||||
export async function save(gradleUserHome: string, cacheListener: CacheListener): Promise<void> {
|
||||
if (!shouldSaveCaches()) {
|
||||
export async function save(
|
||||
gradleUserHome: string,
|
||||
cacheListener: CacheListener,
|
||||
daemonController: DaemonController
|
||||
): Promise<void> {
|
||||
if (isCacheDisabled()) {
|
||||
core.info('Cache is disabled: will not save state for later builds.')
|
||||
return
|
||||
}
|
||||
|
||||
if (!core.getState(CACHE_RESTORED_VAR)) {
|
||||
core.info('Cache will not be saved: not restored in main action step.')
|
||||
return
|
||||
}
|
||||
|
||||
if (isCacheReadOnly()) {
|
||||
core.info('Cache is read-only: will not save state for use in subsequent builds.')
|
||||
cacheListener.isCacheReadOnly = true
|
||||
cacheListener.cacheReadOnly = true
|
||||
return
|
||||
}
|
||||
|
||||
await daemonController.stopAllDaemons()
|
||||
|
||||
await core.group('Caching Gradle state', async () => {
|
||||
return new GradleStateCache(gradleUserHome).save(cacheListener)
|
||||
})
|
||||
}
|
||||
|
||||
function shouldSaveCaches(): boolean {
|
||||
if (isCacheDisabled()) {
|
||||
core.info('Cache is disabled: will not save state for later builds.')
|
||||
return false
|
||||
}
|
||||
|
||||
if (!core.getState(CACHE_RESTORED_VAR)) {
|
||||
core.info('Cache will not be saved: not restored in main action step.')
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
36
src/daemon-controller.ts
Normal file
36
src/daemon-controller.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
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'
|
||||
|
||||
export class DaemonController {
|
||||
private readonly gradleHomes
|
||||
|
||||
constructor(buildResults: BuildResult[]) {
|
||||
const allHomes = buildResults.map(buildResult => buildResult.gradleHomeDir)
|
||||
this.gradleHomes = Array.from(new Set(allHomes))
|
||||
}
|
||||
|
||||
async stopAllDaemons(): Promise<void> {
|
||||
core.info('Stopping all Gradle daemons before saving Gradle User Home state')
|
||||
|
||||
const executions: Promise<number>[] = []
|
||||
const args = ['--stop']
|
||||
|
||||
for (const gradleHome of this.gradleHomes) {
|
||||
const executable = path.resolve(gradleHome, 'bin', 'gradle')
|
||||
if (!fs.existsSync(executable)) {
|
||||
core.warning(`Gradle executable not found at ${executable}. Could not stop Gradle daemons.`)
|
||||
continue
|
||||
}
|
||||
core.info(`Stopping Gradle daemons for ${gradleHome}`)
|
||||
executions.push(
|
||||
exec.exec(executable, args, {
|
||||
ignoreReturnCode: true
|
||||
})
|
||||
)
|
||||
}
|
||||
await Promise.all(executions)
|
||||
}
|
||||
}
|
@@ -1,19 +1,8 @@
|
||||
import * as core from '@actions/core'
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import {logCachingReport, CacheListener} from './cache-reporting'
|
||||
import {BuildResult} from './build-results'
|
||||
import {writeCachingReport, CacheListener, logCachingReport} from './cache-reporting'
|
||||
|
||||
export interface BuildResult {
|
||||
get rootProjectName(): string
|
||||
get rootProjectDir(): string
|
||||
get requestedTasks(): string
|
||||
get gradleVersion(): string
|
||||
get gradleHomeDir(): string
|
||||
get buildFailed(): boolean
|
||||
get buildScanUri(): string
|
||||
}
|
||||
|
||||
export function writeJobSummary(buildResults: BuildResult[], cacheListener: CacheListener): void {
|
||||
export async function writeJobSummary(buildResults: BuildResult[], cacheListener: CacheListener): Promise<void> {
|
||||
core.info('Writing job summary')
|
||||
|
||||
if (buildResults.length === 0) {
|
||||
@@ -22,49 +11,84 @@ export function writeJobSummary(buildResults: BuildResult[], cacheListener: Cach
|
||||
writeSummaryTable(buildResults)
|
||||
}
|
||||
|
||||
logCachingReport(cacheListener)
|
||||
writeCachingReport(cacheListener)
|
||||
|
||||
core.summary.write()
|
||||
await core.summary.write()
|
||||
}
|
||||
|
||||
export function loadBuildResults(): BuildResult[] {
|
||||
const buildResultsDir = path.resolve(process.env['RUNNER_TEMP']!, '.build-results')
|
||||
if (!fs.existsSync(buildResultsDir)) {
|
||||
return []
|
||||
export async function logJobSummary(buildResults: BuildResult[], cacheListener: CacheListener): Promise<void> {
|
||||
if (buildResults.length === 0) {
|
||||
core.debug('No Gradle build results found. Summary table will not be logged.')
|
||||
} else {
|
||||
logSummaryTable(buildResults)
|
||||
}
|
||||
|
||||
return fs.readdirSync(buildResultsDir).map(file => {
|
||||
// Every file in the .build-results dir should be a BuildResults JSON
|
||||
const filePath = path.join(buildResultsDir, file)
|
||||
const content = fs.readFileSync(filePath, 'utf8')
|
||||
return JSON.parse(content) as BuildResult
|
||||
})
|
||||
logCachingReport(cacheListener)
|
||||
}
|
||||
|
||||
function writeSummaryTable(results: BuildResult[]): void {
|
||||
core.summary.addHeading('Gradle Builds', 3)
|
||||
core.summary.addTable([
|
||||
[
|
||||
{data: 'Root Project', header: true},
|
||||
{data: 'Tasks', header: true},
|
||||
{data: 'Gradle Version', header: true},
|
||||
{data: 'Outcome', header: true}
|
||||
],
|
||||
...results.map(result => [
|
||||
result.rootProjectName,
|
||||
result.requestedTasks,
|
||||
result.gradleVersion,
|
||||
renderOutcome(result)
|
||||
])
|
||||
])
|
||||
core.summary.addRaw('\n')
|
||||
|
||||
core.summary.addRaw(`
|
||||
<table>
|
||||
<tr>
|
||||
<th>Root Project</th>
|
||||
<th>Requested Tasks</th>
|
||||
<th>Gradle Version</th>
|
||||
<th>Build Outcome</th>
|
||||
<th>Build Scan™</th>
|
||||
</tr>${results.map(result => renderBuildResultRow(result)).join('')}
|
||||
</table>
|
||||
`)
|
||||
}
|
||||
|
||||
function renderBuildResultRow(result: BuildResult): string {
|
||||
return `
|
||||
<tr>
|
||||
<td>${result.rootProjectName}</td>
|
||||
<td>${result.requestedTasks}</td>
|
||||
<td align='center'>${result.gradleVersion}</td>
|
||||
<td align='center'>${renderOutcome(result)}</td>
|
||||
<td>${renderBuildScan(result)}</td>
|
||||
</tr>`
|
||||
}
|
||||
|
||||
function renderOutcome(result: BuildResult): string {
|
||||
const labelPart = result.buildScanUri ? 'Build%20Scan%E2%84%A2' : 'Build'
|
||||
const outcomePart = result.buildFailed ? 'FAILED-red' : 'SUCCESS-brightgreen'
|
||||
const badgeUrl = `https://img.shields.io/badge/${labelPart}-${outcomePart}?logo=Gradle`
|
||||
const badgeHtml = `<img src="${badgeUrl}" alt="Gradle Build">`
|
||||
const targetUrl = result.buildScanUri ? result.buildScanUri : '#'
|
||||
return result.buildFailed ? ':x:' : ':white_check_mark:'
|
||||
}
|
||||
|
||||
function renderBuildScan(result: BuildResult): string {
|
||||
if (result.buildScanFailed) {
|
||||
return renderBuildScanBadge(
|
||||
'PUBLISH_FAILED',
|
||||
'orange',
|
||||
'https://docs.gradle.com/enterprise/gradle-plugin/#troubleshooting'
|
||||
)
|
||||
}
|
||||
if (result.buildScanUri) {
|
||||
return renderBuildScanBadge('PUBLISHED', '06A0CE', result.buildScanUri)
|
||||
}
|
||||
return renderBuildScanBadge('NOT_PUBLISHED', 'lightgrey', 'https://scans.gradle.com')
|
||||
}
|
||||
|
||||
function renderBuildScanBadge(outcomeText: string, outcomeColor: string, targetUrl: string): string {
|
||||
const badgeUrl = `https://img.shields.io/badge/Build%20Scan%E2%84%A2-${outcomeText}-${outcomeColor}?logo=Gradle`
|
||||
const badgeHtml = `<img src="${badgeUrl}" alt="Build Scan ${outcomeText}" />`
|
||||
return `<a href="${targetUrl}" rel="nofollow">${badgeHtml}</a>`
|
||||
}
|
||||
|
||||
function logSummaryTable(results: BuildResult[]): void {
|
||||
core.info('============================')
|
||||
core.info('Gradle Builds')
|
||||
core.info('----------------------------')
|
||||
core.info('Root Project | Requested Tasks | Gradle Version | Build Outcome | Build Scan™')
|
||||
core.info('----------------------------')
|
||||
for (const result of results) {
|
||||
core.info(
|
||||
`${result.rootProjectName} | ${result.requestedTasks} | ${result.gradleVersion} | ${
|
||||
result.buildFailed ? 'FAILED' : 'SUCCESS'
|
||||
} | ${result.buildScanFailed ? 'Publish failed' : result.buildScanUri}`
|
||||
)
|
||||
}
|
||||
core.info('============================')
|
||||
}
|
||||
|
@@ -41,12 +41,19 @@ abstract class BuildResultsRecorder implements BuildService<BuildResultsRecorder
|
||||
gradleVersion: GradleVersion.current().version,
|
||||
gradleHomeDir: getParameters().getGradleHomeDir().get(),
|
||||
buildFailed: buildFailed,
|
||||
buildScanUri: null
|
||||
buildScanUri: null,
|
||||
buildScanFailed: false
|
||||
]
|
||||
|
||||
def buildResultsDir = new File(System.getenv("RUNNER_TEMP"), ".build-results")
|
||||
def runnerTempDir = System.getenv("RUNNER_TEMP")
|
||||
def githubActionStep = System.getenv("GITHUB_ACTION")
|
||||
if (!runnerTempDir || !githubActionStep) {
|
||||
return
|
||||
}
|
||||
|
||||
def buildResultsDir = new File(runnerTempDir, ".build-results")
|
||||
buildResultsDir.mkdirs()
|
||||
def buildResultsFile = new File(buildResultsDir, System.getenv("GITHUB_ACTION") + getParameters().getInvocationId().get() + ".json")
|
||||
def buildResultsFile = new File(buildResultsDir, githubActionStep + getParameters().getInvocationId().get() + ".json")
|
||||
buildResultsFile << groovy.json.JsonOutput.toJson(buildResults)
|
||||
}
|
||||
}
|
@@ -40,65 +40,33 @@ if (isTopLevelBuild) {
|
||||
|
||||
def captureUsingBuildScanPublished(buildScanExtension, rootProject, invocationId) {
|
||||
buildScanExtension.with {
|
||||
def requestedTasks = gradle.startParameter.taskNames.join(" ")
|
||||
def rootProjectName = rootProject.name
|
||||
def rootProjectDir = rootProject.projectDir.absolutePath
|
||||
def gradleVersion = GradleVersion.current().version
|
||||
def gradleHomeDir = gradle.gradleHomeDir.absolutePath
|
||||
def buildFailed = false
|
||||
def buildResults = new BuildResults(invocationId, gradle, rootProject)
|
||||
|
||||
buildFinished { result ->
|
||||
buildFailed = (result.failure != null)
|
||||
buildResults.setBuildResult(result)
|
||||
}
|
||||
|
||||
buildScanPublished { buildScan ->
|
||||
|
||||
def buildScanUri = buildScan.buildScanUri.toASCIIString()
|
||||
def buildResults = [
|
||||
rootProjectName: rootProjectName,
|
||||
rootProjectDir: rootProjectDir,
|
||||
requestedTasks: requestedTasks,
|
||||
gradleVersion: gradleVersion,
|
||||
gradleHomeDir: gradleHomeDir,
|
||||
buildFailed: buildFailed,
|
||||
buildScanUri: buildScanUri
|
||||
]
|
||||
|
||||
def buildResultsDir = new File(System.getenv("RUNNER_TEMP"), ".build-results")
|
||||
buildResultsDir.mkdirs()
|
||||
def buildResultsFile = new File(buildResultsDir, System.getenv("GITHUB_ACTION") + invocationId + ".json")
|
||||
|
||||
// Overwrite any contents written by buildFinished or build service, since this result is a superset.
|
||||
if (buildResultsFile.exists()) {
|
||||
buildResultsFile.text = groovy.json.JsonOutput.toJson(buildResults)
|
||||
} else {
|
||||
buildResultsFile << groovy.json.JsonOutput.toJson(buildResults)
|
||||
}
|
||||
buildResults.setBuildScanUri(buildScan.buildScanUri.toASCIIString())
|
||||
buildResults.writeToResultsFile(true)
|
||||
|
||||
println("::set-output name=build-scan-url::${buildScan.buildScanUri}")
|
||||
}
|
||||
|
||||
onError { error ->
|
||||
buildResults.setBuildScanFailed()
|
||||
buildResults.writeToResultsFile(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def captureUsingBuildFinished(gradle, invocationId) {
|
||||
gradle.buildFinished { result ->
|
||||
def buildResults = [
|
||||
rootProjectName: gradle.rootProject.name,
|
||||
rootProjectDir: gradle.rootProject.rootDir.absolutePath,
|
||||
requestedTasks: gradle.startParameter.taskNames.join(" "),
|
||||
gradleVersion: GradleVersion.current().version,
|
||||
gradleHomeDir: gradle.gradleHomeDir.absolutePath,
|
||||
buildFailed: result.failure != null,
|
||||
buildScanUri: null
|
||||
]
|
||||
def buildResults = new BuildResults(invocationId, gradle, gradle.rootProject)
|
||||
buildResults.setBuildResult(result)
|
||||
|
||||
buildResults.writeToResultsFile(false)
|
||||
|
||||
def buildResultsDir = new File(System.getenv("RUNNER_TEMP"), ".build-results")
|
||||
buildResultsDir.mkdirs()
|
||||
def buildResultsFile = new File(buildResultsDir, System.getenv("GITHUB_ACTION") + invocationId + ".json")
|
||||
// Don't overwrite file generated by build-scan plugin if present (which has build-scan-uri)
|
||||
if (!buildResultsFile.exists()) {
|
||||
buildResultsFile << groovy.json.JsonOutput.toJson(buildResults)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,3 +74,55 @@ def captureUsingBuildService(settings, invocationId) {
|
||||
gradle.ext.invocationId = invocationId
|
||||
apply from: '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) {
|
||||
buildResults['buildFailed'] = result.failure != null
|
||||
}
|
||||
|
||||
def setBuildScanUri(def buildScanUrl) {
|
||||
buildResults['buildScanUri'] = buildScanUrl
|
||||
}
|
||||
|
||||
def setBuildScanFailed() {
|
||||
buildResults['buildScanFailed'] = true
|
||||
}
|
||||
|
||||
def writeToResultsFile(boolean overwrite) {
|
||||
def runnerTempDir = System.getenv("RUNNER_TEMP")
|
||||
def githubActionStep = System.getenv("GITHUB_ACTION")
|
||||
if (!runnerTempDir || !githubActionStep) {
|
||||
return
|
||||
}
|
||||
|
||||
def buildResultsDir = new File(runnerTempDir, ".build-results")
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,12 +1,14 @@
|
||||
import * as core from '@actions/core'
|
||||
import * as exec from '@actions/exec'
|
||||
import * as fs from 'fs'
|
||||
import {SUMMARY_ENV_VAR} from '@actions/core/lib/summary'
|
||||
import * as path from 'path'
|
||||
import * as os from 'os'
|
||||
import * as caches from './caches'
|
||||
|
||||
import {logJobSummary, writeJobSummary} from './job-summary'
|
||||
import {loadBuildResults} from './build-results'
|
||||
import {CacheListener} from './cache-reporting'
|
||||
import {BuildResult, loadBuildResults, writeJobSummary} from './job-summary'
|
||||
import {DaemonController} from './daemon-controller'
|
||||
|
||||
const GRADLE_SETUP_VAR = 'GRADLE_BUILD_ACTION_SETUP_COMPLETED'
|
||||
const GRADLE_USER_HOME = 'GRADLE_USER_HOME'
|
||||
@@ -14,6 +16,11 @@ const CACHE_LISTENER = 'CACHE_LISTENER'
|
||||
const JOB_SUMMARY_ENABLED_PARAMETER = 'generate-job-summary'
|
||||
|
||||
function shouldGenerateJobSummary(): boolean {
|
||||
// Check if Job Summary is supported on this platform
|
||||
if (!process.env[SUMMARY_ENV_VAR]) {
|
||||
return false
|
||||
}
|
||||
|
||||
return core.getBooleanInput(JOB_SUMMARY_ENABLED_PARAMETER)
|
||||
}
|
||||
|
||||
@@ -44,20 +51,20 @@ export async function complete(): Promise<void> {
|
||||
core.info('Gradle setup post-action only performed for first gradle-build-action step in workflow.')
|
||||
return
|
||||
}
|
||||
core.info('In final post-action step, saving state and writing summary')
|
||||
|
||||
const buildResults = loadBuildResults()
|
||||
|
||||
core.info('Stopping all Gradle daemons')
|
||||
await stopAllDaemons(getUniqueGradleHomes(buildResults))
|
||||
|
||||
core.info('In final post-action step, saving state and writing summary')
|
||||
const cacheListener: CacheListener = CacheListener.rehydrate(core.getState(CACHE_LISTENER))
|
||||
|
||||
const gradleUserHome = core.getState(GRADLE_USER_HOME)
|
||||
await caches.save(gradleUserHome, cacheListener)
|
||||
const cacheListener: CacheListener = CacheListener.rehydrate(core.getState(CACHE_LISTENER))
|
||||
const daemonController = new DaemonController(buildResults)
|
||||
|
||||
await caches.save(gradleUserHome, cacheListener, daemonController)
|
||||
|
||||
if (shouldGenerateJobSummary()) {
|
||||
writeJobSummary(buildResults, cacheListener)
|
||||
await writeJobSummary(buildResults, cacheListener)
|
||||
} else {
|
||||
logJobSummary(buildResults, cacheListener)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,28 +93,3 @@ async function determineUserHome(): Promise<string> {
|
||||
core.debug(`Determined user.home from java -version output: '${userHome}'`)
|
||||
return userHome
|
||||
}
|
||||
|
||||
function getUniqueGradleHomes(buildResults: BuildResult[]): string[] {
|
||||
const gradleHomes = buildResults.map(buildResult => buildResult.gradleHomeDir)
|
||||
return Array.from(new Set(gradleHomes))
|
||||
}
|
||||
|
||||
async function stopAllDaemons(gradleHomes: string[]): Promise<void> {
|
||||
const executions: Promise<number>[] = []
|
||||
const args = ['--stop']
|
||||
|
||||
for (const gradleHome of gradleHomes) {
|
||||
const executable = path.resolve(gradleHome, 'bin', 'gradle')
|
||||
if (!fs.existsSync(executable)) {
|
||||
core.warning(`Gradle executable not found at ${executable}. Could not stop Gradle daemons.`)
|
||||
continue
|
||||
}
|
||||
core.info(`Stopping Gradle daemons in ${gradleHome}`)
|
||||
executions.push(
|
||||
exec.exec(executable, args, {
|
||||
ignoreReturnCode: true
|
||||
})
|
||||
)
|
||||
}
|
||||
await Promise.all(executions)
|
||||
}
|
||||
|
@@ -45,6 +45,7 @@ class BaseInitScriptTest extends Specification {
|
||||
static final String PUBLIC_BUILD_SCAN_ID = 'i2wepy2gr7ovw'
|
||||
static final String DEFAULT_SCAN_UPLOAD_TOKEN = 'scan-upload-token'
|
||||
static final String ROOT_PROJECT_NAME = 'test-init-script'
|
||||
boolean failScanUpload = false
|
||||
|
||||
File settingsFile
|
||||
File buildFile
|
||||
@@ -59,6 +60,10 @@ class BaseInitScriptTest extends Specification {
|
||||
|
||||
handlers {
|
||||
post('in/:gradleVersion/:pluginVersion') {
|
||||
if (failScanUpload) {
|
||||
context.response.status(401).send()
|
||||
return
|
||||
}
|
||||
def scanUrlString = "${mockScansServer.address}s/$PUBLIC_BUILD_SCAN_ID"
|
||||
def body = [
|
||||
id : PUBLIC_BUILD_SCAN_ID,
|
||||
@@ -72,6 +77,10 @@ class BaseInitScriptTest extends Specification {
|
||||
}
|
||||
prefix('scans/publish') {
|
||||
post('gradle/:pluginVersion/token') {
|
||||
if (failScanUpload) {
|
||||
context.response.status(401).send()
|
||||
return
|
||||
}
|
||||
def pluginVersion = context.pathTokens.pluginVersion
|
||||
def scanUrlString = "${mockScansServer.address}s/$PUBLIC_BUILD_SCAN_ID"
|
||||
def body = [
|
||||
@@ -85,6 +94,10 @@ class BaseInitScriptTest extends Specification {
|
||||
.send(jsonWriter.writeValueAsBytes(body))
|
||||
}
|
||||
post('gradle/:pluginVersion/upload') {
|
||||
if (failScanUpload) {
|
||||
context.response.status(401).send()
|
||||
return
|
||||
}
|
||||
context.request.getBody(1024 * 1024 * 10).then {
|
||||
context.response
|
||||
.contentType('application/vnd.gradle.scan-upload-ack+json')
|
||||
@@ -100,7 +113,7 @@ class BaseInitScriptTest extends Specification {
|
||||
settingsFile = new File(testProjectDir, 'settings.gradle')
|
||||
buildFile = new File(testProjectDir, 'build.gradle')
|
||||
|
||||
File srcInitScriptsDir = new File("../../src/resources")
|
||||
File srcInitScriptsDir = new File("../../src/resources/init-scripts")
|
||||
File targetInitScriptsDir = new File(testProjectDir, "initScripts")
|
||||
targetInitScriptsDir.mkdirs()
|
||||
|
||||
@@ -187,20 +200,17 @@ task expectFailure {
|
||||
File initScriptsDir = new File(testProjectDir, "initScripts")
|
||||
args << '-I' << new File(initScriptsDir, initScript).absolutePath
|
||||
|
||||
envVars['RUNNER_TEMP'] = testProjectDir.absolutePath
|
||||
envVars['GITHUB_ACTION'] = 'github-step-id'
|
||||
envVars.putIfAbsent('RUNNER_TEMP', testProjectDir.absolutePath)
|
||||
envVars.putIfAbsent('GITHUB_ACTION', 'github-step-id')
|
||||
|
||||
def runner = ((DefaultGradleRunner) GradleRunner.create())
|
||||
.withJvmArguments(jvmArgs)
|
||||
.withGradleVersion(gradleVersion.version)
|
||||
.withProjectDir(testProjectDir)
|
||||
.withArguments(args)
|
||||
.withEnvironment(envVars)
|
||||
.forwardOutput()
|
||||
|
||||
if (envVars) {
|
||||
runner.withEnvironment(envVars)
|
||||
}
|
||||
|
||||
runner
|
||||
}
|
||||
|
@@ -118,7 +118,37 @@ class TestBuildResultRecorder extends BaseInitScriptTest {
|
||||
testGradleVersion << CONFIGURATION_CACHE_VERSIONS
|
||||
}
|
||||
|
||||
void assertResults(String task, TestGradleVersion testGradleVersion, boolean hasFailure, boolean hasBuildScan) {
|
||||
def "produces build results file for failing build on #testGradleVersion when build scan publish fails"() {
|
||||
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
||||
|
||||
when:
|
||||
declareGePluginApplication(testGradleVersion.gradleVersion)
|
||||
addFailingTaskToBuild()
|
||||
failScanUpload = true
|
||||
runAndFail(['expectFailure'], initScript, testGradleVersion.gradleVersion)
|
||||
|
||||
then:
|
||||
assertResults('expectFailure', testGradleVersion, true, false, true)
|
||||
|
||||
where:
|
||||
testGradleVersion << ALL_VERSIONS
|
||||
}
|
||||
|
||||
def "produces no build results file when GitHub env vars not set with #testGradleVersion"() {
|
||||
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
||||
|
||||
when:
|
||||
run(['help'], initScript, testGradleVersion.gradleVersion, [], [RUNNER_TEMP: '', GITHUB_ACTION: ''])
|
||||
|
||||
then:
|
||||
def buildResultsDir = new File(testProjectDir, '.build-results')
|
||||
assert !buildResultsDir.exists()
|
||||
|
||||
where:
|
||||
testGradleVersion << ALL_VERSIONS
|
||||
}
|
||||
|
||||
void assertResults(String task, TestGradleVersion testGradleVersion, boolean hasFailure, boolean hasBuildScan, boolean scanUploadFailed = false) {
|
||||
def results = new JsonSlurper().parse(buildResultFile)
|
||||
assert results['rootProjectName'] == ROOT_PROJECT_NAME
|
||||
assert results['rootProjectDir'] == testProjectDir.canonicalPath
|
||||
@@ -127,6 +157,7 @@ class TestBuildResultRecorder extends BaseInitScriptTest {
|
||||
assert results['gradleHomeDir'] != null
|
||||
assert results['buildFailed'] == hasFailure
|
||||
assert results['buildScanUri'] == (hasBuildScan ? "${mockScansServer.address}s/${PUBLIC_BUILD_SCAN_ID}" : null)
|
||||
assert results['buildScanFailed'] == scanUploadFailed
|
||||
}
|
||||
|
||||
private File getBuildResultFile() {
|
@@ -1,4 +1,4 @@
|
||||
import {CacheEntryListener, CacheListener} from '../src/cache-reporting'
|
||||
import {CacheEntryListener, CacheListener} from '../../src/cache-reporting'
|
||||
|
||||
describe('caching report', () => {
|
||||
describe('reports not fully restored', () => {
|
@@ -1,4 +1,4 @@
|
||||
import * as cacheUtils from '../src/cache-utils'
|
||||
import * as cacheUtils from '../../src/cache-utils'
|
||||
|
||||
describe('cacheUtils-utils', () => {
|
||||
describe('can hash', () => {
|
Reference in New Issue
Block a user