mirror of
https://github.com/gradle/actions.git
synced 2025-11-26 17:09:10 +08:00
Compare commits
146 Commits
v3.3.1
...
v4.0.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
833b05f3e6 | ||
|
|
06905c7a0f | ||
|
|
73f1290de7 | ||
|
|
b6395da67c | ||
|
|
ce4c3a6c5e | ||
|
|
b644be617f | ||
|
|
7179909719 | ||
|
|
c01aea0cb4 | ||
|
|
479297d73e | ||
|
|
fe594a580d | ||
|
|
53f2a5657b | ||
|
|
fd87365911 | ||
|
|
c3f989640d | ||
|
|
6c9e547314 | ||
|
|
1a11891cfe | ||
|
|
fae6382622 | ||
|
|
81b4ac7741 | ||
|
|
c9872874b0 | ||
|
|
561dcd8516 | ||
|
|
7bb45b1dbd | ||
|
|
dc97151e55 | ||
|
|
2289da045c | ||
|
|
40a3605597 | ||
|
|
e6688f31b8 | ||
|
|
46308b920a | ||
|
|
7387edbbb3 | ||
|
|
9e459adb11 | ||
|
|
1371d49f1d | ||
|
|
8e4868ab4a | ||
|
|
5acdee61f0 | ||
|
|
32f9239e2c | ||
|
|
12cb23c359 | ||
|
|
238a3da6f4 | ||
|
|
2041ce6ab1 | ||
|
|
ded8009fcf | ||
|
|
db8e69bc03 | ||
|
|
4b56f19bda | ||
|
|
4576973cce | ||
|
|
5d7c18409c | ||
|
|
7da993afd5 | ||
|
|
de6862d826 | ||
|
|
4c453aec59 | ||
|
|
917439d87d | ||
|
|
77266ec345 | ||
|
|
514ac344fc | ||
|
|
f8aa3ed8b4 | ||
|
|
b175189376 | ||
|
|
20e923b8cb | ||
|
|
e7f9f25d86 | ||
|
|
f8f7d3e704 | ||
|
|
7a630bc41b | ||
|
|
a77cb2b0f8 | ||
|
|
54f7dc55a5 | ||
|
|
579a013225 | ||
|
|
94355bbb2f | ||
|
|
6d20c16462 | ||
|
|
b7e399239c | ||
|
|
723ca4de01 | ||
|
|
72dde7ef1e | ||
|
|
3083f01451 | ||
|
|
27dea2df09 | ||
|
|
91a526b647 | ||
|
|
d92de28b80 | ||
|
|
8d318190ad | ||
|
|
a025cbe7ec | ||
|
|
23dad2b1c7 | ||
|
|
4a315dceb2 | ||
|
|
bb7a843511 | ||
|
|
9a57bcca96 | ||
|
|
22818445b3 | ||
|
|
36c24e793d | ||
|
|
dff3ef9b8d | ||
|
|
01254b3eaa | ||
|
|
d9c87d481d | ||
|
|
ff865cb801 | ||
|
|
c3acd19a4a | ||
|
|
e5bbd4c742 | ||
|
|
d7cd9fc65c | ||
|
|
6407986e96 | ||
|
|
87bf5ca2ea | ||
|
|
81b4ece56a | ||
|
|
cdbbabd09c | ||
|
|
dad038d88d | ||
|
|
621f3b3f79 | ||
|
|
4022faad7e | ||
|
|
95ef72241e | ||
|
|
169bec5d8b | ||
|
|
b9abb7b195 | ||
|
|
c04155e2ca | ||
|
|
1da1cc97d5 | ||
|
|
c401249391 | ||
|
|
a6a0c7dcef | ||
|
|
3f3913eed0 | ||
|
|
2cd2a6e951 | ||
|
|
dbbdc275be | ||
|
|
ae74429826 | ||
|
|
bdc7162ff9 | ||
|
|
31ae3562f6 | ||
|
|
719985db3d | ||
|
|
b53238971c | ||
|
|
5f1c5827bf | ||
|
|
d9336dac04 | ||
|
|
8dbe9a3802 | ||
|
|
9c3430720d | ||
|
|
30c82f0068 | ||
|
|
e3bc05f224 | ||
|
|
485ea107b7 | ||
|
|
c1091c9c8e | ||
|
|
d0a116fff5 | ||
|
|
e238a7ad22 | ||
|
|
1d2ea6e5a8 | ||
|
|
114c1c234e | ||
|
|
2db3ae936e | ||
|
|
a68381d359 | ||
|
|
52ae27f7bb | ||
|
|
d1cd62d80a | ||
|
|
af6e576724 | ||
|
|
775b4d10d7 | ||
|
|
30610bc983 | ||
|
|
d4d72c9934 | ||
|
|
96b9cb4988 | ||
|
|
db270b9337 | ||
|
|
d91e2960eb | ||
|
|
0498421560 | ||
|
|
edb13383f3 | ||
|
|
cd560aa3ad | ||
|
|
500e0ee5b3 | ||
|
|
eb13cf7170 | ||
|
|
ea14aa9caf | ||
|
|
063cfaf0eb | ||
|
|
35f9242e22 | ||
|
|
90f1de0556 | ||
|
|
da512b52a5 | ||
|
|
db19848a5f | ||
|
|
941b289d84 | ||
|
|
bce7daca54 | ||
|
|
11eaed9738 | ||
|
|
cd62d9c9ef | ||
|
|
a54fb6a5bb | ||
|
|
ef36f81b41 | ||
|
|
18998bc43e | ||
|
|
a772c14b33 | ||
|
|
7763d71170 | ||
|
|
9ab93ee864 | ||
|
|
d124ec149f | ||
|
|
6ccde15122 |
5
.github/actions/init-integ-test/action.yml
vendored
5
.github/actions/init-integ-test/action.yml
vendored
@@ -9,6 +9,11 @@ runs:
|
||||
distribution: 'temurin'
|
||||
java-version: 11
|
||||
|
||||
- name: Configure environment
|
||||
shell: bash
|
||||
run: |
|
||||
echo "ALLOWED_GRADLE_WRAPPER_CHECKSUMS=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" >> "$GITHUB_ENV"
|
||||
|
||||
# Downloads a 'dist' directory artifact that was uploaded in an earlier 'build-dist' step
|
||||
- name: Download dist
|
||||
if: ${{ env.SKIP_DIST != 'true' && !env.ACT }}
|
||||
|
||||
Binary file not shown.
@@ -1,7 +1,7 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionSha256Sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
||||
distributionSha256Sum=d725d707bfabd4dfdc958c624003b3c80accc03f7037b5122c4b1d0ef15cecab
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
@@ -55,7 +57,7 @@
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
@@ -84,7 +86,8 @@ done
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
|
||||
' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@@ -43,11 +45,11 @@ set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
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.
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
@@ -57,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
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.
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
|
||||
Binary file not shown.
@@ -1,7 +1,7 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionSha256Sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
||||
distributionSha256Sum=d725d707bfabd4dfdc958c624003b3c80accc03f7037b5122c4b1d0ef15cecab
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
7
.github/workflow-samples/groovy-dsl/gradlew
vendored
7
.github/workflow-samples/groovy-dsl/gradlew
vendored
@@ -15,6 +15,8 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
@@ -55,7 +57,7 @@
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
@@ -84,7 +86,8 @@ done
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
|
||||
' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
22
.github/workflow-samples/groovy-dsl/gradlew.bat
vendored
22
.github/workflow-samples/groovy-dsl/gradlew.bat
vendored
@@ -13,6 +13,8 @@
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@@ -43,11 +45,11 @@ set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
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.
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
@@ -57,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
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.
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
plugins {
|
||||
id "com.gradle.develocity" version "3.17.2"
|
||||
id "com.gradle.develocity" version "3.17.6"
|
||||
id "com.gradle.common-custom-user-data-gradle-plugin" version "2.0.1"
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
@@ -1,7 +1,7 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionSha256Sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
||||
distributionSha256Sum=d725d707bfabd4dfdc958c624003b3c80accc03f7037b5122c4b1d0ef15cecab
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
@@ -55,7 +57,7 @@
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
@@ -84,7 +86,8 @@ done
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
|
||||
' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@@ -43,11 +45,11 @@ set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
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.
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
@@ -57,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
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.
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@ repositories {
|
||||
|
||||
dependencies {
|
||||
api("org.apache.commons:commons-math3:3.6.1")
|
||||
implementation("com.google.guava:guava:33.1.0-jre")
|
||||
implementation("com.google.guava:guava:33.2.1-jre")
|
||||
|
||||
testImplementation("org.junit.jupiter:junit-jupiter:5.10.2")
|
||||
testImplementation("org.junit.jupiter:junit-jupiter:5.10.3")
|
||||
}
|
||||
|
||||
tasks.test {
|
||||
|
||||
Binary file not shown.
@@ -1,7 +1,7 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionSha256Sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
||||
distributionSha256Sum=d725d707bfabd4dfdc958c624003b3c80accc03f7037b5122c4b1d0ef15cecab
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
7
.github/workflow-samples/kotlin-dsl/gradlew
vendored
7
.github/workflow-samples/kotlin-dsl/gradlew
vendored
@@ -15,6 +15,8 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
@@ -55,7 +57,7 @@
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
@@ -84,7 +86,8 @@ done
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
|
||||
' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
22
.github/workflow-samples/kotlin-dsl/gradlew.bat
vendored
22
.github/workflow-samples/kotlin-dsl/gradlew.bat
vendored
@@ -13,6 +13,8 @@
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@@ -43,11 +45,11 @@ set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
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.
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
@@ -57,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
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.
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
plugins {
|
||||
id("com.gradle.develocity") version "3.17.2"
|
||||
id("com.gradle.develocity") version "3.17.6"
|
||||
id("com.gradle.common-custom-user-data-gradle-plugin") version "2.0.1"
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
plugins {
|
||||
id "com.gradle.develocity" version "3.17.2"
|
||||
id "com.gradle.develocity" version "3.17.6"
|
||||
}
|
||||
|
||||
develocity {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
plugins {
|
||||
id "com.gradle.develocity" version "3.17.2"
|
||||
id "com.gradle.develocity" version "3.17.6"
|
||||
}
|
||||
|
||||
develocity {
|
||||
|
||||
Binary file not shown.
@@ -1,7 +1,7 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionSha256Sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
||||
distributionSha256Sum=d725d707bfabd4dfdc958c624003b3c80accc03f7037b5122c4b1d0ef15cecab
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
@@ -55,7 +57,7 @@
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
@@ -84,7 +86,8 @@ done
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
|
||||
' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@@ -43,11 +45,11 @@ set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
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.
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
@@ -57,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
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.
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
plugins {
|
||||
id "com.gradle.develocity" version "3.17.2"
|
||||
id "com.gradle.develocity" version "3.17.6"
|
||||
}
|
||||
|
||||
develocity {
|
||||
|
||||
6
.github/workflows/ci-codeql.yml
vendored
6
.github/workflows/ci-codeql.yml
vendored
@@ -5,6 +5,12 @@ on:
|
||||
branches:
|
||||
- 'main'
|
||||
- 'release/**'
|
||||
- 'dev/**' # Allow running Code QL on dev branches without a PR
|
||||
paths-ignore:
|
||||
- 'dist/**'
|
||||
pull_request:
|
||||
branches:
|
||||
- 'main'
|
||||
paths-ignore:
|
||||
- 'dist/**'
|
||||
schedule:
|
||||
|
||||
2
.github/workflows/ci-init-script-check.yml
vendored
2
.github/workflows/ci-init-script-check.yml
vendored
@@ -24,7 +24,7 @@ jobs:
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 8
|
||||
java-version: 11
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v3 # Use a released version to avoid breakages
|
||||
- name: Run integration tests
|
||||
|
||||
28
.github/workflows/ci-integ-test.yml
vendored
28
.github/workflows/ci-integ-test.yml
vendored
@@ -53,14 +53,6 @@ jobs:
|
||||
if: ${{ needs.determine-suite.outputs.suite != 'full' }}
|
||||
uses: ./.github/actions/build-dist
|
||||
|
||||
action-inputs:
|
||||
needs: [determine-suite, build-distribution]
|
||||
uses: ./.github/workflows/integ-test-action-inputs.yml
|
||||
with:
|
||||
runner-os: '${{ needs.determine-suite.outputs.runner-os }}'
|
||||
cache-key-prefix: '${{ needs.determine-suite.outputs.cache-key-prefix }}-'
|
||||
skip-dist: ${{ needs.determine-suite.outputs.suite == 'full' }}
|
||||
|
||||
build-scan-publish:
|
||||
needs: [determine-suite, build-distribution]
|
||||
uses: ./.github/workflows/integ-test-build-scan-publish.yml
|
||||
@@ -74,7 +66,7 @@ jobs:
|
||||
uses: ./.github/workflows/integ-test-cache-cleanup.yml
|
||||
with:
|
||||
runner-os: '${{ needs.determine-suite.outputs.runner-os }}'
|
||||
cache-key-prefix: '${{github.run_number}}-' # Requires a fresh cache entry each run
|
||||
cache-key-prefix: '${{ needs.determine-suite.outputs.suite}}-${{github.run_number}}-' # Requires a fresh cache entry each run
|
||||
skip-dist: ${{ needs.determine-suite.outputs.suite == 'full' }}
|
||||
|
||||
caching-config:
|
||||
@@ -118,22 +110,6 @@ jobs:
|
||||
cache-key-prefix: '${{ needs.determine-suite.outputs.cache-key-prefix }}-'
|
||||
skip-dist: ${{ needs.determine-suite.outputs.suite == 'full' }}
|
||||
|
||||
execution-with-caching:
|
||||
needs: [determine-suite, build-distribution]
|
||||
uses: ./.github/workflows/integ-test-execution-with-caching.yml
|
||||
with:
|
||||
runner-os: '${{ needs.determine-suite.outputs.runner-os }}'
|
||||
cache-key-prefix: '${{ needs.determine-suite.outputs.cache-key-prefix }}-'
|
||||
skip-dist: ${{ needs.determine-suite.outputs.suite == 'full' }}
|
||||
|
||||
execution:
|
||||
needs: [determine-suite, build-distribution]
|
||||
uses: ./.github/workflows/integ-test-execution.yml
|
||||
with:
|
||||
runner-os: '${{ needs.determine-suite.outputs.runner-os }}'
|
||||
cache-key-prefix: '${{ needs.determine-suite.outputs.cache-key-prefix }}-'
|
||||
skip-dist: ${{ needs.determine-suite.outputs.suite == 'full' }}
|
||||
|
||||
develocity-injection:
|
||||
if: ${{ ! github.event.pull_request.head.repo.fork }}
|
||||
needs: [determine-suite, build-distribution]
|
||||
@@ -143,7 +119,7 @@ jobs:
|
||||
cache-key-prefix: '${{ needs.determine-suite.outputs.cache-key-prefix }}-'
|
||||
skip-dist: ${{ needs.determine-suite.outputs.suite == 'full' }}
|
||||
secrets:
|
||||
DEVELOCITY_ACCESS_KEY: ${{ secrets.GE_SOLUTIONS_ACCESS_TOKEN }}
|
||||
DEVELOCITY_ACCESS_KEY: ${{ secrets.DV_SOLUTIONS_ACCESS_KEY }}
|
||||
|
||||
provision-gradle-versions:
|
||||
needs: [determine-suite, build-distribution]
|
||||
|
||||
62
.github/workflows/demo-failure-cases.yml
vendored
62
.github/workflows/demo-failure-cases.yml
vendored
@@ -1,62 +0,0 @@
|
||||
name: demo-failure-cases
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-distribution:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v4
|
||||
- name: Build and upload distribution
|
||||
uses: ./.github/actions/build-dist
|
||||
|
||||
failing-build:
|
||||
needs: build-distribution
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v4
|
||||
- name: Initialize integ-test
|
||||
uses: ./.github/actions/init-integ-test
|
||||
|
||||
- name: Test build failure
|
||||
uses: ./setup-gradle
|
||||
continue-on-error: true
|
||||
with:
|
||||
build-root-directory: .github/workflow-samples/kotlin-dsl
|
||||
arguments: not-a-valid-task
|
||||
|
||||
wrapper-missing:
|
||||
needs: build-distribution
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v4
|
||||
- name: Initialize integ-test
|
||||
uses: ./.github/actions/init-integ-test
|
||||
|
||||
- name: Test wrapper missing
|
||||
uses: ./setup-gradle
|
||||
continue-on-error: true
|
||||
with:
|
||||
build-root-directory: .github/workflow-samples/no-wrapper
|
||||
arguments: help
|
||||
|
||||
bad-configuration:
|
||||
needs: build-distribution
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v4
|
||||
- name: Initialize integ-test
|
||||
uses: ./.github/actions/init-integ-test
|
||||
|
||||
- name: Test bad config value
|
||||
uses: ./setup-gradle
|
||||
continue-on-error: true
|
||||
with:
|
||||
build-root-directory: .github/workflow-samples/no-wrapper
|
||||
arguments: help
|
||||
cache-disabled: yes
|
||||
3
.github/workflows/demo-job-summary.yml
vendored
3
.github/workflows/demo-job-summary.yml
vendored
@@ -23,6 +23,9 @@ jobs:
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: ./setup-gradle
|
||||
with:
|
||||
cache-read-only: false
|
||||
cache-cleanup: 'on-success'
|
||||
- name: Build kotlin-dsl project
|
||||
working-directory: .github/workflow-samples/kotlin-dsl
|
||||
run: ./gradlew assemble
|
||||
|
||||
42
.github/workflows/integ-test-action-inputs.yml
vendored
42
.github/workflows/integ-test-action-inputs.yml
vendored
@@ -1,42 +0,0 @@
|
||||
name: Test action inputs
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
cache-key-prefix:
|
||||
type: string
|
||||
runner-os:
|
||||
type: string
|
||||
default: '["ubuntu-latest", "windows-latest", "macos-latest"]'
|
||||
skip-dist:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
env:
|
||||
SKIP_DIST: ${{ inputs.skip-dist }}
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: action-inputs-${{ inputs.cache-key-prefix }}
|
||||
|
||||
jobs:
|
||||
action-inputs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: ${{fromJSON(inputs.runner-os)}}
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v4
|
||||
- name: Initialize integ-test
|
||||
uses: ./.github/actions/init-integ-test
|
||||
|
||||
- name: Invoke with multi-line arguments
|
||||
uses: ./setup-gradle
|
||||
with:
|
||||
build-root-directory: .github/workflow-samples/groovy-dsl
|
||||
arguments: |
|
||||
--configuration-cache
|
||||
--build-cache
|
||||
-DsystemProperty=FOO
|
||||
-PgradleProperty=BAR
|
||||
test
|
||||
jar
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 8
|
||||
java-version: 11
|
||||
- name: Setup Gradle
|
||||
id: setup-gradle
|
||||
uses: ./setup-gradle
|
||||
|
||||
19
.github/workflows/integ-test-cache-cleanup.yml
vendored
19
.github/workflows/integ-test-cache-cleanup.yml
vendored
@@ -35,7 +35,7 @@ jobs:
|
||||
cache-read-only: false # For testing, allow writing cache entries on non-default branches
|
||||
- name: Build with 3.1
|
||||
working-directory: sources/test/jest/resources/cache-cleanup
|
||||
run: gradle --no-daemon --build-cache -Dcommons_math3_version="3.1" build
|
||||
run: ./gradlew --no-daemon --build-cache -Dcommons_math3_version="3.1" build
|
||||
|
||||
# Second build will use the cache from the first build, but cleanup should remove unused artifacts
|
||||
assemble-build:
|
||||
@@ -55,10 +55,10 @@ jobs:
|
||||
uses: ./setup-gradle
|
||||
with:
|
||||
cache-read-only: false
|
||||
gradle-home-cache-cleanup: true
|
||||
cache-cleanup: 'on-success'
|
||||
- name: Build with 3.1.1
|
||||
working-directory: sources/test/jest/resources/cache-cleanup
|
||||
run: gradle --no-daemon --build-cache -Dcommons_math3_version="3.1.1" build
|
||||
run: ./gradlew --no-daemon --build-cache -Dcommons_math3_version="3.1.1" build
|
||||
|
||||
check-clean-cache:
|
||||
needs: assemble-build
|
||||
@@ -78,15 +78,22 @@ jobs:
|
||||
with:
|
||||
cache-read-only: true
|
||||
- name: Report Gradle User Home
|
||||
run: du -hc ~/.gradle/caches/modules-2
|
||||
shell: bash
|
||||
run: |
|
||||
du -hc $GRADLE_USER_HOME/caches/modules-2
|
||||
du -hc $GRADLE_USER_HOME/wrapper/dists
|
||||
- name: Verify cleaned cache
|
||||
shell: bash
|
||||
run: |
|
||||
if [ ! -e ~/.gradle/caches/modules-2/files-2.1/org.apache.commons/commons-math3/3.1.1 ]; then
|
||||
if [ ! -e $GRADLE_USER_HOME/caches/modules-2/files-2.1/org.apache.commons/commons-math3/3.1.1 ]; then
|
||||
echo "::error ::Should find commons-math3 3.1.1 in cache"
|
||||
exit 1
|
||||
fi
|
||||
if [ -e ~/.gradle/caches/modules-2/files-2.1/org.apache.commons/commons-math3/3.1 ]; then
|
||||
if [ -e $GRADLE_USER_HOME/caches/modules-2/files-2.1/org.apache.commons/commons-math3/3.1 ]; then
|
||||
echo "::error ::Should NOT find commons-math3 3.1 in cache"
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -e $GRADLE_USER_HOME/wrapper/dists/gradle-8.0.2-bin ]; then
|
||||
echo "::error ::Should find gradle-8.0.2 in wrapper/dists"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -18,9 +18,10 @@ permissions:
|
||||
env:
|
||||
SKIP_DIST: ${{ inputs.skip-dist }}
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: dependency-graph-${{ inputs.cache-key-prefix }}
|
||||
GITHUB_DEPENDENCY_GRAPH_REF: 'refs/tags/v0.0.1' # Use a different ref to avoid updating the real dependency graph for the repository
|
||||
|
||||
jobs:
|
||||
groovy-generate:
|
||||
groovy-upload:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -41,7 +42,7 @@ jobs:
|
||||
working-directory: .github/workflow-samples/groovy-dsl
|
||||
|
||||
groovy-submit:
|
||||
needs: [groovy-generate]
|
||||
needs: [groovy-upload]
|
||||
runs-on: "ubuntu-latest"
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
@@ -53,6 +54,8 @@ jobs:
|
||||
uses: ./setup-gradle
|
||||
with:
|
||||
dependency-graph: download-and-submit
|
||||
env:
|
||||
DEPENDENCY_GRAPH_DOWNLOAD_ARTIFACT_NAME: groovy-upload
|
||||
|
||||
kotlin-generate-and-submit:
|
||||
strategy:
|
||||
|
||||
@@ -15,6 +15,7 @@ on:
|
||||
env:
|
||||
SKIP_DIST: ${{ inputs.skip-dist }}
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: dependency-submission-failures-${{ inputs.cache-key-prefix }}
|
||||
GITHUB_DEPENDENCY_GRAPH_REF: 'refs/tags/v0.0.1' # Use a different ref to avoid updating the real dependency graph for the repository
|
||||
|
||||
jobs:
|
||||
failing-build:
|
||||
|
||||
@@ -18,6 +18,7 @@ permissions:
|
||||
env:
|
||||
SKIP_DIST: ${{ inputs.skip-dist }}
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: dependency-submission-${{ inputs.cache-key-prefix }}
|
||||
GITHUB_DEPENDENCY_GRAPH_REF: 'refs/tags/v0.0.1' # Use a different ref to avoid updating the real dependency graph for the repository
|
||||
|
||||
jobs:
|
||||
groovy-generate-and-upload:
|
||||
@@ -79,6 +80,8 @@ jobs:
|
||||
uses: ./dependency-submission
|
||||
with:
|
||||
dependency-graph: download-and-submit
|
||||
env:
|
||||
DEPENDENCY_GRAPH_DOWNLOAD_ARTIFACT_NAME: groovy-generate-and-upload-${{ matrix.os }}
|
||||
|
||||
kotlin-generate-and-submit:
|
||||
strategy:
|
||||
@@ -223,15 +226,9 @@ jobs:
|
||||
with:
|
||||
gradle-version: ${{ matrix.gradle }}
|
||||
build-root-directory: .github/workflow-samples/no-wrapper${{ matrix.build-root-suffix }}
|
||||
env:
|
||||
GITHUB_DEPENDENCY_GRAPH_REF: 'refs/tags/v0.0.1' # Use a different ref to avoid updating the real dependency graph for the repository
|
||||
|
||||
after-setup-gradle:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: ${{fromJSON(inputs.runner-os)}}
|
||||
runs-on: ${{ matrix.os }}
|
||||
with-setup-gradle:
|
||||
runs-on: ubuntu-latest # Test is not compatible with Windows
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v4
|
||||
@@ -245,6 +242,59 @@ jobs:
|
||||
uses: ./dependency-submission
|
||||
with:
|
||||
build-root-directory: .github/workflow-samples/groovy-dsl
|
||||
- name: Check and delete generated dependency graph
|
||||
shell: bash
|
||||
run: |
|
||||
if [ ! -e "${{ steps.dependency-submission.outputs.dependency-graph-file }}" ]; then
|
||||
echo "Did not find generated dependency graph files"
|
||||
exit 1
|
||||
fi
|
||||
rm ${{ steps.dependency-submission.outputs.dependency-graph-file }}*
|
||||
- name: Run Gradle build
|
||||
run: ./gradlew build
|
||||
working-directory: .github/workflow-samples/groovy-dsl
|
||||
- name: Check no dependency graph is generated
|
||||
shell: bash
|
||||
run: |
|
||||
if [ ! -z "$(ls -A dependency-graph-reports)" ]; then
|
||||
echo "Expected no dependency graph files to be generated"
|
||||
ls -l dependency-graph-reports
|
||||
exit 1
|
||||
fi
|
||||
|
||||
with-includes-and-excludes:
|
||||
runs-on: ubuntu-latest # Test is not compatible with Windows
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v4
|
||||
- name: Initialize integ-test
|
||||
uses: ./.github/actions/init-integ-test
|
||||
|
||||
- name: Generate and submit dependencies
|
||||
id: dependency-submission
|
||||
uses: ./dependency-submission
|
||||
with:
|
||||
build-root-directory: .github/workflow-samples/groovy-dsl
|
||||
dependency-graph-exclude-projects: excluded-project
|
||||
dependency-graph-include-projects: included-project
|
||||
dependency-graph-exclude-configurations: excluded-configuration
|
||||
dependency-graph-include-configurations: included-configuration
|
||||
- name: Check generated dependency graph and env vars
|
||||
shell: bash
|
||||
run: |
|
||||
if [ ! -e "${{ steps.dependency-submission.outputs.dependency-graph-file }}" ]; then
|
||||
echo "Did not find generated dependency graph file"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$DEPENDENCY_GRAPH_EXCLUDE_PROJECTS" != "excluded-project" ] ||
|
||||
[ "$DEPENDENCY_GRAPH_INCLUDE_PROJECTS" != "included-project" ] ||
|
||||
[ "$DEPENDENCY_GRAPH_EXCLUDE_CONFIGURATIONS" != "excluded-configuration" ] ||
|
||||
[ "$DEPENDENCY_GRAPH_INCLUDE_CONFIGURATIONS" != "included-configuration" ]; then
|
||||
echo "Did not set expected environment variables"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
custom-report-dir-submit:
|
||||
strategy:
|
||||
@@ -263,9 +313,8 @@ jobs:
|
||||
uses: ./dependency-submission
|
||||
with:
|
||||
dependency-graph: generate-and-submit
|
||||
dependency-graph-report-dir: '${{ github.workspace }}/custom/report-dir'
|
||||
build-root-directory: .github/workflow-samples/groovy-dsl
|
||||
env:
|
||||
DEPENDENCY_GRAPH_REPORT_DIR: '${{ github.workspace }}/custom/report-dir'
|
||||
- name: Check generated dependency graphs
|
||||
shell: bash
|
||||
run: |
|
||||
@@ -294,9 +343,8 @@ jobs:
|
||||
uses: ./dependency-submission
|
||||
with:
|
||||
dependency-graph: generate-and-upload
|
||||
dependency-graph-report-dir: '${{ github.workspace }}/custom/report-dir'
|
||||
build-root-directory: .github/workflow-samples/groovy-dsl
|
||||
env:
|
||||
DEPENDENCY_GRAPH_REPORT_DIR: '${{ github.workspace }}/custom/report-dir'
|
||||
|
||||
custom-report-dir-download-and-submit:
|
||||
needs: custom-report-dir-upload
|
||||
@@ -311,9 +359,11 @@ jobs:
|
||||
uses: ./dependency-submission
|
||||
with:
|
||||
dependency-graph: download-and-submit
|
||||
dependency-graph-report-dir: '${{ github.workspace }}/custom/report-dir'
|
||||
build-root-directory: .github/workflow-samples/groovy-dsl
|
||||
env:
|
||||
DEPENDENCY_GRAPH_REPORT_DIR: '${{ github.workspace }}/custom/report-dir'
|
||||
DEPENDENCY_GRAPH_DOWNLOAD_ARTIFACT_NAME: custom-report-dir-upload # For testing, to avoid downloading artifacts from other worklfows
|
||||
|
||||
- name: Check downloaded dependency graph
|
||||
shell: bash
|
||||
run: |
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
name: Test execution with caching
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
cache-key-prefix:
|
||||
type: string
|
||||
runner-os:
|
||||
type: string
|
||||
default: '["ubuntu-latest", "windows-latest", "macos-latest"]'
|
||||
skip-dist:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
env:
|
||||
SKIP_DIST: ${{ inputs.skip-dist }}
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: execution-with-caching-${{ inputs.cache-key-prefix }}
|
||||
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
||||
|
||||
jobs:
|
||||
seed-build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: ${{fromJSON(inputs.runner-os)}}
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v4
|
||||
- name: Initialize integ-test
|
||||
uses: ./.github/actions/init-integ-test
|
||||
|
||||
- name: Execute Gradle build
|
||||
uses: ./setup-gradle
|
||||
with:
|
||||
cache-read-only: false # For testing, allow writing cache entries on non-default branches
|
||||
build-root-directory: .github/workflow-samples/groovy-dsl
|
||||
arguments: test
|
||||
|
||||
# Test that the gradle-user-home is restored
|
||||
verify-build:
|
||||
needs: seed-build
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: ${{fromJSON(inputs.runner-os)}}
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v4
|
||||
- name: Initialize integ-test
|
||||
uses: ./.github/actions/init-integ-test
|
||||
|
||||
- name: Execute Gradle build
|
||||
uses: ./setup-gradle
|
||||
with:
|
||||
cache-read-only: true
|
||||
build-root-directory: .github/workflow-samples/groovy-dsl
|
||||
arguments: test --offline -DverifyCachedBuild=true
|
||||
|
||||
97
.github/workflows/integ-test-execution.yml
vendored
97
.github/workflows/integ-test-execution.yml
vendored
@@ -1,97 +0,0 @@
|
||||
name: Test execution
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
cache-key-prefix:
|
||||
type: string
|
||||
runner-os:
|
||||
type: string
|
||||
default: '["ubuntu-latest", "windows-latest", "macos-latest"]'
|
||||
skip-dist:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
env:
|
||||
SKIP_DIST: ${{ inputs.skip-dist }}
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: execution-${{ inputs.cache-key-prefix }}
|
||||
|
||||
jobs:
|
||||
# Tests for executing with different Gradle versions.
|
||||
# Each build verifies that it is executed with the expected Gradle version.
|
||||
gradle-execution:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: ${{fromJSON(inputs.runner-os)}}
|
||||
include:
|
||||
- os: windows-latest
|
||||
script-suffix: '.bat'
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v4
|
||||
- name: Initialize integ-test
|
||||
uses: ./.github/actions/init-integ-test
|
||||
|
||||
- name: Test use defined Gradle version
|
||||
uses: ./setup-gradle
|
||||
with:
|
||||
cache-read-only: false # For testing, allow writing cache entries on non-default branches
|
||||
gradle-version: 6.9
|
||||
build-root-directory: .github/workflow-samples/no-wrapper
|
||||
arguments: help -DgradleVersionCheck=6.9
|
||||
- name: Test use Gradle version alias
|
||||
uses: ./setup-gradle
|
||||
with:
|
||||
gradle-version: release-candidate
|
||||
build-root-directory: .github/workflow-samples/no-wrapper
|
||||
arguments: help
|
||||
- name: Test with non-executable wrapper
|
||||
uses: ./setup-gradle
|
||||
with:
|
||||
gradle-version: wrapper
|
||||
build-root-directory: .github/workflow-samples/non-executable-wrapper
|
||||
arguments: help
|
||||
|
||||
gradle-versions:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
gradle: [7.5.1, 6.9.2, 5.6.4, 4.10.3, 3.5.1]
|
||||
os: ${{fromJSON(inputs.runner-os)}}
|
||||
include:
|
||||
- gradle: 5.6.4
|
||||
build-root-suffix: -gradle-5
|
||||
- gradle: 4.10.3
|
||||
build-root-suffix: -gradle-4
|
||||
- gradle: 3.5.1
|
||||
build-root-suffix: -gradle-4
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v4
|
||||
- name: Initialize integ-test
|
||||
uses: ./.github/actions/init-integ-test
|
||||
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 8
|
||||
- name: Run Gradle build
|
||||
uses: ./setup-gradle
|
||||
id: gradle
|
||||
with:
|
||||
cache-read-only: false # For testing, allow writing cache entries on non-default branches
|
||||
gradle-version: ${{matrix.gradle}}
|
||||
build-root-directory: .github/workflow-samples/no-wrapper${{ matrix.build-root-suffix }}
|
||||
arguments: help -DgradleVersionCheck=${{matrix.gradle}}
|
||||
- name: Check Build Scan url
|
||||
if: ${{ !steps.gradle.outputs.build-scan-url }}
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
core.setFailed('No Build Scan detected')
|
||||
|
||||
|
||||
147
.github/workflows/integ-test-inject-develocity.yml
vendored
147
.github/workflows/integ-test-inject-develocity.yml
vendored
@@ -26,14 +26,19 @@ jobs:
|
||||
DEVELOCITY_URL: https://ge.solutions-team.gradle.com
|
||||
DEVELOCITY_PLUGIN_VERSION: ${{ matrix.plugin-version }}
|
||||
DEVELOCITY_CCUD_PLUGIN_VERSION: '2.0'
|
||||
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }} # required to test against GE plugin 3.16.2
|
||||
DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
|
||||
${{matrix.accessKeyEnv}}: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
gradle: [current, 7.6.2, 6.9.4, 5.6.4]
|
||||
os: ${{fromJSON(inputs.runner-os)}}
|
||||
plugin-version: [3.16.2, 3.17.2]
|
||||
plugin-version: [3.16.2, 3.17.6]
|
||||
include:
|
||||
- plugin-version: 3.16.2
|
||||
accessKeyEnv: GRADLE_ENTERPRISE_ACCESS_KEY
|
||||
- plugin-version: 3.17.6
|
||||
accessKeyEnv: DEVELOCITY_ACCESS_KEY
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
@@ -45,7 +50,7 @@ jobs:
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 8
|
||||
java-version: 11
|
||||
- name: Setup Gradle
|
||||
id: setup-gradle
|
||||
uses: ./setup-gradle
|
||||
@@ -61,4 +66,136 @@ jobs:
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
core.setFailed('No Build Scan detected')
|
||||
core.setFailed('No Build Scan detected')
|
||||
- name: Check short lived token (DEVELOCITY_ACCESS_KEY)
|
||||
run: "[ ${#DEVELOCITY_ACCESS_KEY} -gt 500 ] || (echo 'DEVELOCITY_ACCESS_KEY does not look like a short lived token'; exit 1)"
|
||||
- name: Check short lived token (GRADLE_ENTERPRISE_ACCESS_KEY)
|
||||
run: "[ ${#GRADLE_ENTERPRISE_ACCESS_KEY} -gt 500 ] || (echo 'GRADLE_ENTERPRISE_ACCESS_KEY does not look like a short lived token'; exit 1)"
|
||||
|
||||
inject-develocity-with-access-key:
|
||||
env:
|
||||
DEVELOCITY_INJECTION_ENABLED: true
|
||||
DEVELOCITY_URL: 'https://ge.solutions-team.gradle.com'
|
||||
DEVELOCITY_PLUGIN_VERSION: ${{ matrix.plugin-version }}
|
||||
DEVELOCITY_CCUD_PLUGIN_VERSION: '2.0'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
gradle: [current, 7.6.2, 6.9.4, 5.6.4]
|
||||
os: ${{fromJSON(inputs.runner-os)}}
|
||||
plugin-version: [3.16.2, 3.17.6]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v4
|
||||
- name: Initialize integ-test
|
||||
uses: ./.github/actions/init-integ-test
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 8
|
||||
- name: Setup Gradle
|
||||
id: setup-gradle
|
||||
uses: ./setup-gradle
|
||||
with:
|
||||
cache-read-only: false # For testing, allow writing cache entries on non-default branches
|
||||
gradle-version: ${{ matrix.gradle }}
|
||||
develocity-access-key: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
|
||||
develocity-token-expiry: 1
|
||||
- name: Run Gradle build
|
||||
id: gradle
|
||||
working-directory: .github/workflow-samples/no-ge
|
||||
run: gradle help
|
||||
- name: Check short lived token (DEVELOCITY_ACCESS_KEY)
|
||||
run: "[ ${#DEVELOCITY_ACCESS_KEY} -gt 500 ] || (echo 'DEVELOCITY_ACCESS_KEY does not look like a short lived token'; exit 1)"
|
||||
- name: Check short lived token (GRADLE_ENTERPRISE_ACCESS_KEY)
|
||||
run: "[ ${#GRADLE_ENTERPRISE_ACCESS_KEY} -gt 500 ] || (echo 'GRADLE_ENTERPRISE_ACCESS_KEY does not look like a short lived token'; exit 1)"
|
||||
- name: Check Build Scan url
|
||||
if: ${{ !steps.gradle.outputs.build-scan-url }}
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
core.setFailed('No Build Scan detected')
|
||||
|
||||
inject-develocity-short-lived-token-failed:
|
||||
env:
|
||||
DEVELOCITY_INJECTION_ENABLED: true
|
||||
DEVELOCITY_URL: 'https://localhost:3333/'
|
||||
DEVELOCITY_PLUGIN_VERSION: ${{ matrix.plugin-version }}
|
||||
DEVELOCITY_CCUD_PLUGIN_VERSION: '2.0'
|
||||
# Access key also set as an env var, we want to check it does not leak
|
||||
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
|
||||
DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
gradle: [ current, 7.6.2, 6.9.4, 5.6.4 ]
|
||||
os: ${{fromJSON(inputs.runner-os)}}
|
||||
plugin-version: [ 3.16.2, 3.17.6 ]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v4
|
||||
- name: Initialize integ-test
|
||||
uses: ./.github/actions/init-integ-test
|
||||
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 8
|
||||
- name: Setup Gradle
|
||||
id: setup-gradle
|
||||
uses: ./setup-gradle
|
||||
with:
|
||||
cache-read-only: false # For testing, allow writing cache entries on non-default branches
|
||||
develocity-access-key: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
|
||||
- name: Run Gradle build
|
||||
id: gradle
|
||||
working-directory: .github/workflow-samples/no-ge
|
||||
run: gradle help
|
||||
- name: Check access key is not blank (DEVELOCITY_ACCESS_KEY)
|
||||
run: "[ \"${DEVELOCITY_ACCESS_KEY}\" != \"\" ] || (echo 'using DEVELOCITY_ACCESS_KEY!'; exit 1)"
|
||||
- name: Check access key is not blank (GRADLE_ENTERPRISE_ACCESS_KEY)
|
||||
run: "[ \"${GRADLE_ENTERPRISE_ACCESS_KEY}\" != \"\" ] || (echo 'GRADLE_ENTERPRISE_ACCESS_KEY is still supported in v3!'; exit 1)"
|
||||
|
||||
inject-develocity-with-access-key-from-input-actions:
|
||||
env:
|
||||
DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
gradle: [ current, 7.6.2, 6.9.4, 5.6.4 ]
|
||||
os: ${{fromJSON(inputs.runner-os)}}
|
||||
plugin-version: [ 3.16.2, 3.17.6 ]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v4
|
||||
- name: Initialize integ-test
|
||||
uses: ./.github/actions/init-integ-test
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 8
|
||||
- name: Setup Gradle
|
||||
id: setup-gradle
|
||||
uses: ./setup-gradle
|
||||
with:
|
||||
cache-read-only: false # For testing, allow writing cache entries on non-default branches
|
||||
gradle-version: ${{ matrix.gradle }}
|
||||
develocity-injection-enabled: true
|
||||
develocity-url: 'https://ge.solutions-team.gradle.com'
|
||||
develocity-plugin-version: ${{ matrix.plugin-version }}
|
||||
- name: Run Gradle build
|
||||
id: gradle
|
||||
working-directory: .github/workflow-samples/no-ge
|
||||
run: gradle help
|
||||
- name: Check Build Scan url
|
||||
if: ${{ !steps.gradle.outputs.build-scan-url }}
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
core.setFailed('No Build Scan detected')
|
||||
|
||||
@@ -25,9 +25,6 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: ${{fromJSON(inputs.runner-os)}}
|
||||
include:
|
||||
- os: windows-latest
|
||||
script-suffix: '.bat'
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
@@ -62,6 +59,9 @@ jobs:
|
||||
uses: ./setup-gradle
|
||||
with:
|
||||
gradle-version: current
|
||||
- name: Test use current
|
||||
working-directory: .github/workflow-samples/no-wrapper
|
||||
run: gradle help
|
||||
- name: Check current version output parameter
|
||||
if: ${{ !startsWith(steps.gradle-current.outputs.gradle-version , '8.') }}
|
||||
uses: actions/github-script@v7
|
||||
@@ -73,15 +73,20 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
gradle: [7.3, 6.9, 5.6.4, 4.10.3, 3.5.1]
|
||||
gradle: [8.9, 8.8, 7.6.4, 6.9.4, 5.6.4, 4.10.3, 3.5.1] # 8.8 is the latest installed on windows runners
|
||||
os: ${{fromJSON(inputs.runner-os)}}
|
||||
include:
|
||||
- java-version: 11
|
||||
- gradle: 5.6.4
|
||||
build-root-suffix: -gradle-5
|
||||
- gradle: 4.10.3
|
||||
build-root-suffix: -gradle-4
|
||||
- gradle: 3.5.1
|
||||
build-root-suffix: -gradle-4
|
||||
java-version: 8
|
||||
exclude:
|
||||
- os: macos-latest # Java 8 is not supported on macos-latest, so we cannot test Gradle 3.5.1
|
||||
gradle: 3.5.1
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
@@ -93,7 +98,7 @@ jobs:
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 8
|
||||
java-version: ${{ matrix.java-version }}
|
||||
- name: Setup Gradle
|
||||
id: setup-gradle
|
||||
uses: ./setup-gradle
|
||||
|
||||
@@ -43,6 +43,7 @@ jobs:
|
||||
uses: ./setup-gradle
|
||||
with:
|
||||
cache-read-only: false # For testing, allow writing cache entries on non-default branches
|
||||
cache-write-only: true # Ensure we start with a clean cache entry
|
||||
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
|
||||
gradle-version: 8.6
|
||||
- name: Groovy build with configuration-cache enabled
|
||||
@@ -52,6 +53,7 @@ jobs:
|
||||
verify-build-groovy:
|
||||
env:
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_JOB: restore-cc-groovy
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_JOB_EXECUTION: ${{github.sha}}_1
|
||||
needs: seed-build-groovy
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -64,6 +66,47 @@ jobs:
|
||||
- name: Initialize integ-test
|
||||
uses: ./.github/actions/init-integ-test
|
||||
|
||||
- name: Setup Java to ensure consistency
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'liberica'
|
||||
java-version: 17
|
||||
- name: Setup Gradle
|
||||
uses: ./setup-gradle
|
||||
with:
|
||||
cache-read-only: false
|
||||
cache-cleanup: on-success
|
||||
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
|
||||
gradle-version: 8.6
|
||||
- name: Groovy build with configuration-cache enabled
|
||||
id: execute
|
||||
working-directory: .github/workflow-samples/groovy-dsl
|
||||
run: gradle test --configuration-cache
|
||||
- name: Verify configuration-cache hit
|
||||
shell: bash
|
||||
run: |
|
||||
if [ -e ".github/workflow-samples/groovy-dsl/task-configured.txt" ]; then
|
||||
echo "Configuration cache was not used - task was configured unexpectedly"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Ensure that cache-cleanup doesn't remove all necessary files
|
||||
verify-no-cache-cleanup-groovy:
|
||||
env:
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_JOB: restore-cc-groovy
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_JOB_EXECUTION: ${{github.sha}}_2
|
||||
needs: verify-build-groovy
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: ${{fromJSON(inputs.runner-os)}}
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v4
|
||||
- name: Initialize integ-test
|
||||
uses: ./.github/actions/init-integ-test
|
||||
|
||||
- name: Setup Java to ensure consistency
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
@@ -79,19 +122,19 @@ jobs:
|
||||
id: execute
|
||||
working-directory: .github/workflow-samples/groovy-dsl
|
||||
run: gradle test --configuration-cache
|
||||
- name: Check that configuration-cache was used
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs')
|
||||
if (fs.existsSync('.github/workflow-samples/groovy-dsl/task-configured.txt')) {
|
||||
core.setFailed('Configuration cache was not used - task was configured unexpectedly')
|
||||
}
|
||||
- name: Verify configuration-cache hit
|
||||
shell: bash
|
||||
run: |
|
||||
if [ -e ".github/workflow-samples/groovy-dsl/task-configured.txt" ]; then
|
||||
echo "Configuration cache was not used - task was configured unexpectedly"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check that the build can run when no extracted cache entries are restored
|
||||
gradle-user-home-not-fully-restored:
|
||||
env:
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_JOB: restore-cc-groovy
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_JOB_EXECUTION: ${{github.sha}}_x
|
||||
needs: seed-build-groovy
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -144,6 +187,7 @@ jobs:
|
||||
uses: ./setup-gradle
|
||||
with:
|
||||
cache-read-only: false # For testing, allow writing cache entries on non-default branches
|
||||
cache-write-only: true # Ensure we start with a clean cache entry
|
||||
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
|
||||
gradle-version: 8.6
|
||||
- name: Execute 'help' with configuration-cache enabled
|
||||
@@ -152,7 +196,8 @@ jobs:
|
||||
|
||||
modify-build-kotlin:
|
||||
env:
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_JOB: restore-cc-kotlin-modified
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_JOB: restore-cc-kotlin
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_JOB_EXECUTION: ${{github.sha}}_1
|
||||
needs: seed-build-kotlin
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -183,7 +228,8 @@ jobs:
|
||||
# Test restore configuration-cache from the third build invocation
|
||||
verify-build-kotlin:
|
||||
env:
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_JOB: restore-cc-kotlin-modified
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_JOB: restore-cc-kotlin
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_JOB_EXECUTION: ${{github.sha}}_2
|
||||
needs: modify-build-kotlin
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -211,12 +257,10 @@ jobs:
|
||||
id: execute
|
||||
working-directory: .github/workflow-samples/kotlin-dsl
|
||||
run: gradle test --configuration-cache
|
||||
- name: Check that configuration-cache was used
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs')
|
||||
if (fs.existsSync('.github/workflow-samples/kotlin-dsl/task-configured.txt')) {
|
||||
core.setFailed('Configuration cache was not used - task was configured unexpectedly')
|
||||
}
|
||||
|
||||
- name: Verify configuration-cache hit
|
||||
shell: bash
|
||||
run: |
|
||||
if [ -e ".github/workflow-samples/kotlin-dsl/task-configured.txt" ]; then
|
||||
echo "Configuration cache was not used - task was configured unexpectedly"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -29,8 +29,8 @@ jobs:
|
||||
- name: Run wrapper-validation-action
|
||||
id: setup-gradle
|
||||
uses: ./setup-gradle
|
||||
with:
|
||||
validate-wrappers: true
|
||||
env:
|
||||
ALLOWED_GRADLE_WRAPPER_CHECKSUMS: ''
|
||||
continue-on-error: true
|
||||
|
||||
- name: Check failure
|
||||
|
||||
@@ -6,21 +6,6 @@ The `build` script in the project root provides a convenient way to perform many
|
||||
3. `./build init-scripts` will run the init-script integration tests
|
||||
4. `./build act <act-commands>` will run `act` after building local changes (see below)
|
||||
|
||||
## How to merge a Dependabot PR
|
||||
|
||||
The "distribution" for a GitHub Action is checked into the repository itself.
|
||||
In the case of these actions, the transpiled sources are committed to the `dist` directory.
|
||||
Any production dependencies are inlined into the distribution.
|
||||
So if a Dependabot PR updates a production dependency (or a dev dependency that changes the distribution, like the Typescript compiler),
|
||||
then a manual step is required to rebuild the dist and commit.
|
||||
|
||||
The simplest process to follow is:
|
||||
1. Checkout the dependabot branch locally eg: `git checkout dependabot/npm_and_yarn/actions/github-5.1.0`
|
||||
2. In the `sources` directory, run `npm install` to download NPM dependencies
|
||||
3. In the `sources` directory, run `npm run build` to regenerate the distribution
|
||||
4. Push the changes to the dependabot branch
|
||||
5. If/when the checks pass, you can merge the dependabot PR
|
||||
|
||||
## Using `act` to run integ-test workflows locally
|
||||
|
||||
It's possible to run GitHub Actions workflows locally with https://nektosact.com/.
|
||||
@@ -36,7 +21,6 @@ Example running a single job:
|
||||
`./build act -W .github/workflows/integ-test-caching-config.yml -j cache-disabled-pre-existing-gradle-home`
|
||||
|
||||
Known issues:
|
||||
- `integ-test-cache-cleanup.yml` fails because `gradle` is not installed on the runner. Should be fixed by #33.
|
||||
- `integ-test-detect-java-toolchains.yml` fails when running on a `linux/amd64` container, since the expected pre-installed JDKs are not present. Should be fixed by #89.
|
||||
- `act` is not yet compatible with `actions/upload-artifact@v4` (or related toolkit functions)
|
||||
- See https://github.com/nektos/act/pull/2224
|
||||
@@ -46,4 +30,4 @@ Tips:
|
||||
- Add the following lines to `~/.actrc`:
|
||||
- `--container-daemon-socket -` : Prevents "error while creating mount source path", and yes that's a solitary dash at the end
|
||||
- `--matrix os:ubuntu-latest` : Avoids a lot of logging about unsupported runners being skipped
|
||||
- Runners don't have `java` installed by default, so all workflows that run Gradle require a `setup-java` step.
|
||||
- Runners don't have `java` installed by default, so all workflows that run Gradle require a `setup-java` step.
|
||||
|
||||
12
build
12
build
@@ -5,7 +5,7 @@ cd sources
|
||||
case "$1" in
|
||||
all)
|
||||
npm clean-install
|
||||
nprm run all
|
||||
npm run all
|
||||
;;
|
||||
act)
|
||||
# Build and copy outputs to the dist directory
|
||||
@@ -16,14 +16,20 @@ case "$1" in
|
||||
# Run act
|
||||
$@
|
||||
# Revert the changes to the dist directory
|
||||
git co -- dist
|
||||
git checkout -- dist
|
||||
;;
|
||||
init-scripts)
|
||||
cd test/init-scripts
|
||||
./gradlew check
|
||||
;;
|
||||
dist)
|
||||
npm install
|
||||
npm run build
|
||||
cd ..
|
||||
cp -r sources/dist .
|
||||
;;
|
||||
*)
|
||||
npm install
|
||||
npm run build
|
||||
;;
|
||||
esac
|
||||
esac
|
||||
|
||||
@@ -15,13 +15,13 @@ inputs:
|
||||
|
||||
dependency-resolution-task:
|
||||
description: |
|
||||
Task(s) that should be executed in order to resolve all project dependencies.
|
||||
Task(s) that should be executed in order to resolve all project dependencies.
|
||||
By default, the built-in `:ForceDependencyResolutionPlugin_resolveAllDependencies` task is executed.
|
||||
required: false
|
||||
|
||||
additional-arguments:
|
||||
description: |
|
||||
Additional arguments to pass to Gradle when generating the dependency graph.
|
||||
Additional arguments to pass to Gradle when generating the dependency graph.
|
||||
For example, `--no-configuration-cache --stacktrace`.
|
||||
required: false
|
||||
|
||||
@@ -40,7 +40,7 @@ inputs:
|
||||
|
||||
cache-write-only:
|
||||
description: |
|
||||
When 'true', entries will not be restored from the cache but will be saved at the end of the Job.
|
||||
When 'true', entries will not be restored from the cache but will be saved at the end of the Job.
|
||||
Setting this to 'true' implies cache-read-only will be 'false'.
|
||||
required: false
|
||||
default: false
|
||||
@@ -52,11 +52,24 @@ inputs:
|
||||
|
||||
cache-encryption-key:
|
||||
description: |
|
||||
A base64 encoded AES key used to encrypt the configuration-cache data. The key is exported as 'GRADLE_ENCRYPTION_KEY' for later steps.
|
||||
A base64 encoded AES key used to encrypt the configuration-cache data. The key is exported as 'GRADLE_ENCRYPTION_KEY' for later steps.
|
||||
A suitable key can be generated with `openssl rand -base64 16`.
|
||||
Configuration-cache data will not be saved/restored without an encryption key being provided.
|
||||
required: false
|
||||
|
||||
cache-cleanup:
|
||||
description: |
|
||||
Specifies if the action should attempt to remove any stale/unused entries from the Gradle User Home prior to saving to the GitHub Actions cache.
|
||||
By default, no cleanup is performed. It can be configured to run every time, or only when all Gradle builds succeed for the Job.
|
||||
Valid values are 'never', 'on-success' and 'always'.
|
||||
required: false
|
||||
default: 'on-success'
|
||||
|
||||
gradle-home-cache-cleanup:
|
||||
description: When 'true', the action will attempt to remove any stale/unused entries from the Gradle User Home prior to saving to the GitHub Actions cache.
|
||||
required: false
|
||||
deprecation-message: This input has been superceded by the 'cache-cleanup' input parameter.
|
||||
|
||||
gradle-home-cache-includes:
|
||||
description: Paths within Gradle User Home to cache.
|
||||
required: false
|
||||
@@ -68,11 +81,6 @@ inputs:
|
||||
description: Paths within Gradle User Home to exclude from cache.
|
||||
required: false
|
||||
|
||||
gradle-home-cache-cleanup:
|
||||
description: When 'true', the action will attempt to remove any stale/unused entries from the Gradle User Home prior to saving to the GitHub Actions cache.
|
||||
required: false
|
||||
default: false
|
||||
|
||||
# Job summary configuration
|
||||
add-job-summary:
|
||||
description: Specifies when a Job Summary should be inluded in the action results. Valid values are 'never', 'always' (default), and 'on-failure'.
|
||||
@@ -92,18 +100,49 @@ inputs:
|
||||
'generate-and-submit' (default): Generates a dependency graph for the project and submits it in the same Job.
|
||||
'generate-and-upload': Generates a dependency graph for the project and saves it as a workflow artifact.
|
||||
'download-and-submit': Retrieves a previously saved dependency-graph and submits it to the repository.
|
||||
|
||||
|
||||
The `generate-and-upload` and `download-and-submit` options are designed to be used in an untrusted workflow scenario,
|
||||
where the workflow generating the dependency-graph cannot (or should not) be given the `contents: write` permissions
|
||||
required to submit via the Dependency Submission API.
|
||||
required: false
|
||||
default: 'generate-and-submit'
|
||||
|
||||
dependency-graph-report-dir:
|
||||
description: |
|
||||
Specifies where the dependency graph report will be generated.
|
||||
Paths can relative or absolute. Relative paths are resolved relative to the workspace directory.
|
||||
required: false
|
||||
default: 'dependency-graph-reports'
|
||||
|
||||
dependency-graph-continue-on-failure:
|
||||
description: When 'false' a failure to generate or submit a dependency graph will fail the Step or Job. When 'true' a warning will be emitted but no failure will result.
|
||||
required: false
|
||||
default: false
|
||||
|
||||
dependency-graph-exclude-projects:
|
||||
description: |
|
||||
Gradle projects that should be excluded from dependency graph (regular expression).
|
||||
When set, any matching project will be excluded.
|
||||
required: false
|
||||
|
||||
dependency-graph-include-projects:
|
||||
description: |
|
||||
Gradle projects that should be included in dependency graph (regular expression).
|
||||
When set, only matching projects will be included.
|
||||
required: false
|
||||
|
||||
dependency-graph-exclude-configurations:
|
||||
description: |
|
||||
Gradle configurations that should be included in dependency graph (regular expression).
|
||||
When set, anymatching configurations will be excluded.
|
||||
required: false
|
||||
|
||||
dependency-graph-include-configurations:
|
||||
description: |
|
||||
Gradle configurations that should be included in dependency graph (regular expression).
|
||||
When set, only matching configurations will be included.
|
||||
required: false
|
||||
|
||||
artifact-retention-days:
|
||||
description: Specifies the number of days to retain any artifacts generated by the action. If not set, the default retention settings for the repository will apply.
|
||||
required: false
|
||||
@@ -120,27 +159,35 @@ inputs:
|
||||
build-scan-terms-of-use-url:
|
||||
description: The URL to the Build Scan® terms of use. This input must be set to 'https://gradle.com/terms-of-service' or 'https://gradle.com/help/legal-terms-of-use'.
|
||||
required: false
|
||||
|
||||
|
||||
build-scan-terms-of-use-agree:
|
||||
description: Indicate that you agree to the Build Scan® terms of use. This input value must be "yes".
|
||||
required: false
|
||||
|
||||
develocity-access-key:
|
||||
description: Develocity access key. Should be set to a secret containing the Develocity Access key.
|
||||
required: false
|
||||
|
||||
develocity-token-expiry:
|
||||
description: The Develocity short-lived access tokens expiry in hours. Default is 2 hours.
|
||||
required: false
|
||||
|
||||
# Wrapper validation configuration
|
||||
validate-wrappers:
|
||||
description: |
|
||||
When 'true' the action will automatically validate all wrapper jars found in the repository.
|
||||
If the wrapper checksums are not valid, the action will fail.
|
||||
required: false
|
||||
default: false
|
||||
|
||||
allow-snapshot-wrappers:
|
||||
description: |
|
||||
When 'true', wrapper validation will include the checksums of snapshot wrapper jars.
|
||||
Use this if you are running with nightly or snapshot versions of the Gradle wrapper.
|
||||
required: false
|
||||
default: false
|
||||
|
||||
# DEPRECATED ACTION INPUTS
|
||||
build-scan-terms-of-service-url:
|
||||
description: The URL to the Build Scan® terms of use. This input must be set to 'https://gradle.com/terms-of-service'.
|
||||
required: false
|
||||
deprecation-message: The input has been renamed to align with the Develocity API. Use 'build-scan-terms-of-use-url' instead.
|
||||
|
||||
build-scan-terms-of-service-agree:
|
||||
description: Indicate that you agree to the Build Scan® terms of use. This input value must be "yes".
|
||||
required: false
|
||||
deprecation-message: The input has been renamed to align with the Develocity API. Use 'build-scan-terms-of-use-agree' instead.
|
||||
|
||||
generate-job-summary:
|
||||
description: When 'false', no Job Summary will be generated for the Job.
|
||||
required: false
|
||||
default: true
|
||||
deprecation-message: Superceded by the new 'add-job-summary' and 'add-job-summary-as-pr-comment' parameters.
|
||||
|
||||
# EXPERIMENTAL ACTION INPUTS
|
||||
# The following action properties allow fine-grained tweaking of the action caching behaviour.
|
||||
@@ -150,7 +197,7 @@ inputs:
|
||||
description: When 'true', the action will not attempt to restore the Gradle User Home entries from other Jobs.
|
||||
required: false
|
||||
default: false
|
||||
|
||||
|
||||
# INTERNAL ACTION INPUTS
|
||||
# These inputs should not be configured directly, and are only used to pass environmental information to the action
|
||||
workflow-job-context:
|
||||
|
||||
21142
dist/dependency-submission/main/index.js
vendored
21142
dist/dependency-submission/main/index.js
vendored
File diff suppressed because one or more lines are too long
2
dist/dependency-submission/main/index.js.map
vendored
2
dist/dependency-submission/main/index.js.map
vendored
File diff suppressed because one or more lines are too long
26724
dist/dependency-submission/post/index.js
vendored
26724
dist/dependency-submission/post/index.js
vendored
File diff suppressed because one or more lines are too long
2
dist/dependency-submission/post/index.js.map
vendored
2
dist/dependency-submission/post/index.js.map
vendored
File diff suppressed because one or more lines are too long
21189
dist/setup-gradle/main/index.js
vendored
21189
dist/setup-gradle/main/index.js
vendored
File diff suppressed because one or more lines are too long
2
dist/setup-gradle/main/index.js.map
vendored
2
dist/setup-gradle/main/index.js.map
vendored
File diff suppressed because one or more lines are too long
23915
dist/setup-gradle/post/index.js
vendored
23915
dist/setup-gradle/post/index.js
vendored
File diff suppressed because one or more lines are too long
2
dist/setup-gradle/post/index.js.map
vendored
2
dist/setup-gradle/post/index.js.map
vendored
File diff suppressed because one or more lines are too long
19983
dist/wrapper-validation/main/index.js
vendored
19983
dist/wrapper-validation/main/index.js
vendored
File diff suppressed because one or more lines are too long
2
dist/wrapper-validation/main/index.js.map
vendored
2
dist/wrapper-validation/main/index.js.map
vendored
File diff suppressed because one or more lines are too long
@@ -13,7 +13,7 @@ The generated dependency graph includes all of the dependencies in your build, a
|
||||
for vulnerable dependencies, as well as to populate the
|
||||
[Dependency Graph insights view](https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/exploring-the-dependencies-of-a-repository#viewing-the-dependency-graph).
|
||||
|
||||
If your confused by the behaviour you're seeing or have specific questions, please check out [the FAQ](dependency-submission-faq.md) before raising an issue.
|
||||
If you're confused by the behaviour you're seeing or have specific questions, please check out [the FAQ](dependency-submission-faq.md) before raising an issue.
|
||||
|
||||
## General usage
|
||||
|
||||
@@ -95,13 +95,20 @@ In some cases, the default action configuration will not be sufficient, and addi
|
||||
dependency-resolution-task: myDependencyResolutionTask
|
||||
|
||||
# Additional arguments that should be passed to execute Gradle
|
||||
additonal-arguments: --no-configuration-cache
|
||||
additional-arguments: --no-configuration-cache
|
||||
|
||||
# Enable configuration-cache reuse for this build.
|
||||
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
|
||||
|
||||
# Do not attempt to submit the dependency-graph. Save it as a workflow artifact.
|
||||
dependency-graph: generate-and-upload
|
||||
|
||||
# Specify the location where dependency graph files will be generated.
|
||||
dependency-graph-report-dir: custom-report-dir
|
||||
|
||||
# By default, failure to generate a dependency graph will cause the workflow to fail
|
||||
dependency-graph-continue-on-failure: true
|
||||
|
||||
```
|
||||
|
||||
See the [Action Metadata file](../dependency-submission/action.yml) for a more detailed description of each input parameter.
|
||||
@@ -235,26 +242,26 @@ contribute to the dependency graph.
|
||||
> These dependencies would be assigned to different scopes (eg development, runtime, testing) and the GitHub UI would make it easy to opt-in to security alerts for different dependency scopes.
|
||||
> However, this functionality does not yet exist.
|
||||
|
||||
### Excluding certain Gradle projects from the dependency graph
|
||||
### Selecting Gradle projects that will contribute to the dependency graph
|
||||
|
||||
If you do not want the dependency graph to include dependencies from every project in your build,
|
||||
you can easily exclude certain projects from the dependency extraction process.
|
||||
you can easily exclude or include certain projects from the dependency extraction process.
|
||||
|
||||
To restrict which Gradle subprojects contribute to the report, specify which projects to exclude via a regular expression.
|
||||
You can provide this value via the `DEPENDENCY_GRAPH_EXCLUDE_PROJECTS` environment variable or system property.
|
||||
To restrict which Gradle subprojects contribute to the report, specify which projects to exclude or include via a regular expression.
|
||||
You can use the `dependency-graph-exclude-projects` and `dependency-graph-include-projects` input parameters for this purpose.
|
||||
|
||||
Note that excluding a project in this way only removes dependencies that are _resolved_ as part of that project, and may
|
||||
not necessarily remove all dependencies _declared_ in that project. If another project depends on the excluded project
|
||||
then it may transitively resolve dependencies declared in the excluded project: these dependencies will still be included
|
||||
in the generated dependency graph.
|
||||
|
||||
### Excluding certain Gradle configurations from the dependency graph
|
||||
### Selecting Gradle configurations that will contribute to the dependency graph
|
||||
|
||||
Similarly to Gradle projects, it is possible to exclude a set of configuration instances from dependency graph generation,
|
||||
so that dependencies resolved by those configurations are not included.
|
||||
Similarly to Gradle projects, it is possible to exclude or include a set of dependency configurations from dependency graph generation,
|
||||
so that only dependencies resolved by the included configurations are reported.
|
||||
|
||||
To restrict which Gradle configurations contribute to the report, specify which configurations to exclude via a regular expression.
|
||||
You can provide this value via the `DEPENDENCY_GRAPH_EXCLUDE_CONFIGURATIONS` environment variable or system property.
|
||||
To restrict which Gradle configurations contribute to the report, specify which configurations to exclude or include via a regular expression.
|
||||
You can use the `dependency-graph-exclude-configurations` and `dependency-graph-include-configurations` input parameters for this purpose.
|
||||
|
||||
Note that configuration exclusion applies to the configuration in which the dependency is _resolved_ which is not necessarily
|
||||
the configuration where the dependency is _declared_. For example if you decare a dependency as `implementation` in
|
||||
@@ -262,24 +269,18 @@ a Java project, that dependency will be resolved in `compileClasspath`, `runtime
|
||||
|
||||
### Example of project and configuration filtering
|
||||
|
||||
For example, if you want to exclude dependencies in the `buildSrc` project, and exclude dependencies from the `testCompileClasspath` and `testRuntimeClasspath` configurations, you would use the following configuration:
|
||||
For example, if you want to exclude dependencies resolved by the `buildSrc` project, and exclude dependencies from the `testCompileClasspath` and `testRuntimeClasspath` configurations, you would use the following configuration:
|
||||
|
||||
```yaml
|
||||
- name: Generate and submit dependency graph
|
||||
uses: gradle/actions/dependency-submission@v3
|
||||
env:
|
||||
with:
|
||||
# Exclude all dependencies that originate solely in the 'buildSrc' project
|
||||
DEPENDENCY_GRAPH_EXCLUDE_PROJECTS: ':buildSrc'
|
||||
dependency-graph-exclude-projets: ':buildSrc'
|
||||
# Exclude dependencies that are only resolved in test classpaths
|
||||
DEPENDENCY_GRAPH_EXCLUDE_CONFIGURATIONS: '.*[Tt]est(Compile|Runtime)Classpath'
|
||||
dependency-graph-exclude-configurations: '.*[Tt]est(Compile|Runtime)Classpath'
|
||||
```
|
||||
|
||||
### Other filtering options
|
||||
|
||||
The [GitHub Dependency Graph Gradle Plugin](https://plugins.gradle.org/plugin/org.gradle.github-dependency-graph-gradle-plugin)
|
||||
has other filtering options that may be useful.
|
||||
See [the docs](https://github.com/gradle/github-dependency-graph-gradle-plugin?tab=readme-ov-file#filtering-which-gradle-configurations-contribute-to-the-dependency-graph) for details.
|
||||
|
||||
# Advance usage scenarios
|
||||
|
||||
## Using a custom plugin repository
|
||||
@@ -367,6 +368,7 @@ on:
|
||||
types: [completed]
|
||||
|
||||
permissions:
|
||||
actions: read
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
@@ -417,3 +419,10 @@ Gradle versions `5.2.1`, `5.6.4`, `6.0.1`, `6.9.4`, `7.1.1` and `7.6.3`, as well
|
||||
A known exception to this is that Gradle `7.0`, `7.0.1` and `7.0.2` are not supported.
|
||||
|
||||
See [here](https://github.com/gradle/github-dependency-graph-gradle-plugin?tab=readme-ov-file#gradle-compatibility) for complete compatibility information.
|
||||
|
||||
# Additional references
|
||||
|
||||
- Dependency Submission Demo repository: https://github.com/gradle/github-dependency-submission-demo
|
||||
- GitHub Dependency Graph Gradle Plugin: https://github.com/gradle/github-dependency-graph-gradle-plugin
|
||||
- Webinar - Gradle at Scale with GitHub and GitHub Actions at Allegro: https://www.youtube.com/watch?v=gV94I28FPos
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# Deprecation upgrade guide
|
||||
|
||||
As these actions evolve, certain inputs, behaviour and usages are deprecated for removal.
|
||||
As these actions evolve, certain inputs, behaviour and usages are deprecated for removal.
|
||||
Deprecated functionality will be fully supported during the current major release, and will be
|
||||
removed in the next major release.
|
||||
Users will receive a deprecation warning when they rely on deprecated functionality,
|
||||
removed in the next major release.
|
||||
Users will receive a deprecation warning when they rely on deprecated functionality,
|
||||
prompting them to update their workflows.
|
||||
|
||||
## The action `gradle/gradle-build-action` has been replaced by `gradle/actions/setup-gradle`
|
||||
@@ -25,10 +25,10 @@ with
|
||||
|
||||
## The action `gradle/wrapper-validation-action` has been replaced by `gradle/actions/wrapper-validation`
|
||||
|
||||
To facilitate ongoing development, the `wrapper-validation-action` action implementation has been merged into
|
||||
To facilitate ongoing development, the `wrapper-validation-action` action implementation has been merged into
|
||||
the https://github.com/gradle/actions repository, and the `gradle/wrapper-validation-action` has been replaced by the `gradle/actions/wrapper-validation` action.
|
||||
|
||||
As of `v3.x`, the `gradle/wrapper-validation-action` and `gradle/actions/wrappper-validation` actions are
|
||||
As of `v3.x`, the `gradle/wrapper-validation-action` and `gradle/actions/wrappper-validation` actions are
|
||||
functionally identical, and are released with the same versions.
|
||||
|
||||
In a future major version (likely `v4.x`) we will stop releasing new versions of `gradle/wrapper-validation-action`:
|
||||
@@ -101,7 +101,7 @@ The exact syntax depends on whether or not your project is configured with the [
|
||||
- name: Setup Gradle for a non-wrapper project
|
||||
uses: gradle/actions/setup-gradle@v3
|
||||
with:
|
||||
gradle-version: 8.7
|
||||
gradle-version: 8.9
|
||||
|
||||
- name: Assemble the project
|
||||
run: gradle assemble
|
||||
@@ -143,3 +143,20 @@ to this:
|
||||
build-scan-terms-of-use-agree: "yes"
|
||||
```
|
||||
These deprecated build-scan parameters are scheduled to be removed in `setup-gradle@v4` and `dependency-submission@v4`.
|
||||
|
||||
## The GRADLE_ENTERPRISE_ACCESS_KEY env var is deprecated
|
||||
Gradle Enterprise has been renamed to Develocity starting from Gradle plugin 3.17 and Develocity server 2024.1.
|
||||
In v4 release of the action, it will require setting the access key with the `develocity-access-key` input and Develocity 2024.1 at least to generate short-lived tokens.
|
||||
If those requirements are not met, the `GRADLE_ENTERPRISE_ACCESS_KEY` env var will be cleared out and build scan publication or other authenticated Develocity operations won't be possible.
|
||||
|
||||
## The `gradle-home-cache-cleanup` input parameter has been replaced by `cache-cleanup`
|
||||
|
||||
In versions of the action prior to `v4`, the boolean `gradle-home-cache-cleanup` parameter allows users to opt-in
|
||||
to cache cleanup, removing unused files in Gradle User Home prior to saving to the cache.
|
||||
|
||||
With `v4`, cache-cleanup is enabled by default, and controlled by the `cache-cleanup` input parameter.
|
||||
|
||||
To remove this deprecation:
|
||||
- If you are using `gradle-home-cache-cleanup: true` in your workflow, you can remove this option as this is now enabled by default.
|
||||
- If you want cache-cleanup to run even when a Gradle build fails, then add the `cache-cleanup: always` input.
|
||||
- If cache-cleanup is causing problems with your workflow, you can disable it with `cache-cleanup: never`.
|
||||
|
||||
@@ -4,22 +4,22 @@ This GitHub Action can be used to configure Gradle for optimal execution on any
|
||||
|
||||
## Why use the `setup-gradle` action?
|
||||
|
||||
It is possible to directly invoke Gradle in your workflow, and the `actions/setup-java@v4` action provides a simple way to cache Gradle dependencies.
|
||||
It is possible to directly invoke Gradle in your workflow, and the `actions/setup-java@v4` action provides a simple way to cache Gradle dependencies.
|
||||
|
||||
However, the `setup-gradle` action offers a several advantages over this approach:
|
||||
|
||||
- Easily [configure your workflow to use a specific version of Gradle](#build-with-a-specific-gradle-version) using the `gradle-version` parameter. Gradle distributions are automatically downloaded and cached.
|
||||
- Easily [configure your workflow to use a specific version of Gradle](#build-with-a-specific-gradle-version) using the `gradle-version` parameter. Gradle distributions are automatically downloaded and cached.
|
||||
- More sophisticated and more efficient caching of Gradle User Home between invocations, compared to `setup-java` and most custom configurations using `actions/cache`. [More details below](#caching-build-state-between-jobs).
|
||||
- Detailed reporting of cache usage and cache configuration options allow you to [optimize the use of the GitHub actions cache](#optimizing-cache-effectiveness).
|
||||
- [Generate and Submit a GitHub Dependency Graph](#github-dependency-graph-support) for your project, enabling Dependabot security alerts.
|
||||
- [Automatic capture of Build Scan® links](#build-reporting) from the build, making them easier to locate in workflow runs.
|
||||
|
||||
The `setup-gradle` action is designed to provide these benefits with minimal configuration.
|
||||
The `setup-gradle` action is designed to provide these benefits with minimal configuration.
|
||||
These features work both when Gradle is executed via `setup-gradle` and for any Gradle execution in subsequent steps.
|
||||
|
||||
## General usage
|
||||
|
||||
The `setup-gradle` action works by configuring environment variables and by adding a set of Gradle init-scripts to the Gradle User Home. These will apply to all Gradle executions on the runner, no matter how Gradle is invoked.
|
||||
The `setup-gradle` action works by configuring environment variables and by adding a set of Gradle init-scripts to the Gradle User Home. These will apply to all Gradle executions on the runner, no matter how Gradle is invoked.
|
||||
This means that if you have an existing workflow that executes Gradle with a `run` step, you can add an initial "Setup Gradle" Step to benefit from caching, build-scan capture, and other features of this action.
|
||||
|
||||
The recommended way to execute any Gradle build is with the help of the [Gradle Wrapper](https://docs.gradle.org/current/userguide/gradle_wrapper.html), and the following examples assume that the Gradle Wrapper has been configured for the project. See [this example](#build-with-a-specific-gradle-version) if your project doesn't use the Gradle Wrapper.
|
||||
@@ -46,7 +46,7 @@ jobs:
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v3
|
||||
|
||||
|
||||
- name: Execute Gradle build
|
||||
run: ./gradlew build
|
||||
```
|
||||
@@ -126,7 +126,7 @@ cache-disabled: true
|
||||
### Using the cache read-only
|
||||
|
||||
By default, The `setup-gradle` 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.
|
||||
Jobs on other branches will read entries from the cache but will not write updated entries.
|
||||
See [Optimizing cache effectiveness](#select-which-branches-should-write-to-the-cache) for a more detailed explanation.
|
||||
|
||||
In some circumstances, it makes sense to change this default and configure a workflow Job to read existing cache entries but not to write changes back.
|
||||
@@ -153,12 +153,35 @@ In certain circumstances it may be desirable to start with a clean Gradle User H
|
||||
cache-write-only: true
|
||||
```
|
||||
|
||||
### Configuring cache cleanup
|
||||
|
||||
The Gradle User Home directory tends to grow over time. When you switch to a new Gradle wrapper version
|
||||
or upgrade a dependency version the old files are not automatically and immediately removed.
|
||||
While this can make sense in a local environment, in a GitHub Actions environment
|
||||
it can lead to ever-larger Gradle User Home cache entries being saved and restored.
|
||||
|
||||
To avoid this situation, the `setup-gradle` and `dependency-submission` actions will perform "cache-cleanup",
|
||||
purging any unused files from the Gradle User Home before saving it to the GitHub Actions cache.
|
||||
Cache cleanup will attempt to remove any files that are initially restored to the Gradle User Home directory
|
||||
but that are not used used by Gradle during the GitHub Actions Workflow.
|
||||
|
||||
If a Gradle build fails when running the Job, then it is possible that some required files and dependencies
|
||||
will not be touched during the Job. To prevent these files from being purged, the default behavior is for
|
||||
cache cleanup to run only when all Gradle builds in the Job are successful.
|
||||
|
||||
Gradle Home cache cleanup is enabled by default, and can be controlled by the `cache-cleanup` parameter as follows:
|
||||
- `cache-cleanup: always`: Always run cache cleanup, even when a Gradle build fails in the Job.
|
||||
- `cache-cleanup: on-success` (default): Run cache cleanup when the Job contains no failing Gradle builds.
|
||||
- `cache-cleanup: never`: Disable cache cleanup for the Job.
|
||||
|
||||
Cache cleanup will never run when the cache is configured as read-only or disabled.
|
||||
|
||||
### Overwriting an existing Gradle User Home
|
||||
|
||||
When the action detects that the Gradle User Home caches directory already exists (`~/.gradle/caches`), then by default it will not overwrite the existing content of this directory.
|
||||
When the action detects that the Gradle User Home caches directory already exists (`$GRADLE_USER_HOME/caches`), then by default it will not overwrite the existing content of this directory.
|
||||
This can occur when a prior action initializes this directory, or when using a self-hosted runner that retains this directory between uses.
|
||||
|
||||
In this case, the Job Summary will display a message like:
|
||||
In this case, the Job Summary will display a message like:
|
||||
> Caching for Gradle actions was disabled due to pre-existing Gradle User Home
|
||||
|
||||
If you want to override the default and have the caches of the `setup-gradle` action overwrite existing content in the Gradle User Home, you can set the `cache-overwrite-existing` parameter to `true`:
|
||||
@@ -198,13 +221,13 @@ jobs:
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
> The configuration cache cannot be saved or restored in workflows triggered by a pull requests from a repsitory fork.
|
||||
> The configuration cache cannot be saved or restored in workflows triggered by a pull requests from a repository fork.
|
||||
> This is because [GitHub secrets are not passed to workflows triggered by PRs from forks](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions#using-secrets-in-a-workflow).
|
||||
> This prevents a malicious PR from reading the configuration-cache data, which may encode secrets read by Gradle.
|
||||
|
||||
### Incompatibility with other caching mechanisms
|
||||
|
||||
When using `setup-gradle` we recommend that you avoid using other mechanisms to save and restore the Gradle User Home.
|
||||
When using `setup-gradle` we recommend that you avoid using other mechanisms to save and restore the Gradle User Home.
|
||||
|
||||
Specifically:
|
||||
- Avoid using `actions/cache` configured to cache the Gradle User Home, [as described in this example](https://github.com/actions/cache/blob/main/examples.md#java---gradle).
|
||||
@@ -218,7 +241,7 @@ Using either of these mechanisms may interfere with the caching provided by this
|
||||
|
||||
The GitHub Actions cache has some properties that present problems for efficient caching of the Gradle User Home.
|
||||
- Immutable entries: once a cache entry is written for a key, it cannot be overwritten or changed.
|
||||
- Branch scope: cache entries written for a Git branch are not visible from actions running against different branches. Entries written for the default branch are visible to all. https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#restrictions-for-accessing-a-cache
|
||||
- Branch scope: cache entries written for a Git branch are not visible from actions running against different branches or tags. Entries written for the default branch are visible to all. https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#restrictions-for-accessing-a-cache
|
||||
- Restore keys: if no exact match is found, a set of partial keys can be provided that will match by cache key prefix. https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#matching-a-cache-key
|
||||
|
||||
Each of these properties has influenced the design and implementation of the caching in `setup-gradle`, as described below.
|
||||
@@ -256,7 +279,7 @@ The Gradle User Home cache key is composed of:
|
||||
|
||||
Specifically, the cache key is: `${cache-protocol}-gradle|${runner-os}|${job-id}[${hash-of-job-matrix-and-workflow-name}]-${git-sha}`
|
||||
|
||||
As such, the cache key is likely to change on each subsequent run of GitHub actions.
|
||||
As such, the cache key is likely to change on each subsequent run of GitHub actions.
|
||||
This allows the most recent state to always be available in the GitHub actions cache.
|
||||
|
||||
### Finding a matching cache entry
|
||||
@@ -271,7 +294,7 @@ Due to branch scoping of cache entries, the above match will be first performed
|
||||
|
||||
After the Job is complete, the current Gradle User Home state will be collected and written as a new cache entry with the complete cache key. Old entries will be expunged from the GitHub Actions cache on a least recently used basis.
|
||||
|
||||
Note that while effective, this mechanism is not inherently efficient. It requires the entire Gradle User Home directory to be stored separately for each branch, for every OS+Job+Matrix combination. In addition, it writes a new cache entry on every GitHub Actions run.
|
||||
Note that while effective, this mechanism is not inherently efficient. It requires the entire Gradle User Home directory to be stored separately for each branch, for every OS+Job+Matrix combination. In addition, it writes a new cache entry on every GitHub Actions run.
|
||||
|
||||
This inefficiency is effectively mitigated by [Deduplication of Gradle User Home cache entries](#deduplication-of-gradle-user-home-cache-entries) and can be further optimized for a workflow using the techniques described in [Optimizing cache effectiveness](#optimizing-cache-effectiveness).
|
||||
|
||||
@@ -289,7 +312,7 @@ For example, this means that all jobs executing a particular version of the Grad
|
||||
|
||||
### Stopping the Gradle daemon
|
||||
|
||||
By default, the action will stop all running Gradle daemons in the post-action step, before saving the Gradle User Home state.
|
||||
By default, the action will stop all running Gradle daemons in the post-action step, before 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 disabled or the cache is in read-only mode, the daemon will not be stopped and will continue running after the job is completed.
|
||||
@@ -316,23 +339,23 @@ Some techniques can be used to avoid/mitigate this issue:
|
||||
|
||||
### Select which branches should write to the cache
|
||||
|
||||
GitHub cache entries are not shared between builds on different branches.
|
||||
Workflow runs can restore caches created in either the current branch or the default branch (usually main).
|
||||
GitHub cache entries are not shared between builds on different branches or tags.
|
||||
Workflow runs can _only_ restore caches created in either the same branch or the default branch (usually `main`).
|
||||
This means that each branch will have its own Gradle User Home cache scope, and will not benefit from cache entries written for other (non-default) branches.
|
||||
|
||||
By default, The `setup-gradle` action will only _write_ to the cache for builds run on the default (`master`/`main`) branch.
|
||||
Jobs running on other branches will only read from the cache. In most cases, this is the desired behavior.
|
||||
This is because Jobs running on other branches will benefit from the cached Gradle User Home from `main`,
|
||||
By default, The `setup-gradle` action will only _write_ to the cache for builds run on the default (`master`/`main`) branch.
|
||||
Jobs running on other branches will only read from the cache. In most cases, this is the desired behavior.
|
||||
This is because Jobs running on other branches will benefit from the cached Gradle User Home from `main`,
|
||||
without writing private cache entries which could lead to evicting these shared entries.
|
||||
|
||||
If you have other long-lived development branches that would benefit from writing to the cache,
|
||||
you can configure this by disabling the `cache-read-only` action parameter for these branches.
|
||||
If you have other long-lived development branches that would benefit from writing to the cache,
|
||||
you can configure this by disabling the `cache-read-only` action parameter for these branches.
|
||||
See [Using the cache read-only](#using-the-cache-read-only) for more details.
|
||||
|
||||
Note there are some cases where writing cache entries is typically unhelpful (these are disabled by default):
|
||||
- For `pull_request` triggered runs, the cache scope is limited to the merge ref (`refs/pull/.../merge`) and can only be restored by re-runs of the same pull request.
|
||||
- For `merge_group` triggered runs, the cache scope is limited to a temporary branch with a special prefix created to validate pull request changes, and won't be available on subsequent Merge Queue executions.
|
||||
|
||||
|
||||
### Exclude content from Gradle User Home cache
|
||||
|
||||
As well as any wrapper distributions, the action will attempt to save and restore the `caches` and `notifications` directories from Gradle User Home.
|
||||
@@ -353,30 +376,16 @@ gradle-home-cache-excludes: |
|
||||
caches/keyrings
|
||||
```
|
||||
|
||||
You can specify any number of fixed paths or patterns to include or exclude.
|
||||
You can specify any number of fixed paths or patterns to include or exclude.
|
||||
File pattern support is documented at https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions#patterns-to-match-file-paths.
|
||||
|
||||
### Remove unused files from Gradle User Home before saving to the cache
|
||||
|
||||
The Gradle User Home directory tends to grow over time. When you switch to a new Gradle wrapper version or upgrade a dependency version
|
||||
the old files are not automatically and immediately removed. While this can make sense in a local environment, in a GitHub Actions environment
|
||||
it can lead to ever-larger Gradle User Home cache entries being saved and restored.
|
||||
|
||||
To avoid this situation, The `setup-gradle` action supports the `gradle-home-cache-cleanup` parameter.
|
||||
When enabled, this feature will attempt to delete any files in the Gradle User Home that were not used by Gradle during the GitHub Actions Workflow, before saving the Gradle User Home to the GitHub Actions cache.
|
||||
|
||||
Gradle Home cache cleanup is considered experimental and is disabled by default. You can enable this feature for the action as follows:
|
||||
```yaml
|
||||
gradle-home-cache-cleanup: true
|
||||
```
|
||||
|
||||
### Disable local build-cache when remote build-cache is available
|
||||
|
||||
If you have a remote build-cache available for your build, then it is recommended to do the following:
|
||||
- Enable [remote build-cache push](https://docs.gradle.org/current/userguide/build_cache.html#sec:build_cache_configure_use_cases) for your GitHub Actions builds
|
||||
- Disable [local build-cache]() for your GitHub Actions build
|
||||
|
||||
As well as reducing the content that needs to be saved to the GitHub Actions cache,
|
||||
As well as reducing the content that needs to be saved to the GitHub Actions cache,
|
||||
this setup will ensure that your CI builds populate the remote cache and keep the cache entries fresh by reading these entries.
|
||||
Local builds can then benefit from the remote cache.
|
||||
|
||||
@@ -389,8 +398,8 @@ You can enable debug logging either by:
|
||||
|
||||
### Increased logging from Gradle builds
|
||||
|
||||
When debug logging is enabled, this action will cause all builds to run with the `--info` and `--stacktrace` options.
|
||||
This is done by inserting the relevant [Gradle properties](https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_configuration_properties)
|
||||
When debug logging is enabled, this action will cause all builds to run with the `--info` and `--stacktrace` options.
|
||||
This is done by inserting the relevant [Gradle properties](https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_configuration_properties)
|
||||
at the top of the `${GRADLE_USER_HOME}/gradle.properties` file.
|
||||
|
||||
If the additional Gradle logging produced is problematic, you may opt out of this behavior by setting these properties manually in your project `gradle.properties` file:
|
||||
@@ -403,7 +412,7 @@ org.gradle.logging.stacktrace=internal
|
||||
|
||||
### Cache debugging and analysis
|
||||
|
||||
A report of all cache entries restored and saved is printed to the Job Summary 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 insight into how much cache space is being used.
|
||||
|
||||
When debug logging is enabled, more detailed logging of cache operations is included in the GitHub actions log.
|
||||
@@ -461,18 +470,18 @@ Note that to add a Pull Request comment, the workflow must be configured with th
|
||||
As well as reporting all [Build Scan](https://gradle.com/build-scans/) links in the Job Summary,
|
||||
The `setup-gradle` action makes this link available as an output of any Step that executes Gradle.
|
||||
|
||||
The output name is `build-scan-url`. You can then use the build scan link in subsequent actions of your workflow.
|
||||
The output name is `build-scan-url`. You can then use the build scan link in subsequent actions of your workflow.
|
||||
|
||||
### Saving arbitrary build outputs
|
||||
|
||||
By default, a GitHub Actions workflow using `setup-gradle` will record the log output and any Build Scan
|
||||
By default, a GitHub Actions workflow using `setup-gradle` will record the log output and any Build Scan
|
||||
links for your build, but any output files generated by the build will not be saved.
|
||||
|
||||
To save selected files from your build execution, you can use the core [Upload-Artifact](https://github.com/actions/upload-artifact) action.
|
||||
For example:
|
||||
|
||||
```yaml
|
||||
jobs:
|
||||
jobs:
|
||||
gradle:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -506,14 +515,30 @@ Since Gradle applies init scripts in alphabetical order, one way to ensure this
|
||||
|
||||
## Gradle Wrapper validation
|
||||
|
||||
Instead of using the [wrapper-validation action](./wrapper-validation.md) separately, you can enable
|
||||
wrapper validation directly in your Setup Gradle step.
|
||||
By default, this action will perform the same wrapper validation as is performed by the dedicated
|
||||
[wrapper-validation action](./wrapper-validation.md).
|
||||
This means that invalid wrapper jars will be automatically detected when using `setup-gradle`.
|
||||
|
||||
If you do not want wrapper-validation to occur automatically, you can disable it:
|
||||
|
||||
```yaml
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v3
|
||||
with:
|
||||
validate-wrappers: false
|
||||
```
|
||||
|
||||
If your repository uses snapshot versions of the Gradle wrapper, such as nightly builds, then you'll need to
|
||||
explicitly allow snapshot wrappers in wrapper validation.
|
||||
These are not allowed by default.
|
||||
|
||||
|
||||
```yaml
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v3
|
||||
with:
|
||||
validate-wrappers: true
|
||||
allow-snapshot-wrappers: true
|
||||
```
|
||||
|
||||
If you need more advanced configuration, then you're advised to continue using a separate workflow step
|
||||
@@ -530,7 +555,7 @@ You can use the `setup-gradle` action on GitHub Enterprise Server, and benefit f
|
||||
## GitHub Dependency Graph support
|
||||
|
||||
> [!IMPORTANT]
|
||||
> The simplest (and recommended) way to generate a dependency graph is via a separate workflow
|
||||
> The simplest (and recommended) way to generate a dependency graph is via a separate workflow
|
||||
> using `gradle/actions/dependency-submission`. This action will attempt to detect all dependencies used by your build
|
||||
> without building and testing the project itself.
|
||||
>
|
||||
@@ -544,7 +569,7 @@ The dependency graph snapshot is generated via integration with the [GitHub Depe
|
||||
The generated dependency graph snapshot reports all of the dependencies that were resolved during a build execution, and is used by GitHub to generate [Dependabot Alerts](https://docs.github.com/en/code-security/dependabot/dependabot-alerts/about-dependabot-alerts) for vulnerable dependencies, as well as to populate the [Dependency Graph insights view](https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/exploring-the-dependencies-of-a-repository#viewing-the-dependency-graph).
|
||||
|
||||
### Basic usage
|
||||
|
||||
|
||||
You enable GitHub Dependency Graph support by setting the `dependency-graph` action parameter. Valid values are:
|
||||
|
||||
| Option | Behaviour |
|
||||
@@ -560,7 +585,7 @@ Example of a CI workflow that generates and submits a dependency graph:
|
||||
name: CI build
|
||||
on:
|
||||
push:
|
||||
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
@@ -582,13 +607,13 @@ jobs:
|
||||
run: ./gradlew build
|
||||
```
|
||||
|
||||
The `contents: write` permission is required to submit (but not generate) the dependency graph file.
|
||||
The `contents: write` permission is required to submit (but not generate) the dependency graph file.
|
||||
Depending on [repository settings](https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token), this permission may be available by default or may need to be explicitly enabled in the workflow file (as above).
|
||||
|
||||
> [!IMPORTANT]
|
||||
> The above configuration will work for workflows that run as a result of commits to a repository branch,
|
||||
> The above configuration will work for workflows that run as a result of commits to a repository branch,
|
||||
> but not when a workflow is triggered by a PR from a repository fork.
|
||||
> This is because the `contents: write` permission is not available when executing a workflow
|
||||
> This is because the `contents: write` permission is not available when executing a workflow
|
||||
> for a PR submitted from a forked repository.
|
||||
> For a configuration that supports this setup, see [Dependency Graphs for pull request workflows](dependency-submission.md#usage-with-pull-requests-from-public-forked-repositories).
|
||||
|
||||
@@ -610,7 +635,7 @@ graph cannot be generated or submitted. You can enable this behavior with the `d
|
||||
|
||||
### Using a custom plugin repository
|
||||
|
||||
By default, the action downloads the `github-dependency-graph-gradle-plugin` from the Gradle Plugin Portal (https://plugins.gradle.org). If your GitHub Actions environment does not have access to this URL, you can specify a custom plugin repository to use.
|
||||
By default, the action downloads the `github-dependency-graph-gradle-plugin` from the Gradle Plugin Portal (https://plugins.gradle.org). If your GitHub Actions environment does not have access to this URL, you can specify a custom plugin repository to use.
|
||||
|
||||
Do so by setting the `GRADLE_PLUGIN_REPOSITORY_URL` environment variable with your Gradle invocation.
|
||||
The `GRADLE_PLUGIN_REPOSITORY_USERNAME` and `GRADLE_PLUGIN_REPOSITORY_PASSWORD` can be used when the plugin repository requires authentication.
|
||||
@@ -670,7 +695,7 @@ jobs:
|
||||
|
||||
### Filtering which Gradle Configurations contribute to the dependency graph
|
||||
|
||||
If you do not want the dependency graph to include every dependency configuration in every project in your build,
|
||||
If you do not want the dependency graph to include every dependency configuration in every project in your build,
|
||||
you can limit the dependency extraction to a subset of these.
|
||||
|
||||
See the documentation for [dependency-submission](dependency-submission.md) and the
|
||||
@@ -678,7 +703,7 @@ See the documentation for [dependency-submission](dependency-submission.md) and
|
||||
|
||||
### Gradle version compatibility
|
||||
|
||||
Dependency-graph generation is compatible with most versions of Gradle >= `5.2`, and is tested regularly against
|
||||
Dependency-graph generation is compatible with most versions of Gradle >= `5.2`, and is tested regularly against
|
||||
Gradle versions `5.2.1`, `5.6.4`, `6.0.1`, `6.9.4`, `7.1.1` and `7.6.3`, as well as all patched versions of Gradle 8.x.
|
||||
|
||||
A known exception to this is that Gradle `7.0`, `7.0.1`, and `7.0.2` are not supported.
|
||||
@@ -687,7 +712,7 @@ See [here](https://github.com/gradle/github-dependency-graph-gradle-plugin?tab=r
|
||||
|
||||
### Reducing storage costs for saved dependency graph artifacts
|
||||
|
||||
When `generate` or `generate-and-submit` is used with the action, the dependency graph that is generated is stored as a workflow artifact.
|
||||
When `generate` or `generate-and-submit` is used with the action, the dependency graph that is generated is stored as a workflow artifact.
|
||||
By default, these artifacts are retained for 30 days (or as configured for the repository).
|
||||
To reduce storage costs for these artifacts, you can set the `artifact-retention-days` value to a lower number.
|
||||
|
||||
@@ -708,27 +733,49 @@ The same auto-injection behavior is available for the Common Custom User Data Gr
|
||||
|
||||
## Enabling Develocity injection
|
||||
|
||||
To enable Develocity injection for your build, you must provide the required configuration via environment variables.
|
||||
To enable Develocity injection for your build, you must provide the required configuration via inputs.
|
||||
|
||||
Here's a minimal example:
|
||||
|
||||
```yaml
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v3
|
||||
with:
|
||||
develocity-injection-enabled: true
|
||||
develocity-url: https://develocity.your-server.com
|
||||
develocity-plugin-version: 3.17.5
|
||||
|
||||
- name: Run a Gradle build with Develocity injection enabled
|
||||
run: ./gradlew build
|
||||
```
|
||||
|
||||
This configuration will automatically apply `v3.17.6` of the [Develocity Gradle plugin](https://docs.gradle.com/develocity/gradle-plugin/), and publish build scans to https://develocity.your-server.com.
|
||||
|
||||
This example assumes that the `develocity.your-server.com` server allows anonymous publishing of build scans.
|
||||
In the likely scenario that your Develocity server requires authentication, you will also need to pass a valid [Develocity access key](https://docs.gradle.com/develocity/gradle-plugin/#via_environment_variable) taken from a secret:
|
||||
|
||||
```yaml
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v3
|
||||
with:
|
||||
develocity-access-key: ${{ secrets.MY_DEVELOCITY_ACCESS_KEY }}
|
||||
|
||||
- name: Run a Gradle build with Develocity injection enabled
|
||||
run: ./gradlew build
|
||||
env:
|
||||
DEVELOCITY_INJECTION_ENABLED: true
|
||||
DEVELOCITY_URL: https://develocity.your-server.com
|
||||
DEVELOCITY_PLUGIN_VERSION: 3.17.2
|
||||
DEVELOCITY_PLUGIN_VERSION: 3.17
|
||||
```
|
||||
|
||||
This configuration will automatically apply `v3.17.2` of the [Develocity Gradle plugin](https://docs.gradle.com/develocity/gradle-plugin/), and publish build scans to https://develocity.your-server.com.
|
||||
This access key will be used during the action execution to get a short-lived token and set it to the DEVELOCITY_ACCESS_KEY environment variable.
|
||||
|
||||
This example assumes that the `develocity.your-server.com` server allows anonymous publishing of build scans.
|
||||
In the likely scenario that your Develocity server requires authentication, you will also need to configure an additional environment variable
|
||||
with a valid [Develocity access key](https://docs.gradle.com/develocity/gradle-plugin/#via_environment_variable).
|
||||
### Short-lived access tokens
|
||||
Develocity access keys are long-lived, creating risks if they are leaked. To avoid this, users can use short-lived access tokens to authenticate with Develocity. Access tokens can be used wherever an access key would be used. Access tokens are only valid for the Develocity instance that created them.
|
||||
If a short-lived token fails to be retrieved (for example, if the Develocity server version is lower than `2024.1`):
|
||||
- if a `GRADLE_ENTERPRISE_ACCESS_KEY` env var has been set, we're falling back to it with a deprecation warning
|
||||
- otherwise no access key env var will be set. In that case Develocity authenticated operations like build cache read/write and build scan publication will fail without failing the build.
|
||||
For more information on short-lived tokens, see [Develocity API documentation](https://docs.gradle.com/develocity/api-manual/#short_lived_access_tokens).
|
||||
|
||||
## Configuring Develocity injection
|
||||
|
||||
@@ -736,16 +783,46 @@ The `init-script` supports several additional configuration parameters that you
|
||||
|
||||
| Variable | Required | Description |
|
||||
|--------------------------------------| --- |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| DEVELOCITY_INJECTION_ENABLED | :white_check_mark: | enables Develocity injection |
|
||||
| DEVELOCITY_URL | :white_check_mark: | the URL of the Develocity server |
|
||||
| DEVELOCITY_ALLOW_UNTRUSTED_SERVER | | allow communication with an untrusted server; set to _true_ if your Develocity instance is using a self-signed certificate |
|
||||
| DEVELOCITY_CAPTURE_FILE_FINGERPRINTS | | enables capturing the paths and content hashes of each individual input file |
|
||||
| DEVELOCITY_ENFORCE_URL | | enforce the configured Develocity URL over a URL configured in the project's build; set to _true_ to enforce publication of build scans to the configured Develocity URL |
|
||||
| DEVELOCITY_PLUGIN_VERSION | :white_check_mark: | the version of the [Develocity Gradle plugin](https://docs.gradle.com/develocity/gradle-plugin/) to apply |
|
||||
| DEVELOCITY_CCUD_PLUGIN_VERSION | | the version of the [Common Custom User Data Gradle plugin](https://github.com/gradle/common-custom-user-data-gradle-plugin) to apply, if any |
|
||||
| GRADLE_PLUGIN_REPOSITORY_URL | | the URL of the repository to use when resolving the Develocity and CCUD plugins; the Gradle Plugin Portal is used by default |
|
||||
| GRADLE_PLUGIN_REPOSITORY_USERNAME | | the username for the repository URL to use when resolving the Develocity and CCUD plugins |
|
||||
| GRADLE_PLUGIN_REPOSITORY_PASSWORD | | the password for the repository URL to use when resolving the Develocity and CCUD plugins; Consider using secrets to pass the value to this variable |
|
||||
| develocity-injection-enabled | :white_check_mark: | enables Develocity injection |
|
||||
| develocity-url | :white_check_mark: | the URL of the Develocity server |
|
||||
| develocity-allow-untrusted-server | | allow communication with an untrusted server; set to _true_ if your Develocity instance is using a self-signed certificate |
|
||||
| develocity-capture-file-fingerprints | | enables capturing the paths and content hashes of each individual input file |
|
||||
| develocity-enforce-url | | enforce the configured Develocity URL over a URL configured in the project's build; set to _true_ to enforce publication of build scans to the configured Develocity URL |
|
||||
| develocity-plugin-version | :white_check_mark: | the version of the [Develocity Gradle plugin](https://docs.gradle.com/develocity/gradle-plugin/) to apply |
|
||||
| develocity-ccud-plugin-version | | the version of the [Common Custom User Data Gradle plugin](https://github.com/gradle/common-custom-user-data-gradle-plugin) to apply, if any |
|
||||
| gradle-plugin-repository-url | | the URL of the repository to use when resolving the Develocity and CCUD plugins; the Gradle Plugin Portal is used by default |
|
||||
| gradle-plugin-repository-username | | the username for the repository URL to use when resolving the Develocity and CCUD plugins |
|
||||
| gradle-plugin-repository-password | | the password for the repository URL to use when resolving the Develocity and CCUD plugins; Consider using secrets to pass the value to this variable |
|
||||
|
||||
The input parameters can be expressed as environment variables following the relationships outlined in the table below:
|
||||
|
||||
| Input | Environment Variable |
|
||||
|--------------------------------------|--------------------------------------|
|
||||
| develocity-injection-enabled | DEVELOCITY_INJECTION_ENABLED |
|
||||
| develocity-url | DEVELOCITY_URL |
|
||||
| develocity-allow-untrusted-server | DEVELOCITY_ALLOW_UNTRUSTED_SERVER |
|
||||
| develocity-capture-file-fingerprints | DEVELOCITY_CAPTURE_FILE_FINGERPRINTS |
|
||||
| develocity-enforce-url | DEVELOCITY_ENFORCE_URL |
|
||||
| develocity-plugin-version | DEVELOCITY_PLUGIN_VERSION |
|
||||
| develocity-ccud-plugin-version | DEVELOCITY_CCUD_PLUGIN_VERSION |
|
||||
| gradle-plugin-repository-url | GRADLE_PLUGIN_REPOSITORY_URL |
|
||||
| gradle-plugin-repository-username | GRADLE_PLUGIN_REPOSITORY_USERNAME |
|
||||
| gradle-plugin-repository-password | GRADLE_PLUGIN_REPOSITORY_PASSWORD |
|
||||
|
||||
|
||||
Here's an example using the env vars:
|
||||
|
||||
```yaml
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v3
|
||||
|
||||
- name: Run a Gradle build with Develocity injection enabled with environment variables
|
||||
run: ./gradlew build
|
||||
env:
|
||||
DEVELOCITY_INJECTION_ENABLED: true
|
||||
DEVELOCITY_URL: https://develocity.your-server.com
|
||||
DEVELOCITY_PLUGIN_VERSION: 3.17.6
|
||||
```
|
||||
|
||||
## Publishing to scans.gradle.com
|
||||
|
||||
@@ -765,3 +842,21 @@ To publish to https://scans.gradle.com, you must specify in your workflow that y
|
||||
- name: Run a Gradle build - a build scan will be published automatically
|
||||
run: ./gradlew build
|
||||
```
|
||||
|
||||
# Dependency verification
|
||||
|
||||
Develocity injection, Build Scan publishing and Dependency Graph generation all work by applying external plugins to your build.
|
||||
If you project has [dependency verification enabled](https://docs.gradle.org/current/userguide/dependency_verification.html#sec:signature-verification),
|
||||
then you'll need to update your verification metadata to trust these plugins.
|
||||
|
||||
Each of the plugins is signed by Gradle, and you can simply add the following snippet to your `dependency-verificaton.xml` file:
|
||||
|
||||
```xml
|
||||
<trusted-keys>
|
||||
<trusted-key id="7B79ADD11F8A779FE90FD3D0893A028475557671">
|
||||
<trusting group="com.gradle"/>
|
||||
<trusting group="org.gradle"/>
|
||||
</trusted-key>
|
||||
</trusted-keys>
|
||||
```
|
||||
|
||||
|
||||
@@ -4,6 +4,9 @@ This action validates the checksums of _all_ [Gradle Wrapper](https://docs.gradl
|
||||
|
||||
The action should be run in the root of the repository, as it will recursively search for any files named `gradle-wrapper.jar`.
|
||||
|
||||
The `setup-gradle` action will perform wrapper validation on each execution. If you are using `setup-gradle` in your
|
||||
workflows, it is unlikely that you will need to use this action.
|
||||
|
||||
## The Gradle Wrapper Problem in Open Source
|
||||
|
||||
The `gradle-wrapper.jar` is a binary blob of executable code that is checked into nearly
|
||||
@@ -90,18 +93,22 @@ We recommend the message commit contents of:
|
||||
|
||||
From there, you can easily follow the rest of the prompts to create a Pull Request against the project.
|
||||
|
||||
## Reporting Failures
|
||||
## Validation Failures
|
||||
|
||||
If this GitHub action fails because a `gradle-wrapper.jar` doesn't match one of our published SHA-256 checksums,
|
||||
A wrapper jar can fail validation for a few reasons:
|
||||
1. The wrapper is from a snapshot build of Gradle (nightly or release nightly) and you have not set `allow-snapshots`
|
||||
or `allow-snapshot-wrappers` to `true`.
|
||||
2. The wrapper jar is from a version of Gradle with an unverifiable wrapper jar (see below).
|
||||
3. The wrapper jar was not published by Gradle, and could be compromised.
|
||||
|
||||
If this GitHub action fails because a `gradle-wrapper.jar` was not published by Gradle,
|
||||
we highly recommend that you reach out to us at [security@gradle.com](mailto:security@gradle.com).
|
||||
|
||||
**Note:** `gradle-wrapper.jar` generated by Gradle 3.3 to 4.0 are not verifiable because those files were dynamically generated by Gradle in a non-reproducible way. It's not possible to verify the `gradle-wrapper.jar` for those versions are legitimate using a hash comparison. You should try to determine if the `gradle-wrapper.jar` was generated by one of these versions before running the build.
|
||||
#### Unverifiable Wrapper Jars
|
||||
Wrapper Jars generated by Gradle versions `3.3` to `4.0` are not verifiable because those files were dynamically generated by Gradle in a non-reproducible way. It's not possible to verify the `gradle-wrapper.jar` for those versions are legitimate using a hash comparison. If you have a validation failure, you should try to determine if the `gradle-wrapper.jar` was generated by one of these versions before running the build.
|
||||
|
||||
If the Gradle version in `gradle-wrapper.properties` is out of this range, you may need to regenerate the `gradle-wrapper.jar` by running `./gradlew wrapper`. If you need to use a version of Gradle between 3.3 and 4.0, you can use a newer version of Gradle to generate the `gradle-wrapper.jar`.
|
||||
|
||||
If you're curious and want to explore what the differences are between the `gradle-wrapper.jar` in your possession
|
||||
and one of our valid release, you can compare them using this online utility: [diffoscope](https://try.diffoscope.org/).
|
||||
Regardless of what you find, we still kindly request that you reach out to us and let us know.
|
||||
- If the Gradle version in `gradle-wrapper.properties` is outside of this range, you can regenerate the `gradle-wrapper.jar` by running `./gradlew wrapper`. This will generate a new, verifiable wrapper jar.
|
||||
- If you need to run your build with a version of Gradle between 3.3 and 4.0, you can use a newer version of Gradle to generate the `gradle-wrapper.jar`.
|
||||
|
||||
## Resources
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ inputs:
|
||||
|
||||
cache-write-only:
|
||||
description: |
|
||||
When 'true', entries will not be restored from the cache but will be saved at the end of the Job.
|
||||
When 'true', entries will not be restored from the cache but will be saved at the end of the Job.
|
||||
Setting this to 'true' implies cache-read-only will be 'false'.
|
||||
required: false
|
||||
default: false
|
||||
@@ -35,11 +35,24 @@ inputs:
|
||||
|
||||
cache-encryption-key:
|
||||
description: |
|
||||
A base64 encoded AES key used to encrypt the configuration-cache data. The key is exported as 'GRADLE_ENCRYPTION_KEY' for later steps.
|
||||
A base64 encoded AES key used to encrypt the configuration-cache data. The key is exported as 'GRADLE_ENCRYPTION_KEY' for later steps.
|
||||
A suitable key can be generated with `openssl rand -base64 16`.
|
||||
Configuration-cache data will not be saved/restored without an encryption key being provided.
|
||||
required: false
|
||||
|
||||
cache-cleanup:
|
||||
description: |
|
||||
Specifies if the action should attempt to remove any stale/unused entries from the Gradle User Home prior to saving to the GitHub Actions cache.
|
||||
By default, no cleanup is performed. It can be configured to run every time, or only when all Gradle builds succeed for the Job.
|
||||
Valid values are 'never', 'on-success' and 'always'.
|
||||
required: false
|
||||
default: 'on-success'
|
||||
|
||||
gradle-home-cache-cleanup:
|
||||
description: When 'true', the action will attempt to remove any stale/unused entries from the Gradle User Home prior to saving to the GitHub Actions cache.
|
||||
required: false
|
||||
deprecation-message: This input has been superceded by the 'cache-cleanup' input parameter.
|
||||
|
||||
gradle-home-cache-includes:
|
||||
description: Paths within Gradle User Home to cache.
|
||||
required: false
|
||||
@@ -51,11 +64,6 @@ inputs:
|
||||
description: Paths within Gradle User Home to exclude from cache.
|
||||
required: false
|
||||
|
||||
gradle-home-cache-cleanup:
|
||||
description: When 'true', the action will attempt to remove any stale/unused entries from the Gradle User Home prior to saving to the GitHub Actions cache.
|
||||
required: false
|
||||
default: false
|
||||
|
||||
# Job summary configuration
|
||||
add-job-summary:
|
||||
description: Specifies when a Job Summary should be inluded in the action results. Valid values are 'never', 'always' (default), and 'on-failure'.
|
||||
@@ -70,16 +78,47 @@ inputs:
|
||||
# Dependency Graph configuration
|
||||
dependency-graph:
|
||||
description: |
|
||||
Specifies if a GitHub dependency snapshot should be generated for each Gradle build, and if so, how.
|
||||
Valid values are 'disabled' (default), 'generate', 'generate-and-submit', 'generate-and-upload', 'download-and-submit' and 'clear'.
|
||||
Specifies if a GitHub dependency snapshot should be generated for each Gradle build, and if so, how.
|
||||
Valid values are 'disabled' (default), 'generate', 'generate-and-submit', 'generate-and-upload', and 'download-and-submit'.
|
||||
required: false
|
||||
default: 'disabled'
|
||||
|
||||
dependency-graph-report-dir:
|
||||
description: |
|
||||
Specifies where the dependency graph report will be generated.
|
||||
Paths can relative or absolute. Relative paths are resolved relative to the workspace directory.
|
||||
required: false
|
||||
default: 'dependency-graph-reports'
|
||||
|
||||
dependency-graph-continue-on-failure:
|
||||
description: When 'false' a failure to generate or submit a dependency graph will fail the Step or Job. When 'true' a warning will be emitted but no failure will result.
|
||||
required: false
|
||||
default: true
|
||||
|
||||
dependency-graph-exclude-projects:
|
||||
description: |
|
||||
Gradle projects that should be excluded from dependency graph (regular expression).
|
||||
When set, any matching project will be excluded.
|
||||
required: false
|
||||
|
||||
dependency-graph-include-projects:
|
||||
description: |
|
||||
Gradle projects that should be included in dependency graph (regular expression).
|
||||
When set, only matching projects will be included.
|
||||
required: false
|
||||
|
||||
dependency-graph-exclude-configurations:
|
||||
description: |
|
||||
Gradle configurations that should be included in dependency graph (regular expression).
|
||||
When set, anymatching configurations will be excluded.
|
||||
required: false
|
||||
|
||||
dependency-graph-include-configurations:
|
||||
description: |
|
||||
Gradle configurations that should be included in dependency graph (regular expression).
|
||||
When set, only matching configurations will be included.
|
||||
required: false
|
||||
|
||||
artifact-retention-days:
|
||||
description: Specifies the number of days to retain any artifacts generated by the action. If not set, the default retention settings for the repository will apply.
|
||||
required: false
|
||||
@@ -95,45 +134,79 @@ inputs:
|
||||
build-scan-terms-of-use-url:
|
||||
description: The URL to the Build Scan® terms of use. This input must be set to 'https://gradle.com/terms-of-service' or 'https://gradle.com/help/legal-terms-of-use'.
|
||||
required: false
|
||||
|
||||
|
||||
build-scan-terms-of-use-agree:
|
||||
description: Indicate that you agree to the Build Scan® terms of use. This input value must be "yes".
|
||||
required: false
|
||||
|
||||
develocity-access-key:
|
||||
description: Develocity access key. Should be set to a secret containing the Develocity Access key.
|
||||
required: false
|
||||
|
||||
develocity-token-expiry:
|
||||
description: The Develocity short-lived access tokens expiry in hours. Default is 2 hours.
|
||||
required: false
|
||||
|
||||
develocity-injection-enabled:
|
||||
description: Enables Develocity injection.
|
||||
required: false
|
||||
|
||||
develocity-url:
|
||||
description: The URL for the Develocity server.
|
||||
required: false
|
||||
|
||||
develocity-allow-untrusted-server:
|
||||
description: Allow communication with an untrusted server; set to _true_ if your Develocity instance is using a self-signed.
|
||||
required: false
|
||||
|
||||
develocity-capture-file-fingerprints:
|
||||
description: Enables capturing the paths and content hashes of each individual input file.
|
||||
required: false
|
||||
|
||||
develocity-enforce-url:
|
||||
description: Enforce the configured Develocity URL over a URL configured in the project's build; set to _true_ to enforce publication of build scans to the configured Develocity URL.
|
||||
required: false
|
||||
|
||||
develocity-plugin-version:
|
||||
description: The version of the Develocity Gradle plugin to apply.
|
||||
required: false
|
||||
|
||||
develocity-ccud-plugin-version:
|
||||
description: The version of the Common Custom User Data Gradle plugin to apply, if any.
|
||||
required: false
|
||||
|
||||
gradle-plugin-repository-url:
|
||||
description: The URL of the repository to use when resolving the Develocity and CCUD plugins; the Gradle Plugin Portal is used by default.
|
||||
required: false
|
||||
|
||||
gradle-plugin-repository-username:
|
||||
description: The username for the repository URL to use when resolving the Develocity and CCUD.
|
||||
required: false
|
||||
|
||||
gradle-plugin-repository-password:
|
||||
description: The password for the repository URL to use when resolving the Develocity and CCUD plugins; Consider using secrets to pass the value to this variable.
|
||||
required: false
|
||||
|
||||
# Wrapper validation configuration
|
||||
validate-wrappers:
|
||||
description: |
|
||||
When 'true', the action will perform the 'wrapper-validation' action automatically.
|
||||
When 'true' (the default) the action will automatically validate all wrapper jars found in the repository.
|
||||
If the wrapper checksums are not valid, the action will fail.
|
||||
required: false
|
||||
default: true
|
||||
|
||||
allow-snapshot-wrappers:
|
||||
description: |
|
||||
When 'true', wrapper validation will include the checksums of snapshot wrapper jars.
|
||||
Use this if you are running with nightly or snapshot versions of the Gradle wrapper.
|
||||
required: false
|
||||
default: false
|
||||
|
||||
# DEPRECATED ACTION INPUTS
|
||||
build-scan-terms-of-service-url:
|
||||
description: The URL to the Build Scan® terms of use. This input must be set to 'https://gradle.com/terms-of-service'.
|
||||
required: false
|
||||
deprecation-message: The input has been renamed to align with the Develocity API. Use 'build-scan-terms-of-use-url' instead.
|
||||
|
||||
build-scan-terms-of-service-agree:
|
||||
description: Indicate that you agree to the Build Scan® terms of use. This input value must be "yes".
|
||||
required: false
|
||||
deprecation-message: The input has been renamed to align with the Develocity API. Use 'build-scan-terms-of-use-agree' instead.
|
||||
|
||||
generate-job-summary:
|
||||
description: When 'false', no Job Summary will be generated for the Job.
|
||||
required: false
|
||||
default: true
|
||||
deprecation-message: Superceded by the new 'add-job-summary' and 'add-job-summary-as-pr-comment' parameters.
|
||||
|
||||
arguments:
|
||||
description: Gradle command line arguments (supports multi-line input)
|
||||
required: false
|
||||
deprecation-message: Using the action to execute Gradle directly is deprecated in favor of using the action to setup Gradle, and executing Gradle in a subsequent Step.
|
||||
|
||||
build-root-directory:
|
||||
description: Path to the root directory of the build. Default is the root of the GitHub workspace.
|
||||
required: false
|
||||
deprecation-message: Using the action to execute Gradle directly is deprecated in favor of using the action to setup Gradle, and executing Gradle in a subsequent Step.
|
||||
deprecation-message: This parameter has been deprecated and removed. It is only left here to allow for better reporting to assist users to migrate.
|
||||
|
||||
# EXPERIMENTAL ACTION INPUTS
|
||||
# The following action properties allow fine-grained tweaking of the action caching behaviour.
|
||||
@@ -143,7 +216,7 @@ inputs:
|
||||
description: When 'true', the action will not attempt to restore the Gradle User Home entries from other Jobs.
|
||||
required: false
|
||||
default: false
|
||||
|
||||
|
||||
# INTERNAL ACTION INPUTS
|
||||
# These inputs should not be configured directly, and are only used to pass environmental information to the action
|
||||
workflow-job-context:
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
# Configuration file for asdf version manager
|
||||
nodejs 20.10.0
|
||||
gradle 8.7
|
||||
gradle 8.9
|
||||
|
||||
412
sources/package-lock.json
generated
412
sources/package-lock.json
generated
@@ -20,15 +20,18 @@
|
||||
"@actions/tool-cache": "2.0.1",
|
||||
"@octokit/rest": "20.1.0",
|
||||
"@octokit/webhooks-types": "7.5.0",
|
||||
"cheerio": "^1.0.0-rc.12",
|
||||
"semver": "7.6.0",
|
||||
"string-argv": "0.3.2",
|
||||
"typed-rest-client": "1.8.11",
|
||||
"unhomoglyph": "1.0.6"
|
||||
"unhomoglyph": "1.0.6",
|
||||
"which": "4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "29.5.12",
|
||||
"@types/node": "20.12.4",
|
||||
"@types/unzipper": "0.10.9",
|
||||
"@types/which": "3.0.4",
|
||||
"@typescript-eslint/parser": "7.5.0",
|
||||
"@vercel/ncc": "0.38.1",
|
||||
"eslint": "8.57.0",
|
||||
@@ -2215,6 +2218,12 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/which": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/which/-/which-3.0.4.tgz",
|
||||
"integrity": "sha512-liyfuo/106JdlgSchJzXEQCVArk0CvevqPote8F8HgWgJ3dRCcTHgJIsLDuee0kxk/mhbInzIZk3QWSZJ8R+2w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/yargs": {
|
||||
"version": "17.0.23",
|
||||
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.23.tgz",
|
||||
@@ -3301,6 +3310,11 @@
|
||||
"readable-stream": "^3.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/boolbase": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
|
||||
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="
|
||||
},
|
||||
"node_modules/bottleneck": {
|
||||
"version": "2.19.5",
|
||||
"resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz",
|
||||
@@ -3316,12 +3330,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
|
||||
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fill-range": "^7.0.1"
|
||||
"fill-range": "^7.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
@@ -3518,6 +3532,42 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/cheerio": {
|
||||
"version": "1.0.0-rc.12",
|
||||
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz",
|
||||
"integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==",
|
||||
"dependencies": {
|
||||
"cheerio-select": "^2.1.0",
|
||||
"dom-serializer": "^2.0.0",
|
||||
"domhandler": "^5.0.3",
|
||||
"domutils": "^3.0.1",
|
||||
"htmlparser2": "^8.0.1",
|
||||
"parse5": "^7.0.0",
|
||||
"parse5-htmlparser2-tree-adapter": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/cheeriojs/cheerio?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/cheerio-select": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz",
|
||||
"integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==",
|
||||
"dependencies": {
|
||||
"boolbase": "^1.0.0",
|
||||
"css-select": "^5.1.0",
|
||||
"css-what": "^6.1.0",
|
||||
"domelementtype": "^2.3.0",
|
||||
"domhandler": "^5.0.3",
|
||||
"domutils": "^3.0.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/fb55"
|
||||
}
|
||||
},
|
||||
"node_modules/ci-info": {
|
||||
"version": "3.8.0",
|
||||
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz",
|
||||
@@ -3694,12 +3744,53 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/cross-spawn/node_modules/which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"isexe": "^2.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"node-which": "bin/node-which"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/crypto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz",
|
||||
"integrity": "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==",
|
||||
"deprecated": "This package is no longer supported. It's now a built-in Node module. If you've depended on crypto, you should switch to the one that's built-in."
|
||||
},
|
||||
"node_modules/css-select": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
|
||||
"integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==",
|
||||
"dependencies": {
|
||||
"boolbase": "^1.0.0",
|
||||
"css-what": "^6.1.0",
|
||||
"domhandler": "^5.0.2",
|
||||
"domutils": "^3.0.1",
|
||||
"nth-check": "^2.0.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/fb55"
|
||||
}
|
||||
},
|
||||
"node_modules/css-what": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
|
||||
"integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/fb55"
|
||||
}
|
||||
},
|
||||
"node_modules/damerau-levenshtein": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
|
||||
@@ -3877,6 +3968,57 @@
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dom-serializer": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
|
||||
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.3.0",
|
||||
"domhandler": "^5.0.2",
|
||||
"entities": "^4.2.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/domelementtype": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
|
||||
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/fb55"
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/domhandler": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
|
||||
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/domhandler?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/domutils": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",
|
||||
"integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==",
|
||||
"dependencies": {
|
||||
"dom-serializer": "^2.0.0",
|
||||
"domelementtype": "^2.3.0",
|
||||
"domhandler": "^5.0.3"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/domutils?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/dot-object": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/dot-object/-/dot-object-2.1.4.tgz",
|
||||
@@ -3921,6 +4063,17 @@
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/entities": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
||||
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/error-ex": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
|
||||
@@ -4736,9 +4889,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
@@ -5164,6 +5317,24 @@
|
||||
"integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/htmlparser2": {
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz",
|
||||
"integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==",
|
||||
"funding": [
|
||||
"https://github.com/fb55/htmlparser2?sponsor=1",
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/fb55"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.3.0",
|
||||
"domhandler": "^5.0.3",
|
||||
"domutils": "^3.0.1",
|
||||
"entities": "^4.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/human-signals": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
|
||||
@@ -7037,6 +7208,17 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/nth-check": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
|
||||
"integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
|
||||
"dependencies": {
|
||||
"boolbase": "^1.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/nth-check?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/object-inspect": {
|
||||
"version": "1.13.1",
|
||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
|
||||
@@ -7270,6 +7452,29 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/parse5": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz",
|
||||
"integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==",
|
||||
"dependencies": {
|
||||
"entities": "^4.4.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/inikulin/parse5?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/parse5-htmlparser2-tree-adapter": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz",
|
||||
"integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==",
|
||||
"dependencies": {
|
||||
"domhandler": "^5.0.2",
|
||||
"parse5": "^7.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/inikulin/parse5?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/pascal-case": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz",
|
||||
@@ -8885,18 +9090,17 @@
|
||||
}
|
||||
},
|
||||
"node_modules/which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||
"dev": true,
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz",
|
||||
"integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==",
|
||||
"dependencies": {
|
||||
"isexe": "^2.0.0"
|
||||
"isexe": "^3.1.1"
|
||||
},
|
||||
"bin": {
|
||||
"node-which": "bin/node-which"
|
||||
"node-which": "bin/which.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
"node": "^16.13.0 || >=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/which-boxed-primitive": {
|
||||
@@ -8949,6 +9153,14 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/which/node_modules/isexe": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz",
|
||||
"integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==",
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/wrap-ansi": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
||||
@@ -10875,6 +11087,12 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/which": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/which/-/which-3.0.4.tgz",
|
||||
"integrity": "sha512-liyfuo/106JdlgSchJzXEQCVArk0CvevqPote8F8HgWgJ3dRCcTHgJIsLDuee0kxk/mhbInzIZk3QWSZJ8R+2w==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/yargs": {
|
||||
"version": "17.0.23",
|
||||
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.23.tgz",
|
||||
@@ -11613,6 +11831,11 @@
|
||||
"readable-stream": "^3.4.0"
|
||||
}
|
||||
},
|
||||
"boolbase": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
|
||||
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="
|
||||
},
|
||||
"bottleneck": {
|
||||
"version": "2.19.5",
|
||||
"resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz",
|
||||
@@ -11628,12 +11851,12 @@
|
||||
}
|
||||
},
|
||||
"braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
|
||||
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fill-range": "^7.0.1"
|
||||
"fill-range": "^7.1.1"
|
||||
}
|
||||
},
|
||||
"browserslist": {
|
||||
@@ -11754,6 +11977,33 @@
|
||||
"integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==",
|
||||
"dev": true
|
||||
},
|
||||
"cheerio": {
|
||||
"version": "1.0.0-rc.12",
|
||||
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz",
|
||||
"integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==",
|
||||
"requires": {
|
||||
"cheerio-select": "^2.1.0",
|
||||
"dom-serializer": "^2.0.0",
|
||||
"domhandler": "^5.0.3",
|
||||
"domutils": "^3.0.1",
|
||||
"htmlparser2": "^8.0.1",
|
||||
"parse5": "^7.0.0",
|
||||
"parse5-htmlparser2-tree-adapter": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"cheerio-select": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz",
|
||||
"integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==",
|
||||
"requires": {
|
||||
"boolbase": "^1.0.0",
|
||||
"css-select": "^5.1.0",
|
||||
"css-what": "^6.1.0",
|
||||
"domelementtype": "^2.3.0",
|
||||
"domhandler": "^5.0.3",
|
||||
"domutils": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"ci-info": {
|
||||
"version": "3.8.0",
|
||||
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz",
|
||||
@@ -11882,6 +12132,17 @@
|
||||
"path-key": "^3.1.0",
|
||||
"shebang-command": "^2.0.0",
|
||||
"which": "^2.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"isexe": "^2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"crypto": {
|
||||
@@ -11889,6 +12150,23 @@
|
||||
"resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz",
|
||||
"integrity": "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig=="
|
||||
},
|
||||
"css-select": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
|
||||
"integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==",
|
||||
"requires": {
|
||||
"boolbase": "^1.0.0",
|
||||
"css-what": "^6.1.0",
|
||||
"domhandler": "^5.0.2",
|
||||
"domutils": "^3.0.1",
|
||||
"nth-check": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"css-what": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
|
||||
"integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw=="
|
||||
},
|
||||
"damerau-levenshtein": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
|
||||
@@ -12015,6 +12293,39 @@
|
||||
"esutils": "^2.0.2"
|
||||
}
|
||||
},
|
||||
"dom-serializer": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
|
||||
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
|
||||
"requires": {
|
||||
"domelementtype": "^2.3.0",
|
||||
"domhandler": "^5.0.2",
|
||||
"entities": "^4.2.0"
|
||||
}
|
||||
},
|
||||
"domelementtype": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
|
||||
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="
|
||||
},
|
||||
"domhandler": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
|
||||
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
|
||||
"requires": {
|
||||
"domelementtype": "^2.3.0"
|
||||
}
|
||||
},
|
||||
"domutils": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",
|
||||
"integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==",
|
||||
"requires": {
|
||||
"dom-serializer": "^2.0.0",
|
||||
"domelementtype": "^2.3.0",
|
||||
"domhandler": "^5.0.3"
|
||||
}
|
||||
},
|
||||
"dot-object": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/dot-object/-/dot-object-2.1.4.tgz",
|
||||
@@ -12050,6 +12361,11 @@
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"entities": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
||||
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="
|
||||
},
|
||||
"error-ex": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
|
||||
@@ -12659,9 +12975,9 @@
|
||||
}
|
||||
},
|
||||
"fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
@@ -12960,6 +13276,17 @@
|
||||
"integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
|
||||
"dev": true
|
||||
},
|
||||
"htmlparser2": {
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz",
|
||||
"integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==",
|
||||
"requires": {
|
||||
"domelementtype": "^2.3.0",
|
||||
"domhandler": "^5.0.3",
|
||||
"domutils": "^3.0.1",
|
||||
"entities": "^4.4.0"
|
||||
}
|
||||
},
|
||||
"human-signals": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
|
||||
@@ -14379,6 +14706,14 @@
|
||||
"path-key": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"nth-check": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
|
||||
"integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
|
||||
"requires": {
|
||||
"boolbase": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"object-inspect": {
|
||||
"version": "1.13.1",
|
||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
|
||||
@@ -14537,6 +14872,23 @@
|
||||
"lines-and-columns": "^1.1.6"
|
||||
}
|
||||
},
|
||||
"parse5": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz",
|
||||
"integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==",
|
||||
"requires": {
|
||||
"entities": "^4.4.0"
|
||||
}
|
||||
},
|
||||
"parse5-htmlparser2-tree-adapter": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz",
|
||||
"integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==",
|
||||
"requires": {
|
||||
"domhandler": "^5.0.2",
|
||||
"parse5": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"pascal-case": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz",
|
||||
@@ -15700,12 +16052,18 @@
|
||||
}
|
||||
},
|
||||
"which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||
"dev": true,
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz",
|
||||
"integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==",
|
||||
"requires": {
|
||||
"isexe": "^2.0.0"
|
||||
"isexe": "^3.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"isexe": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz",
|
||||
"integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"which-boxed-primitive": {
|
||||
|
||||
@@ -8,11 +8,11 @@
|
||||
"prettier-write": "prettier --write 'src/**/*.ts'",
|
||||
"prettier-check": "prettier --check 'src/**/*.ts'",
|
||||
"lint": "eslint 'src/**/*.ts'",
|
||||
"compile-dependency-submission-main": "ncc build src/dependency-submission/main.ts --out dist/dependency-submission/main --source-map --no-source-map-register",
|
||||
"compile-dependency-submission-post": "ncc build src/dependency-submission/post.ts --out dist/dependency-submission/post --source-map --no-source-map-register",
|
||||
"compile-setup-gradle-main": "ncc build src/setup-gradle/main.ts --out dist/setup-gradle/main --source-map --no-source-map-register",
|
||||
"compile-setup-gradle-post": "ncc build src/setup-gradle/post.ts --out dist/setup-gradle/post --source-map --no-source-map-register",
|
||||
"compile-wrapper-validation-main": "ncc build src/wrapper-validation/main.ts --out dist/wrapper-validation/main --source-map --no-source-map-register",
|
||||
"compile-dependency-submission-main": "ncc build src/actions/dependency-submission/main.ts --out dist/dependency-submission/main --source-map --no-source-map-register",
|
||||
"compile-dependency-submission-post": "ncc build src/actions/dependency-submission/post.ts --out dist/dependency-submission/post --source-map --no-source-map-register",
|
||||
"compile-setup-gradle-main": "ncc build src/actions/setup-gradle/main.ts --out dist/setup-gradle/main --source-map --no-source-map-register",
|
||||
"compile-setup-gradle-post": "ncc build src/actions/setup-gradle/post.ts --out dist/setup-gradle/post --source-map --no-source-map-register",
|
||||
"compile-wrapper-validation-main": "ncc build src/actions/wrapper-validation/main.ts --out dist/wrapper-validation/main --source-map --no-source-map-register",
|
||||
"compile": "npm-run-all --parallel compile-*",
|
||||
"check": "npm-run-all --parallel prettier-check lint",
|
||||
"format": "npm-run-all --parallel prettier-write lint",
|
||||
@@ -42,15 +42,18 @@
|
||||
"@actions/tool-cache": "2.0.1",
|
||||
"@octokit/rest": "20.1.0",
|
||||
"@octokit/webhooks-types": "7.5.0",
|
||||
"cheerio": "^1.0.0-rc.12",
|
||||
"semver": "7.6.0",
|
||||
"string-argv": "0.3.2",
|
||||
"typed-rest-client": "1.8.11",
|
||||
"unhomoglyph": "1.0.6"
|
||||
},
|
||||
"unhomoglyph": "1.0.6",
|
||||
"which": "4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "29.5.12",
|
||||
"@types/node": "20.12.4",
|
||||
"@types/unzipper": "0.10.9",
|
||||
"@types/which": "3.0.4",
|
||||
"@typescript-eslint/parser": "7.5.0",
|
||||
"@vercel/ncc": "0.38.1",
|
||||
"eslint": "8.57.0",
|
||||
@@ -59,11 +62,11 @@
|
||||
"eslint-plugin-prettier": "5.1.3",
|
||||
"jest": "29.7.0",
|
||||
"js-yaml": "4.1.0",
|
||||
"nock": "13.5.4",
|
||||
"npm-run-all": "4.1.5",
|
||||
"patch-package": "8.0.0",
|
||||
"prettier": "3.2.5",
|
||||
"ts-jest": "29.1.2",
|
||||
"typescript": "5.4.3",
|
||||
"nock": "13.5.4"
|
||||
"typescript": "5.4.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import * as setupGradle from '../setup-gradle'
|
||||
import * as gradle from '../execution/gradle'
|
||||
import * as dependencyGraph from '../dependency-graph'
|
||||
import * as core from '@actions/core'
|
||||
import * as setupGradle from '../../setup-gradle'
|
||||
import * as gradle from '../../execution/gradle'
|
||||
import * as dependencyGraph from '../../dependency-graph'
|
||||
|
||||
import {parseArgsStringToArgv} from 'string-argv'
|
||||
import {
|
||||
@@ -9,10 +10,11 @@ import {
|
||||
DependencyGraphConfig,
|
||||
DependencyGraphOption,
|
||||
GradleExecutionConfig,
|
||||
setActionId
|
||||
} from '../configuration'
|
||||
import {saveDeprecationState} from '../deprecation-collector'
|
||||
import {handleMainActionError} from '../errors'
|
||||
setActionId,
|
||||
WrapperValidationConfig
|
||||
} from '../../configuration'
|
||||
import {saveDeprecationState} from '../../deprecation-collector'
|
||||
import {handleMainActionError} from '../../errors'
|
||||
|
||||
/**
|
||||
* The main entry point for the action, called by Github Actions for the step.
|
||||
@@ -22,7 +24,10 @@ export async function run(): Promise<void> {
|
||||
setActionId('gradle/actions/dependency-submission')
|
||||
|
||||
// Configure Gradle environment (Gradle User Home)
|
||||
await setupGradle.setup(new CacheConfig(), new BuildScanConfig())
|
||||
await setupGradle.setup(new CacheConfig(), new BuildScanConfig(), new WrapperValidationConfig())
|
||||
|
||||
// Capture the enabled state of dependency-graph
|
||||
const originallyEnabled = process.env['GITHUB_DEPENDENCY_GRAPH_ENABLED']
|
||||
|
||||
// Configure the dependency graph submission
|
||||
const config = new DependencyGraphConfig()
|
||||
@@ -53,6 +58,9 @@ export async function run(): Promise<void> {
|
||||
|
||||
await dependencyGraph.complete(config)
|
||||
|
||||
// Reset the enabled state of dependency graph
|
||||
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_ENABLED', originallyEnabled)
|
||||
|
||||
saveDeprecationState()
|
||||
} catch (error) {
|
||||
handleMainActionError(error)
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as setupGradle from '../setup-gradle'
|
||||
import * as setupGradle from '../../setup-gradle'
|
||||
|
||||
import {CacheConfig, SummaryConfig} from '../configuration'
|
||||
import {handlePostActionError} from '../errors'
|
||||
import {CacheConfig, SummaryConfig} from '../../configuration'
|
||||
import {handlePostActionError} from '../../errors'
|
||||
|
||||
// Catch and log any unhandled exceptions. These exceptions can leak out of the uploadChunk method in
|
||||
// @actions/toolkit when a failed upload closes the file descriptor causing any in-process reads to
|
||||
@@ -1,17 +1,17 @@
|
||||
import * as setupGradle from '../setup-gradle'
|
||||
import * as gradle from '../execution/gradle'
|
||||
import * as dependencyGraph from '../dependency-graph'
|
||||
import * as setupGradle from '../../setup-gradle'
|
||||
import * as provisioner from '../../execution/provision'
|
||||
import * as dependencyGraph from '../../dependency-graph'
|
||||
import {
|
||||
BuildScanConfig,
|
||||
CacheConfig,
|
||||
DependencyGraphConfig,
|
||||
GradleExecutionConfig,
|
||||
doValidateWrappers,
|
||||
WrapperValidationConfig,
|
||||
getActionId,
|
||||
setActionId
|
||||
} from '../configuration'
|
||||
import {recordDeprecation, saveDeprecationState} from '../deprecation-collector'
|
||||
import {handleMainActionError} from '../errors'
|
||||
} from '../../configuration'
|
||||
import {failOnUseOfRemovedFeature, saveDeprecationState} from '../../deprecation-collector'
|
||||
import {handleMainActionError} from '../../errors'
|
||||
|
||||
/**
|
||||
* The main entry point for the action, called by Github Actions for the step.
|
||||
@@ -19,30 +19,22 @@ import {handleMainActionError} from '../errors'
|
||||
export async function run(): Promise<void> {
|
||||
try {
|
||||
if (getActionId() === 'gradle/gradle-build-action') {
|
||||
recordDeprecation(
|
||||
failOnUseOfRemovedFeature(
|
||||
'The action `gradle/gradle-build-action` has been replaced by `gradle/actions/setup-gradle`'
|
||||
)
|
||||
} else {
|
||||
setActionId('gradle/actions/setup-gradle')
|
||||
}
|
||||
|
||||
// Check for invalid wrapper JARs if requested
|
||||
if (doValidateWrappers()) {
|
||||
await setupGradle.checkNoInvalidWrapperJars()
|
||||
}
|
||||
setActionId('gradle/actions/setup-gradle')
|
||||
|
||||
// Configure Gradle environment (Gradle User Home)
|
||||
await setupGradle.setup(new CacheConfig(), new BuildScanConfig())
|
||||
await setupGradle.setup(new CacheConfig(), new BuildScanConfig(), new WrapperValidationConfig())
|
||||
|
||||
// Configure the dependency graph submission
|
||||
await dependencyGraph.setup(new DependencyGraphConfig())
|
||||
|
||||
const config = new GradleExecutionConfig()
|
||||
await gradle.provisionAndMaybeExecute(
|
||||
config.getGradleVersion(),
|
||||
config.getBuildRootDirectory(),
|
||||
config.getArguments()
|
||||
)
|
||||
config.verifyNoArguments()
|
||||
await provisioner.provisionGradle(config.getGradleVersion())
|
||||
|
||||
saveDeprecationState()
|
||||
} catch (error) {
|
||||
@@ -1,9 +1,9 @@
|
||||
import * as setupGradle from '../setup-gradle'
|
||||
import * as dependencyGraph from '../dependency-graph'
|
||||
import * as setupGradle from '../../setup-gradle'
|
||||
import * as dependencyGraph from '../../dependency-graph'
|
||||
|
||||
import {CacheConfig, DependencyGraphConfig, SummaryConfig} from '../configuration'
|
||||
import {handlePostActionError} from '../errors'
|
||||
import {emitDeprecationWarnings, restoreDeprecationState} from '../deprecation-collector'
|
||||
import {CacheConfig, DependencyGraphConfig, SummaryConfig} from '../../configuration'
|
||||
import {handlePostActionError} from '../../errors'
|
||||
import {emitDeprecationWarnings, restoreDeprecationState} from '../../deprecation-collector'
|
||||
|
||||
// Catch and log any unhandled exceptions. These exceptions can leak out of the uploadChunk method in
|
||||
// @actions/toolkit when a failed upload closes the file descriptor causing any in-process reads to
|
||||
@@ -1,21 +1,21 @@
|
||||
import * as path from 'path'
|
||||
import * as core from '@actions/core'
|
||||
|
||||
import * as validate from './validate'
|
||||
import {getActionId, setActionId} from '../configuration'
|
||||
import {recordDeprecation, emitDeprecationWarnings} from '../deprecation-collector'
|
||||
import {handleMainActionError} from '../errors'
|
||||
import * as validate from '../../wrapper-validation/validate'
|
||||
import {getActionId, setActionId} from '../../configuration'
|
||||
import {failOnUseOfRemovedFeature, emitDeprecationWarnings} from '../../deprecation-collector'
|
||||
import {handleMainActionError} from '../../errors'
|
||||
|
||||
export async function run(): Promise<void> {
|
||||
try {
|
||||
if (getActionId() === 'gradle/wrapper-validation-action') {
|
||||
recordDeprecation(
|
||||
failOnUseOfRemovedFeature(
|
||||
'The action `gradle/wrapper-validation-action` has been replaced by `gradle/actions/wrapper-validation`'
|
||||
)
|
||||
} else {
|
||||
setActionId('gradle/actions/wrapper-validation')
|
||||
}
|
||||
|
||||
setActionId('gradle/actions/wrapper-validation')
|
||||
|
||||
const result = await validate.findInvalidWrapperJars(
|
||||
path.resolve('.'),
|
||||
+core.getInput('min-wrapper-count'),
|
||||
@@ -8,15 +8,40 @@ export interface BuildResult {
|
||||
get gradleVersion(): string
|
||||
get gradleHomeDir(): string
|
||||
get buildFailed(): boolean
|
||||
get configCacheHit(): boolean
|
||||
get buildScanUri(): string
|
||||
get buildScanFailed(): boolean
|
||||
}
|
||||
|
||||
export function loadBuildResults(): BuildResult[] {
|
||||
return getUnprocessedResults().map(filePath => {
|
||||
export class BuildResults {
|
||||
results: BuildResult[]
|
||||
|
||||
constructor(results: BuildResult[]) {
|
||||
this.results = results
|
||||
}
|
||||
|
||||
anyFailed(): boolean {
|
||||
return this.results.some(result => result.buildFailed)
|
||||
}
|
||||
|
||||
anyConfigCacheHit(): boolean {
|
||||
return this.results.some(result => result.configCacheHit)
|
||||
}
|
||||
|
||||
uniqueGradleHomes(): string[] {
|
||||
const allHomes = this.results.map(buildResult => buildResult.gradleHomeDir)
|
||||
return Array.from(new Set(allHomes))
|
||||
}
|
||||
}
|
||||
|
||||
export function loadBuildResults(): BuildResults {
|
||||
const results = getUnprocessedResults().map(filePath => {
|
||||
const content = fs.readFileSync(filePath, 'utf8')
|
||||
return JSON.parse(content) as BuildResult
|
||||
const buildResult = JSON.parse(content) as BuildResult
|
||||
addScanResults(filePath, buildResult)
|
||||
return buildResult
|
||||
})
|
||||
return new BuildResults(results)
|
||||
}
|
||||
|
||||
export function markBuildResultsProcessed(): void {
|
||||
@@ -24,7 +49,7 @@ export function markBuildResultsProcessed(): void {
|
||||
}
|
||||
|
||||
function getUnprocessedResults(): string[] {
|
||||
const buildResultsDir = path.resolve(process.env['RUNNER_TEMP']!, '.build-results')
|
||||
const buildResultsDir = path.resolve(process.env['RUNNER_TEMP']!, '.gradle-actions', 'build-results')
|
||||
if (!fs.existsSync(buildResultsDir)) {
|
||||
return []
|
||||
}
|
||||
@@ -39,6 +64,22 @@ function getUnprocessedResults(): string[] {
|
||||
})
|
||||
}
|
||||
|
||||
function addScanResults(buildResultsFile: string, buildResult: BuildResult): void {
|
||||
const buildScansDir = path.resolve(process.env['RUNNER_TEMP']!, '.gradle-actions', 'build-scans')
|
||||
if (!fs.existsSync(buildScansDir)) {
|
||||
return
|
||||
}
|
||||
|
||||
const buildScanResults = path.resolve(buildScansDir, path.basename(buildResultsFile))
|
||||
if (fs.existsSync(buildScanResults)) {
|
||||
const content = fs.readFileSync(buildScanResults, 'utf8')
|
||||
const scanResults = JSON.parse(content)
|
||||
Object.assign(buildResult, scanResults)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
function isProcessed(resultFile: string): boolean {
|
||||
const markerFile = `${resultFile}.processed`
|
||||
return fs.existsSync(markerFile)
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
import * as core from '@actions/core'
|
||||
import {BuildScanConfig} from './configuration'
|
||||
|
||||
export function setup(config: BuildScanConfig): void {
|
||||
maybeExportVariable('DEVELOCITY_INJECTION_INIT_SCRIPT_NAME', 'gradle-actions.inject-develocity.init.gradle')
|
||||
maybeExportVariable('DEVELOCITY_AUTO_INJECTION_CUSTOM_VALUE', 'gradle-actions')
|
||||
if (config.getBuildScanPublishEnabled()) {
|
||||
maybeExportVariable('DEVELOCITY_INJECTION_ENABLED', 'true')
|
||||
maybeExportVariable('DEVELOCITY_PLUGIN_VERSION', '3.17.2')
|
||||
maybeExportVariable('DEVELOCITY_CCUD_PLUGIN_VERSION', '2.0')
|
||||
maybeExportVariable('DEVELOCITY_TERMS_OF_USE_URL', config.getBuildScanTermsOfUseUrl())
|
||||
maybeExportVariable('DEVELOCITY_TERMS_OF_USE_AGREE', config.getBuildScanTermsOfUseAgree())
|
||||
}
|
||||
}
|
||||
|
||||
function maybeExportVariable(variableName: string, value: unknown): void {
|
||||
if (!process.env[variableName]) {
|
||||
core.exportVariable(variableName, value)
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
import * as core from '@actions/core'
|
||||
import * as exec from '@actions/exec'
|
||||
import * as glob from '@actions/glob'
|
||||
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import * as provisioner from '../execution/provision'
|
||||
|
||||
export class CacheCleaner {
|
||||
private readonly gradleUserHome: string
|
||||
@@ -13,26 +14,20 @@ export class CacheCleaner {
|
||||
this.tmpDir = tmpDir
|
||||
}
|
||||
|
||||
async prepare(): Promise<void> {
|
||||
// Reset the file-access journal so that files appear not to have been used recently
|
||||
fs.rmSync(path.resolve(this.gradleUserHome, 'caches/journal-1'), {recursive: true, force: true})
|
||||
fs.mkdirSync(path.resolve(this.gradleUserHome, 'caches/journal-1'), {recursive: true})
|
||||
fs.writeFileSync(
|
||||
path.resolve(this.gradleUserHome, 'caches/journal-1/file-access.properties'),
|
||||
'inceptionTimestamp=0'
|
||||
)
|
||||
|
||||
// Set the modification time of all files to the past: this timestamp is used when there is no matching entry in the journal
|
||||
await this.ageAllFiles()
|
||||
|
||||
// Touch all 'gc' files so that cache cleanup won't run immediately.
|
||||
await this.touchAllFiles('gc.properties')
|
||||
async prepare(): Promise<string> {
|
||||
// Save the current timestamp
|
||||
const timestamp = Date.now().toString()
|
||||
core.saveState('clean-timestamp', timestamp)
|
||||
return timestamp
|
||||
}
|
||||
|
||||
async forceCleanup(): Promise<void> {
|
||||
// Age all 'gc' files so that cache cleanup will run immediately.
|
||||
await this.ageAllFiles('gc.properties')
|
||||
const cleanTimestamp = core.getState('clean-timestamp')
|
||||
await this.forceCleanupFilesOlderThan(cleanTimestamp)
|
||||
}
|
||||
|
||||
// Visible for testing
|
||||
async forceCleanupFilesOlderThan(cleanTimestamp: string): Promise<void> {
|
||||
// Run a dummy Gradle build to trigger cache cleanup
|
||||
const cleanupProjectDir = path.resolve(this.tmpDir, 'dummy-cleanup-project')
|
||||
fs.mkdirSync(cleanupProjectDir, {recursive: true})
|
||||
@@ -40,30 +35,53 @@ export class CacheCleaner {
|
||||
path.resolve(cleanupProjectDir, 'settings.gradle'),
|
||||
'rootProject.name = "dummy-cleanup-project"'
|
||||
)
|
||||
fs.writeFileSync(
|
||||
path.resolve(cleanupProjectDir, 'init.gradle'),
|
||||
`
|
||||
beforeSettings { settings ->
|
||||
def cleanupTime = ${cleanTimestamp}
|
||||
|
||||
settings.caches {
|
||||
cleanup = Cleanup.ALWAYS
|
||||
|
||||
releasedWrappers.removeUnusedEntriesOlderThan.set(cleanupTime)
|
||||
snapshotWrappers.removeUnusedEntriesOlderThan.set(cleanupTime)
|
||||
downloadedResources.removeUnusedEntriesOlderThan.set(cleanupTime)
|
||||
createdResources.removeUnusedEntriesOlderThan.set(cleanupTime)
|
||||
buildCache.removeUnusedEntriesOlderThan.set(cleanupTime)
|
||||
}
|
||||
}
|
||||
`
|
||||
)
|
||||
fs.writeFileSync(path.resolve(cleanupProjectDir, 'build.gradle'), 'task("noop") {}')
|
||||
|
||||
const gradleCommand = `gradle -g ${this.gradleUserHome} --no-daemon --build-cache --no-scan --quiet -DGITHUB_DEPENDENCY_GRAPH_ENABLED=false noop`
|
||||
await exec.exec(gradleCommand, [], {
|
||||
cwd: cleanupProjectDir
|
||||
const executable = await provisioner.provisionGradle('current')
|
||||
|
||||
await core.group('Executing Gradle to clean up caches', async () => {
|
||||
core.info(`Cleaning up caches last used before ${cleanTimestamp}`)
|
||||
await this.executeCleanupBuild(executable!, cleanupProjectDir)
|
||||
})
|
||||
}
|
||||
|
||||
private async ageAllFiles(fileName = '*'): Promise<void> {
|
||||
core.debug(`Aging all files in Gradle User Home with name ${fileName}`)
|
||||
await this.setUtimes(`${this.gradleUserHome}/**/${fileName}`, new Date(0))
|
||||
}
|
||||
private async executeCleanupBuild(executable: string, cleanupProjectDir: string): Promise<void> {
|
||||
const args = [
|
||||
'-g',
|
||||
this.gradleUserHome,
|
||||
'-I',
|
||||
'init.gradle',
|
||||
'--info',
|
||||
'--no-daemon',
|
||||
'--no-scan',
|
||||
'--build-cache',
|
||||
'-DGITHUB_DEPENDENCY_GRAPH_ENABLED=false',
|
||||
'noop'
|
||||
]
|
||||
|
||||
private async touchAllFiles(fileName = '*'): Promise<void> {
|
||||
core.debug(`Touching all files in Gradle User Home with name ${fileName}`)
|
||||
await this.setUtimes(`${this.gradleUserHome}/**/${fileName}`, new Date())
|
||||
}
|
||||
|
||||
private async setUtimes(pattern: string, timestamp: Date): Promise<void> {
|
||||
const globber = await glob.create(pattern, {
|
||||
implicitDescendants: false
|
||||
const result = await exec.getExecOutput(executable, args, {
|
||||
cwd: cleanupProjectDir,
|
||||
silent: true
|
||||
})
|
||||
for await (const file of globber.globGenerator()) {
|
||||
fs.utimesSync(file, timestamp, timestamp)
|
||||
}
|
||||
|
||||
core.info(result.stdout)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,8 @@ export function getCacheKeyBase(cacheName: string, cacheProtocolVersion: string)
|
||||
|
||||
function getCacheKeyEnvironment(): string {
|
||||
const runnerOs = process.env['RUNNER_OS'] || ''
|
||||
return process.env[CACHE_KEY_OS_VAR] || runnerOs
|
||||
const runnerArch = process.env['RUNNER_ARCH'] || ''
|
||||
return process.env[CACHE_KEY_OS_VAR] || `${runnerOs}-${runnerArch}`
|
||||
}
|
||||
|
||||
function getCacheKeyJob(): string {
|
||||
|
||||
@@ -1,5 +1,27 @@
|
||||
import * as cache from '@actions/cache'
|
||||
|
||||
export const DEFAULT_CACHE_ENABLED_REASON = `[Cache was enabled](https://github.com/gradle/actions/blob/main/docs/setup-gradle.md#caching-build-state-between-jobs). Action attempted to both restore and save the Gradle User Home.`
|
||||
|
||||
export const DEFAULT_READONLY_REASON = `[Cache was read-only](https://github.com/gradle/actions/blob/main/docs/setup-gradle.md#using-the-cache-read-only). By default, the action will only write to the cache for Jobs running on the default branch.`
|
||||
|
||||
export const DEFAULT_DISABLED_REASON = `[Cache was disabled](https://github.com/gradle/actions/blob/main/docs/setup-gradle.md#disabling-caching) via action confiugration. Gradle User Home was not restored from or saved to the cache.`
|
||||
|
||||
export const DEFAULT_WRITEONLY_REASON = `[Cache was set to write-only](https://github.com/gradle/actions/blob/main/docs/setup-gradle.md#using-the-cache-write-only) via action configuration. Gradle User Home was not restored from cache.`
|
||||
|
||||
export const EXISTING_GRADLE_HOME = `[Cache was disabled to avoid overwriting a pre-existing Gradle User Home](https://github.com/gradle/actions/blob/main/docs/setup-gradle.md#overwriting-an-existing-gradle-user-home). Gradle User Home was not restored from or saved to the cache.`
|
||||
|
||||
export const CLEANUP_DISABLED_READONLY = `[Cache cleanup](https://github.com/gradle/actions/blob/main/docs/setup-gradle.md#configuring-cache-cleanup) is always disabled when cache is read-only or disabled.`
|
||||
|
||||
export const DEFAULT_CLEANUP_ENABLED_REASON = `[Cache cleanup](https://github.com/gradle/actions/blob/main/docs/setup-gradle.md#configuring-cache-cleanup) was enabled. Stale files in Gradle User Home were purged before saving to the cache.`
|
||||
|
||||
export const DEFAULT_CLEANUP_DISABLED_REASON = `[Cache cleanup](https://github.com/gradle/actions/blob/main/docs/setup-gradle.md#configuring-cache-cleanup) was disabled via action parameter. No cleanup of Gradle User Home was performed.`
|
||||
|
||||
export const CLEANUP_DISABLED_DUE_TO_FAILURE =
|
||||
'[Cache cleanup was disabled due to build failure](https://github.com/gradle/actions/blob/main/docs/setup-gradle.md#configuring-cache-cleanup). Use `cache-cleanup: always` to override this behavior.'
|
||||
|
||||
export const CLEANUP_DISABLED_DUE_TO_CONFIG_CACHE_HIT =
|
||||
'[Cache cleanup was disabled due to configuration-cache reuse](https://github.com/gradle/actions/blob/main/docs/setup-gradle.md#configuring-cache-cleanup). This is expected.'
|
||||
|
||||
/**
|
||||
* Collects information on what entries were saved and restored during the action.
|
||||
* This information is used to generate a summary of the cache usage.
|
||||
@@ -9,7 +31,8 @@ export class CacheListener {
|
||||
cacheReadOnly = false
|
||||
cacheWriteOnly = false
|
||||
cacheDisabled = false
|
||||
cacheDisabledReason = 'disabled'
|
||||
cacheStatusReason: string = DEFAULT_CACHE_ENABLED_REASON
|
||||
cacheCleanupMessage: string = DEFAULT_CLEANUP_DISABLED_REASON
|
||||
|
||||
get fullyRestored(): boolean {
|
||||
return this.cacheEntries.every(x => !x.wasRequestedButNotRestored())
|
||||
@@ -17,12 +40,37 @@ export class CacheListener {
|
||||
|
||||
get cacheStatus(): string {
|
||||
if (!cache.isFeatureAvailable()) return 'not available'
|
||||
if (this.cacheDisabled) return this.cacheDisabledReason
|
||||
if (this.cacheDisabled) return 'disabled'
|
||||
if (this.cacheWriteOnly) return 'write-only'
|
||||
if (this.cacheReadOnly) return 'read-only'
|
||||
return 'enabled'
|
||||
}
|
||||
|
||||
setReadOnly(reason: string = DEFAULT_READONLY_REASON): void {
|
||||
this.cacheReadOnly = true
|
||||
this.cacheStatusReason = reason
|
||||
this.cacheCleanupMessage = CLEANUP_DISABLED_READONLY
|
||||
}
|
||||
|
||||
setDisabled(reason: string = DEFAULT_DISABLED_REASON): void {
|
||||
this.cacheDisabled = true
|
||||
this.cacheStatusReason = reason
|
||||
this.cacheCleanupMessage = CLEANUP_DISABLED_READONLY
|
||||
}
|
||||
|
||||
setWriteOnly(reason: string = DEFAULT_WRITEONLY_REASON): void {
|
||||
this.cacheWriteOnly = true
|
||||
this.cacheStatusReason = reason
|
||||
}
|
||||
|
||||
setCacheCleanupEnabled(): void {
|
||||
this.cacheCleanupMessage = DEFAULT_CLEANUP_ENABLED_REASON
|
||||
}
|
||||
|
||||
setCacheCleanupDisabled(reason: string = DEFAULT_CLEANUP_DISABLED_REASON): void {
|
||||
this.cacheCleanupMessage = reason
|
||||
}
|
||||
|
||||
entry(name: string): CacheEntryListener {
|
||||
for (const entry of this.cacheEntries) {
|
||||
if (entry.entryName === name) {
|
||||
@@ -117,6 +165,10 @@ export function generateCachingReport(listener: CacheListener): string {
|
||||
return `
|
||||
<details>
|
||||
<summary><h4>Caching for Gradle actions was ${listener.cacheStatus} - expand for details</h4></summary>
|
||||
|
||||
- ${listener.cacheStatusReason}
|
||||
- ${listener.cacheCleanupMessage}
|
||||
|
||||
${renderEntryTable(entries)}
|
||||
|
||||
<h5>Cache Entry Details</h5>
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
import * as core from '@actions/core'
|
||||
import {CacheListener} from './cache-reporting'
|
||||
import {
|
||||
CacheListener,
|
||||
EXISTING_GRADLE_HOME,
|
||||
CLEANUP_DISABLED_DUE_TO_FAILURE,
|
||||
CLEANUP_DISABLED_DUE_TO_CONFIG_CACHE_HIT
|
||||
} from './cache-reporting'
|
||||
import {GradleUserHomeCache} from './gradle-user-home-cache'
|
||||
import {CacheCleaner} from './cache-cleaner'
|
||||
import {DaemonController} from '../daemon-controller'
|
||||
import {CacheConfig} from '../configuration'
|
||||
import {BuildResults} from '../build-results'
|
||||
|
||||
const CACHE_RESTORED_VAR = 'GRADLE_BUILD_ACTION_CACHE_RESTORED'
|
||||
|
||||
@@ -26,7 +32,7 @@ export async function restore(
|
||||
core.info('Cache is disabled: will not restore state from previous builds.')
|
||||
// Initialize the Gradle User Home even when caching is disabled.
|
||||
gradleStateCache.init()
|
||||
cacheListener.cacheDisabled = true
|
||||
cacheListener.setDisabled()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -35,8 +41,7 @@ export async function restore(
|
||||
core.info('Gradle User Home already exists: will not restore from cache.')
|
||||
// Initialize pre-existing Gradle User Home.
|
||||
gradleStateCache.init()
|
||||
cacheListener.cacheDisabled = true
|
||||
cacheListener.cacheDisabledReason = 'disabled due to pre-existing Gradle User Home'
|
||||
cacheListener.setDisabled(EXISTING_GRADLE_HOME)
|
||||
return
|
||||
}
|
||||
core.info('Gradle User Home already exists: will overwrite with cached contents.')
|
||||
@@ -46,21 +51,21 @@ export async function restore(
|
||||
// Mark the state as restored so that post-action will perform save.
|
||||
core.saveState(CACHE_RESTORED_VAR, true)
|
||||
|
||||
if (cacheConfig.isCacheCleanupEnabled()) {
|
||||
core.info('Preparing cache for cleanup.')
|
||||
const cacheCleaner = new CacheCleaner(gradleUserHome, process.env['RUNNER_TEMP']!)
|
||||
await cacheCleaner.prepare()
|
||||
}
|
||||
|
||||
if (cacheConfig.isCacheWriteOnly()) {
|
||||
core.info('Cache is write-only: will not restore from cache.')
|
||||
cacheListener.cacheWriteOnly = true
|
||||
cacheListener.setWriteOnly()
|
||||
return
|
||||
}
|
||||
|
||||
await core.group('Restore Gradle state from cache', async () => {
|
||||
await gradleStateCache.restore(cacheListener)
|
||||
})
|
||||
|
||||
if (cacheConfig.isCacheCleanupEnabled()) {
|
||||
core.info('Preparing cache for cleanup.')
|
||||
const cacheCleaner = new CacheCleaner(gradleUserHome, process.env['RUNNER_TEMP']!)
|
||||
await cacheCleaner.prepare()
|
||||
}
|
||||
}
|
||||
|
||||
export async function save(
|
||||
@@ -68,6 +73,7 @@ export async function save(
|
||||
gradleUserHome: string,
|
||||
cacheListener: CacheListener,
|
||||
daemonController: DaemonController,
|
||||
buildResults: BuildResults,
|
||||
cacheConfig: CacheConfig
|
||||
): Promise<void> {
|
||||
if (cacheConfig.isCacheDisabled()) {
|
||||
@@ -82,19 +88,24 @@ export async function save(
|
||||
|
||||
if (cacheConfig.isCacheReadOnly()) {
|
||||
core.info('Cache is read-only: will not save state for use in subsequent builds.')
|
||||
cacheListener.cacheReadOnly = true
|
||||
cacheListener.setReadOnly()
|
||||
return
|
||||
}
|
||||
|
||||
await daemonController.stopAllDaemons()
|
||||
await core.group('Stopping Gradle daemons', async () => {
|
||||
await daemonController.stopAllDaemons()
|
||||
})
|
||||
|
||||
if (cacheConfig.isCacheCleanupEnabled()) {
|
||||
core.info('Forcing cache cleanup.')
|
||||
const cacheCleaner = new CacheCleaner(gradleUserHome, process.env['RUNNER_TEMP']!)
|
||||
try {
|
||||
await cacheCleaner.forceCleanup()
|
||||
} catch (e) {
|
||||
core.warning(`Cache cleanup failed. Will continue. ${String(e)}`)
|
||||
if (buildResults.anyConfigCacheHit()) {
|
||||
core.info('Not performing cache-cleanup due to config-cache reuse')
|
||||
cacheListener.setCacheCleanupDisabled(CLEANUP_DISABLED_DUE_TO_CONFIG_CACHE_HIT)
|
||||
} else if (cacheConfig.shouldPerformCacheCleanup(buildResults.anyFailed())) {
|
||||
cacheListener.setCacheCleanupEnabled()
|
||||
await performCacheCleanup(gradleUserHome)
|
||||
} else {
|
||||
core.info('Not performing cache-cleanup due to build failure')
|
||||
cacheListener.setCacheCleanupDisabled(CLEANUP_DISABLED_DUE_TO_FAILURE)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,3 +113,12 @@ export async function save(
|
||||
return new GradleUserHomeCache(userHome, gradleUserHome, cacheConfig).save(cacheListener)
|
||||
})
|
||||
}
|
||||
|
||||
async function performCacheCleanup(gradleUserHome: string): Promise<void> {
|
||||
const cacheCleaner = new CacheCleaner(gradleUserHome, process.env['RUNNER_TEMP']!)
|
||||
try {
|
||||
await cacheCleaner.forceCleanup()
|
||||
} catch (e) {
|
||||
core.warning(`Cache cleanup failed. Will continue. ${String(e)}`)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,11 @@ import * as core from '@actions/core'
|
||||
import * as glob from '@actions/glob'
|
||||
import * as semver from 'semver'
|
||||
|
||||
import {META_FILE_DIR} from './gradle-user-home-cache'
|
||||
import {CacheEntryListener, CacheListener} from './cache-reporting'
|
||||
import {cacheDebug, hashFileNames, isCacheDebuggingEnabled, restoreCache, saveCache, tryDelete} from './cache-utils'
|
||||
|
||||
import {BuildResult, loadBuildResults} from '../build-results'
|
||||
import {CacheConfig} from '../configuration'
|
||||
import {CacheConfig, ACTION_METADATA_DIR} from '../configuration'
|
||||
import {getCacheKeyBase} from './cache-key'
|
||||
|
||||
const SKIP_RESTORE_VAR = 'GRADLE_BUILD_ACTION_SKIP_RESTORE'
|
||||
@@ -298,7 +297,7 @@ abstract class AbstractEntryExtractor {
|
||||
}
|
||||
|
||||
private getCacheMetadataFile(): string {
|
||||
const actionMetadataDirectory = path.resolve(this.gradleUserHome, META_FILE_DIR)
|
||||
const actionMetadataDirectory = path.resolve(this.gradleUserHome, ACTION_METADATA_DIR)
|
||||
fs.mkdirSync(actionMetadataDirectory, {recursive: true})
|
||||
|
||||
return path.resolve(actionMetadataDirectory, `${this.extractorName}-entry-metadata.json`)
|
||||
@@ -449,7 +448,7 @@ export class ConfigurationCacheEntryExtractor extends AbstractEntryExtractor {
|
||||
}
|
||||
|
||||
private getConfigCacheDirectoriesWithAssociatedBuildResults(): Record<string, BuildResult[]> {
|
||||
return loadBuildResults().reduce(
|
||||
return loadBuildResults().results.reduce(
|
||||
(acc, buildResult) => {
|
||||
// For each build result, find the config-cache dir
|
||||
const configCachePath = path.resolve(buildResult.rootProjectDir, '.gradle/configuration-cache')
|
||||
|
||||
@@ -7,14 +7,12 @@ import fs from 'fs'
|
||||
import {generateCacheKey} from './cache-key'
|
||||
import {CacheListener} from './cache-reporting'
|
||||
import {saveCache, restoreCache, cacheDebug, isCacheDebuggingEnabled, tryDelete} from './cache-utils'
|
||||
import {CacheConfig} from '../configuration'
|
||||
import {CacheConfig, ACTION_METADATA_DIR} from '../configuration'
|
||||
import {GradleHomeEntryExtractor, ConfigurationCacheEntryExtractor} from './gradle-home-extry-extractor'
|
||||
import {getPredefinedToolchains, mergeToolchainContent, readResourceFileAsString} from './gradle-user-home-utils'
|
||||
|
||||
const RESTORED_CACHE_KEY_KEY = 'restored-cache-key'
|
||||
|
||||
export const META_FILE_DIR = '.setup-gradle'
|
||||
|
||||
export class GradleUserHomeCache {
|
||||
private readonly cacheName = 'home'
|
||||
private readonly cacheDescription = 'Gradle User Home'
|
||||
@@ -86,6 +84,7 @@ export class GradleUserHomeCache {
|
||||
await this.debugReportGradleUserHomeSize('as restored from cache')
|
||||
await new GradleHomeEntryExtractor(this.gradleUserHome, this.cacheConfig).restore(listener)
|
||||
await new ConfigurationCacheEntryExtractor(this.gradleUserHome, this.cacheConfig).restore(listener)
|
||||
await this.deleteExcludedPaths()
|
||||
await this.debugReportGradleUserHomeSize('after restoring common artifacts')
|
||||
}
|
||||
|
||||
@@ -171,7 +170,7 @@ export class GradleUserHomeCache {
|
||||
*/
|
||||
protected getCachePath(): string[] {
|
||||
const rawPaths: string[] = this.cacheConfig.getCacheIncludes()
|
||||
rawPaths.push(META_FILE_DIR)
|
||||
rawPaths.push(ACTION_METADATA_DIR)
|
||||
const resolvedPaths = rawPaths.map(x => this.resolveCachePath(x))
|
||||
cacheDebug(`Using cache paths: ${resolvedPaths}`)
|
||||
return resolvedPaths
|
||||
@@ -187,7 +186,7 @@ export class GradleUserHomeCache {
|
||||
|
||||
private initializeGradleUserHome(): void {
|
||||
// Create a directory for storing action metadata
|
||||
const actionCacheDir = path.resolve(this.gradleUserHome, META_FILE_DIR)
|
||||
const actionCacheDir = path.resolve(this.gradleUserHome, ACTION_METADATA_DIR)
|
||||
fs.mkdirSync(actionCacheDir, {recursive: true})
|
||||
|
||||
this.copyInitScripts()
|
||||
|
||||
@@ -4,11 +4,12 @@ import * as cache from '@actions/cache'
|
||||
import * as deprecator from './deprecation-collector'
|
||||
import {SUMMARY_ENV_VAR} from '@actions/core/lib/summary'
|
||||
|
||||
import {parseArgsStringToArgv} from 'string-argv'
|
||||
import path from 'path'
|
||||
|
||||
const ACTION_ID_VAR = 'GRADLE_ACTION_ID'
|
||||
|
||||
export const ACTION_METADATA_DIR = '.setup-gradle'
|
||||
|
||||
export class DependencyGraphConfig {
|
||||
getDependencyGraphOption(): DependencyGraphOption {
|
||||
const val = core.getInput('dependency-graph')
|
||||
@@ -23,11 +24,9 @@ export class DependencyGraphConfig {
|
||||
return DependencyGraphOption.GenerateAndUpload
|
||||
case 'download-and-submit':
|
||||
return DependencyGraphOption.DownloadAndSubmit
|
||||
case 'clear':
|
||||
return DependencyGraphOption.Clear
|
||||
}
|
||||
throw TypeError(
|
||||
`The value '${val}' is not valid for 'dependency-graph'. Valid values are: [disabled, generate, generate-and-submit, generate-and-upload, download-and-submit, clear]. The default value is 'disabled'.`
|
||||
`The value '${val}' is not valid for 'dependency-graph'. Valid values are: [disabled, generate, generate-and-submit, generate-and-upload, download-and-submit]. The default value is 'disabled'.`
|
||||
)
|
||||
}
|
||||
|
||||
@@ -46,7 +45,28 @@ export class DependencyGraphConfig {
|
||||
}
|
||||
|
||||
getReportDirectory(): string {
|
||||
return path.resolve(getWorkspaceDirectory(), 'dependency-graph-reports')
|
||||
const param = core.getInput('dependency-graph-report-dir')
|
||||
return path.resolve(getWorkspaceDirectory(), param)
|
||||
}
|
||||
|
||||
getDownloadArtifactName(): string | undefined {
|
||||
return process.env['DEPENDENCY_GRAPH_DOWNLOAD_ARTIFACT_NAME']
|
||||
}
|
||||
|
||||
getExcludeProjects(): string | undefined {
|
||||
return getOptionalInput('dependency-graph-exclude-projects')
|
||||
}
|
||||
|
||||
getIncludeProjects(): string | undefined {
|
||||
return getOptionalInput('dependency-graph-include-projects')
|
||||
}
|
||||
|
||||
getExcludeConfigurations(): string | undefined {
|
||||
return getOptionalInput('dependency-graph-exclude-configurations')
|
||||
}
|
||||
|
||||
getIncludeConfigurations(): string | undefined {
|
||||
return getOptionalInput('dependency-graph-include-configurations')
|
||||
}
|
||||
|
||||
static constructJobCorrelator(workflow: string, jobId: string, matrixJson: string): string {
|
||||
@@ -77,8 +97,7 @@ export enum DependencyGraphOption {
|
||||
Generate = 'generate',
|
||||
GenerateAndSubmit = 'generate-and-submit',
|
||||
GenerateAndUpload = 'generate-and-upload',
|
||||
DownloadAndSubmit = 'download-and-submit',
|
||||
Clear = 'clear'
|
||||
DownloadAndSubmit = 'download-and-submit'
|
||||
}
|
||||
|
||||
export class CacheConfig {
|
||||
@@ -107,7 +126,45 @@ export class CacheConfig {
|
||||
}
|
||||
|
||||
isCacheCleanupEnabled(): boolean {
|
||||
return getBooleanInput('gradle-home-cache-cleanup') && !this.isCacheReadOnly()
|
||||
if (this.isCacheReadOnly()) {
|
||||
return false
|
||||
}
|
||||
const cleanupOption = this.getCacheCleanupOption()
|
||||
return cleanupOption === CacheCleanupOption.Always || cleanupOption === CacheCleanupOption.OnSuccess
|
||||
}
|
||||
|
||||
shouldPerformCacheCleanup(hasFailure: boolean): boolean {
|
||||
const cleanupOption = this.getCacheCleanupOption()
|
||||
if (cleanupOption === CacheCleanupOption.Always) {
|
||||
return true
|
||||
}
|
||||
if (cleanupOption === CacheCleanupOption.OnSuccess) {
|
||||
return !hasFailure
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private getCacheCleanupOption(): CacheCleanupOption {
|
||||
const legacyVal = getOptionalBooleanInput('gradle-home-cache-cleanup')
|
||||
if (legacyVal !== undefined) {
|
||||
deprecator.recordDeprecation(
|
||||
'The `gradle-home-cache-cleanup` input parameter has been replaced by `cache-cleanup`'
|
||||
)
|
||||
return legacyVal ? CacheCleanupOption.Always : CacheCleanupOption.Never
|
||||
}
|
||||
|
||||
const val = core.getInput('cache-cleanup')
|
||||
switch (val.toLowerCase().trim()) {
|
||||
case 'always':
|
||||
return CacheCleanupOption.Always
|
||||
case 'on-success':
|
||||
return CacheCleanupOption.OnSuccess
|
||||
case 'never':
|
||||
return CacheCleanupOption.Never
|
||||
}
|
||||
throw TypeError(
|
||||
`The value '${val}' is not valid for cache-cleanup. Valid values are: [never, always, on-success].`
|
||||
)
|
||||
}
|
||||
|
||||
getCacheEncryptionKey(): string {
|
||||
@@ -123,6 +180,12 @@ export class CacheConfig {
|
||||
}
|
||||
}
|
||||
|
||||
export enum CacheCleanupOption {
|
||||
Never = 'never',
|
||||
OnSuccess = 'on-success',
|
||||
Always = 'always'
|
||||
}
|
||||
|
||||
export class SummaryConfig {
|
||||
shouldGenerateJobSummary(hasFailure: boolean): boolean {
|
||||
// Check if Job Summary is supported on this platform
|
||||
@@ -130,11 +193,6 @@ export class SummaryConfig {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check if Job Summary is disabled using the deprecated input
|
||||
if (!this.isJobSummaryEnabled()) {
|
||||
return false
|
||||
}
|
||||
|
||||
return this.shouldAddJobSummary(this.getJobSummaryOption(), hasFailure)
|
||||
}
|
||||
|
||||
@@ -153,10 +211,6 @@ export class SummaryConfig {
|
||||
}
|
||||
}
|
||||
|
||||
private isJobSummaryEnabled(): boolean {
|
||||
return getBooleanInput('generate-job-summary', true)
|
||||
}
|
||||
|
||||
private getJobSummaryOption(): JobSummaryOption {
|
||||
return this.parseJobSummaryOption('add-job-summary')
|
||||
}
|
||||
@@ -188,16 +242,72 @@ export enum JobSummaryOption {
|
||||
}
|
||||
|
||||
export class BuildScanConfig {
|
||||
static DevelocityAccessKeyEnvVar = 'DEVELOCITY_ACCESS_KEY'
|
||||
static GradleEnterpriseAccessKeyEnvVar = 'GRADLE_ENTERPRISE_ACCESS_KEY'
|
||||
|
||||
getBuildScanPublishEnabled(): boolean {
|
||||
return getBooleanInput('build-scan-publish') && this.verifyTermsOfUseAgreement()
|
||||
}
|
||||
|
||||
getBuildScanTermsOfUseUrl(): string {
|
||||
return this.getTermsOfUseProp('build-scan-terms-of-use-url', 'build-scan-terms-of-service-url')
|
||||
return core.getInput('build-scan-terms-of-use-url')
|
||||
}
|
||||
|
||||
getBuildScanTermsOfUseAgree(): string {
|
||||
return this.getTermsOfUseProp('build-scan-terms-of-use-agree', 'build-scan-terms-of-service-agree')
|
||||
return core.getInput('build-scan-terms-of-use-agree')
|
||||
}
|
||||
|
||||
getDevelocityAccessKey(): string {
|
||||
return (
|
||||
core.getInput('develocity-access-key') ||
|
||||
process.env[BuildScanConfig.DevelocityAccessKeyEnvVar] ||
|
||||
process.env[BuildScanConfig.GradleEnterpriseAccessKeyEnvVar] ||
|
||||
''
|
||||
)
|
||||
}
|
||||
|
||||
getDevelocityTokenExpiry(): string {
|
||||
return core.getInput('develocity-token-expiry')
|
||||
}
|
||||
|
||||
getDevelocityInjectionEnabled(): boolean | undefined {
|
||||
return getOptionalBooleanInput('develocity-injection-enabled')
|
||||
}
|
||||
|
||||
getDevelocityUrl(): string {
|
||||
return core.getInput('develocity-url')
|
||||
}
|
||||
|
||||
getDevelocityAllowUntrustedServer(): boolean | undefined {
|
||||
return getOptionalBooleanInput('develocity-allow-untrusted-server')
|
||||
}
|
||||
|
||||
getDevelocityCaptureFileFingerprints(): boolean | undefined {
|
||||
return getOptionalBooleanInput('develocity-capture-file-fingerprints')
|
||||
}
|
||||
|
||||
getDevelocityEnforceUrl(): boolean | undefined {
|
||||
return getOptionalBooleanInput('develocity-enforce-url')
|
||||
}
|
||||
|
||||
getDevelocityPluginVersion(): string {
|
||||
return core.getInput('develocity-plugin-version')
|
||||
}
|
||||
|
||||
getDevelocityCcudPluginVersion(): string {
|
||||
return core.getInput('develocity-ccud-plugin-version')
|
||||
}
|
||||
|
||||
getGradlePluginRepositoryUrl(): string {
|
||||
return core.getInput('gradle-plugin-repository-url')
|
||||
}
|
||||
|
||||
getGradlePluginRepositoryUsername(): string {
|
||||
return core.getInput('gradle-plugin-repository-username')
|
||||
}
|
||||
|
||||
getGradlePluginRepositoryPassword(): string {
|
||||
return core.getInput('gradle-plugin-repository-password')
|
||||
}
|
||||
|
||||
private verifyTermsOfUseAgreement(): boolean {
|
||||
@@ -213,22 +323,6 @@ export class BuildScanConfig {
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO @bigdaz: remove support for the deprecated input property in the next major release of the action
|
||||
*/
|
||||
private getTermsOfUseProp(newPropName: string, oldPropName: string): string {
|
||||
const newProp = core.getInput(newPropName)
|
||||
if (newProp !== '') {
|
||||
return newProp
|
||||
}
|
||||
const oldProp = core.getInput(oldPropName)
|
||||
if (oldProp !== '') {
|
||||
deprecator.recordDeprecation('The `build-scan-terms-of-service` input parameters have been renamed')
|
||||
return oldProp
|
||||
}
|
||||
return core.getInput(oldPropName)
|
||||
}
|
||||
}
|
||||
|
||||
export class GradleExecutionConfig {
|
||||
@@ -246,16 +340,6 @@ export class GradleExecutionConfig {
|
||||
return resolvedBuildRootDirectory
|
||||
}
|
||||
|
||||
getArguments(): string[] {
|
||||
const input = core.getInput('arguments')
|
||||
if (input.length !== 0) {
|
||||
deprecator.recordDeprecation(
|
||||
'Using the action to execute Gradle via the `arguments` parameter is deprecated'
|
||||
)
|
||||
}
|
||||
return parseArgsStringToArgv(input)
|
||||
}
|
||||
|
||||
getDependencyResolutionTask(): string {
|
||||
return core.getInput('dependency-resolution-task') || ':ForceDependencyResolutionPlugin_resolveAllDependencies'
|
||||
}
|
||||
@@ -263,10 +347,26 @@ export class GradleExecutionConfig {
|
||||
getAdditionalArguments(): string {
|
||||
return core.getInput('additional-arguments')
|
||||
}
|
||||
|
||||
verifyNoArguments(): void {
|
||||
const input = core.getInput('arguments')
|
||||
if (input.length !== 0) {
|
||||
deprecator.failOnUseOfRemovedFeature(
|
||||
`The 'arguments' parameter is no longer supported for ${getActionId()}`,
|
||||
'Using the action to execute Gradle via the `arguments` parameter is deprecated'
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function doValidateWrappers(): boolean {
|
||||
return getBooleanInput('validate-wrappers')
|
||||
export class WrapperValidationConfig {
|
||||
doValidateWrappers(): boolean {
|
||||
return getBooleanInput('validate-wrappers')
|
||||
}
|
||||
|
||||
allowSnapshotWrappers(): boolean {
|
||||
return getBooleanInput('allow-snapshot-wrappers')
|
||||
}
|
||||
}
|
||||
|
||||
// Internal parameters
|
||||
@@ -301,6 +401,14 @@ export function parseNumericInput(paramName: string, paramValue: string, paramDe
|
||||
return numericValue
|
||||
}
|
||||
|
||||
function getOptionalInput(paramName: string): string | undefined {
|
||||
const paramValue = core.getInput(paramName)
|
||||
if (paramValue.length > 0) {
|
||||
return paramValue
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
function getBooleanInput(paramName: string, paramDefault = false): boolean {
|
||||
const paramValue = core.getInput(paramName)
|
||||
switch (paramValue.toLowerCase().trim()) {
|
||||
@@ -313,3 +421,11 @@ function getBooleanInput(paramName: string, paramDefault = false): boolean {
|
||||
}
|
||||
throw TypeError(`The value '${paramValue} is not valid for '${paramName}. Valid values are: [true, false]`)
|
||||
}
|
||||
|
||||
function getOptionalBooleanInput(paramName: string): boolean | undefined {
|
||||
const paramValue = core.getInput(paramName)
|
||||
if (paramValue === '') {
|
||||
return undefined
|
||||
}
|
||||
return getBooleanInput(paramName)
|
||||
}
|
||||
|
||||
@@ -2,19 +2,16 @@ import * as core from '@actions/core'
|
||||
import * as exec from '@actions/exec'
|
||||
import * as fs from 'fs'
|
||||
import * as path from 'path'
|
||||
import {BuildResult} from './build-results'
|
||||
import {BuildResults} from './build-results'
|
||||
|
||||
export class DaemonController {
|
||||
private readonly gradleHomes
|
||||
|
||||
constructor(buildResults: BuildResult[]) {
|
||||
const allHomes = buildResults.map(buildResult => buildResult.gradleHomeDir)
|
||||
this.gradleHomes = Array.from(new Set(allHomes))
|
||||
constructor(buildResults: BuildResults) {
|
||||
this.gradleHomes = buildResults.uniqueGradleHomes()
|
||||
}
|
||||
|
||||
async stopAllDaemons(): Promise<void> {
|
||||
core.info('Stopping all Gradle daemons before saving Gradle User Home state')
|
||||
|
||||
const executions: Promise<number>[] = []
|
||||
const args = ['--stop']
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ export async function setup(config: DependencyGraphConfig): Promise<void> {
|
||||
}
|
||||
// Download and submit early, for compatability with dependency review.
|
||||
if (option === DependencyGraphOption.DownloadAndSubmit) {
|
||||
maybeExportVariable('DEPENDENCY_GRAPH_REPORT_DIR', config.getReportDirectory())
|
||||
await downloadAndSubmitDependencyGraphs(config)
|
||||
return
|
||||
}
|
||||
@@ -30,22 +31,23 @@ export async function setup(config: DependencyGraphConfig): Promise<void> {
|
||||
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_ENABLED', 'true')
|
||||
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_CONTINUE_ON_FAILURE', config.getDependencyGraphContinueOnFailure())
|
||||
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_CORRELATOR', config.getJobCorrelator())
|
||||
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_ID', github.context.runId)
|
||||
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_ID', github.context.runId.toString())
|
||||
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_REF', github.context.ref)
|
||||
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_SHA', getShaFromContext())
|
||||
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_WORKSPACE', getWorkspaceDirectory())
|
||||
maybeExportVariable('DEPENDENCY_GRAPH_REPORT_DIR', config.getReportDirectory())
|
||||
|
||||
// To clear the dependency graph, we generate an empty graph by excluding all projects and configurations
|
||||
if (option === DependencyGraphOption.Clear) {
|
||||
core.exportVariable('DEPENDENCY_GRAPH_INCLUDE_PROJECTS', '')
|
||||
core.exportVariable('DEPENDENCY_GRAPH_INCLUDE_CONFIGURATIONS', '')
|
||||
}
|
||||
maybeExportVariable('DEPENDENCY_GRAPH_EXCLUDE_PROJECTS', config.getExcludeProjects())
|
||||
maybeExportVariable('DEPENDENCY_GRAPH_INCLUDE_PROJECTS', config.getIncludeProjects())
|
||||
maybeExportVariable('DEPENDENCY_GRAPH_EXCLUDE_CONFIGURATIONS', config.getExcludeConfigurations())
|
||||
maybeExportVariable('DEPENDENCY_GRAPH_INCLUDE_CONFIGURATIONS', config.getIncludeConfigurations())
|
||||
}
|
||||
|
||||
function maybeExportVariable(variableName: string, value: unknown): void {
|
||||
function maybeExportVariable(variableName: string, value: string | boolean | undefined): void {
|
||||
if (!process.env[variableName]) {
|
||||
core.exportVariable(variableName, value)
|
||||
if (value !== undefined) {
|
||||
core.exportVariable(variableName, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,26 +60,104 @@ export async function complete(config: DependencyGraphConfig): Promise<void> {
|
||||
case DependencyGraphOption.DownloadAndSubmit: // Performed in setup
|
||||
return
|
||||
case DependencyGraphOption.GenerateAndSubmit:
|
||||
case DependencyGraphOption.Clear: // Submit the empty dependency graph
|
||||
await submitDependencyGraphs(await findDependencyGraphFiles())
|
||||
await findAndSubmitDependencyGraphs(config)
|
||||
return
|
||||
case DependencyGraphOption.GenerateAndUpload:
|
||||
await uploadDependencyGraphs(await findDependencyGraphFiles(), config)
|
||||
await findAndUploadDependencyGraphs(config)
|
||||
}
|
||||
} catch (e) {
|
||||
warnOrFail(config, option, e)
|
||||
}
|
||||
}
|
||||
|
||||
async function uploadDependencyGraphs(dependencyGraphFiles: string[], config: DependencyGraphConfig): Promise<void> {
|
||||
if (dependencyGraphFiles.length === 0) {
|
||||
core.info('No dependency graph files found to upload.')
|
||||
async function downloadAndSubmitDependencyGraphs(config: DependencyGraphConfig): Promise<void> {
|
||||
if (isRunningInActEnvironment()) {
|
||||
core.info('Dependency graph not supported in the ACT environment.')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
await submitDependencyGraphs(await downloadDependencyGraphs(config))
|
||||
} catch (e) {
|
||||
warnOrFail(config, DependencyGraphOption.DownloadAndSubmit, e)
|
||||
}
|
||||
}
|
||||
|
||||
async function findAndSubmitDependencyGraphs(config: DependencyGraphConfig): Promise<void> {
|
||||
if (isRunningInActEnvironment()) {
|
||||
core.info('Dependency graph upload not supported in the ACT environment.')
|
||||
core.info(`Would upload: ${dependencyGraphFiles.join(', ')}`)
|
||||
core.info('Dependency graph not supported in the ACT environment.')
|
||||
return
|
||||
}
|
||||
|
||||
const dependencyGraphFiles = await findDependencyGraphFiles()
|
||||
try {
|
||||
await submitDependencyGraphs(dependencyGraphFiles)
|
||||
} catch (e) {
|
||||
try {
|
||||
await uploadDependencyGraphs(dependencyGraphFiles, config)
|
||||
} catch (uploadError) {
|
||||
core.info(String(uploadError))
|
||||
}
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
async function findAndUploadDependencyGraphs(config: DependencyGraphConfig): Promise<void> {
|
||||
if (isRunningInActEnvironment()) {
|
||||
core.info('Dependency graph not supported in the ACT environment.')
|
||||
return
|
||||
}
|
||||
|
||||
await uploadDependencyGraphs(await findDependencyGraphFiles(), config)
|
||||
}
|
||||
|
||||
async function downloadDependencyGraphs(config: DependencyGraphConfig): Promise<string[]> {
|
||||
const findBy = github.context.payload.workflow_run
|
||||
? {
|
||||
token: getGithubToken(),
|
||||
workflowRunId: github.context.payload.workflow_run.id,
|
||||
repositoryName: github.context.repo.repo,
|
||||
repositoryOwner: github.context.repo.owner
|
||||
}
|
||||
: undefined
|
||||
|
||||
const artifactClient = new DefaultArtifactClient()
|
||||
|
||||
let dependencyGraphArtifacts = (
|
||||
await artifactClient.listArtifacts({
|
||||
latest: true,
|
||||
findBy
|
||||
})
|
||||
).artifacts.filter(artifact => artifact.name.startsWith(DEPENDENCY_GRAPH_PREFIX))
|
||||
|
||||
const artifactName = config.getDownloadArtifactName()
|
||||
if (artifactName) {
|
||||
core.info(`Filtering for artifacts ending with ${artifactName}`)
|
||||
dependencyGraphArtifacts = dependencyGraphArtifacts.filter(artifact => artifact.name.includes(artifactName))
|
||||
}
|
||||
|
||||
for (const artifact of dependencyGraphArtifacts) {
|
||||
const downloadedArtifact = await artifactClient.downloadArtifact(artifact.id, {
|
||||
findBy
|
||||
})
|
||||
core.info(`Downloading dependency-graph artifact ${artifact.name} to ${downloadedArtifact.downloadPath}`)
|
||||
}
|
||||
|
||||
return findDependencyGraphFiles()
|
||||
}
|
||||
|
||||
async function findDependencyGraphFiles(): Promise<string[]> {
|
||||
const globber = await glob.create(`${getReportDirectory()}/**/*.json`)
|
||||
const allFiles = await globber.glob()
|
||||
const unprocessedFiles = allFiles.filter(file => !isProcessed(file))
|
||||
unprocessedFiles.forEach(markProcessed)
|
||||
core.info(`Found dependency graph files: ${unprocessedFiles.join(', ')}`)
|
||||
return unprocessedFiles
|
||||
}
|
||||
|
||||
async function uploadDependencyGraphs(dependencyGraphFiles: string[], config: DependencyGraphConfig): Promise<void> {
|
||||
if (dependencyGraphFiles.length === 0) {
|
||||
core.info('No dependency graph files found to upload.')
|
||||
return
|
||||
}
|
||||
|
||||
@@ -94,47 +174,27 @@ async function uploadDependencyGraphs(dependencyGraphFiles: string[], config: De
|
||||
}
|
||||
}
|
||||
|
||||
async function downloadAndSubmitDependencyGraphs(config: DependencyGraphConfig): Promise<void> {
|
||||
if (isRunningInActEnvironment()) {
|
||||
core.info('Dependency graph download and submit not supported in the ACT environment.')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
await submitDependencyGraphs(await downloadDependencyGraphs())
|
||||
} catch (e) {
|
||||
warnOrFail(config, DependencyGraphOption.DownloadAndSubmit, e)
|
||||
}
|
||||
}
|
||||
|
||||
async function submitDependencyGraphs(dependencyGraphFiles: string[]): Promise<void> {
|
||||
if (dependencyGraphFiles.length === 0) {
|
||||
core.info('No dependency graph files found to submit.')
|
||||
return
|
||||
}
|
||||
|
||||
if (isRunningInActEnvironment()) {
|
||||
core.info('Dependency graph submit not supported in the ACT environment.')
|
||||
core.info(`Would submit: ${dependencyGraphFiles.join(', ')}`)
|
||||
return
|
||||
}
|
||||
|
||||
for (const dependencyGraphFile of dependencyGraphFiles) {
|
||||
try {
|
||||
await submitDependencyGraphFile(dependencyGraphFile)
|
||||
} catch (error) {
|
||||
if (error instanceof RequestError) {
|
||||
throw new Error(translateErrorMessage(dependencyGraphFile, error))
|
||||
} else {
|
||||
throw error
|
||||
error.message = translateErrorMessage(dependencyGraphFile, error)
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function translateErrorMessage(jsonFile: string, error: RequestError): string {
|
||||
const relativeJsonFile = getRelativePathFromWorkspace(jsonFile)
|
||||
const mainWarning = `Dependency submission failed for ${relativeJsonFile}.\n${String(error)}`
|
||||
const mainWarning = `Dependency submission failed for ${relativeJsonFile}.\n${error.message}`
|
||||
if (error.message === 'Resource not accessible by integration') {
|
||||
return `${mainWarning}
|
||||
Please ensure that the 'contents: write' permission is available for the workflow job.
|
||||
@@ -156,45 +216,6 @@ async function submitDependencyGraphFile(jsonFile: string): Promise<void> {
|
||||
const relativeJsonFile = getRelativePathFromWorkspace(jsonFile)
|
||||
core.notice(`Submitted ${relativeJsonFile}: ${response.data.message}`)
|
||||
}
|
||||
|
||||
async function downloadDependencyGraphs(): Promise<string[]> {
|
||||
const findBy = github.context.payload.workflow_run
|
||||
? {
|
||||
token: getGithubToken(),
|
||||
workflowRunId: github.context.payload.workflow_run.id,
|
||||
repositoryName: github.context.repo.repo,
|
||||
repositoryOwner: github.context.repo.owner
|
||||
}
|
||||
: undefined
|
||||
|
||||
const artifactClient = new DefaultArtifactClient()
|
||||
|
||||
const dependencyGraphArtifacts = (
|
||||
await artifactClient.listArtifacts({
|
||||
latest: true,
|
||||
findBy
|
||||
})
|
||||
).artifacts.filter(artifact => artifact.name.startsWith(DEPENDENCY_GRAPH_PREFIX))
|
||||
|
||||
for (const artifact of dependencyGraphArtifacts) {
|
||||
const downloadedArtifact = await artifactClient.downloadArtifact(artifact.id, {
|
||||
findBy
|
||||
})
|
||||
core.info(`Downloading dependency-graph artifact ${artifact.name} to ${downloadedArtifact.downloadPath}`)
|
||||
}
|
||||
|
||||
return findDependencyGraphFiles()
|
||||
}
|
||||
|
||||
async function findDependencyGraphFiles(): Promise<string[]> {
|
||||
const globber = await glob.create(`${getReportDirectory()}/**/*.json`)
|
||||
const allFiles = await globber.glob()
|
||||
const unprocessedFiles = allFiles.filter(file => !isProcessed(file))
|
||||
unprocessedFiles.forEach(markProcessed)
|
||||
core.info(`Found dependency graph files: ${unprocessedFiles.join(', ')}`)
|
||||
return unprocessedFiles
|
||||
}
|
||||
|
||||
function getReportDirectory(): string {
|
||||
return process.env.DEPENDENCY_GRAPH_REPORT_DIR!
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import {getActionId} from './configuration'
|
||||
|
||||
const DEPRECATION_UPGRADE_PAGE = 'https://github.com/gradle/actions/blob/main/docs/deprecation-upgrade-guide.md'
|
||||
const recordedDeprecations: Deprecation[] = []
|
||||
const recordedErrors: string[] = []
|
||||
|
||||
export class Deprecation {
|
||||
constructor(readonly message: string) {}
|
||||
@@ -22,10 +23,21 @@ export function recordDeprecation(message: string): void {
|
||||
}
|
||||
}
|
||||
|
||||
export function failOnUseOfRemovedFeature(removalMessage: string, deprecationMessage: string = removalMessage): void {
|
||||
const deprecation = new Deprecation(deprecationMessage)
|
||||
const errorMessage = `${removalMessage}.\nSee ${deprecation.getDocumentationLink()}`
|
||||
recordedErrors.push(errorMessage)
|
||||
core.setFailed(errorMessage)
|
||||
}
|
||||
|
||||
export function getDeprecations(): Deprecation[] {
|
||||
return recordedDeprecations
|
||||
}
|
||||
|
||||
export function getErrors(): string[] {
|
||||
return recordedErrors
|
||||
}
|
||||
|
||||
export function emitDeprecationWarnings(hasJobSummary = true): void {
|
||||
if (recordedDeprecations.length > 0) {
|
||||
core.warning(
|
||||
@@ -38,17 +50,21 @@ export function emitDeprecationWarnings(hasJobSummary = true): void {
|
||||
}
|
||||
|
||||
export function saveDeprecationState(): void {
|
||||
core.saveState('deprecations', JSON.stringify(recordedDeprecations))
|
||||
core.saveState('deprecation-collector_deprecations', JSON.stringify(recordedDeprecations))
|
||||
core.saveState('deprecation-collector_errors', JSON.stringify(recordedErrors))
|
||||
}
|
||||
|
||||
export function restoreDeprecationState(): void {
|
||||
const stringRep = core.getState('deprecations')
|
||||
if (stringRep === '') {
|
||||
return
|
||||
const savedDeprecations = core.getState('deprecation-collector_deprecations')
|
||||
if (savedDeprecations) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
JSON.parse(savedDeprecations).forEach((obj: any) => {
|
||||
recordedDeprecations.push(new Deprecation(obj.message))
|
||||
})
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
JSON.parse(stringRep).forEach((obj: any) => {
|
||||
recordedDeprecations.push(new Deprecation(obj.message))
|
||||
})
|
||||
const savedErrors = core.getState('deprecation-collector_errors')
|
||||
if (savedErrors) {
|
||||
recordedErrors.push(...JSON.parse(savedErrors))
|
||||
}
|
||||
}
|
||||
|
||||
39
sources/src/develocity/build-scan.ts
Normal file
39
sources/src/develocity/build-scan.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import * as core from '@actions/core'
|
||||
import {BuildScanConfig} from '../configuration'
|
||||
import {setupToken} from './short-lived-token'
|
||||
|
||||
export async function setup(config: BuildScanConfig): Promise<void> {
|
||||
maybeExportVariable('DEVELOCITY_INJECTION_INIT_SCRIPT_NAME', 'gradle-actions.inject-develocity.init.gradle')
|
||||
maybeExportVariable('DEVELOCITY_AUTO_INJECTION_CUSTOM_VALUE', 'gradle-actions')
|
||||
if (config.getBuildScanPublishEnabled()) {
|
||||
maybeExportVariable('DEVELOCITY_INJECTION_ENABLED', 'true')
|
||||
maybeExportVariable('DEVELOCITY_PLUGIN_VERSION', '3.17.6')
|
||||
maybeExportVariable('DEVELOCITY_CCUD_PLUGIN_VERSION', '2.0')
|
||||
maybeExportVariable('DEVELOCITY_TERMS_OF_USE_URL', config.getBuildScanTermsOfUseUrl())
|
||||
maybeExportVariable('DEVELOCITY_TERMS_OF_USE_AGREE', config.getBuildScanTermsOfUseAgree())
|
||||
}
|
||||
|
||||
maybeExportVariableNotEmpty('DEVELOCITY_INJECTION_ENABLED', config.getDevelocityInjectionEnabled())
|
||||
maybeExportVariableNotEmpty('DEVELOCITY_URL', config.getDevelocityUrl())
|
||||
maybeExportVariableNotEmpty('DEVELOCITY_ALLOW_UNTRUSTED_SERVER', config.getDevelocityAllowUntrustedServer())
|
||||
maybeExportVariableNotEmpty('DEVELOCITY_CAPTURE_FILE_FINGERPRINTS', config.getDevelocityCaptureFileFingerprints())
|
||||
maybeExportVariableNotEmpty('DEVELOCITY_ENFORCE_URL', config.getDevelocityEnforceUrl())
|
||||
maybeExportVariableNotEmpty('DEVELOCITY_PLUGIN_VERSION', config.getDevelocityPluginVersion())
|
||||
maybeExportVariableNotEmpty('GRADLE_PLUGIN_REPOSITORY_URL', config.getGradlePluginRepositoryUrl())
|
||||
maybeExportVariableNotEmpty('GRADLE_PLUGIN_REPOSITORY_USERNAME', config.getGradlePluginRepositoryUsername())
|
||||
maybeExportVariableNotEmpty('GRADLE_PLUGIN_REPOSITORY_PASSWORD', config.getGradlePluginRepositoryPassword())
|
||||
|
||||
return setupToken(config.getDevelocityAccessKey(), config.getDevelocityTokenExpiry())
|
||||
}
|
||||
|
||||
function maybeExportVariable(variableName: string, value: unknown): void {
|
||||
if (!process.env[variableName]) {
|
||||
core.exportVariable(variableName, value)
|
||||
}
|
||||
}
|
||||
|
||||
function maybeExportVariableNotEmpty(variableName: string, value: unknown): void {
|
||||
if (value !== null && value !== undefined && value !== '') {
|
||||
maybeExportVariable(variableName, value)
|
||||
}
|
||||
}
|
||||
160
sources/src/develocity/short-lived-token.ts
Normal file
160
sources/src/develocity/short-lived-token.ts
Normal file
@@ -0,0 +1,160 @@
|
||||
import * as httpm from 'typed-rest-client/HttpClient'
|
||||
import * as core from '@actions/core'
|
||||
import {BuildScanConfig} from '../configuration'
|
||||
import {recordDeprecation} from '../deprecation-collector'
|
||||
|
||||
export async function setupToken(develocityAccessKey: string, develocityTokenExpiry: string): Promise<void> {
|
||||
if (develocityAccessKey) {
|
||||
try {
|
||||
core.debug('Fetching short-lived token...')
|
||||
const tokens = await getToken(develocityAccessKey, develocityTokenExpiry)
|
||||
if (tokens != null && !tokens.isEmpty()) {
|
||||
core.debug(`Got token(s), setting the access key env vars`)
|
||||
const token = tokens.raw()
|
||||
core.setSecret(token)
|
||||
exportAccessKeyEnvVars(token)
|
||||
} else {
|
||||
handleMissingAccessToken()
|
||||
}
|
||||
} catch (e) {
|
||||
handleMissingAccessToken()
|
||||
core.warning(`Failed to fetch short-lived token, reason: ${e}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function exportAccessKeyEnvVars(value: string): void {
|
||||
;[BuildScanConfig.DevelocityAccessKeyEnvVar, BuildScanConfig.GradleEnterpriseAccessKeyEnvVar].forEach(key =>
|
||||
core.exportVariable(key, value)
|
||||
)
|
||||
}
|
||||
|
||||
function handleMissingAccessToken(): void {
|
||||
core.warning(`Failed to fetch short-lived token for Develocity`)
|
||||
|
||||
if (process.env[BuildScanConfig.GradleEnterpriseAccessKeyEnvVar]) {
|
||||
// We do not clear the GRADLE_ENTERPRISE_ACCESS_KEY env var in v3, to let the users upgrade to DV 2024.1
|
||||
recordDeprecation(`The ${BuildScanConfig.GradleEnterpriseAccessKeyEnvVar} env var is deprecated`)
|
||||
}
|
||||
if (process.env[BuildScanConfig.DevelocityAccessKeyEnvVar]) {
|
||||
core.warning(`The ${BuildScanConfig.DevelocityAccessKeyEnvVar} env var should be mapped to a short-lived token`)
|
||||
}
|
||||
}
|
||||
|
||||
export async function getToken(accessKey: string, expiry: string): Promise<DevelocityAccessCredentials | null> {
|
||||
const empty: Promise<DevelocityAccessCredentials | null> = new Promise(r => r(null))
|
||||
const develocityAccessKey = DevelocityAccessCredentials.parse(accessKey)
|
||||
const shortLivedTokenClient = new ShortLivedTokenClient()
|
||||
|
||||
if (develocityAccessKey == null) {
|
||||
return empty
|
||||
}
|
||||
const tokens = new Array<HostnameAccessKey>()
|
||||
for (const k of develocityAccessKey.keys) {
|
||||
try {
|
||||
core.info(`Requesting short-lived Develocity access token for ${k.hostname}`)
|
||||
const token = await shortLivedTokenClient.fetchToken(`https://${k.hostname}`, k, expiry)
|
||||
tokens.push(token)
|
||||
} catch (e) {
|
||||
// Ignore failure to obtain token
|
||||
core.info(`Failed to obtain short-lived Develocity access token for ${k.hostname}: ${e}`)
|
||||
}
|
||||
}
|
||||
if (tokens.length > 0) {
|
||||
return DevelocityAccessCredentials.of(tokens)
|
||||
}
|
||||
return empty
|
||||
}
|
||||
|
||||
class ShortLivedTokenClient {
|
||||
httpc = new httpm.HttpClient('gradle/actions/setup-gradle')
|
||||
maxRetries = 3
|
||||
retryInterval = 1000
|
||||
|
||||
async fetchToken(serverUrl: string, accessKey: HostnameAccessKey, expiry: string): Promise<HostnameAccessKey> {
|
||||
const queryParams = expiry ? `?expiresInHours${expiry}` : ''
|
||||
const sanitizedServerUrl = !serverUrl.endsWith('/') ? `${serverUrl}/` : serverUrl
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${accessKey.key}`
|
||||
}
|
||||
|
||||
let attempts = 0
|
||||
while (attempts < this.maxRetries) {
|
||||
try {
|
||||
const requestUrl = `${sanitizedServerUrl}api/auth/token${queryParams}`
|
||||
core.debug(`Attempt ${attempts} to fetch short lived token at ${requestUrl}`)
|
||||
const response = await this.httpc.post(requestUrl, '', headers)
|
||||
if (response.message.statusCode === 200) {
|
||||
const text = await response.readBody()
|
||||
return new Promise<HostnameAccessKey>(resolve => resolve({hostname: accessKey.hostname, key: text}))
|
||||
}
|
||||
// This should be only 404
|
||||
attempts++
|
||||
if (attempts === this.maxRetries) {
|
||||
return new Promise((resolve, reject) =>
|
||||
reject(
|
||||
new Error(
|
||||
`Develocity short lived token request failed ${serverUrl} with status code ${response.message.statusCode}`
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
} catch (error) {
|
||||
attempts++
|
||||
if (attempts === this.maxRetries) {
|
||||
return new Promise((resolve, reject) => reject(error))
|
||||
}
|
||||
}
|
||||
await new Promise(resolve => setTimeout(resolve, this.retryInterval))
|
||||
}
|
||||
return new Promise((resolve, reject) => reject(new Error('Illegal state')))
|
||||
}
|
||||
}
|
||||
|
||||
type HostnameAccessKey = {
|
||||
hostname: string
|
||||
key: string
|
||||
}
|
||||
|
||||
export class DevelocityAccessCredentials {
|
||||
static readonly accessKeyRegexp = /^([^;=\s]+=\w+)(;[^;=\s]+=\w+)*$/
|
||||
readonly keys: HostnameAccessKey[]
|
||||
|
||||
private constructor(allKeys: HostnameAccessKey[]) {
|
||||
this.keys = allKeys
|
||||
}
|
||||
|
||||
static of(allKeys: HostnameAccessKey[]): DevelocityAccessCredentials {
|
||||
return new DevelocityAccessCredentials(allKeys)
|
||||
}
|
||||
|
||||
private static readonly keyDelimiter = ';'
|
||||
private static readonly hostDelimiter = '='
|
||||
|
||||
static parse(rawKey: string): DevelocityAccessCredentials | null {
|
||||
if (!this.isValid(rawKey)) {
|
||||
return null
|
||||
}
|
||||
return new DevelocityAccessCredentials(
|
||||
rawKey.split(this.keyDelimiter).map(hostKey => {
|
||||
const pair = hostKey.split(this.hostDelimiter)
|
||||
return {hostname: pair[0], key: pair[1]}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
isEmpty(): boolean {
|
||||
return this.keys.length === 0
|
||||
}
|
||||
|
||||
raw(): string {
|
||||
return this.keys
|
||||
.map(k => `${k.hostname}${DevelocityAccessCredentials.hostDelimiter}${k.key}`)
|
||||
.join(DevelocityAccessCredentials.keyDelimiter)
|
||||
}
|
||||
|
||||
private static isValid(allKeys: string): boolean {
|
||||
return this.accessKeyRegexp.test(allKeys)
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,10 @@ export function handleMainActionError(error: unknown): void {
|
||||
}
|
||||
}
|
||||
} else if (error instanceof JobFailure) {
|
||||
core.setFailed(String(error)) // No stack trace for JobFailure: these are known errors
|
||||
core.setFailed(String(error))
|
||||
if (error.stack) {
|
||||
core.info(error.stack)
|
||||
}
|
||||
} else {
|
||||
core.setFailed(String(error))
|
||||
if (error instanceof Error && error.stack) {
|
||||
@@ -34,6 +37,9 @@ export function handleMainActionError(error: unknown): void {
|
||||
export function handlePostActionError(error: unknown): void {
|
||||
if (error instanceof JobFailure) {
|
||||
core.setFailed(String(error))
|
||||
if (error.stack) {
|
||||
core.info(error.stack)
|
||||
}
|
||||
} else {
|
||||
core.warning(`Unhandled error in Gradle post-action - job will continue: ${error}`)
|
||||
if (error instanceof Error && error.stack) {
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import * as fs from 'fs'
|
||||
import * as os from 'os'
|
||||
import * as path from 'path'
|
||||
import which from 'which'
|
||||
import * as httpm from '@actions/http-client'
|
||||
import * as core from '@actions/core'
|
||||
import * as cache from '@actions/cache'
|
||||
import * as exec from '@actions/exec'
|
||||
import * as toolCache from '@actions/tool-cache'
|
||||
|
||||
import * as gradlew from './gradlew'
|
||||
@@ -95,12 +97,18 @@ async function findGradleVersionDeclaration(version: string): Promise<GradleVers
|
||||
|
||||
async function installGradleVersion(versionInfo: GradleVersionInfo): Promise<string> {
|
||||
return core.group(`Provision Gradle ${versionInfo.version}`, async () => {
|
||||
const preInstalledGradle = await findGradleVersionOnPath(versionInfo)
|
||||
if (preInstalledGradle !== undefined) {
|
||||
core.info(`Gradle version ${versionInfo.version} is already available on PATH. Not installing.`)
|
||||
return preInstalledGradle
|
||||
}
|
||||
|
||||
return locateGradleAndDownloadIfRequired(versionInfo)
|
||||
})
|
||||
}
|
||||
|
||||
async function locateGradleAndDownloadIfRequired(versionInfo: GradleVersionInfo): Promise<string> {
|
||||
const installsDir = path.join(os.homedir(), 'gradle-installations/installs')
|
||||
const installsDir = path.join(getProvisionDir(), 'installs')
|
||||
const installDir = path.join(installsDir, `gradle-${versionInfo.version}`)
|
||||
if (fs.existsSync(installDir)) {
|
||||
core.info(`Gradle installation already exists at ${installDir}`)
|
||||
@@ -119,7 +127,7 @@ async function locateGradleAndDownloadIfRequired(versionInfo: GradleVersionInfo)
|
||||
}
|
||||
|
||||
async function downloadAndCacheGradleDistribution(versionInfo: GradleVersionInfo): Promise<string> {
|
||||
const downloadPath = path.join(os.homedir(), `gradle-installations/downloads/gradle-${versionInfo.version}-bin.zip`)
|
||||
const downloadPath = path.join(getProvisionDir(), `downloads/gradle-${versionInfo.version}-bin.zip`)
|
||||
|
||||
// TODO: Convert this to a class and inject config
|
||||
const cacheConfig = new CacheConfig()
|
||||
@@ -152,6 +160,11 @@ async function downloadAndCacheGradleDistribution(versionInfo: GradleVersionInfo
|
||||
return downloadPath
|
||||
}
|
||||
|
||||
function getProvisionDir(): string {
|
||||
const tmpDir = process.env['RUNNER_TEMP'] ?? os.tmpdir()
|
||||
return path.join(tmpDir, `.gradle-actions/gradle-installations`)
|
||||
}
|
||||
|
||||
async function downloadGradleDistribution(versionInfo: GradleVersionInfo, downloadPath: string): Promise<void> {
|
||||
await toolCache.downloadTool(versionInfo.downloadUrl, downloadPath)
|
||||
core.info(`Downloaded ${versionInfo.downloadUrl} to ${downloadPath} (size ${fs.statSync(downloadPath).size})`)
|
||||
@@ -179,3 +192,15 @@ interface GradleVersionInfo {
|
||||
version: string
|
||||
downloadUrl: string
|
||||
}
|
||||
|
||||
async function findGradleVersionOnPath(versionInfo: GradleVersionInfo): Promise<string | undefined> {
|
||||
const gradleExecutable = await which('gradle', {nothrow: true})
|
||||
if (gradleExecutable) {
|
||||
const output = await exec.getExecOutput(gradleExecutable, ['-v'], {silent: true})
|
||||
if (output.stdout.includes(`Gradle ${versionInfo.version}`)) {
|
||||
return gradleExecutable
|
||||
}
|
||||
}
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
@@ -2,18 +2,25 @@ import * as core from '@actions/core'
|
||||
import * as github from '@actions/github'
|
||||
import {RequestError} from '@octokit/request-error'
|
||||
|
||||
import {BuildResult} from './build-results'
|
||||
import {BuildResults, BuildResult} from './build-results'
|
||||
import {SummaryConfig, getActionId, getGithubToken} from './configuration'
|
||||
import {Deprecation, getDeprecations} from './deprecation-collector'
|
||||
import {Deprecation, getDeprecations, getErrors} from './deprecation-collector'
|
||||
|
||||
export async function generateJobSummary(
|
||||
buildResults: BuildResult[],
|
||||
buildResults: BuildResults,
|
||||
cachingReport: string,
|
||||
config: SummaryConfig
|
||||
): Promise<void> {
|
||||
const summaryTable = renderSummaryTable(buildResults)
|
||||
const errors = renderErrors()
|
||||
if (errors) {
|
||||
core.summary.addRaw(errors)
|
||||
await core.summary.write()
|
||||
return
|
||||
}
|
||||
|
||||
const hasFailure = buildResults.some(result => result.buildFailed)
|
||||
const summaryTable = renderSummaryTable(buildResults.results)
|
||||
|
||||
const hasFailure = buildResults.anyFailed()
|
||||
if (config.shouldGenerateJobSummary(hasFailure)) {
|
||||
core.info('Generating Job Summary')
|
||||
|
||||
@@ -78,10 +85,18 @@ Note that this permission is never available for a workflow triggered from a rep
|
||||
return mainWarning
|
||||
}
|
||||
|
||||
function renderSummaryTable(results: BuildResult[]): string {
|
||||
export function renderSummaryTable(results: BuildResult[]): string {
|
||||
return `${renderDeprecations()}\n${renderBuildResults(results)}`
|
||||
}
|
||||
|
||||
function renderErrors(): string | undefined {
|
||||
const errors = getErrors()
|
||||
if (errors.length === 0) {
|
||||
return undefined
|
||||
}
|
||||
return errors.map(error => `<b>:x: ${error}</b>`).join('\n')
|
||||
}
|
||||
|
||||
function renderDeprecations(): string {
|
||||
const deprecations = getDeprecations()
|
||||
if (deprecations.length === 0) {
|
||||
@@ -113,7 +128,7 @@ function renderBuildResults(results: BuildResult[]): string {
|
||||
<th>Requested Tasks</th>
|
||||
<th>Gradle Version</th>
|
||||
<th>Build Outcome</th>
|
||||
<th>Build Scan®</th>
|
||||
<th>Build Scan®</th>
|
||||
</tr>${results.map(result => renderBuildResultRow(result)).join('')}
|
||||
</table>
|
||||
`
|
||||
@@ -134,23 +149,46 @@ function renderOutcome(result: BuildResult): string {
|
||||
return result.buildFailed ? ':x:' : ':white_check_mark:'
|
||||
}
|
||||
|
||||
function renderBuildScan(result: BuildResult): string {
|
||||
if (result.buildScanFailed) {
|
||||
return renderBuildScanBadge(
|
||||
'PUBLISH_FAILED',
|
||||
'orange',
|
||||
'https://docs.gradle.com/develocity/gradle-plugin/#troubleshooting'
|
||||
)
|
||||
}
|
||||
if (result.buildScanUri) {
|
||||
return renderBuildScanBadge('PUBLISHED', '06A0CE', result.buildScanUri)
|
||||
}
|
||||
return renderBuildScanBadge('NOT_PUBLISHED', 'lightgrey', 'https://scans.gradle.com')
|
||||
interface BadgeSpec {
|
||||
text: string
|
||||
alt: string
|
||||
color: string
|
||||
logo: boolean
|
||||
targetUrl: string
|
||||
}
|
||||
|
||||
function renderBuildScanBadge(outcomeText: string, outcomeColor: string, targetUrl: string): string {
|
||||
const badgeUrl = `https://img.shields.io/badge/Build%20Scan%C2%AE-${outcomeText}-${outcomeColor}?logo=Gradle`
|
||||
const badgeHtml = `<img src="${badgeUrl}" alt="Build Scan ${outcomeText}" />`
|
||||
function renderBuildScan(result: BuildResult): string {
|
||||
if (result.buildScanFailed) {
|
||||
return renderBuildScanBadge({
|
||||
text: 'Publish failed',
|
||||
alt: 'Build Scan publish failed',
|
||||
color: 'orange',
|
||||
logo: false,
|
||||
targetUrl: 'https://docs.gradle.com/develocity/gradle-plugin/#troubleshooting'
|
||||
})
|
||||
}
|
||||
if (result.buildScanUri) {
|
||||
return renderBuildScanBadge({
|
||||
text: 'Build Scan®',
|
||||
alt: 'Build Scan published',
|
||||
color: '06A0CE',
|
||||
logo: true,
|
||||
targetUrl: result.buildScanUri
|
||||
})
|
||||
}
|
||||
return renderBuildScanBadge({
|
||||
text: 'Not published',
|
||||
alt: 'Build Scan not published',
|
||||
color: 'lightgrey',
|
||||
logo: false,
|
||||
targetUrl: 'https://scans.gradle.com'
|
||||
})
|
||||
}
|
||||
|
||||
function renderBuildScanBadge({text, alt, color, logo, targetUrl}: BadgeSpec): string {
|
||||
const encodedText = encodeURIComponent(text)
|
||||
const badgeUrl = `https://img.shields.io/badge/${encodedText}-${color}${logo ? '?logo=Gradle' : ''}`
|
||||
const badgeHtml = `<img src="${badgeUrl}" alt="${alt}" />`
|
||||
return `<a href="${targetUrl}" rel="nofollow" target="_blank">${badgeHtml}</a>`
|
||||
}
|
||||
|
||||
|
||||
@@ -1,23 +1,27 @@
|
||||
import org.gradle.tooling.events.*
|
||||
import org.gradle.tooling.events.task.*
|
||||
import org.gradle.internal.operations.*
|
||||
import org.gradle.initialization.*
|
||||
import org.gradle.api.internal.tasks.execution.*
|
||||
import org.gradle.execution.*
|
||||
import org.gradle.internal.build.event.BuildEventListenerRegistryInternal
|
||||
import org.gradle.util.GradleVersion
|
||||
|
||||
// Can't use settingsEvaluated since this script is applied inside a settingsEvaluated handler
|
||||
// But projectsEvaluated is good enough, since the build service won't catch configuration failures anyway
|
||||
projectsEvaluated {
|
||||
settingsEvaluated { settings ->
|
||||
def projectTracker = gradle.sharedServices.registerIfAbsent("gradle-action-buildResultsRecorder", BuildResultsRecorder, { spec ->
|
||||
spec.getParameters().getRootProjectName().set(gradle.rootProject.name)
|
||||
spec.getParameters().getRootProjectDir().set(gradle.rootProject.rootDir.absolutePath)
|
||||
spec.getParameters().getRootProjectName().set(settings.rootProject.name)
|
||||
spec.getParameters().getRootProjectDir().set(settings.rootDir.absolutePath)
|
||||
spec.getParameters().getRequestedTasks().set(gradle.startParameter.taskNames.join(" "))
|
||||
spec.getParameters().getGradleHomeDir().set(gradle.gradleHomeDir.absolutePath)
|
||||
spec.getParameters().getInvocationId().set(gradle.ext.invocationId)
|
||||
})
|
||||
|
||||
gradle.services.get(BuildEventsListenerRegistry).onTaskCompletion(projectTracker)
|
||||
gradle.services.get(BuildEventListenerRegistryInternal).onOperationCompletion(projectTracker)
|
||||
}
|
||||
|
||||
abstract class BuildResultsRecorder implements BuildService<BuildResultsRecorder.Params>, OperationCompletionListener, AutoCloseable {
|
||||
abstract class BuildResultsRecorder implements BuildService<BuildResultsRecorder.Params>, BuildOperationListener, AutoCloseable {
|
||||
private boolean buildFailed = false
|
||||
private boolean configCacheHit = true
|
||||
interface Params extends BuildServiceParameters {
|
||||
Property<String> getRootProjectName()
|
||||
Property<String> getRootProjectDir()
|
||||
@@ -26,9 +30,19 @@ abstract class BuildResultsRecorder implements BuildService<BuildResultsRecorder
|
||||
Property<String> getInvocationId()
|
||||
}
|
||||
|
||||
public void onFinish(FinishEvent finishEvent) {
|
||||
if (finishEvent instanceof TaskFinishEvent && finishEvent.result instanceof TaskFailureResult) {
|
||||
buildFailed = true
|
||||
void started(BuildOperationDescriptor buildOperation, OperationStartEvent startEvent) {}
|
||||
|
||||
void progress(OperationIdentifier operationIdentifier, OperationProgressEvent progressEvent) {}
|
||||
|
||||
void finished(BuildOperationDescriptor buildOperation, OperationFinishEvent finishEvent) {
|
||||
if (buildOperation.details in EvaluateSettingsBuildOperationType.Details) {
|
||||
// Got EVALUATE SETTINGS event: not a config-cache hit"
|
||||
configCacheHit = false
|
||||
}
|
||||
if (buildOperation.details in RunRootBuildWorkBuildOperationType.Details) {
|
||||
if (finishEvent.failure != null) {
|
||||
buildFailed = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,8 +55,7 @@ abstract class BuildResultsRecorder implements BuildService<BuildResultsRecorder
|
||||
gradleVersion: GradleVersion.current().version,
|
||||
gradleHomeDir: getParameters().getGradleHomeDir().get(),
|
||||
buildFailed: buildFailed,
|
||||
buildScanUri: null,
|
||||
buildScanFailed: false
|
||||
configCacheHit: configCacheHit
|
||||
]
|
||||
|
||||
def runnerTempDir = System.getProperty("RUNNER_TEMP") ?: System.getenv("RUNNER_TEMP")
|
||||
@@ -52,7 +65,7 @@ abstract class BuildResultsRecorder implements BuildService<BuildResultsRecorder
|
||||
}
|
||||
|
||||
try {
|
||||
def buildResultsDir = new File(runnerTempDir, ".build-results")
|
||||
def buildResultsDir = new File(runnerTempDir, ".gradle-actions/build-results")
|
||||
buildResultsDir.mkdirs()
|
||||
def buildResultsFile = new File(buildResultsDir, githubActionStep + getParameters().getInvocationId().get() + ".json")
|
||||
if (!buildResultsFile.exists()) {
|
||||
|
||||
@@ -13,6 +13,7 @@ def GE_EXTENSION = "gradleEnterprise"
|
||||
// Only run against root build. Do not run against included builds.
|
||||
def isTopLevelBuild = gradle.getParent() == null
|
||||
if (isTopLevelBuild) {
|
||||
def resultsWriter = new ResultsWriter()
|
||||
def version = GradleVersion.current().baseVersion
|
||||
|
||||
def atLeastGradle3 = version >= GradleVersion.version("3.0")
|
||||
@@ -21,59 +22,77 @@ if (isTopLevelBuild) {
|
||||
def invocationId = "-${System.currentTimeMillis()}"
|
||||
|
||||
if (atLeastGradle6) {
|
||||
// By default, use standard mechanisms to capture build results
|
||||
def useBuildService = version >= GradleVersion.version("6.6")
|
||||
if (useBuildService) {
|
||||
captureUsingBuildService(invocationId)
|
||||
} else {
|
||||
captureUsingBuildFinished(gradle, invocationId, resultsWriter)
|
||||
}
|
||||
|
||||
// Use the Develocity plugin to also capture build scan links, when available
|
||||
settingsEvaluated { settings ->
|
||||
// By default, use standard mechanisms to capture build results
|
||||
if (useBuildService) {
|
||||
captureUsingBuildService(settings, invocationId)
|
||||
} else {
|
||||
captureUsingBuildFinished(gradle, invocationId)
|
||||
}
|
||||
|
||||
|
||||
settings.pluginManager.withPlugin(GE_PLUGIN_ID) {
|
||||
// Only execute if develocity plugin isn't applied.
|
||||
if (!settings.extensions.findByName(DEVELOCITY_EXTENSION)) {
|
||||
captureUsingBuildScanPublished(settings.extensions[GE_EXTENSION].buildScan, settings.rootProject, invocationId)
|
||||
captureUsingBuildScanPublished(settings.extensions[GE_EXTENSION].buildScan, invocationId, resultsWriter)
|
||||
}
|
||||
}
|
||||
|
||||
settings.pluginManager.withPlugin(DEVELOCITY_PLUGIN_ID) {
|
||||
captureUsingBuildScanPublished(settings.extensions[DEVELOCITY_EXTENSION].buildScan, settings.rootProject, invocationId)
|
||||
captureUsingBuildScanPublished(settings.extensions[DEVELOCITY_EXTENSION].buildScan, invocationId, resultsWriter)
|
||||
}
|
||||
}
|
||||
} else if (atLeastGradle3) {
|
||||
projectsEvaluated { gradle ->
|
||||
// By default, use 'buildFinished' to capture build results
|
||||
captureUsingBuildFinished(gradle, invocationId)
|
||||
captureUsingBuildFinished(gradle, invocationId, resultsWriter)
|
||||
|
||||
gradle.rootProject.pluginManager.withPlugin(BUILD_SCAN_PLUGIN_ID) {
|
||||
// Only execute if develocity plugin isn't applied.
|
||||
if (!gradle.rootProject.extensions.findByName(DEVELOCITY_EXTENSION)) {
|
||||
captureUsingBuildScanPublished(gradle.rootProject.extensions[BUILD_SCAN_EXTENSION], gradle.rootProject, invocationId)
|
||||
captureUsingBuildScanPublished(gradle.rootProject.extensions[BUILD_SCAN_EXTENSION], invocationId, resultsWriter)
|
||||
}
|
||||
}
|
||||
|
||||
gradle.rootProject.pluginManager.withPlugin(DEVELOCITY_PLUGIN_ID) {
|
||||
captureUsingBuildScanPublished(gradle.rootProject.extensions[DEVELOCITY_EXTENSION].buildScan, gradle.rootProject, invocationId)
|
||||
captureUsingBuildScanPublished(gradle.rootProject.extensions[DEVELOCITY_EXTENSION].buildScan, invocationId, resultsWriter)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def captureUsingBuildService(invocationId) {
|
||||
gradle.ext.invocationId = invocationId
|
||||
apply from: 'gradle-actions.build-result-capture-service.plugin.groovy'
|
||||
}
|
||||
|
||||
void captureUsingBuildFinished(gradle, String invocationId, ResultsWriter resultsWriter) {
|
||||
gradle.buildFinished { result ->
|
||||
println "Got buildFinished: ${result}"
|
||||
def buildResults = [
|
||||
rootProjectName: rootProject.name,
|
||||
rootProjectDir: rootProject.projectDir.absolutePath,
|
||||
requestedTasks: gradle.startParameter.taskNames.join(" "),
|
||||
gradleVersion: GradleVersion.current().version,
|
||||
gradleHomeDir: gradle.gradleHomeDir.absolutePath,
|
||||
buildFailed: result.failure != null,
|
||||
configCacheHit: false
|
||||
]
|
||||
resultsWriter.writeToResultsFile("build-results", invocationId, buildResults)
|
||||
}
|
||||
}
|
||||
|
||||
// The `buildScanPublished` hook allows the capture of the Build Scan URI.
|
||||
// Results captured this way will overwrite any results from 'buildFinished'.
|
||||
def captureUsingBuildScanPublished(buildScanExtension, rootProject, invocationId) {
|
||||
void captureUsingBuildScanPublished(buildScanExtension, String invocationId, ResultsWriter resultsWriter) {
|
||||
buildScanExtension.with {
|
||||
def buildResults = new BuildResults(invocationId, gradle, rootProject)
|
||||
|
||||
buildFinished { result ->
|
||||
buildResults.setBuildResult(result)
|
||||
}
|
||||
|
||||
buildScanPublished { buildScan ->
|
||||
buildResults.setBuildScanUri(buildScan.buildScanUri.toASCIIString())
|
||||
buildResults.writeToResultsFile(true)
|
||||
def scanResults = [
|
||||
buildScanUri: buildScan.buildScanUri.toASCIIString(),
|
||||
buildScanFailed: false
|
||||
]
|
||||
resultsWriter.writeToResultsFile("build-scans", invocationId, scanResults)
|
||||
|
||||
def githubOutput = System.getenv("GITHUB_OUTPUT")
|
||||
if (githubOutput) {
|
||||
@@ -85,63 +104,17 @@ def captureUsingBuildScanPublished(buildScanExtension, rootProject, invocationId
|
||||
}
|
||||
|
||||
onError { error ->
|
||||
buildResults.setBuildScanFailed()
|
||||
buildResults.writeToResultsFile(true)
|
||||
def scanResults = [
|
||||
buildScanUri: null,
|
||||
buildScanFailed: true
|
||||
]
|
||||
resultsWriter.writeToResultsFile("build-scans", invocationId, scanResults)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def captureUsingBuildFinished(gradle, invocationId) {
|
||||
gradle.buildFinished { result ->
|
||||
println "Got buildFinished: ${result}"
|
||||
def buildResults = new BuildResults(invocationId, gradle, gradle.rootProject)
|
||||
buildResults.setBuildResult(result)
|
||||
buildResults.writeToResultsFile(false)
|
||||
}
|
||||
}
|
||||
|
||||
def captureUsingBuildService(settings, invocationId) {
|
||||
gradle.ext.invocationId = invocationId
|
||||
apply from: 'gradle-actions.build-result-capture-service.plugin.groovy'
|
||||
}
|
||||
|
||||
class BuildResults {
|
||||
def invocationId
|
||||
def buildResults
|
||||
|
||||
BuildResults(String invocationId, def gradle, def rootProject) {
|
||||
this.invocationId = invocationId
|
||||
buildResults = [
|
||||
rootProjectName: rootProject.name,
|
||||
rootProjectDir: rootProject.projectDir.absolutePath,
|
||||
requestedTasks: gradle.startParameter.taskNames.join(" "),
|
||||
gradleVersion: GradleVersion.current().version,
|
||||
gradleHomeDir: gradle.gradleHomeDir.absolutePath,
|
||||
buildFailed: false,
|
||||
buildScanUri: null,
|
||||
buildScanFailed: false
|
||||
]
|
||||
}
|
||||
|
||||
def setBuildResult(def result) {
|
||||
try {
|
||||
// Gradle and old Build Scan/Gradle Enterprise plugins report a single optional failure in the build result
|
||||
buildResults['buildFailed'] = result.failure != null
|
||||
} catch (Exception e) {
|
||||
// Develocity plugin unwraps all build failures and reports them as a mandatory array
|
||||
buildResults['buildFailed'] = !result.failures.empty
|
||||
}
|
||||
}
|
||||
|
||||
def setBuildScanUri(def buildScanUrl) {
|
||||
buildResults['buildScanUri'] = buildScanUrl
|
||||
}
|
||||
|
||||
def setBuildScanFailed() {
|
||||
buildResults['buildScanFailed'] = true
|
||||
}
|
||||
|
||||
def writeToResultsFile(boolean overwrite) {
|
||||
class ResultsWriter {
|
||||
void writeToResultsFile(String subDir, String invocationId, def content) {
|
||||
def runnerTempDir = System.getProperty("RUNNER_TEMP") ?: System.getenv("RUNNER_TEMP")
|
||||
def githubActionStep = System.getProperty("GITHUB_ACTION") ?: System.getenv("GITHUB_ACTION")
|
||||
if (!runnerTempDir || !githubActionStep) {
|
||||
@@ -149,19 +122,12 @@ class BuildResults {
|
||||
}
|
||||
|
||||
try {
|
||||
def buildResultsDir = new File(runnerTempDir, ".build-results")
|
||||
def buildResultsDir = new File(runnerTempDir, ".gradle-actions/${subDir}")
|
||||
buildResultsDir.mkdirs()
|
||||
def buildResultsFile = new File(buildResultsDir, githubActionStep + invocationId + ".json")
|
||||
|
||||
// Overwrite any contents written by buildFinished or build service, since this result is a superset.
|
||||
if (buildResultsFile.exists()) {
|
||||
if (overwrite) {
|
||||
buildResultsFile.text = groovy.json.JsonOutput.toJson(buildResults)
|
||||
}
|
||||
} else {
|
||||
buildResultsFile << groovy.json.JsonOutput.toJson(buildResults)
|
||||
if (!buildResultsFile.exists()) {
|
||||
buildResultsFile << groovy.json.JsonOutput.toJson(content)
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
println "\ngradle action failed to write build-results file. Will continue.\n> ${e.getLocalizedMessage()}"
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ buildscript {
|
||||
def pluginRepositoryUrl = getInputParam('gradle.plugin-repository.url') ?: 'https://plugins.gradle.org/m2'
|
||||
def pluginRepositoryUsername = getInputParam('gradle.plugin-repository.username')
|
||||
def pluginRepositoryPassword = getInputParam('gradle.plugin-repository.password')
|
||||
def dependencyGraphPluginVersion = getInputParam('dependency-graph-plugin.version') ?: '1.3.0'
|
||||
def dependencyGraphPluginVersion = getInputParam('dependency-graph-plugin.version') ?: '1.3.1'
|
||||
|
||||
logger.lifecycle("Resolving dependency graph plugin ${dependencyGraphPluginVersion} from plugin repository: ${pluginRepositoryUrl}")
|
||||
repositories {
|
||||
|
||||
@@ -12,7 +12,7 @@ if (gradleVersion < GradleVersion.version("5.2") ||
|
||||
if (getVariable('GITHUB_DEPENDENCY_GRAPH_CONTINUE_ON_FAILURE') != "true") {
|
||||
throw new GradleException("Dependency Graph is not supported for ${gradleVersion}. No dependency snapshot will be generated.")
|
||||
}
|
||||
println "::warning::Dependency Graph is not supported for ${gradleVersion}. No dependency snapshot will be generated."
|
||||
logger.warn("::warning::Dependency Graph is not supported for ${gradleVersion}. No dependency snapshot will be generated.")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -23,11 +23,11 @@ if (isTopLevelBuild) {
|
||||
def reportFile = getUniqueReportFile(getVariable('GITHUB_DEPENDENCY_GRAPH_JOB_CORRELATOR'))
|
||||
|
||||
if (reportFile == null) {
|
||||
println "::warning::No dependency snapshot generated for step. Could not determine unique job correlator - specify GITHUB_DEPENDENCY_GRAPH_JOB_CORRELATOR var for this step."
|
||||
logger.warn("::warning::No dependency snapshot generated for step. Could not determine unique job correlator - specify GITHUB_DEPENDENCY_GRAPH_JOB_CORRELATOR var for this step.")
|
||||
return
|
||||
}
|
||||
|
||||
println "Generating dependency graph into '${reportFile}'"
|
||||
logger.lifecycle("Generating dependency graph into '${reportFile}'")
|
||||
}
|
||||
|
||||
apply from: 'gradle-actions.github-dependency-graph-gradle-plugin-apply.groovy'
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
/*
|
||||
* Initscript for injection of Develocity into Gradle builds.
|
||||
* Version: v1.0
|
||||
*/
|
||||
|
||||
import org.gradle.util.GradleVersion
|
||||
|
||||
// note that there is no mechanism to share code between the initscript{} block and the main script, so some logic is duplicated
|
||||
|
||||
// conditionally apply the Develocity plugin to the classpath so it can be applied to the build further down in this script
|
||||
initscript {
|
||||
// NOTE: there is no mechanism to share code between the initscript{} block and the main script, so some logic is duplicated
|
||||
def isTopLevelBuild = !gradle.parent
|
||||
if (!isTopLevelBuild) {
|
||||
return
|
||||
}
|
||||
|
||||
def getInputParam = { String name ->
|
||||
def envVarName = name.toUpperCase().replace('.', '_').replace('-', '_')
|
||||
def ENV_VAR_PREFIX = ''
|
||||
def envVarName = ENV_VAR_PREFIX + name.toUpperCase().replace('.', '_').replace('-', '_')
|
||||
return System.getProperty(name) ?: System.getenv(envVarName)
|
||||
}
|
||||
|
||||
@@ -20,9 +24,9 @@ initscript {
|
||||
return
|
||||
}
|
||||
|
||||
// finish early if injection is disabled
|
||||
def gradleInjectionEnabled = getInputParam("develocity.injection-enabled")
|
||||
if (gradleInjectionEnabled != "true") {
|
||||
// Plugin loading is only required for Develocity injection. Abort early if not enabled.
|
||||
def develocityInjectionEnabled = Boolean.parseBoolean(getInputParam("develocity.injection-enabled"))
|
||||
if (!develocityInjectionEnabled) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -75,29 +79,17 @@ initscript {
|
||||
}
|
||||
}
|
||||
|
||||
def BUILD_SCAN_PLUGIN_ID = 'com.gradle.build-scan'
|
||||
def BUILD_SCAN_PLUGIN_CLASS = 'com.gradle.scan.plugin.BuildScanPlugin'
|
||||
|
||||
def GRADLE_ENTERPRISE_PLUGIN_ID = 'com.gradle.enterprise'
|
||||
def GRADLE_ENTERPRISE_PLUGIN_CLASS = 'com.gradle.enterprise.gradleplugin.GradleEnterprisePlugin'
|
||||
|
||||
def DEVELOCITY_PLUGIN_ID = 'com.gradle.develocity'
|
||||
def DEVELOCITY_PLUGIN_CLASS = 'com.gradle.develocity.agent.gradle.DevelocityPlugin'
|
||||
|
||||
def CI_AUTO_INJECTION_CUSTOM_VALUE_NAME = 'CI auto injection'
|
||||
def CCUD_PLUGIN_ID = 'com.gradle.common-custom-user-data-gradle-plugin'
|
||||
def CCUD_PLUGIN_CLASS = 'com.gradle.CommonCustomUserDataGradlePlugin'
|
||||
static getInputParam(String name) {
|
||||
def ENV_VAR_PREFIX = ''
|
||||
def envVarName = ENV_VAR_PREFIX + name.toUpperCase().replace('.', '_').replace('-', '_')
|
||||
return System.getProperty(name) ?: System.getenv(envVarName)
|
||||
}
|
||||
|
||||
def isTopLevelBuild = !gradle.parent
|
||||
if (!isTopLevelBuild) {
|
||||
return
|
||||
}
|
||||
|
||||
def getInputParam = { String name ->
|
||||
def envVarName = name.toUpperCase().replace('.', '_').replace('-', '_')
|
||||
return System.getProperty(name) ?: System.getenv(envVarName)
|
||||
}
|
||||
|
||||
def requestedInitScriptName = getInputParam('develocity.injection.init-script-name')
|
||||
def initScriptName = buildscript.sourceFile.name
|
||||
if (requestedInitScriptName != initScriptName) {
|
||||
@@ -105,205 +97,226 @@ if (requestedInitScriptName != initScriptName) {
|
||||
return
|
||||
}
|
||||
|
||||
// finish early if injection is disabled
|
||||
def gradleInjectionEnabled = getInputParam("develocity.injection-enabled")
|
||||
if (gradleInjectionEnabled != "true") {
|
||||
return
|
||||
def develocityInjectionEnabled = Boolean.parseBoolean(getInputParam("develocity.injection-enabled"))
|
||||
if (develocityInjectionEnabled) {
|
||||
enableDevelocityInjection()
|
||||
}
|
||||
|
||||
def develocityUrl = getInputParam('develocity.url')
|
||||
def develocityAllowUntrustedServer = Boolean.parseBoolean(getInputParam('develocity.allow-untrusted-server'))
|
||||
def develocityEnforceUrl = Boolean.parseBoolean(getInputParam('develocity.enforce-url'))
|
||||
def buildScanUploadInBackground = Boolean.parseBoolean(getInputParam('develocity.build-scan.upload-in-background'))
|
||||
def develocityCaptureFileFingerprints = getInputParam('develocity.capture-file-fingerprints') ? Boolean.parseBoolean(getInputParam('develocity.capture-file-fingerprints')) : true
|
||||
def develocityPluginVersion = getInputParam('develocity.plugin.version')
|
||||
def ccudPluginVersion = getInputParam('develocity.ccud-plugin.version')
|
||||
def buildScanTermsOfUseUrl = getInputParam('develocity.terms-of-use.url')
|
||||
def buildScanTermsOfUseAgree = getInputParam('develocity.terms-of-use.agree')
|
||||
def ciAutoInjectionCustomValueValue = getInputParam('develocity.auto-injection.custom-value')
|
||||
// To enable build-scan capture, a `captureBuildScanLink(String)` method must be added to `BuildScanCollector`.
|
||||
def buildScanCollector = new BuildScanCollector()
|
||||
def buildScanCaptureEnabled = buildScanCollector.metaClass.respondsTo(buildScanCollector, 'captureBuildScanLink', String)
|
||||
if (buildScanCaptureEnabled) {
|
||||
enableBuildScanLinkCapture(buildScanCollector)
|
||||
}
|
||||
|
||||
def atLeastGradle5 = GradleVersion.current() >= GradleVersion.version('5.0')
|
||||
def atLeastGradle4 = GradleVersion.current() >= GradleVersion.version('4.0')
|
||||
def shouldApplyDevelocityPlugin = atLeastGradle5 && develocityPluginVersion && isAtLeast(develocityPluginVersion, '3.17')
|
||||
void enableDevelocityInjection() {
|
||||
def BUILD_SCAN_PLUGIN_ID = 'com.gradle.build-scan'
|
||||
def BUILD_SCAN_PLUGIN_CLASS = 'com.gradle.scan.plugin.BuildScanPlugin'
|
||||
|
||||
def dvOrGe = { def dvValue, def geValue ->
|
||||
if (shouldApplyDevelocityPlugin) {
|
||||
return dvValue instanceof Closure<?> ? dvValue() : dvValue
|
||||
def GRADLE_ENTERPRISE_PLUGIN_ID = 'com.gradle.enterprise'
|
||||
def GRADLE_ENTERPRISE_PLUGIN_CLASS = 'com.gradle.enterprise.gradleplugin.GradleEnterprisePlugin'
|
||||
|
||||
def DEVELOCITY_PLUGIN_ID = 'com.gradle.develocity'
|
||||
def DEVELOCITY_PLUGIN_CLASS = 'com.gradle.develocity.agent.gradle.DevelocityPlugin'
|
||||
|
||||
def CI_AUTO_INJECTION_CUSTOM_VALUE_NAME = 'CI auto injection'
|
||||
def CCUD_PLUGIN_ID = 'com.gradle.common-custom-user-data-gradle-plugin'
|
||||
def CCUD_PLUGIN_CLASS = 'com.gradle.CommonCustomUserDataGradlePlugin'
|
||||
|
||||
def develocityUrl = getInputParam('develocity.url')
|
||||
def develocityAllowUntrustedServer = Boolean.parseBoolean(getInputParam('develocity.allow-untrusted-server'))
|
||||
def develocityEnforceUrl = Boolean.parseBoolean(getInputParam('develocity.enforce-url'))
|
||||
def buildScanUploadInBackground = Boolean.parseBoolean(getInputParam('develocity.build-scan.upload-in-background'))
|
||||
def develocityCaptureFileFingerprints = getInputParam('develocity.capture-file-fingerprints') ? Boolean.parseBoolean(getInputParam('develocity.capture-file-fingerprints')) : true
|
||||
def develocityPluginVersion = getInputParam('develocity.plugin.version')
|
||||
def ccudPluginVersion = getInputParam('develocity.ccud-plugin.version')
|
||||
def buildScanTermsOfUseUrl = getInputParam('develocity.terms-of-use.url')
|
||||
def buildScanTermsOfUseAgree = getInputParam('develocity.terms-of-use.agree')
|
||||
def ciAutoInjectionCustomValueValue = getInputParam('develocity.auto-injection.custom-value')
|
||||
|
||||
def atLeastGradle5 = GradleVersion.current() >= GradleVersion.version('5.0')
|
||||
def atLeastGradle4 = GradleVersion.current() >= GradleVersion.version('4.0')
|
||||
def shouldApplyDevelocityPlugin = atLeastGradle5 && develocityPluginVersion && isAtLeast(develocityPluginVersion, '3.17')
|
||||
|
||||
def dvOrGe = { def dvValue, def geValue ->
|
||||
if (shouldApplyDevelocityPlugin) {
|
||||
return dvValue instanceof Closure<?> ? dvValue() : dvValue
|
||||
}
|
||||
return geValue instanceof Closure<?> ? geValue() : geValue
|
||||
}
|
||||
return geValue instanceof Closure<?> ? geValue() : geValue
|
||||
}
|
||||
|
||||
// finish early if configuration parameters passed in via system properties are not valid/supported
|
||||
if (ccudPluginVersion && isNotAtLeast(ccudPluginVersion, '1.7')) {
|
||||
logger.warn("Common Custom User Data Gradle plugin must be at least 1.7. Configured version is $ccudPluginVersion.")
|
||||
return
|
||||
}
|
||||
// finish early if configuration parameters passed in via system properties are not valid/supported
|
||||
if (ccudPluginVersion && isNotAtLeast(ccudPluginVersion, '1.7')) {
|
||||
logger.warn("Common Custom User Data Gradle plugin must be at least 1.7. Configured version is $ccudPluginVersion.")
|
||||
return
|
||||
}
|
||||
|
||||
// register buildScanPublished listener and optionally apply the Develocity plugin
|
||||
if (GradleVersion.current() < GradleVersion.version('6.0')) {
|
||||
rootProject {
|
||||
buildscript.configurations.getByName("classpath").incoming.afterResolve { ResolvableDependencies incoming ->
|
||||
def resolutionResult = incoming.resolutionResult
|
||||
// Conditionally apply and configure the Develocity plugin
|
||||
if (GradleVersion.current() < GradleVersion.version('6.0')) {
|
||||
rootProject {
|
||||
buildscript.configurations.getByName("classpath").incoming.afterResolve { ResolvableDependencies incoming ->
|
||||
def resolutionResult = incoming.resolutionResult
|
||||
|
||||
if (develocityPluginVersion) {
|
||||
def scanPluginComponent = resolutionResult.allComponents.find {
|
||||
it.moduleVersion.with { group == "com.gradle" && ['build-scan-plugin', 'gradle-enterprise-gradle-plugin', 'develocity-gradle-plugin'].contains(name) }
|
||||
}
|
||||
if (!scanPluginComponent) {
|
||||
def pluginClass = dvOrGe(DEVELOCITY_PLUGIN_CLASS, BUILD_SCAN_PLUGIN_CLASS)
|
||||
logger.lifecycle("Applying $pluginClass via init script")
|
||||
applyPluginExternally(pluginManager, pluginClass)
|
||||
def rootExtension = dvOrGe(
|
||||
if (develocityPluginVersion) {
|
||||
def scanPluginComponent = resolutionResult.allComponents.find {
|
||||
it.moduleVersion.with { group == "com.gradle" && ['build-scan-plugin', 'gradle-enterprise-gradle-plugin', 'develocity-gradle-plugin'].contains(name) }
|
||||
}
|
||||
if (!scanPluginComponent) {
|
||||
def pluginClass = dvOrGe(DEVELOCITY_PLUGIN_CLASS, BUILD_SCAN_PLUGIN_CLASS)
|
||||
logger.lifecycle("Applying $pluginClass via init script")
|
||||
applyPluginExternally(pluginManager, pluginClass)
|
||||
def rootExtension = dvOrGe(
|
||||
{ develocity },
|
||||
{ buildScan }
|
||||
)
|
||||
def buildScanExtension = dvOrGe(
|
||||
)
|
||||
def buildScanExtension = dvOrGe(
|
||||
{ rootExtension.buildScan },
|
||||
{ rootExtension }
|
||||
)
|
||||
if (develocityUrl) {
|
||||
logger.lifecycle("Connection to Develocity: $develocityUrl, allowUntrustedServer: $develocityAllowUntrustedServer, captureFileFingerprints: $develocityCaptureFileFingerprints")
|
||||
rootExtension.server = develocityUrl
|
||||
rootExtension.allowUntrustedServer = develocityAllowUntrustedServer
|
||||
}
|
||||
if (!shouldApplyDevelocityPlugin) {
|
||||
// Develocity plugin publishes scans by default
|
||||
buildScanExtension.publishAlways()
|
||||
}
|
||||
// uploadInBackground not available for build-scan-plugin 1.16
|
||||
if (buildScanExtension.metaClass.respondsTo(buildScanExtension, 'setUploadInBackground', Boolean)) buildScanExtension.uploadInBackground = buildScanUploadInBackground
|
||||
buildScanExtension.value CI_AUTO_INJECTION_CUSTOM_VALUE_NAME, ciAutoInjectionCustomValueValue
|
||||
if (isAtLeast(develocityPluginVersion, '2.1') && atLeastGradle5) {
|
||||
logger.lifecycle("Setting captureFileFingerprints: $develocityCaptureFileFingerprints")
|
||||
if (isAtLeast(develocityPluginVersion, '3.17')) {
|
||||
buildScanExtension.capture.fileFingerprints.set(develocityCaptureFileFingerprints)
|
||||
} else if (isAtLeast(develocityPluginVersion, '3.7')) {
|
||||
buildScanExtension.capture.taskInputFiles = develocityCaptureFileFingerprints
|
||||
} else {
|
||||
buildScanExtension.captureTaskInputFiles = develocityCaptureFileFingerprints
|
||||
)
|
||||
if (develocityUrl) {
|
||||
logger.lifecycle("Connection to Develocity: $develocityUrl, allowUntrustedServer: $develocityAllowUntrustedServer, captureFileFingerprints: $develocityCaptureFileFingerprints")
|
||||
rootExtension.server = develocityUrl
|
||||
rootExtension.allowUntrustedServer = develocityAllowUntrustedServer
|
||||
}
|
||||
if (!shouldApplyDevelocityPlugin) {
|
||||
// Develocity plugin publishes scans by default
|
||||
buildScanExtension.publishAlways()
|
||||
}
|
||||
// uploadInBackground not available for build-scan-plugin 1.16
|
||||
if (buildScanExtension.metaClass.respondsTo(buildScanExtension, 'setUploadInBackground', Boolean)) buildScanExtension.uploadInBackground = buildScanUploadInBackground
|
||||
buildScanExtension.value CI_AUTO_INJECTION_CUSTOM_VALUE_NAME, ciAutoInjectionCustomValueValue
|
||||
if (isAtLeast(develocityPluginVersion, '2.1') && atLeastGradle5) {
|
||||
logger.lifecycle("Setting captureFileFingerprints: $develocityCaptureFileFingerprints")
|
||||
if (isAtLeast(develocityPluginVersion, '3.17')) {
|
||||
buildScanExtension.capture.fileFingerprints.set(develocityCaptureFileFingerprints)
|
||||
} else if (isAtLeast(develocityPluginVersion, '3.7')) {
|
||||
buildScanExtension.capture.taskInputFiles = develocityCaptureFileFingerprints
|
||||
} else {
|
||||
buildScanExtension.captureTaskInputFiles = develocityCaptureFileFingerprints
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (develocityUrl && develocityEnforceUrl) {
|
||||
logger.lifecycle("Enforcing Develocity: $develocityUrl, allowUntrustedServer: $develocityAllowUntrustedServer, captureFileFingerprints: $develocityCaptureFileFingerprints")
|
||||
}
|
||||
|
||||
pluginManager.withPlugin(BUILD_SCAN_PLUGIN_ID) {
|
||||
// Only execute if develocity plugin isn't applied.
|
||||
if (gradle.rootProject.extensions.findByName("develocity")) return
|
||||
afterEvaluate {
|
||||
if (develocityUrl && develocityEnforceUrl) {
|
||||
buildScan.server = develocityUrl
|
||||
buildScan.allowUntrustedServer = develocityAllowUntrustedServer
|
||||
}
|
||||
}
|
||||
|
||||
if (buildScanTermsOfUseUrl && buildScanTermsOfUseAgree) {
|
||||
buildScan.termsOfServiceUrl = buildScanTermsOfUseUrl
|
||||
buildScan.termsOfServiceAgree = buildScanTermsOfUseAgree
|
||||
}
|
||||
}
|
||||
|
||||
pluginManager.withPlugin(DEVELOCITY_PLUGIN_ID) {
|
||||
afterEvaluate {
|
||||
if (develocityUrl && develocityEnforceUrl) {
|
||||
develocity.server = develocityUrl
|
||||
develocity.allowUntrustedServer = develocityAllowUntrustedServer
|
||||
}
|
||||
}
|
||||
|
||||
if (buildScanTermsOfUseUrl && buildScanTermsOfUseAgree) {
|
||||
develocity.buildScan.termsOfUseUrl = buildScanTermsOfUseUrl
|
||||
develocity.buildScan.termsOfUseAgree = buildScanTermsOfUseAgree
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ccudPluginVersion && atLeastGradle4) {
|
||||
def ccudPluginComponent = resolutionResult.allComponents.find {
|
||||
it.moduleVersion.with { group == "com.gradle" && name == "common-custom-user-data-gradle-plugin" }
|
||||
}
|
||||
if (!ccudPluginComponent) {
|
||||
logger.lifecycle("Applying $CCUD_PLUGIN_CLASS via init script")
|
||||
pluginManager.apply(initscript.classLoader.loadClass(CCUD_PLUGIN_CLASS))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
gradle.settingsEvaluated { settings ->
|
||||
if (develocityPluginVersion) {
|
||||
if (!settings.pluginManager.hasPlugin(GRADLE_ENTERPRISE_PLUGIN_ID) && !settings.pluginManager.hasPlugin(DEVELOCITY_PLUGIN_ID)) {
|
||||
def pluginClass = dvOrGe(DEVELOCITY_PLUGIN_CLASS, GRADLE_ENTERPRISE_PLUGIN_CLASS)
|
||||
logger.lifecycle("Applying $pluginClass via init script")
|
||||
applyPluginExternally(settings.pluginManager, pluginClass)
|
||||
if (develocityUrl) {
|
||||
logger.lifecycle("Connection to Develocity: $develocityUrl, allowUntrustedServer: $develocityAllowUntrustedServer, captureFileFingerprints: $develocityCaptureFileFingerprints")
|
||||
eachDevelocitySettingsExtension(settings) { ext ->
|
||||
ext.server = develocityUrl
|
||||
ext.allowUntrustedServer = develocityAllowUntrustedServer
|
||||
}
|
||||
}
|
||||
|
||||
eachDevelocitySettingsExtension(settings) { ext ->
|
||||
ext.buildScan.uploadInBackground = buildScanUploadInBackground
|
||||
ext.buildScan.value CI_AUTO_INJECTION_CUSTOM_VALUE_NAME, ciAutoInjectionCustomValueValue
|
||||
}
|
||||
|
||||
eachDevelocitySettingsExtension(settings,
|
||||
{ develocity ->
|
||||
logger.lifecycle("Setting captureFileFingerprints: $develocityCaptureFileFingerprints")
|
||||
develocity.buildScan.capture.fileFingerprints = develocityCaptureFileFingerprints
|
||||
},
|
||||
{ gradleEnterprise ->
|
||||
gradleEnterprise.buildScan.publishAlways()
|
||||
if (isAtLeast(develocityPluginVersion, '2.1')) {
|
||||
logger.lifecycle("Setting captureFileFingerprints: $develocityCaptureFileFingerprints")
|
||||
if (isAtLeast(develocityPluginVersion, '3.7')) {
|
||||
gradleEnterprise.buildScan.capture.taskInputFiles = develocityCaptureFileFingerprints
|
||||
} else {
|
||||
gradleEnterprise.buildScan.captureTaskInputFiles = develocityCaptureFileFingerprints
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if (develocityUrl && develocityEnforceUrl) {
|
||||
logger.lifecycle("Enforcing Develocity: $develocityUrl, allowUntrustedServer: $develocityAllowUntrustedServer, captureFileFingerprints: $develocityCaptureFileFingerprints")
|
||||
}
|
||||
|
||||
pluginManager.withPlugin(BUILD_SCAN_PLUGIN_ID) {
|
||||
// Only execute if develocity plugin isn't applied.
|
||||
if (gradle.rootProject.extensions.findByName("develocity")) return
|
||||
afterEvaluate {
|
||||
if (develocityUrl && develocityEnforceUrl) {
|
||||
buildScan.server = develocityUrl
|
||||
buildScan.allowUntrustedServer = develocityAllowUntrustedServer
|
||||
}
|
||||
}
|
||||
|
||||
if (buildScanTermsOfUseUrl && buildScanTermsOfUseAgree) {
|
||||
buildScan.termsOfServiceUrl = buildScanTermsOfUseUrl
|
||||
buildScan.termsOfServiceAgree = buildScanTermsOfUseAgree
|
||||
}
|
||||
}
|
||||
|
||||
pluginManager.withPlugin(DEVELOCITY_PLUGIN_ID) {
|
||||
afterEvaluate {
|
||||
eachDevelocitySettingsExtension(settings,
|
||||
{ develocity ->
|
||||
if (develocityUrl && develocityEnforceUrl) {
|
||||
develocity.server = develocityUrl
|
||||
develocity.allowUntrustedServer = develocityAllowUntrustedServer
|
||||
}
|
||||
}
|
||||
|
||||
if (buildScanTermsOfUseUrl && buildScanTermsOfUseAgree) {
|
||||
develocity.buildScan.termsOfUseUrl = buildScanTermsOfUseUrl
|
||||
develocity.buildScan.termsOfUseAgree = buildScanTermsOfUseAgree
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ccudPluginVersion && atLeastGradle4) {
|
||||
def ccudPluginComponent = resolutionResult.allComponents.find {
|
||||
it.moduleVersion.with { group == "com.gradle" && name == "common-custom-user-data-gradle-plugin" }
|
||||
}
|
||||
if (!ccudPluginComponent) {
|
||||
logger.lifecycle("Applying $CCUD_PLUGIN_CLASS via init script")
|
||||
pluginManager.apply(initscript.classLoader.loadClass(CCUD_PLUGIN_CLASS))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
gradle.settingsEvaluated { settings ->
|
||||
if (develocityPluginVersion) {
|
||||
if (!settings.pluginManager.hasPlugin(GRADLE_ENTERPRISE_PLUGIN_ID) && !settings.pluginManager.hasPlugin(DEVELOCITY_PLUGIN_ID)) {
|
||||
def pluginClass = dvOrGe(DEVELOCITY_PLUGIN_CLASS, GRADLE_ENTERPRISE_PLUGIN_CLASS)
|
||||
logger.lifecycle("Applying $pluginClass via init script")
|
||||
applyPluginExternally(settings.pluginManager, pluginClass)
|
||||
if (develocityUrl) {
|
||||
logger.lifecycle("Connection to Develocity: $develocityUrl, allowUntrustedServer: $develocityAllowUntrustedServer, captureFileFingerprints: $develocityCaptureFileFingerprints")
|
||||
eachDevelocitySettingsExtension(settings) { ext ->
|
||||
ext.server = develocityUrl
|
||||
ext.allowUntrustedServer = develocityAllowUntrustedServer
|
||||
}
|
||||
}
|
||||
|
||||
eachDevelocitySettingsExtension(settings) { ext ->
|
||||
ext.buildScan.uploadInBackground = buildScanUploadInBackground
|
||||
ext.buildScan.value CI_AUTO_INJECTION_CUSTOM_VALUE_NAME, ciAutoInjectionCustomValueValue
|
||||
}
|
||||
|
||||
eachDevelocitySettingsExtension(settings,
|
||||
{ develocity ->
|
||||
logger.lifecycle("Setting captureFileFingerprints: $develocityCaptureFileFingerprints")
|
||||
develocity.buildScan.capture.fileFingerprints = develocityCaptureFileFingerprints
|
||||
if (buildScanTermsOfUseUrl && buildScanTermsOfUseAgree) {
|
||||
develocity.buildScan.termsOfUseUrl = buildScanTermsOfUseUrl
|
||||
develocity.buildScan.termsOfUseAgree = buildScanTermsOfUseAgree
|
||||
}
|
||||
},
|
||||
{ gradleEnterprise ->
|
||||
gradleEnterprise.buildScan.publishAlways()
|
||||
if (isAtLeast(develocityPluginVersion, '2.1')) {
|
||||
logger.lifecycle("Setting captureFileFingerprints: $develocityCaptureFileFingerprints")
|
||||
if (isAtLeast(develocityPluginVersion, '3.7')) {
|
||||
gradleEnterprise.buildScan.capture.taskInputFiles = develocityCaptureFileFingerprints
|
||||
} else {
|
||||
gradleEnterprise.buildScan.captureTaskInputFiles = develocityCaptureFileFingerprints
|
||||
}
|
||||
if (develocityUrl && develocityEnforceUrl) {
|
||||
gradleEnterprise.server = develocityUrl
|
||||
gradleEnterprise.allowUntrustedServer = develocityAllowUntrustedServer
|
||||
}
|
||||
|
||||
if (buildScanTermsOfUseUrl && buildScanTermsOfUseAgree) {
|
||||
gradleEnterprise.buildScan.termsOfServiceUrl = buildScanTermsOfUseUrl
|
||||
gradleEnterprise.buildScan.termsOfServiceAgree = buildScanTermsOfUseAgree
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if (develocityUrl && develocityEnforceUrl) {
|
||||
logger.lifecycle("Enforcing Develocity: $develocityUrl, allowUntrustedServer: $develocityAllowUntrustedServer, captureFileFingerprints: $develocityCaptureFileFingerprints")
|
||||
}
|
||||
|
||||
eachDevelocitySettingsExtension(settings,
|
||||
{ develocity ->
|
||||
if (develocityUrl && develocityEnforceUrl) {
|
||||
develocity.server = develocityUrl
|
||||
develocity.allowUntrustedServer = develocityAllowUntrustedServer
|
||||
}
|
||||
|
||||
if (buildScanTermsOfUseUrl && buildScanTermsOfUseAgree) {
|
||||
develocity.buildScan.termsOfUseUrl = buildScanTermsOfUseUrl
|
||||
develocity.buildScan.termsOfUseAgree = buildScanTermsOfUseAgree
|
||||
}
|
||||
},
|
||||
{ gradleEnterprise ->
|
||||
if (develocityUrl && develocityEnforceUrl) {
|
||||
gradleEnterprise.server = develocityUrl
|
||||
gradleEnterprise.allowUntrustedServer = develocityAllowUntrustedServer
|
||||
}
|
||||
|
||||
if (buildScanTermsOfUseUrl && buildScanTermsOfUseAgree) {
|
||||
gradleEnterprise.buildScan.termsOfServiceUrl = buildScanTermsOfUseUrl
|
||||
gradleEnterprise.buildScan.termsOfServiceAgree = buildScanTermsOfUseAgree
|
||||
}
|
||||
if (ccudPluginVersion) {
|
||||
if (!settings.pluginManager.hasPlugin(CCUD_PLUGIN_ID)) {
|
||||
logger.lifecycle("Applying $CCUD_PLUGIN_CLASS via init script")
|
||||
settings.pluginManager.apply(initscript.classLoader.loadClass(CCUD_PLUGIN_CLASS))
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if (ccudPluginVersion) {
|
||||
if (!settings.pluginManager.hasPlugin(CCUD_PLUGIN_ID)) {
|
||||
logger.lifecycle("Applying $CCUD_PLUGIN_CLASS via init script")
|
||||
settings.pluginManager.apply(initscript.classLoader.loadClass(CCUD_PLUGIN_CLASS))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -360,4 +373,42 @@ static boolean isAtLeast(String versionUnderTest, String referenceVersion) {
|
||||
|
||||
static boolean isNotAtLeast(String versionUnderTest, String referenceVersion) {
|
||||
!isAtLeast(versionUnderTest, referenceVersion)
|
||||
}
|
||||
}
|
||||
|
||||
void enableBuildScanLinkCapture(BuildScanCollector collector) {
|
||||
def BUILD_SCAN_PLUGIN_ID = 'com.gradle.build-scan'
|
||||
def DEVELOCITY_PLUGIN_ID = 'com.gradle.develocity'
|
||||
|
||||
// Conditionally apply and configure the Develocity plugin
|
||||
if (GradleVersion.current() < GradleVersion.version('6.0')) {
|
||||
rootProject {
|
||||
pluginManager.withPlugin(BUILD_SCAN_PLUGIN_ID) {
|
||||
// Only execute if develocity plugin isn't applied.
|
||||
if (gradle.rootProject.extensions.findByName("develocity")) return
|
||||
buildScanPublishedAction(buildScan, collector)
|
||||
}
|
||||
|
||||
pluginManager.withPlugin(DEVELOCITY_PLUGIN_ID) {
|
||||
buildScanPublishedAction(develocity.buildScan, collector)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
gradle.settingsEvaluated { settings ->
|
||||
eachDevelocitySettingsExtension(settings) { ext ->
|
||||
buildScanPublishedAction(ext.buildScan, collector)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Action will only be called if a `BuildScanCollector.captureBuildScanLink` method is present.
|
||||
// Add `void captureBuildScanLink(String) {}` to the `BuildScanCollector` class to respond to buildScanPublished events
|
||||
static buildScanPublishedAction(def buildScanExtension, BuildScanCollector collector) {
|
||||
if (buildScanExtension.metaClass.respondsTo(buildScanExtension, 'buildScanPublished', Action)) {
|
||||
buildScanExtension.buildScanPublished { scan ->
|
||||
collector.captureBuildScanLink(scan.buildScanUri.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class BuildScanCollector {}
|
||||
|
||||
@@ -1,24 +1,34 @@
|
||||
import * as core from '@actions/core'
|
||||
import * as exec from '@actions/exec'
|
||||
import * as fs from 'fs'
|
||||
import * as path from 'path'
|
||||
import * as os from 'os'
|
||||
import * as caches from './caching/caches'
|
||||
import * as jobSummary from './job-summary'
|
||||
import * as buildScan from './build-scan'
|
||||
import * as buildScan from './develocity/build-scan'
|
||||
|
||||
import {loadBuildResults, markBuildResultsProcessed} from './build-results'
|
||||
import {CacheListener, generateCachingReport} from './caching/cache-reporting'
|
||||
import {DaemonController} from './daemon-controller'
|
||||
import {BuildScanConfig, CacheConfig, SummaryConfig, getWorkspaceDirectory} from './configuration'
|
||||
import {findInvalidWrapperJars} from './wrapper-validation/validate'
|
||||
import {JobFailure} from './errors'
|
||||
import {
|
||||
BuildScanConfig,
|
||||
CacheConfig,
|
||||
SummaryConfig,
|
||||
WrapperValidationConfig,
|
||||
getWorkspaceDirectory
|
||||
} from './configuration'
|
||||
import * as wrapperValidator from './wrapper-validation/wrapper-validator'
|
||||
|
||||
const GRADLE_SETUP_VAR = 'GRADLE_BUILD_ACTION_SETUP_COMPLETED'
|
||||
const USER_HOME = 'USER_HOME'
|
||||
const GRADLE_USER_HOME = 'GRADLE_USER_HOME'
|
||||
const CACHE_LISTENER = 'CACHE_LISTENER'
|
||||
|
||||
export async function setup(cacheConfig: CacheConfig, buildScanConfig: BuildScanConfig): Promise<boolean> {
|
||||
export async function setup(
|
||||
cacheConfig: CacheConfig,
|
||||
buildScanConfig: BuildScanConfig,
|
||||
wrapperValidationConfig: WrapperValidationConfig
|
||||
): Promise<boolean> {
|
||||
const userHome = await determineUserHome()
|
||||
const gradleUserHome = await determineGradleUserHome()
|
||||
|
||||
@@ -41,7 +51,9 @@ export async function setup(cacheConfig: CacheConfig, buildScanConfig: BuildScan
|
||||
|
||||
core.saveState(CACHE_LISTENER, cacheListener.stringify())
|
||||
|
||||
buildScan.setup(buildScanConfig)
|
||||
await wrapperValidator.validateWrappers(wrapperValidationConfig, getWorkspaceDirectory(), gradleUserHome)
|
||||
|
||||
await buildScan.setup(buildScanConfig)
|
||||
|
||||
return true
|
||||
}
|
||||
@@ -60,7 +72,7 @@ export async function complete(cacheConfig: CacheConfig, summaryConfig: SummaryC
|
||||
const cacheListener: CacheListener = CacheListener.rehydrate(core.getState(CACHE_LISTENER))
|
||||
|
||||
const daemonController = new DaemonController(buildResults)
|
||||
await caches.save(userHome, gradleUserHome, cacheListener, daemonController, cacheConfig)
|
||||
await caches.save(userHome, gradleUserHome, cacheListener, daemonController, buildResults, cacheConfig)
|
||||
|
||||
const cachingReport = generateCachingReport(cacheListener)
|
||||
await jobSummary.generateJobSummary(buildResults, cachingReport, summaryConfig)
|
||||
@@ -79,7 +91,24 @@ async function determineGradleUserHome(): Promise<string> {
|
||||
return path.resolve(rootDir, customGradleUserHome)
|
||||
}
|
||||
|
||||
return path.resolve(await determineUserHome(), '.gradle')
|
||||
const defaultGradleUserHome = path.resolve(await determineUserHome(), '.gradle')
|
||||
// Use the default Gradle User Home if it already exists
|
||||
if (fs.existsSync(defaultGradleUserHome)) {
|
||||
core.info(`Gradle User Home already exists at ${defaultGradleUserHome}`)
|
||||
core.exportVariable('GRADLE_USER_HOME', defaultGradleUserHome)
|
||||
return defaultGradleUserHome
|
||||
}
|
||||
|
||||
// Switch Gradle User Home to faster 'D:' drive if possible
|
||||
if (os.platform() === 'win32' && defaultGradleUserHome.startsWith('C:\\') && fs.existsSync('D:\\a\\')) {
|
||||
const fasterGradleUserHome = 'D:\\a\\.gradle'
|
||||
core.info(`Setting GRADLE_USER_HOME to ${fasterGradleUserHome} to leverage (potentially) faster drive.`)
|
||||
core.exportVariable('GRADLE_USER_HOME', fasterGradleUserHome)
|
||||
return fasterGradleUserHome
|
||||
}
|
||||
|
||||
core.exportVariable('GRADLE_USER_HOME', defaultGradleUserHome)
|
||||
return defaultGradleUserHome
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,16 +127,3 @@ async function determineUserHome(): Promise<string> {
|
||||
core.debug(`Determined user.home from java -version output: '${userHome}'`)
|
||||
return userHome
|
||||
}
|
||||
|
||||
export async function checkNoInvalidWrapperJars(rootDir = getWorkspaceDirectory()): Promise<void> {
|
||||
const allowedChecksums = process.env['ALLOWED_GRADLE_WRAPPER_CHECKSUMS']?.split(',') || []
|
||||
const result = await findInvalidWrapperJars(rootDir, 1, false, allowedChecksums)
|
||||
if (result.isValid()) {
|
||||
core.info(result.toDisplayString())
|
||||
} else {
|
||||
core.info(result.toDisplayString())
|
||||
throw new JobFailure(
|
||||
`Gradle Wrapper Validation Failed!\n See https://github.com/gradle/actions/blob/main/docs/wrapper-validation.md#reporting-failures\n${result.toDisplayString()}`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
26
sources/src/wrapper-validation/cache.ts
Normal file
26
sources/src/wrapper-validation/cache.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import {ACTION_METADATA_DIR} from '../configuration'
|
||||
|
||||
export class ChecksumCache {
|
||||
private readonly cacheFile: string
|
||||
|
||||
constructor(gradleUserHome: string) {
|
||||
this.cacheFile = path.resolve(gradleUserHome, ACTION_METADATA_DIR, 'valid-wrappers.json')
|
||||
}
|
||||
|
||||
load(): string[] {
|
||||
// Load previously validated checksums saved in Gradle User Home
|
||||
if (fs.existsSync(this.cacheFile)) {
|
||||
return JSON.parse(fs.readFileSync(this.cacheFile, 'utf-8'))
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
save(checksums: string[]): void {
|
||||
const uniqueChecksums = [...new Set(checksums)]
|
||||
// Save validated checksums to Gradle User Home
|
||||
fs.mkdirSync(path.dirname(this.cacheFile), {recursive: true})
|
||||
fs.writeFileSync(this.cacheFile, JSON.stringify(uniqueChecksums))
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,31 @@
|
||||
import * as httpm from 'typed-rest-client/HttpClient'
|
||||
import * as cheerio from 'cheerio'
|
||||
|
||||
import fileWrapperChecksums from './wrapper-checksums.json'
|
||||
|
||||
const httpc = new httpm.HttpClient('gradle/wrapper-validation-action', undefined, {allowRetries: true, maxRetries: 3})
|
||||
|
||||
function getKnownValidChecksums(): Map<string, Set<string>> {
|
||||
const versionsMap = new Map<string, Set<string>>()
|
||||
for (const entry of fileWrapperChecksums) {
|
||||
const checksum = entry.checksum
|
||||
export class WrapperChecksums {
|
||||
checksums = new Map<string, Set<string>>()
|
||||
versions = new Set<string>()
|
||||
|
||||
let versionNames = versionsMap.get(checksum)
|
||||
if (versionNames === undefined) {
|
||||
versionNames = new Set()
|
||||
versionsMap.set(checksum, versionNames)
|
||||
add(version: string, checksum: string): void {
|
||||
if (this.checksums.has(checksum)) {
|
||||
this.checksums.get(checksum)!.add(version)
|
||||
} else {
|
||||
this.checksums.set(checksum, new Set([version]))
|
||||
}
|
||||
|
||||
versionNames.add(entry.version)
|
||||
this.versions.add(version)
|
||||
}
|
||||
}
|
||||
|
||||
return versionsMap
|
||||
function loadKnownChecksums(): WrapperChecksums {
|
||||
const checksums = new WrapperChecksums()
|
||||
for (const entry of fileWrapperChecksums) {
|
||||
checksums.add(entry.version, entry.checksum)
|
||||
}
|
||||
return checksums
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -26,9 +33,12 @@ function getKnownValidChecksums(): Map<string, Set<string>> {
|
||||
*
|
||||
* Maps from the checksum to the names of the Gradle versions whose wrapper has this checksum.
|
||||
*/
|
||||
export const KNOWN_VALID_CHECKSUMS = getKnownValidChecksums()
|
||||
export const KNOWN_CHECKSUMS = loadKnownChecksums()
|
||||
|
||||
export async function fetchValidChecksums(allowSnapshots: boolean): Promise<Set<string>> {
|
||||
export async function fetchUnknownChecksums(
|
||||
allowSnapshots: boolean,
|
||||
knownChecksums: WrapperChecksums
|
||||
): Promise<Set<string>> {
|
||||
const all = await httpGetJsonArray('https://services.gradle.org/versions/all')
|
||||
const withChecksum = all.filter(
|
||||
entry => typeof entry === 'object' && entry != null && entry.hasOwnProperty('wrapperChecksumUrl')
|
||||
@@ -37,11 +47,23 @@ export async function fetchValidChecksums(allowSnapshots: boolean): Promise<Set<
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(entry: any) => allowSnapshots || !entry.snapshot
|
||||
)
|
||||
const checksumUrls = allowed.map(
|
||||
const notKnown = allowed.filter(
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(entry: any) => !knownChecksums.versions.has(entry.version)
|
||||
)
|
||||
const checksumUrls = notKnown.map(
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(entry: any) => entry.wrapperChecksumUrl as string
|
||||
)
|
||||
const checksums = await Promise.all(checksumUrls.map(async (url: string) => httpGetText(url)))
|
||||
if (allowSnapshots) {
|
||||
await addDistributionSnapshotChecksums(checksumUrls)
|
||||
}
|
||||
const checksums = await Promise.all(
|
||||
checksumUrls.map(async (url: string) => {
|
||||
// console.log(`Fetching checksum from ${url}`)
|
||||
return httpGetText(url)
|
||||
})
|
||||
)
|
||||
return new Set(checksums)
|
||||
}
|
||||
|
||||
@@ -53,3 +75,22 @@ async function httpGetText(url: string): Promise<string> {
|
||||
const response = await httpc.get(url)
|
||||
return await response.readBody()
|
||||
}
|
||||
|
||||
// Public for testing
|
||||
export async function addDistributionSnapshotChecksums(checksumUrls: string[]): Promise<void> {
|
||||
// Load the index page of the distribution snapshot repository
|
||||
const indexPage = await httpGetText('https://services.gradle.org/distributions-snapshots/')
|
||||
|
||||
// // Extract all wrapper checksum from the index page. These end in -wrapper.jar.sha256
|
||||
// // Load the HTML into cheerio
|
||||
const $ = cheerio.load(indexPage)
|
||||
|
||||
// // Find all links ending with '-wrapper.jar.sha256'
|
||||
const wrapperChecksumLinks = $('a[href$="-wrapper.jar.sha256"]')
|
||||
|
||||
// build the absolute URL for each wrapper checksum
|
||||
wrapperChecksumLinks.each((index, element) => {
|
||||
const url = $(element).attr('href')
|
||||
checksumUrls.push(`https://services.gradle.org${url}`)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -8,7 +8,8 @@ export async function findInvalidWrapperJars(
|
||||
minWrapperCount: number,
|
||||
allowSnapshots: boolean,
|
||||
allowedChecksums: string[],
|
||||
knownValidChecksums: Map<string, Set<string>> = checksums.KNOWN_VALID_CHECKSUMS
|
||||
previouslyValidatedChecksums: string[] = [],
|
||||
knownValidChecksums: checksums.WrapperChecksums = checksums.KNOWN_CHECKSUMS
|
||||
): Promise<ValidationResult> {
|
||||
const wrapperJars = await find.findWrapperJars(gitRepoRoot)
|
||||
const result = new ValidationResult([], [])
|
||||
@@ -21,7 +22,11 @@ export async function findInvalidWrapperJars(
|
||||
const notYetValidatedWrappers = []
|
||||
for (const wrapperJar of wrapperJars) {
|
||||
const sha = await hash.sha256File(resolve(gitRepoRoot, wrapperJar))
|
||||
if (allowedChecksums.includes(sha) || knownValidChecksums.has(sha)) {
|
||||
if (
|
||||
allowedChecksums.includes(sha) ||
|
||||
previouslyValidatedChecksums.includes(sha) ||
|
||||
knownValidChecksums.checksums.has(sha)
|
||||
) {
|
||||
result.valid.push(new WrapperJar(wrapperJar, sha))
|
||||
} else {
|
||||
notYetValidatedWrappers.push(new WrapperJar(wrapperJar, sha))
|
||||
@@ -31,7 +36,7 @@ export async function findInvalidWrapperJars(
|
||||
// Otherwise fall back to fetching checksums from Gradle API and compare against them
|
||||
if (notYetValidatedWrappers.length > 0) {
|
||||
result.fetchedChecksums = true
|
||||
const fetchedValidChecksums = await checksums.fetchValidChecksums(allowSnapshots)
|
||||
const fetchedValidChecksums = await checksums.fetchUnknownChecksums(allowSnapshots, knownValidChecksums)
|
||||
|
||||
for (const wrapperJar of notYetValidatedWrappers) {
|
||||
if (!fetchedValidChecksums.has(wrapperJar.checksum)) {
|
||||
|
||||
@@ -1,4 +1,28 @@
|
||||
[
|
||||
{
|
||||
"version": "8.9",
|
||||
"checksum": "498495120a03b9a6ab5d155f5de3c8f0d986a449153702fb80fc80e134484f17"
|
||||
},
|
||||
{
|
||||
"version": "8.9-rc-2",
|
||||
"checksum": "498495120a03b9a6ab5d155f5de3c8f0d986a449153702fb80fc80e134484f17"
|
||||
},
|
||||
{
|
||||
"version": "8.9-rc-1",
|
||||
"checksum": "498495120a03b9a6ab5d155f5de3c8f0d986a449153702fb80fc80e134484f17"
|
||||
},
|
||||
{
|
||||
"version": "8.8",
|
||||
"checksum": "cb0da6751c2b753a16ac168bb354870ebb1e162e9083f116729cec9c781156b8"
|
||||
},
|
||||
{
|
||||
"version": "8.8-rc-2",
|
||||
"checksum": "cb0da6751c2b753a16ac168bb354870ebb1e162e9083f116729cec9c781156b8"
|
||||
},
|
||||
{
|
||||
"version": "8.8-rc-1",
|
||||
"checksum": "cb0da6751c2b753a16ac168bb354870ebb1e162e9083f116729cec9c781156b8"
|
||||
},
|
||||
{
|
||||
"version": "8.7",
|
||||
"checksum": "cb0da6751c2b753a16ac168bb354870ebb1e162e9083f116729cec9c781156b8"
|
||||
|
||||
41
sources/src/wrapper-validation/wrapper-validator.ts
Normal file
41
sources/src/wrapper-validation/wrapper-validator.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import * as core from '@actions/core'
|
||||
|
||||
import {WrapperValidationConfig} from '../configuration'
|
||||
import {ChecksumCache} from './cache'
|
||||
import {findInvalidWrapperJars} from './validate'
|
||||
import {JobFailure} from '../errors'
|
||||
|
||||
export async function validateWrappers(
|
||||
config: WrapperValidationConfig,
|
||||
workspaceRoot: string,
|
||||
gradleUserHome: string
|
||||
): Promise<void> {
|
||||
if (!config.doValidateWrappers()) {
|
||||
return // Wrapper validation is disabled
|
||||
}
|
||||
const checksumCache = new ChecksumCache(gradleUserHome)
|
||||
|
||||
const allowedChecksums = process.env['ALLOWED_GRADLE_WRAPPER_CHECKSUMS']?.split(',') || []
|
||||
const previouslyValidatedChecksums = checksumCache.load()
|
||||
|
||||
const result = await findInvalidWrapperJars(
|
||||
workspaceRoot,
|
||||
0,
|
||||
config.allowSnapshotWrappers(),
|
||||
allowedChecksums,
|
||||
previouslyValidatedChecksums
|
||||
)
|
||||
if (result.isValid()) {
|
||||
await core.group('All Gradle Wrapper jars are valid', async () => {
|
||||
core.info(`Loaded previously validated checksums from cache: ${previouslyValidatedChecksums.join(', ')}`)
|
||||
core.info(result.toDisplayString())
|
||||
})
|
||||
} else {
|
||||
core.info(result.toDisplayString())
|
||||
throw new JobFailure(
|
||||
`Gradle Wrapper Validation Failed!\n See https://github.com/gradle/actions/blob/main/docs/wrapper-validation.md#validation-failures\n${result.toDisplayString()}`
|
||||
)
|
||||
}
|
||||
|
||||
checksumCache.save(result.valid.map(wrapper => wrapper.checksum))
|
||||
}
|
||||
@@ -20,7 +20,7 @@ dependencies {
|
||||
testImplementation ('io.ratpack:ratpack-groovy-test:1.9.0') {
|
||||
exclude group: 'org.codehaus.groovy', module: 'groovy-all'
|
||||
}
|
||||
testImplementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-smile:2.17.0'
|
||||
testImplementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-smile:2.17.2'
|
||||
}
|
||||
|
||||
test {
|
||||
|
||||
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user