mirror of
https://github.com/gradle/gradle-build-action.git
synced 2025-07-04 14:12:37 +08:00
Compare commits
No commits in common. "main" and "v2.4.2" have entirely different histories.
3
.eslintignore
Normal file
3
.eslintignore
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
dist/
|
||||||
|
lib/
|
||||||
|
node_modules/
|
54
.eslintrc.json
Normal file
54
.eslintrc.json
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
{
|
||||||
|
"plugins": ["jest", "@typescript-eslint"],
|
||||||
|
"extends": ["plugin:github/recommended"],
|
||||||
|
"parser": "@typescript-eslint/parser",
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": 9,
|
||||||
|
"sourceType": "module",
|
||||||
|
"project": "./tsconfig.json"
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"eslint-comments/no-use": "off",
|
||||||
|
"import/no-namespace": "off",
|
||||||
|
"i18n-text/no-en": "off",
|
||||||
|
"no-unused-vars": "off",
|
||||||
|
"sort-imports": "off",
|
||||||
|
"@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }],
|
||||||
|
"@typescript-eslint/explicit-member-accessibility": ["error", {"accessibility": "no-public"}],
|
||||||
|
"@typescript-eslint/no-require-imports": "error",
|
||||||
|
"@typescript-eslint/array-type": "error",
|
||||||
|
"@typescript-eslint/await-thenable": "error",
|
||||||
|
"camelcase": "off",
|
||||||
|
"@typescript-eslint/explicit-function-return-type": ["error", {"allowExpressions": true}],
|
||||||
|
"@typescript-eslint/func-call-spacing": ["error", "never"],
|
||||||
|
"@typescript-eslint/no-array-constructor": "error",
|
||||||
|
"@typescript-eslint/no-empty-interface": "error",
|
||||||
|
"@typescript-eslint/no-explicit-any": "error",
|
||||||
|
"@typescript-eslint/no-extraneous-class": "error",
|
||||||
|
"@typescript-eslint/no-for-in-array": "error",
|
||||||
|
"@typescript-eslint/no-inferrable-types": "error",
|
||||||
|
"@typescript-eslint/no-misused-new": "error",
|
||||||
|
"@typescript-eslint/no-namespace": "error",
|
||||||
|
"@typescript-eslint/no-non-null-assertion": "off",
|
||||||
|
"@typescript-eslint/no-unnecessary-qualifier": "error",
|
||||||
|
"@typescript-eslint/no-unnecessary-type-assertion": "error",
|
||||||
|
"@typescript-eslint/no-useless-constructor": "error",
|
||||||
|
"@typescript-eslint/no-var-requires": "error",
|
||||||
|
"@typescript-eslint/prefer-for-of": "warn",
|
||||||
|
"@typescript-eslint/prefer-function-type": "warn",
|
||||||
|
"@typescript-eslint/prefer-includes": "error",
|
||||||
|
"@typescript-eslint/prefer-string-starts-ends-with": "error",
|
||||||
|
"@typescript-eslint/promise-function-async": "error",
|
||||||
|
"@typescript-eslint/require-array-sort-compare": ["error", {"ignoreStringArrays": true}],
|
||||||
|
"@typescript-eslint/restrict-plus-operands": "error",
|
||||||
|
"semi": "off",
|
||||||
|
"@typescript-eslint/semi": ["error", "never"],
|
||||||
|
"@typescript-eslint/type-annotation-spacing": "error",
|
||||||
|
"@typescript-eslint/unbound-method": "error"
|
||||||
|
},
|
||||||
|
"env": {
|
||||||
|
"node": true,
|
||||||
|
"es6": true,
|
||||||
|
"jest/globals": true
|
||||||
|
}
|
||||||
|
}
|
16
.github/actions/build-dist/action.yml
vendored
Normal file
16
.github/actions/build-dist/action.yml
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
name: 'Build and upload distribution'
|
||||||
|
# Builds the action distribution an uploads as an artifact for later download
|
||||||
|
runs:
|
||||||
|
using: "composite"
|
||||||
|
steps:
|
||||||
|
- name: Build distribution
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
npm install
|
||||||
|
npm run build
|
||||||
|
- name: Upload distribution
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: dist
|
||||||
|
path: dist/
|
||||||
|
|
12
.github/actions/download-dist/action.yml
vendored
Normal file
12
.github/actions/download-dist/action.yml
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
name: 'Download dist'
|
||||||
|
# Downloads a 'dist' directory artifact that was uploaded in an earlier step
|
||||||
|
# We control this with an environment variable to allow for easier global configuration.
|
||||||
|
runs:
|
||||||
|
using: "composite"
|
||||||
|
steps:
|
||||||
|
- name: Download dist
|
||||||
|
if: ${{ env.DOWNLOAD_DIST == 'true' }}
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: dist
|
||||||
|
path: dist/
|
60
.github/dependabot.yml
vendored
Normal file
60
.github/dependabot.yml
vendored
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
version: 2
|
||||||
|
registries:
|
||||||
|
gradle-plugin-portal:
|
||||||
|
type: maven-repository
|
||||||
|
url: https://plugins.gradle.org/m2
|
||||||
|
username: dummy # Required by dependabot
|
||||||
|
password: dummy # Required by dependabot
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: "github-actions"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
|
- package-ecosystem: "npm"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
|
ignore:
|
||||||
|
- dependency-name: "@types/node"
|
||||||
|
- package-ecosystem: "gradle"
|
||||||
|
directory: ".github/workflow-samples/gradle-plugin"
|
||||||
|
registries:
|
||||||
|
- gradle-plugin-portal
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
||||||
|
- package-ecosystem: "gradle"
|
||||||
|
directory: ".github/workflow-samples/groovy-dsl"
|
||||||
|
registries:
|
||||||
|
- gradle-plugin-portal
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
||||||
|
- package-ecosystem: "gradle"
|
||||||
|
directory: ".github/workflow-samples/java-toolchain"
|
||||||
|
registries:
|
||||||
|
- gradle-plugin-portal
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
||||||
|
- package-ecosystem: "gradle"
|
||||||
|
directory: ".github/workflow-samples/kotlin-dsl"
|
||||||
|
registries:
|
||||||
|
- gradle-plugin-portal
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
||||||
|
- package-ecosystem: "gradle"
|
||||||
|
directory: ".github/workflow-samples/no-wrapper"
|
||||||
|
registries:
|
||||||
|
- gradle-plugin-portal
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
||||||
|
- package-ecosystem: "gradle"
|
||||||
|
directory: ".github/workflow-samples/no-wrapper-gradle-5"
|
||||||
|
registries:
|
||||||
|
- gradle-plugin-portal
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
||||||
|
- package-ecosystem: "gradle"
|
||||||
|
directory: "test/init-scripts"
|
||||||
|
registries:
|
||||||
|
- gradle-plugin-portal
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
Binary file not shown.
@ -1,8 +1,7 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionSha256Sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d
|
distributionSha256Sum=ff7bf6a86f09b9b2c40bb8f48b25fc19cf2b2664fd1d220cd7ab833ec758d0d7
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
29
.github/workflow-samples/gradle-plugin/gradlew
vendored
29
.github/workflow-samples/gradle-plugin/gradlew
vendored
@ -83,8 +83,10 @@ done
|
|||||||
# This is normally unused
|
# This is normally unused
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
APP_BASE_NAME=${0##*/}
|
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:-./}" && pwd -P ) || exit
|
||||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD=maximum
|
MAX_FD=maximum
|
||||||
@ -131,13 +133,10 @@ location of your Java installation."
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
JAVACMD=java
|
JAVACMD=java
|
||||||
if ! command -v java >/dev/null 2>&1
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
then
|
|
||||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
|
||||||
|
|
||||||
Please set the JAVA_HOME variable in your environment to match the
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
location of your Java installation."
|
location of your Java installation."
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
# Increase the maximum file descriptors if we can.
|
||||||
@ -145,7 +144,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
|||||||
case $MAX_FD in #(
|
case $MAX_FD in #(
|
||||||
max*)
|
max*)
|
||||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||||
# shellcheck disable=SC2039,SC3045
|
# shellcheck disable=SC3045
|
||||||
MAX_FD=$( ulimit -H -n ) ||
|
MAX_FD=$( ulimit -H -n ) ||
|
||||||
warn "Could not query maximum file descriptor limit"
|
warn "Could not query maximum file descriptor limit"
|
||||||
esac
|
esac
|
||||||
@ -153,7 +152,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
|||||||
'' | soft) :;; #(
|
'' | soft) :;; #(
|
||||||
*)
|
*)
|
||||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||||
# shellcheck disable=SC2039,SC3045
|
# shellcheck disable=SC3045
|
||||||
ulimit -n "$MAX_FD" ||
|
ulimit -n "$MAX_FD" ||
|
||||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||||
esac
|
esac
|
||||||
@ -198,15 +197,11 @@ if "$cygwin" || "$msys" ; then
|
|||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Collect all arguments for the java command;
|
||||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
# shell script including quotes and variable substitutions, so put them in
|
||||||
|
# double quotes to make sure that they get re-expanded; and
|
||||||
# Collect all arguments for the java command:
|
# * put everything else in single quotes, so that it's not re-expanded.
|
||||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
|
||||||
# and any embedded shellness will be escaped.
|
|
||||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
|
||||||
# treated as '${Hostname}' itself on the command line.
|
|
||||||
|
|
||||||
set -- \
|
set -- \
|
||||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||||
|
@ -43,11 +43,11 @@ set JAVA_EXE=java.exe
|
|||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if %ERRORLEVEL% equ 0 goto execute
|
if %ERRORLEVEL% equ 0 goto execute
|
||||||
|
|
||||||
echo. 1>&2
|
echo.
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
echo. 1>&2
|
echo.
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
echo location of your Java installation. 1>&2
|
echo location of your Java installation.
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
|||||||
|
|
||||||
if exist "%JAVA_EXE%" goto execute
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
echo. 1>&2
|
echo.
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
echo. 1>&2
|
echo.
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
echo location of your Java installation. 1>&2
|
echo location of your Java installation.
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
|
Binary file not shown.
@ -1,8 +1,7 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionSha256Sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d
|
distributionSha256Sum=ff7bf6a86f09b9b2c40bb8f48b25fc19cf2b2664fd1d220cd7ab833ec758d0d7
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
29
.github/workflow-samples/groovy-dsl/gradlew
vendored
29
.github/workflow-samples/groovy-dsl/gradlew
vendored
@ -83,8 +83,10 @@ done
|
|||||||
# This is normally unused
|
# This is normally unused
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
APP_BASE_NAME=${0##*/}
|
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:-./}" && pwd -P ) || exit
|
||||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD=maximum
|
MAX_FD=maximum
|
||||||
@ -131,13 +133,10 @@ location of your Java installation."
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
JAVACMD=java
|
JAVACMD=java
|
||||||
if ! command -v java >/dev/null 2>&1
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
then
|
|
||||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
|
||||||
|
|
||||||
Please set the JAVA_HOME variable in your environment to match the
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
location of your Java installation."
|
location of your Java installation."
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
# Increase the maximum file descriptors if we can.
|
||||||
@ -145,7 +144,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
|||||||
case $MAX_FD in #(
|
case $MAX_FD in #(
|
||||||
max*)
|
max*)
|
||||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||||
# shellcheck disable=SC2039,SC3045
|
# shellcheck disable=SC3045
|
||||||
MAX_FD=$( ulimit -H -n ) ||
|
MAX_FD=$( ulimit -H -n ) ||
|
||||||
warn "Could not query maximum file descriptor limit"
|
warn "Could not query maximum file descriptor limit"
|
||||||
esac
|
esac
|
||||||
@ -153,7 +152,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
|||||||
'' | soft) :;; #(
|
'' | soft) :;; #(
|
||||||
*)
|
*)
|
||||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||||
# shellcheck disable=SC2039,SC3045
|
# shellcheck disable=SC3045
|
||||||
ulimit -n "$MAX_FD" ||
|
ulimit -n "$MAX_FD" ||
|
||||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||||
esac
|
esac
|
||||||
@ -198,15 +197,11 @@ if "$cygwin" || "$msys" ; then
|
|||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Collect all arguments for the java command;
|
||||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
# shell script including quotes and variable substitutions, so put them in
|
||||||
|
# double quotes to make sure that they get re-expanded; and
|
||||||
# Collect all arguments for the java command:
|
# * put everything else in single quotes, so that it's not re-expanded.
|
||||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
|
||||||
# and any embedded shellness will be escaped.
|
|
||||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
|
||||||
# treated as '${Hostname}' itself on the command line.
|
|
||||||
|
|
||||||
set -- \
|
set -- \
|
||||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||||
|
20
.github/workflow-samples/groovy-dsl/gradlew.bat
vendored
20
.github/workflow-samples/groovy-dsl/gradlew.bat
vendored
@ -43,11 +43,11 @@ set JAVA_EXE=java.exe
|
|||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if %ERRORLEVEL% equ 0 goto execute
|
if %ERRORLEVEL% equ 0 goto execute
|
||||||
|
|
||||||
echo. 1>&2
|
echo.
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
echo. 1>&2
|
echo.
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
echo location of your Java installation. 1>&2
|
echo location of your Java installation.
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
|||||||
|
|
||||||
if exist "%JAVA_EXE%" goto execute
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
echo. 1>&2
|
echo.
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
echo. 1>&2
|
echo.
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
echo location of your Java installation. 1>&2
|
echo location of your Java installation.
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id "com.gradle.enterprise" version "3.16.2"
|
id "com.gradle.enterprise" version "3.12.6"
|
||||||
id "com.gradle.common-custom-user-data-gradle-plugin" version "1.13"
|
id "com.gradle.common-custom-user-data-gradle-plugin" version "1.10"
|
||||||
}
|
}
|
||||||
|
|
||||||
gradleEnterprise {
|
gradleEnterprise {
|
||||||
|
Binary file not shown.
@ -1,8 +1,7 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionSha256Sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d
|
distributionSha256Sum=ff7bf6a86f09b9b2c40bb8f48b25fc19cf2b2664fd1d220cd7ab833ec758d0d7
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
29
.github/workflow-samples/java-toolchain/gradlew
vendored
29
.github/workflow-samples/java-toolchain/gradlew
vendored
@ -83,8 +83,10 @@ done
|
|||||||
# This is normally unused
|
# This is normally unused
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
APP_BASE_NAME=${0##*/}
|
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:-./}" && pwd -P ) || exit
|
||||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD=maximum
|
MAX_FD=maximum
|
||||||
@ -131,13 +133,10 @@ location of your Java installation."
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
JAVACMD=java
|
JAVACMD=java
|
||||||
if ! command -v java >/dev/null 2>&1
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
then
|
|
||||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
|
||||||
|
|
||||||
Please set the JAVA_HOME variable in your environment to match the
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
location of your Java installation."
|
location of your Java installation."
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
# Increase the maximum file descriptors if we can.
|
||||||
@ -145,7 +144,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
|||||||
case $MAX_FD in #(
|
case $MAX_FD in #(
|
||||||
max*)
|
max*)
|
||||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||||
# shellcheck disable=SC2039,SC3045
|
# shellcheck disable=SC3045
|
||||||
MAX_FD=$( ulimit -H -n ) ||
|
MAX_FD=$( ulimit -H -n ) ||
|
||||||
warn "Could not query maximum file descriptor limit"
|
warn "Could not query maximum file descriptor limit"
|
||||||
esac
|
esac
|
||||||
@ -153,7 +152,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
|||||||
'' | soft) :;; #(
|
'' | soft) :;; #(
|
||||||
*)
|
*)
|
||||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||||
# shellcheck disable=SC2039,SC3045
|
# shellcheck disable=SC3045
|
||||||
ulimit -n "$MAX_FD" ||
|
ulimit -n "$MAX_FD" ||
|
||||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||||
esac
|
esac
|
||||||
@ -198,15 +197,11 @@ if "$cygwin" || "$msys" ; then
|
|||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Collect all arguments for the java command;
|
||||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
# shell script including quotes and variable substitutions, so put them in
|
||||||
|
# double quotes to make sure that they get re-expanded; and
|
||||||
# Collect all arguments for the java command:
|
# * put everything else in single quotes, so that it's not re-expanded.
|
||||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
|
||||||
# and any embedded shellness will be escaped.
|
|
||||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
|
||||||
# treated as '${Hostname}' itself on the command line.
|
|
||||||
|
|
||||||
set -- \
|
set -- \
|
||||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||||
|
@ -43,11 +43,11 @@ set JAVA_EXE=java.exe
|
|||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if %ERRORLEVEL% equ 0 goto execute
|
if %ERRORLEVEL% equ 0 goto execute
|
||||||
|
|
||||||
echo. 1>&2
|
echo.
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
echo. 1>&2
|
echo.
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
echo location of your Java installation. 1>&2
|
echo location of your Java installation.
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
|||||||
|
|
||||||
if exist "%JAVA_EXE%" goto execute
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
echo. 1>&2
|
echo.
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
echo. 1>&2
|
echo.
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
echo location of your Java installation. 1>&2
|
echo location of your Java installation.
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("org.gradle.toolchains.foojay-resolver-convention") version("0.7.0")
|
id("org.gradle.toolchains.foojay-resolver-convention") version("0.4.0")
|
||||||
}
|
}
|
||||||
|
|
||||||
rootProject.name = 'basic'
|
rootProject.name = 'basic'
|
||||||
|
@ -8,9 +8,9 @@ repositories {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api("org.apache.commons:commons-math3:3.6.1")
|
api("org.apache.commons:commons-math3:3.6.1")
|
||||||
implementation("com.google.guava:guava:33.1.0-jre")
|
implementation("com.google.guava:guava:31.1-jre")
|
||||||
|
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter:5.10.2")
|
testImplementation("org.junit.jupiter:junit-jupiter:5.9.2")
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.test {
|
tasks.test {
|
||||||
|
Binary file not shown.
@ -1,8 +1,7 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionSha256Sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d
|
distributionSha256Sum=ff7bf6a86f09b9b2c40bb8f48b25fc19cf2b2664fd1d220cd7ab833ec758d0d7
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
29
.github/workflow-samples/kotlin-dsl/gradlew
vendored
29
.github/workflow-samples/kotlin-dsl/gradlew
vendored
@ -83,8 +83,10 @@ done
|
|||||||
# This is normally unused
|
# This is normally unused
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
APP_BASE_NAME=${0##*/}
|
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:-./}" && pwd -P ) || exit
|
||||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD=maximum
|
MAX_FD=maximum
|
||||||
@ -131,13 +133,10 @@ location of your Java installation."
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
JAVACMD=java
|
JAVACMD=java
|
||||||
if ! command -v java >/dev/null 2>&1
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
then
|
|
||||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
|
||||||
|
|
||||||
Please set the JAVA_HOME variable in your environment to match the
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
location of your Java installation."
|
location of your Java installation."
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
# Increase the maximum file descriptors if we can.
|
||||||
@ -145,7 +144,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
|||||||
case $MAX_FD in #(
|
case $MAX_FD in #(
|
||||||
max*)
|
max*)
|
||||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||||
# shellcheck disable=SC2039,SC3045
|
# shellcheck disable=SC3045
|
||||||
MAX_FD=$( ulimit -H -n ) ||
|
MAX_FD=$( ulimit -H -n ) ||
|
||||||
warn "Could not query maximum file descriptor limit"
|
warn "Could not query maximum file descriptor limit"
|
||||||
esac
|
esac
|
||||||
@ -153,7 +152,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
|||||||
'' | soft) :;; #(
|
'' | soft) :;; #(
|
||||||
*)
|
*)
|
||||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||||
# shellcheck disable=SC2039,SC3045
|
# shellcheck disable=SC3045
|
||||||
ulimit -n "$MAX_FD" ||
|
ulimit -n "$MAX_FD" ||
|
||||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||||
esac
|
esac
|
||||||
@ -198,15 +197,11 @@ if "$cygwin" || "$msys" ; then
|
|||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Collect all arguments for the java command;
|
||||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
# shell script including quotes and variable substitutions, so put them in
|
||||||
|
# double quotes to make sure that they get re-expanded; and
|
||||||
# Collect all arguments for the java command:
|
# * put everything else in single quotes, so that it's not re-expanded.
|
||||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
|
||||||
# and any embedded shellness will be escaped.
|
|
||||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
|
||||||
# treated as '${Hostname}' itself on the command line.
|
|
||||||
|
|
||||||
set -- \
|
set -- \
|
||||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||||
|
20
.github/workflow-samples/kotlin-dsl/gradlew.bat
vendored
20
.github/workflow-samples/kotlin-dsl/gradlew.bat
vendored
@ -43,11 +43,11 @@ set JAVA_EXE=java.exe
|
|||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if %ERRORLEVEL% equ 0 goto execute
|
if %ERRORLEVEL% equ 0 goto execute
|
||||||
|
|
||||||
echo. 1>&2
|
echo.
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
echo. 1>&2
|
echo.
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
echo location of your Java installation. 1>&2
|
echo location of your Java installation.
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
|||||||
|
|
||||||
if exist "%JAVA_EXE%" goto execute
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
echo. 1>&2
|
echo.
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
echo. 1>&2
|
echo.
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
echo location of your Java installation. 1>&2
|
echo location of your Java installation.
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("com.gradle.enterprise") version "3.16.2"
|
id("com.gradle.enterprise") version "3.12.6"
|
||||||
id("com.gradle.common-custom-user-data-gradle-plugin") version "1.13"
|
id("com.gradle.common-custom-user-data-gradle-plugin") version "1.10"
|
||||||
}
|
}
|
||||||
|
|
||||||
gradleEnterprise {
|
gradleEnterprise {
|
||||||
|
1
.github/workflow-samples/no-ge/build.gradle
vendored
1
.github/workflow-samples/no-ge/build.gradle
vendored
@ -1 +0,0 @@
|
|||||||
// Required to keep dependabot happy
|
|
@ -1 +0,0 @@
|
|||||||
rootProject.name = 'no-ge'
|
|
@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id "com.gradle.build-scan" version "3.16.2"
|
id "com.gradle.build-scan" version "3.12.6"
|
||||||
}
|
}
|
||||||
|
|
||||||
gradleEnterprise {
|
gradleEnterprise {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id "com.gradle.enterprise" version "3.16.2"
|
id "com.gradle.enterprise" version "3.12.6"
|
||||||
}
|
}
|
||||||
|
|
||||||
gradleEnterprise {
|
gradleEnterprise {
|
||||||
|
70
.github/workflows/ci-codeql.yml
vendored
Normal file
70
.github/workflows/ci-codeql.yml
vendored
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
# For most projects, this workflow file will not need changing; you simply need
|
||||||
|
# to commit it to your repository.
|
||||||
|
#
|
||||||
|
# You may wish to alter this file to override the set of languages analyzed,
|
||||||
|
# or to provide custom queries or build logic.
|
||||||
|
#
|
||||||
|
# ******** NOTE ********
|
||||||
|
# We have attempted to detect the languages in your repository. Please check
|
||||||
|
# the `language` matrix defined below to confirm you have the correct set of
|
||||||
|
# supported CodeQL languages.
|
||||||
|
#
|
||||||
|
name: CI-codeql
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ main ]
|
||||||
|
pull_request:
|
||||||
|
# The branches below must be a subset of the branches above
|
||||||
|
branches: [ main ]
|
||||||
|
schedule:
|
||||||
|
- cron: '25 23 * * 2'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
analyze:
|
||||||
|
name: Analyze
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
actions: read
|
||||||
|
contents: read
|
||||||
|
security-events: write
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
language: [ 'javascript' ]
|
||||||
|
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||||
|
# Learn more about CodeQL language support at https://git.io/codeql-language-support
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
# Initializes the CodeQL tools for scanning.
|
||||||
|
- name: Initialize CodeQL
|
||||||
|
uses: github/codeql-action/init@v2
|
||||||
|
with:
|
||||||
|
languages: ${{ matrix.language }}
|
||||||
|
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||||
|
# By default, queries listed here will override any specified in a config file.
|
||||||
|
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||||
|
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||||
|
|
||||||
|
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||||
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
|
- name: Autobuild
|
||||||
|
uses: github/codeql-action/autobuild@v2
|
||||||
|
|
||||||
|
# ℹ️ Command-line programs to run using the OS shell.
|
||||||
|
# 📚 https://git.io/JvXDl
|
||||||
|
|
||||||
|
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||||
|
# and modify them (or add more) to build your code if your project
|
||||||
|
# uses a compiled language
|
||||||
|
|
||||||
|
#- run: |
|
||||||
|
# make bootstrap
|
||||||
|
# make release
|
||||||
|
|
||||||
|
- name: Perform CodeQL Analysis
|
||||||
|
uses: github/codeql-action/analyze@v2
|
20
.github/workflows/ci-dependency-review.yml
vendored
Normal file
20
.github/workflows/ci-dependency-review.yml
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# Dependency Review Action
|
||||||
|
#
|
||||||
|
# This Action will scan dependency manifest files that change as part of a Pull Request, surfacing known-vulnerable versions of the packages declared or updated in the PR. Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable packages will be blocked from merging.
|
||||||
|
#
|
||||||
|
# Source repository: https://github.com/actions/dependency-review-action
|
||||||
|
# Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement
|
||||||
|
name: CI-dependency-review
|
||||||
|
on: [pull_request]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
dependency-review:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: 'Checkout Repository'
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: 'Dependency Review'
|
||||||
|
uses: actions/dependency-review-action@v3
|
51
.github/workflows/ci-full-check.yml
vendored
51
.github/workflows/ci-full-check.yml
vendored
@ -2,6 +2,16 @@ name: CI-full-check
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
pull_request:
|
||||||
|
types:
|
||||||
|
- assigned
|
||||||
|
- review_requested
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
paths:
|
||||||
|
- '.github/**'
|
||||||
|
- 'dist/**'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
action-inputs:
|
action-inputs:
|
||||||
@ -9,20 +19,13 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
cache-key-prefix: ${{github.run_number}}-
|
cache-key-prefix: ${{github.run_number}}-
|
||||||
|
|
||||||
|
cache-cleanup:
|
||||||
|
uses: ./.github/workflows/integ-test-cache-cleanup.yml
|
||||||
|
with:
|
||||||
|
cache-key-prefix: ${{github.run_number}}-
|
||||||
|
|
||||||
caching-config:
|
caching-config:
|
||||||
uses: ./.github/workflows/integ-test-caching-config.yml
|
uses: ./.github/workflows/integ-test-action-inputs-caching.yml
|
||||||
with:
|
|
||||||
cache-key-prefix: ${{github.run_number}}-
|
|
||||||
|
|
||||||
dependency-graph:
|
|
||||||
uses: ./.github/workflows/integ-test-dependency-graph.yml
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
with:
|
|
||||||
cache-key-prefix: ${{github.run_number}}-
|
|
||||||
|
|
||||||
dependency-graph-failures:
|
|
||||||
uses: ./.github/workflows/integ-test-dependency-graph-failures.yml
|
|
||||||
with:
|
with:
|
||||||
cache-key-prefix: ${{github.run_number}}-
|
cache-key-prefix: ${{github.run_number}}-
|
||||||
|
|
||||||
@ -36,24 +39,15 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
cache-key-prefix: ${{github.run_number}}-
|
cache-key-prefix: ${{github.run_number}}-
|
||||||
|
|
||||||
develocity-injection:
|
|
||||||
uses: ./.github/workflows/integ-test-inject-develocity.yml
|
|
||||||
with:
|
|
||||||
cache-key-prefix: ${{github.run_number}}-
|
|
||||||
secrets:
|
|
||||||
DEVELOCITY_ACCESS_KEY: ${{ secrets.GE_SOLUTIONS_ACCESS_TOKEN }}
|
|
||||||
|
|
||||||
provision-gradle-versions:
|
provision-gradle-versions:
|
||||||
uses: ./.github/workflows/integ-test-provision-gradle-versions.yml
|
uses: ./.github/workflows/integ-test-provision-gradle-versions.yml
|
||||||
with:
|
with:
|
||||||
cache-key-prefix: ${{github.run_number}}-
|
cache-key-prefix: ${{github.run_number}}-
|
||||||
|
|
||||||
restore-configuration-cache:
|
# restore-configuration-cache:
|
||||||
uses: ./.github/workflows/integ-test-restore-configuration-cache.yml
|
# uses: ./.github/workflows/integ-test-restore-configuration-cache.yml
|
||||||
with:
|
# with:
|
||||||
cache-key-prefix: ${{github.run_number}}-
|
# cache-key-prefix: ${{github.run_number}}-
|
||||||
secrets:
|
|
||||||
GRADLE_ENCRYPTION_KEY: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
|
|
||||||
|
|
||||||
restore-custom-gradle-home:
|
restore-custom-gradle-home:
|
||||||
uses: ./.github/workflows/integ-test-restore-custom-gradle-home.yml
|
uses: ./.github/workflows/integ-test-restore-custom-gradle-home.yml
|
||||||
@ -84,8 +78,3 @@ jobs:
|
|||||||
uses: ./.github/workflows/integ-test-sample-gradle-plugin.yml
|
uses: ./.github/workflows/integ-test-sample-gradle-plugin.yml
|
||||||
with:
|
with:
|
||||||
cache-key-prefix: ${{github.run_number}}-
|
cache-key-prefix: ${{github.run_number}}-
|
||||||
|
|
||||||
toolchain-detection:
|
|
||||||
uses: ./.github/workflows/integ-test-detect-java-toolchains.yml
|
|
||||||
with:
|
|
||||||
cache-key-prefix: ${{github.run_number}}-
|
|
||||||
|
26
.github/workflows/ci-init-script-check.yml
vendored
Normal file
26
.github/workflows/ci-init-script-check.yml
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
name: CI-init-script-check
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- '.github/workflows/ci-init-script-check.yml'
|
||||||
|
- 'src/resources/init-scripts/**'
|
||||||
|
- 'test/init-scripts/**'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test-init-scripts:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout sources
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Setup Java
|
||||||
|
uses: actions/setup-java@v3
|
||||||
|
with:
|
||||||
|
distribution: temurin
|
||||||
|
java-version: 8
|
||||||
|
- name: Setup Gradle
|
||||||
|
uses: gradle/gradle-build-action@v2 # Use a released version to avoid breakages
|
||||||
|
- name: Run integration tests
|
||||||
|
working-directory: test/init-scripts
|
||||||
|
run: ./gradlew check
|
93
.github/workflows/ci-quick-check.yml
vendored
93
.github/workflows/ci-quick-check.yml
vendored
@ -3,86 +3,117 @@ name: CI-quick-check
|
|||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
push:
|
push:
|
||||||
|
branches-ignore: main
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
build-distribution:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout sources
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Build and upload distribution
|
||||||
|
uses: ./.github/actions/build-dist
|
||||||
|
|
||||||
|
run-unit-tests:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout sources
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Configure Gradle as default for unit test
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
gradle-version: 7.6.1
|
||||||
|
- name: Run tests
|
||||||
|
run: |
|
||||||
|
npm install
|
||||||
|
npm run all
|
||||||
|
|
||||||
action-inputs:
|
action-inputs:
|
||||||
|
needs: build-distribution
|
||||||
uses: ./.github/workflows/integ-test-action-inputs.yml
|
uses: ./.github/workflows/integ-test-action-inputs.yml
|
||||||
with:
|
with:
|
||||||
runner-os: '["ubuntu-latest"]'
|
runner-os: '["ubuntu-latest"]'
|
||||||
|
download-dist: true
|
||||||
|
|
||||||
|
cache-cleanup:
|
||||||
|
needs: build-distribution
|
||||||
|
uses: ./.github/workflows/integ-test-cache-cleanup.yml
|
||||||
|
with:
|
||||||
|
runner-os: '["ubuntu-latest"]'
|
||||||
|
download-dist: true
|
||||||
|
cache-key-prefix: ${{github.run_number}}- # Requires a fresh cache entry each run
|
||||||
|
|
||||||
caching-config:
|
caching-config:
|
||||||
uses: ./.github/workflows/integ-test-caching-config.yml
|
needs: build-distribution
|
||||||
with:
|
uses: ./.github/workflows/integ-test-action-inputs-caching.yml
|
||||||
runner-os: '["ubuntu-latest"]'
|
|
||||||
|
|
||||||
dependency-graph:
|
|
||||||
uses: ./.github/workflows/integ-test-dependency-graph.yml
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
with:
|
|
||||||
runner-os: '["ubuntu-latest"]'
|
|
||||||
|
|
||||||
dependency-graph-failures:
|
|
||||||
uses: ./.github/workflows/integ-test-dependency-graph-failures.yml
|
|
||||||
with:
|
with:
|
||||||
runner-os: '["ubuntu-latest"]'
|
runner-os: '["ubuntu-latest"]'
|
||||||
|
download-dist: true
|
||||||
|
|
||||||
execution-with-caching:
|
execution-with-caching:
|
||||||
|
needs: build-distribution
|
||||||
uses: ./.github/workflows/integ-test-execution-with-caching.yml
|
uses: ./.github/workflows/integ-test-execution-with-caching.yml
|
||||||
with:
|
with:
|
||||||
runner-os: '["ubuntu-latest"]'
|
runner-os: '["ubuntu-latest"]'
|
||||||
|
download-dist: true
|
||||||
|
|
||||||
execution:
|
execution:
|
||||||
|
needs: build-distribution
|
||||||
uses: ./.github/workflows/integ-test-execution.yml
|
uses: ./.github/workflows/integ-test-execution.yml
|
||||||
with:
|
with:
|
||||||
runner-os: '["ubuntu-latest"]'
|
runner-os: '["ubuntu-latest"]'
|
||||||
|
download-dist: true
|
||||||
develocity-injection:
|
|
||||||
uses: ./.github/workflows/integ-test-inject-develocity.yml
|
|
||||||
with:
|
|
||||||
runner-os: '["ubuntu-latest"]'
|
|
||||||
secrets:
|
|
||||||
DEVELOCITY_ACCESS_KEY: ${{ secrets.GE_SOLUTIONS_ACCESS_TOKEN }}
|
|
||||||
|
|
||||||
provision-gradle-versions:
|
provision-gradle-versions:
|
||||||
|
needs: build-distribution
|
||||||
uses: ./.github/workflows/integ-test-provision-gradle-versions.yml
|
uses: ./.github/workflows/integ-test-provision-gradle-versions.yml
|
||||||
with:
|
with:
|
||||||
runner-os: '["ubuntu-latest"]'
|
runner-os: '["ubuntu-latest"]'
|
||||||
|
download-dist: true
|
||||||
|
|
||||||
restore-configuration-cache:
|
# restore-configuration-cache:
|
||||||
uses: ./.github/workflows/integ-test-restore-configuration-cache.yml
|
# needs: build-distribution
|
||||||
with:
|
# uses: ./.github/workflows/integ-test-restore-configuration-cache.yml
|
||||||
runner-os: '["ubuntu-latest"]'
|
# with:
|
||||||
secrets:
|
# runner-os: '["ubuntu-latest"]'
|
||||||
GRADLE_ENCRYPTION_KEY: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
|
# download-dist: true
|
||||||
|
|
||||||
restore-containerized-gradle-home:
|
restore-containerized-gradle-home:
|
||||||
|
needs: build-distribution
|
||||||
uses: ./.github/workflows/integ-test-restore-containerized-gradle-home.yml
|
uses: ./.github/workflows/integ-test-restore-containerized-gradle-home.yml
|
||||||
|
with:
|
||||||
|
download-dist: true
|
||||||
|
|
||||||
restore-custom-gradle-home:
|
restore-custom-gradle-home:
|
||||||
|
needs: build-distribution
|
||||||
uses: ./.github/workflows/integ-test-restore-custom-gradle-home.yml
|
uses: ./.github/workflows/integ-test-restore-custom-gradle-home.yml
|
||||||
|
with:
|
||||||
|
download-dist: true
|
||||||
|
|
||||||
restore-gradle-home:
|
restore-gradle-home:
|
||||||
|
needs: build-distribution
|
||||||
uses: ./.github/workflows/integ-test-restore-gradle-home.yml
|
uses: ./.github/workflows/integ-test-restore-gradle-home.yml
|
||||||
with:
|
with:
|
||||||
runner-os: '["ubuntu-latest"]'
|
runner-os: '["ubuntu-latest"]'
|
||||||
|
download-dist: true
|
||||||
|
|
||||||
restore-java-toolchain:
|
restore-java-toolchain:
|
||||||
|
needs: build-distribution
|
||||||
uses: ./.github/workflows/integ-test-restore-java-toolchain.yml
|
uses: ./.github/workflows/integ-test-restore-java-toolchain.yml
|
||||||
with:
|
with:
|
||||||
runner-os: '["ubuntu-latest"]'
|
runner-os: '["ubuntu-latest"]'
|
||||||
|
download-dist: true
|
||||||
|
|
||||||
sample-kotlin-dsl:
|
sample-kotlin-dsl:
|
||||||
|
needs: build-distribution
|
||||||
uses: ./.github/workflows/integ-test-sample-kotlin-dsl.yml
|
uses: ./.github/workflows/integ-test-sample-kotlin-dsl.yml
|
||||||
with:
|
with:
|
||||||
runner-os: '["ubuntu-latest"]'
|
runner-os: '["ubuntu-latest"]'
|
||||||
|
download-dist: true
|
||||||
|
|
||||||
sample-gradle-plugin:
|
sample-gradle-plugin:
|
||||||
|
needs: build-distribution
|
||||||
uses: ./.github/workflows/integ-test-sample-gradle-plugin.yml
|
uses: ./.github/workflows/integ-test-sample-gradle-plugin.yml
|
||||||
with:
|
with:
|
||||||
runner-os: '["ubuntu-latest"]'
|
runner-os: '["ubuntu-latest"]'
|
||||||
|
download-dist: true
|
||||||
toolchain-detection:
|
|
||||||
uses: ./.github/workflows/integ-test-detect-java-toolchains.yml
|
|
||||||
with:
|
|
||||||
runner-os: '["ubuntu-latest"]'
|
|
||||||
|
40
.github/workflows/ci-verify-outputs.yml
vendored
Normal file
40
.github/workflows/ci-verify-outputs.yml
vendored
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
name: CI-verify-outputs
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types:
|
||||||
|
- assigned
|
||||||
|
- review_requested
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- dependabot/**
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout sources
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
npm -v
|
||||||
|
node -v
|
||||||
|
npm install
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
- name: Compare the expected and actual dist/ directories
|
||||||
|
run: |
|
||||||
|
if [ "$(git diff --ignore-space-at-eol dist/ | wc -l)" -gt "0" ]; then
|
||||||
|
echo "Detected uncommitted changes after build. See status below:"
|
||||||
|
git diff
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
id: diff
|
||||||
|
|
||||||
|
# If index.js was different than expected, upload the expected version as an artifact
|
||||||
|
- uses: actions/upload-artifact@v3
|
||||||
|
if: ${{ failure() && steps.diff.conclusion == 'failure' }}
|
||||||
|
with:
|
||||||
|
name: dist
|
||||||
|
path: dist/
|
6
.github/workflows/demo-failure-cases.yml
vendored
6
.github/workflows/demo-failure-cases.yml
vendored
@ -9,7 +9,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
- name: Test build failure
|
- name: Test build failure
|
||||||
uses: ./
|
uses: ./
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
@ -21,7 +21,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
- name: Test wrapper missing
|
- name: Test wrapper missing
|
||||||
uses: ./
|
uses: ./
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
@ -33,7 +33,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
- name: Test bad config value
|
- name: Test bad config value
|
||||||
uses: ./
|
uses: ./
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
|
48
.github/workflows/demo-job-summary.yml
vendored
48
.github/workflows/demo-job-summary.yml
vendored
@ -1,4 +1,4 @@
|
|||||||
name: Demo Job Summary, for Gradle builds
|
name: Demo Job Summary for Gradle builds
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
@ -8,20 +8,25 @@ env:
|
|||||||
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
many-gradle-builds:
|
run-gradle-builds:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
|
- name: Build distribution
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
npm install
|
||||||
|
npm run build
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: ./
|
uses: ./
|
||||||
- name: Build kotlin-dsl project
|
- name: Build kotlin-dsl project
|
||||||
working-directory: .github/workflow-samples/kotlin-dsl
|
working-directory: .github/workflow-samples/kotlin-dsl
|
||||||
run: ./gradlew assemble
|
run: ./gradlew assemble
|
||||||
- name: Build kotlin-dsl project without Build Scan®
|
- name: Build kotlin-dsl project without build scan
|
||||||
working-directory: .github/workflow-samples/kotlin-dsl
|
working-directory: .github/workflow-samples/kotlin-dsl
|
||||||
run: ./gradlew assemble check --no-scan
|
run: ./gradlew assemble check --no-scan
|
||||||
- name: Build kotlin-dsl project with Build Scan® publish failure
|
- name: Build kotlin-dsl project with build scan publish failure
|
||||||
working-directory: .github/workflow-samples/kotlin-dsl
|
working-directory: .github/workflow-samples/kotlin-dsl
|
||||||
run: ./gradlew check -Dgradle.enterprise.url=https://not.valid.server
|
run: ./gradlew check -Dgradle.enterprise.url=https://not.valid.server
|
||||||
- name: Build groovy-dsl project
|
- name: Build groovy-dsl project
|
||||||
@ -36,36 +41,3 @@ jobs:
|
|||||||
working-directory: .github/workflow-samples/groovy-dsl
|
working-directory: .github/workflow-samples/groovy-dsl
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
run: ./gradlew not-a-real-task
|
run: ./gradlew not-a-real-task
|
||||||
|
|
||||||
successful-builds-with-no-summary:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout sources
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Setup Gradle
|
|
||||||
uses: ./
|
|
||||||
with:
|
|
||||||
add-job-summary: on-failure
|
|
||||||
- name: Build kotlin-dsl project
|
|
||||||
working-directory: .github/workflow-samples/kotlin-dsl
|
|
||||||
run: ./gradlew assemble
|
|
||||||
- name: Build kotlin-dsl project without Build Scan®
|
|
||||||
working-directory: .github/workflow-samples/kotlin-dsl
|
|
||||||
run: ./gradlew assemble check --no-scan
|
|
||||||
|
|
||||||
pre-existing-gradle-home:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout sources
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Pre-create Gradle User Home
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
mkdir ~/.gradle
|
|
||||||
mkdir ~/.gradle/caches
|
|
||||||
touch ~/.gradle/caches/dummy.txt
|
|
||||||
- name: Setup Gradle
|
|
||||||
uses: ./
|
|
||||||
- name: Run build
|
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
|
||||||
run: ./gradlew assemble
|
|
||||||
|
50
.github/workflows/demo-pr-build-scan-comment.yml
vendored
50
.github/workflows/demo-pr-build-scan-comment.yml
vendored
@ -1,51 +1,27 @@
|
|||||||
name: Demo adding Build Scan® comment to PR
|
name: Demo adding build scan comment to PR
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
types: [assigned, review_requested]
|
types: [assigned, review_requested]
|
||||||
|
|
||||||
permissions:
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
successful-build-with-always-comment:
|
gradle:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout project sources
|
- name: Checkout project sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
|
||||||
add-job-summary-as-pr-comment: always
|
|
||||||
- name: Run build with Gradle wrapper
|
- name: Run build with Gradle wrapper
|
||||||
id: gradle
|
id: gradle
|
||||||
working-directory: .github/workflow-samples/kotlin-dsl
|
working-directory: .github/workflow-samples/kotlin-dsl
|
||||||
run: ./gradlew build --scan
|
run: ./gradlew build --scan
|
||||||
|
- name: "Add build scan URL as PR comment"
|
||||||
successful-build-with-comment-on-failure:
|
uses: actions/github-script@v6
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout project sources
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Setup Gradle
|
|
||||||
uses: ./
|
|
||||||
with:
|
with:
|
||||||
add-job-summary-as-pr-comment: on-failure
|
github-token: ${{secrets.GITHUB_TOKEN}}
|
||||||
- name: Run build with Gradle wrapper
|
script: |
|
||||||
id: gradle
|
github.rest.issues.createComment({
|
||||||
working-directory: .github/workflow-samples/kotlin-dsl
|
issue_number: context.issue.number,
|
||||||
run: ./gradlew build --scan
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
failing-build-with-comment-on-failure:
|
body: 'PR ready for review: ${{ steps.gradle.outputs.build-scan-url }}'
|
||||||
runs-on: ubuntu-latest
|
})
|
||||||
steps:
|
|
||||||
- name: Checkout project sources
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Setup Gradle
|
|
||||||
uses: ./
|
|
||||||
with:
|
|
||||||
add-job-summary-as-pr-comment: on-failure
|
|
||||||
- name: Run build with Gradle wrapper
|
|
||||||
id: gradle
|
|
||||||
working-directory: .github/workflow-samples/kotlin-dsl
|
|
||||||
run: ./gradlew no-a-real-task --scan
|
|
||||||
continue-on-error: true
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
name: Test caching configuration
|
name: Test action inputs for caching
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_call:
|
workflow_call:
|
||||||
@ -8,8 +8,12 @@ on:
|
|||||||
runner-os:
|
runner-os:
|
||||||
type: string
|
type: string
|
||||||
default: '["ubuntu-latest", "windows-latest", "macos-latest"]'
|
default: '["ubuntu-latest", "windows-latest", "macos-latest"]'
|
||||||
|
download-dist:
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
DOWNLOAD_DIST: ${{ inputs.download-dist }}
|
||||||
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: action-inputs-caching-${{ inputs.cache-key-prefix }}
|
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: action-inputs-caching-${{ inputs.cache-key-prefix }}
|
||||||
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
||||||
|
|
||||||
@ -21,7 +25,9 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
@ -32,8 +38,7 @@ jobs:
|
|||||||
enterprise
|
enterprise
|
||||||
# Exclude build-cache from main cache entry
|
# Exclude build-cache from main cache entry
|
||||||
gradle-home-cache-excludes: |
|
gradle-home-cache-excludes: |
|
||||||
caches/build-cache-*
|
caches/build-cache-1
|
||||||
caches/*/executionHistory
|
|
||||||
- name: Build using Gradle wrapper
|
- name: Build using Gradle wrapper
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
working-directory: .github/workflow-samples/groovy-dsl
|
||||||
run: ./gradlew test
|
run: ./gradlew test
|
||||||
@ -47,7 +52,9 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
@ -56,8 +63,7 @@ jobs:
|
|||||||
caches
|
caches
|
||||||
enterprise
|
enterprise
|
||||||
gradle-home-cache-excludes: |
|
gradle-home-cache-excludes: |
|
||||||
caches/build-cache-*
|
caches/build-cache-1
|
||||||
caches/*/executionHistory
|
|
||||||
cache-read-only: true
|
cache-read-only: true
|
||||||
- name: Execute Gradle build with --offline
|
- name: Execute Gradle build with --offline
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
working-directory: .github/workflow-samples/groovy-dsl
|
||||||
@ -71,7 +77,9 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
@ -80,19 +88,21 @@ jobs:
|
|||||||
id: gradle
|
id: gradle
|
||||||
working-directory: .github/workflow-samples/no-wrapper${{ matrix.build-root-suffix }}
|
working-directory: .github/workflow-samples/no-wrapper${{ matrix.build-root-suffix }}
|
||||||
run: gradle help "-DgradleVersionCheck=${{matrix.gradle}}"
|
run: gradle help "-DgradleVersionCheck=${{matrix.gradle}}"
|
||||||
- name: Check Build Scan url is captured
|
- name: Check build scan url is captured
|
||||||
if: ${{ !steps.gradle.outputs.build-scan-url }}
|
if: ${{ !steps.gradle.outputs.build-scan-url }}
|
||||||
uses: actions/github-script@v7
|
uses: actions/github-script@v6
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
core.setFailed('No Build Scan detected')
|
core.setFailed('No build scan detected')
|
||||||
|
|
||||||
# Test that build scans are captured when caching is disabled because Gradle User Home already exists
|
# Test that build scans are captured when caching is disabled because Gradle User Home already exists
|
||||||
cache-disabled-pre-existing-gradle-home:
|
cache-disabled-pre-existing-gradle-home:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
- name: Create dummy Gradle User Home
|
- name: Create dummy Gradle User Home
|
||||||
run: mkdir -p ~/.gradle/caches
|
run: mkdir -p ~/.gradle/caches
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
@ -101,12 +111,12 @@ jobs:
|
|||||||
id: gradle
|
id: gradle
|
||||||
working-directory: .github/workflow-samples/no-wrapper${{ matrix.build-root-suffix }}
|
working-directory: .github/workflow-samples/no-wrapper${{ matrix.build-root-suffix }}
|
||||||
run: gradle help "-DgradleVersionCheck=${{matrix.gradle}}"
|
run: gradle help "-DgradleVersionCheck=${{matrix.gradle}}"
|
||||||
- name: Check Build Scan url is captured
|
- name: Check build scan url is captured
|
||||||
if: ${{ !steps.gradle.outputs.build-scan-url }}
|
if: ${{ !steps.gradle.outputs.build-scan-url }}
|
||||||
uses: actions/github-script@v7
|
uses: actions/github-script@v6
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
core.setFailed('No Build Scan detected')
|
core.setFailed('No build scan detected')
|
||||||
|
|
||||||
# Test seed the cache with cache-write-only and verify with cache-read-only
|
# Test seed the cache with cache-write-only and verify with cache-read-only
|
||||||
seed-build-write-only:
|
seed-build-write-only:
|
||||||
@ -118,7 +128,9 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
@ -137,7 +149,9 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
@ -8,8 +8,12 @@ on:
|
|||||||
runner-os:
|
runner-os:
|
||||||
type: string
|
type: string
|
||||||
default: '["ubuntu-latest", "windows-latest", "macos-latest"]'
|
default: '["ubuntu-latest", "windows-latest", "macos-latest"]'
|
||||||
|
download-dist:
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
DOWNLOAD_DIST: ${{ inputs.download-dist }}
|
||||||
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: action-inputs-${{ inputs.cache-key-prefix }}
|
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: action-inputs-${{ inputs.cache-key-prefix }}
|
||||||
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
||||||
|
|
||||||
@ -21,7 +25,9 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
- name: Invoke with multi-line arguments
|
- name: Invoke with multi-line arguments
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
|
87
.github/workflows/integ-test-cache-cleanup.yml
vendored
Normal file
87
.github/workflows/integ-test-cache-cleanup.yml
vendored
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
name: Test cache cleanup
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
cache-key-prefix:
|
||||||
|
type: string
|
||||||
|
runner-os:
|
||||||
|
type: string
|
||||||
|
default: '["ubuntu-latest", "windows-latest", "macos-latest"]'
|
||||||
|
download-dist:
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
|
||||||
|
env:
|
||||||
|
DOWNLOAD_DIST: ${{ inputs.download-dist }}
|
||||||
|
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: integ-test-cache-cleanup-${{ inputs.cache-key-prefix }}
|
||||||
|
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
full-build:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: ${{fromJSON(inputs.runner-os)}}
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout sources
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
|
- name: Setup Gradle
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
cache-read-only: false # For testing, allow writing cache entries on non-default branches
|
||||||
|
- name: Build with 3.1
|
||||||
|
working-directory: test/jest/resources/cache-cleanup
|
||||||
|
run: gradle --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:
|
||||||
|
needs: full-build
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: ${{fromJSON(inputs.runner-os)}}
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout sources
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
|
- name: Setup Gradle
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
cache-read-only: false
|
||||||
|
gradle-home-cache-cleanup: true
|
||||||
|
- name: Build with 3.1.1
|
||||||
|
working-directory: test/jest/resources/cache-cleanup
|
||||||
|
run: gradle --no-daemon --build-cache -Dcommons_math3_version="3.1.1" build
|
||||||
|
|
||||||
|
check-clean-cache:
|
||||||
|
needs: assemble-build
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: ${{fromJSON(inputs.runner-os)}}
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout sources
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
|
- name: Setup Gradle
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
cache-read-only: true
|
||||||
|
- name: Report Gradle User Home
|
||||||
|
run: du -hc ~/.gradle/caches/modules-2
|
||||||
|
- 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
|
||||||
|
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
|
||||||
|
echo "::error ::Should NOT find commons-math3 3.1 in cache"
|
||||||
|
exit 1
|
||||||
|
fi
|
@ -1,91 +0,0 @@
|
|||||||
name: Test dependency graph
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
inputs:
|
|
||||||
cache-key-prefix:
|
|
||||||
type: string
|
|
||||||
runner-os:
|
|
||||||
type: string
|
|
||||||
default: '["ubuntu-latest", "windows-latest", "macos-latest"]'
|
|
||||||
|
|
||||||
env:
|
|
||||||
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: dependency-graph-${{ inputs.cache-key-prefix }}
|
|
||||||
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
unsupported-gradle-version-warning:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout sources
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Setup Gradle for dependency-graph generate
|
|
||||||
uses: ./
|
|
||||||
with:
|
|
||||||
gradle-version: 7.0.1
|
|
||||||
dependency-graph: generate
|
|
||||||
dependency-graph-continue-on-failure: true
|
|
||||||
- name: Run with unsupported Gradle version
|
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
|
||||||
run: |
|
|
||||||
if gradle help | grep -q 'warning::Dependency Graph is not supported for Gradle 7.0.1. No dependency snapshot will be generated.';
|
|
||||||
then
|
|
||||||
echo "Got the expected warning"
|
|
||||||
else
|
|
||||||
echo "Did not get the expected warning"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
unsupported-gradle-version-failure:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout sources
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Setup Gradle for dependency-graph generate
|
|
||||||
uses: ./
|
|
||||||
with:
|
|
||||||
gradle-version: 7.0.1
|
|
||||||
dependency-graph: generate
|
|
||||||
dependency-graph-continue-on-failure: false
|
|
||||||
- name: Run with unsupported Gradle version
|
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
|
||||||
run: |
|
|
||||||
if gradle help; then
|
|
||||||
echo "Expected build to fail with Gradle 7.0.1"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
insufficient-permissions-warning:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
steps:
|
|
||||||
- name: Checkout sources
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Setup Gradle for dependency-graph generate
|
|
||||||
uses: ./
|
|
||||||
with:
|
|
||||||
dependency-graph: generate-and-submit
|
|
||||||
dependency-graph-continue-on-failure: true
|
|
||||||
- name: Run with insufficient permissions
|
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
|
||||||
run: ./gradlew help
|
|
||||||
# This test is primarily for demonstration: it's unclear how to check for warnings emitted in the post-action
|
|
||||||
|
|
||||||
SHOULD_FAIL-insufficient-permissions-failure:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
continue-on-error: true
|
|
||||||
steps:
|
|
||||||
- name: Checkout sources
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Setup Gradle for dependency-graph generate
|
|
||||||
uses: ./
|
|
||||||
with:
|
|
||||||
dependency-graph: generate-and-submit
|
|
||||||
dependency-graph-continue-on-failure: false
|
|
||||||
- name: Run with insufficient permissions
|
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
|
||||||
run: ./gradlew help
|
|
||||||
# This test is primarily for demonstration: it's unclear how to check for a failure in the post-action
|
|
134
.github/workflows/integ-test-dependency-graph.yml
vendored
134
.github/workflows/integ-test-dependency-graph.yml
vendored
@ -1,134 +0,0 @@
|
|||||||
name: Test dependency graph
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
inputs:
|
|
||||||
cache-key-prefix:
|
|
||||||
type: string
|
|
||||||
runner-os:
|
|
||||||
type: string
|
|
||||||
default: '["ubuntu-latest", "windows-latest", "macos-latest"]'
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
|
|
||||||
env:
|
|
||||||
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: dependency-graph-${{ inputs.cache-key-prefix }}
|
|
||||||
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
groovy-generate:
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
os: ${{fromJSON(inputs.runner-os)}}
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout sources
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Setup Gradle for dependency-graph generate
|
|
||||||
uses: ./
|
|
||||||
with:
|
|
||||||
dependency-graph: generate-and-upload
|
|
||||||
- name: Run gradle build
|
|
||||||
run: ./gradlew build
|
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
|
||||||
|
|
||||||
kotlin-generate:
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
os: ${{fromJSON(inputs.runner-os)}}
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout sources
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Setup Gradle for dependency-graph generate
|
|
||||||
uses: ./
|
|
||||||
with:
|
|
||||||
dependency-graph: generate-and-submit
|
|
||||||
- name: Run gradle build
|
|
||||||
run: ./gradlew build
|
|
||||||
working-directory: .github/workflow-samples/kotlin-dsl
|
|
||||||
|
|
||||||
submit:
|
|
||||||
needs: [groovy-generate]
|
|
||||||
runs-on: "ubuntu-latest"
|
|
||||||
steps:
|
|
||||||
- name: Checkout sources
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Submit dependency graphs
|
|
||||||
uses: ./
|
|
||||||
with:
|
|
||||||
dependency-graph: download-and-submit
|
|
||||||
|
|
||||||
multiple-builds:
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
os: ${{fromJSON(inputs.runner-os)}}
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout sources
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Setup Gradle for dependency-graph generate
|
|
||||||
uses: ./
|
|
||||||
with:
|
|
||||||
dependency-graph: generate-and-submit
|
|
||||||
- id: gradle-assemble
|
|
||||||
run: ./gradlew assemble
|
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
|
||||||
- id: gradle-build
|
|
||||||
run: ./gradlew build
|
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
|
||||||
- id: gradle-build-again
|
|
||||||
run: ./gradlew build
|
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
|
||||||
- name: Check generated dependency graphs
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
echo "gradle-assemble report file: ${{ steps.gradle-assemble.outputs.dependency-graph-file }}"
|
|
||||||
echo "gradle-build report file: ${{ steps.gradle-build.outputs.dependency-graph-file }}"
|
|
||||||
echo "gradle-build-again report file: ${{ steps.gradle-build-again.outputs.dependency-graph-file }}"
|
|
||||||
ls -l dependency-graph-reports
|
|
||||||
if [ ! -e "${{ steps.gradle-assemble.outputs.dependency-graph-file }}" ]; then
|
|
||||||
echo "Did not find gradle-assemble dependency graph file"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
if [ ! -e "${{ steps.gradle-build.outputs.dependency-graph-file }}" ]; then
|
|
||||||
echo "Did not find gradle-build dependency graph files"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
if [ ! -e "${{ steps.gradle-build-again.outputs.dependency-graph-file }}" ]; then
|
|
||||||
echo "Did not find gradle-build-again dependency graph files"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
config-cache:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout sources
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Setup Gradle for dependency-graph generate
|
|
||||||
uses: ./
|
|
||||||
with:
|
|
||||||
dependency-graph: generate-and-submit
|
|
||||||
- id: config-cache-store
|
|
||||||
run: ./gradlew assemble --configuration-cache
|
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
|
||||||
- name: Check and delete generated dependency graph
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
if [ ! -e "${{ steps.config-cache-store.outputs.dependency-graph-file }}" ]; then
|
|
||||||
echo "Did not find config-cache-store dependency graph files"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
rm ${{ steps.config-cache-store.outputs.dependency-graph-file }}
|
|
||||||
- id: config-cache-reuse
|
|
||||||
run: ./gradlew assemble --configuration-cache
|
|
||||||
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
|
|
@ -1,85 +0,0 @@
|
|||||||
name: Test detect java toolchains
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
inputs:
|
|
||||||
cache-key-prefix:
|
|
||||||
type: string
|
|
||||||
runner-os:
|
|
||||||
type: string
|
|
||||||
default: '["ubuntu-latest", "windows-latest", "macos-latest"]'
|
|
||||||
|
|
||||||
env:
|
|
||||||
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: detect-java-toolchain-${{ inputs.cache-key-prefix }}
|
|
||||||
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
# Test that pre-installed runner JDKs are detected
|
|
||||||
pre-installed-toolchains:
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
os: ${{fromJSON(inputs.runner-os)}}
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout sources
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Setup Gradle
|
|
||||||
uses: ./
|
|
||||||
- name: List detected toolchains
|
|
||||||
shell: bash
|
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
|
||||||
run: |
|
|
||||||
gradle --info javaToolchains > output.txt
|
|
||||||
cat output.txt
|
|
||||||
- name: Verify detected toolchains
|
|
||||||
shell: bash
|
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
|
||||||
run: |
|
|
||||||
grep -q 'Eclipse Temurin JDK 1.8' output.txt || (echo "::error::Did not detect preinstalled JDK 1.8" && exit 1)
|
|
||||||
grep -q 'Eclipse Temurin JDK 11' output.txt || (echo "::error::Did not detect preinstalled JDK 11" && exit 1)
|
|
||||||
grep -q 'Eclipse Temurin JDK 17' output.txt || (echo "::error::Did not detect preinstalled JDK 17" && exit 1)
|
|
||||||
grep -q 'Eclipse Temurin JDK 21' output.txt || (echo "::error::Did not detect preinstalled JDK 21" && exit 1)
|
|
||||||
|
|
||||||
# Test that JDKs provisioned by setup-java are detected
|
|
||||||
setup-java-installed-toolchain:
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
os: ${{fromJSON(inputs.runner-os)}}
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout sources
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Setup Java 20
|
|
||||||
uses: actions/setup-java@v4
|
|
||||||
with:
|
|
||||||
distribution: 'temurin'
|
|
||||||
java-version: '20'
|
|
||||||
- name: Setup Java 16
|
|
||||||
uses: actions/setup-java@v4
|
|
||||||
with:
|
|
||||||
distribution: 'temurin'
|
|
||||||
java-version: '16'
|
|
||||||
- name: Setup Gradle
|
|
||||||
uses: ./
|
|
||||||
- name: List detected toolchains
|
|
||||||
shell: bash
|
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
|
||||||
run: |
|
|
||||||
gradle --info javaToolchains > output.txt
|
|
||||||
cat output.txt
|
|
||||||
- name: Verify setup JDKs are detected
|
|
||||||
shell: bash
|
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
|
||||||
run: |
|
|
||||||
grep -q 'Eclipse Temurin JDK 16' output.txt || (echo "::error::Did not detect setup-java installed JDK 16" && exit 1)
|
|
||||||
grep -q 'Eclipse Temurin JDK 20' output.txt || (echo "::error::Did not detect setup-java installed JDK 20" && exit 1)
|
|
||||||
- name: Verify pre-installed toolchains are detected
|
|
||||||
shell: bash
|
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
|
||||||
run: |
|
|
||||||
grep -q 'Eclipse Temurin JDK 1.8' output.txt || (echo "::error::Did not detect preinstalled JDK 1.8" && exit 1)
|
|
||||||
grep -q 'Eclipse Temurin JDK 11' output.txt || (echo "::error::Did not detect preinstalled JDK 11" && exit 1)
|
|
||||||
grep -q 'Eclipse Temurin JDK 17' output.txt || (echo "::error::Did not detect preinstalled JDK 17" && exit 1)
|
|
||||||
grep -q 'Eclipse Temurin JDK 21' output.txt || (echo "::error::Did not detect preinstalled JDK 21" && exit 1)
|
|
@ -8,8 +8,12 @@ on:
|
|||||||
runner-os:
|
runner-os:
|
||||||
type: string
|
type: string
|
||||||
default: '["ubuntu-latest", "windows-latest", "macos-latest"]'
|
default: '["ubuntu-latest", "windows-latest", "macos-latest"]'
|
||||||
|
download-dist:
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
DOWNLOAD_DIST: ${{ inputs.download-dist }}
|
||||||
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: execution-with-caching-${{ inputs.cache-key-prefix }}
|
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: execution-with-caching-${{ inputs.cache-key-prefix }}
|
||||||
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
||||||
|
|
||||||
@ -21,7 +25,9 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
- name: Execute Gradle build
|
- name: Execute Gradle build
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
@ -38,7 +44,9 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
- name: Execute Gradle build
|
- name: Execute Gradle build
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
|
26
.github/workflows/integ-test-execution.yml
vendored
26
.github/workflows/integ-test-execution.yml
vendored
@ -8,8 +8,12 @@ on:
|
|||||||
runner-os:
|
runner-os:
|
||||||
type: string
|
type: string
|
||||||
default: '["ubuntu-latest", "windows-latest", "macos-latest"]'
|
default: '["ubuntu-latest", "windows-latest", "macos-latest"]'
|
||||||
|
download-dist:
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
DOWNLOAD_DIST: ${{ inputs.download-dist }}
|
||||||
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: execution-${{ inputs.cache-key-prefix }}
|
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: execution-${{ inputs.cache-key-prefix }}
|
||||||
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
||||||
|
|
||||||
@ -26,7 +30,9 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
- name: Test use defined Gradle version
|
- name: Test use defined Gradle version
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
@ -40,6 +46,12 @@ jobs:
|
|||||||
gradle-version: release-candidate
|
gradle-version: release-candidate
|
||||||
build-root-directory: .github/workflow-samples/no-wrapper
|
build-root-directory: .github/workflow-samples/no-wrapper
|
||||||
arguments: help
|
arguments: help
|
||||||
|
- name: Test use defined Gradle executable
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
gradle-executable: .github/workflow-samples/groovy-dsl/gradlew${{ matrix.script-suffix }}
|
||||||
|
build-root-directory: .github/workflow-samples/no-wrapper
|
||||||
|
arguments: help
|
||||||
|
|
||||||
gradle-versions:
|
gradle-versions:
|
||||||
strategy:
|
strategy:
|
||||||
@ -56,9 +68,11 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
- name: Setup Java
|
- name: Setup Java
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
distribution: temurin
|
distribution: temurin
|
||||||
java-version: 8
|
java-version: 8
|
||||||
@ -70,11 +84,11 @@ jobs:
|
|||||||
gradle-version: ${{matrix.gradle}}
|
gradle-version: ${{matrix.gradle}}
|
||||||
build-root-directory: .github/workflow-samples/no-wrapper${{ matrix.build-root-suffix }}
|
build-root-directory: .github/workflow-samples/no-wrapper${{ matrix.build-root-suffix }}
|
||||||
arguments: help -DgradleVersionCheck=${{matrix.gradle}}
|
arguments: help -DgradleVersionCheck=${{matrix.gradle}}
|
||||||
- name: Check Build Scan url
|
- name: Check build scan url
|
||||||
if: ${{ !steps.gradle.outputs.build-scan-url }}
|
if: ${{ !steps.gradle.outputs.build-scan-url }}
|
||||||
uses: actions/github-script@v7
|
uses: actions/github-script@v6
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
core.setFailed('No Build Scan detected')
|
core.setFailed('No build scan detected')
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,89 +0,0 @@
|
|||||||
name: Test develocity injection
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
inputs:
|
|
||||||
cache-key-prefix:
|
|
||||||
type: string
|
|
||||||
runner-os:
|
|
||||||
type: string
|
|
||||||
default: '["ubuntu-latest", "windows-latest", "macos-latest"]'
|
|
||||||
secrets:
|
|
||||||
DEVELOCITY_ACCESS_KEY:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
env:
|
|
||||||
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: provision-gradle-versions-${{ inputs.cache-key-prefix }}
|
|
||||||
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
inject-develocity:
|
|
||||||
env:
|
|
||||||
DEVELOCITY_INJECTION_ENABLED: true
|
|
||||||
DEVELOCITY_URL: https://ge.solutions-team.gradle.com
|
|
||||||
DEVELOCITY_PLUGIN_VERSION: 3.16.2
|
|
||||||
DEVELOCITY_CCUD_PLUGIN_VERSION: 1.13
|
|
||||||
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }} # This env var has not (yet) been renamed/aliased in GE plugin 3.16.2
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
gradle: [current, 7.6.2, 6.9.4, 5.6.4]
|
|
||||||
os: ${{fromJSON(inputs.runner-os)}}
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout sources
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Setup Java
|
|
||||||
uses: actions/setup-java@v4
|
|
||||||
with:
|
|
||||||
distribution: temurin
|
|
||||||
java-version: 8
|
|
||||||
- name: Setup Gradle
|
|
||||||
id: setup-gradle
|
|
||||||
uses: ./
|
|
||||||
with:
|
|
||||||
cache-read-only: false # For testing, allow writing cache entries on non-default branches
|
|
||||||
gradle-version: ${{ matrix.gradle }}
|
|
||||||
- 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')
|
|
||||||
|
|
||||||
build-scan-publish:
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
gradle: [current, 7.6.2, 6.9.4, 5.6.4]
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout sources
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Setup Java
|
|
||||||
uses: actions/setup-java@v4
|
|
||||||
with:
|
|
||||||
distribution: temurin
|
|
||||||
java-version: 8
|
|
||||||
- name: Setup Gradle
|
|
||||||
id: setup-gradle
|
|
||||||
uses: ./
|
|
||||||
with:
|
|
||||||
cache-read-only: false # For testing, allow writing cache entries on non-default branches
|
|
||||||
gradle-version: ${{ matrix.gradle }}
|
|
||||||
build-scan-publish: true
|
|
||||||
build-scan-terms-of-service-url: "https://gradle.com/terms-of-service"
|
|
||||||
build-scan-terms-of-service-agree: "yes"
|
|
||||||
- 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')
|
|
||||||
|
|
@ -8,8 +8,12 @@ on:
|
|||||||
runner-os:
|
runner-os:
|
||||||
type: string
|
type: string
|
||||||
default: '["ubuntu-latest", "windows-latest", "macos-latest"]'
|
default: '["ubuntu-latest", "windows-latest", "macos-latest"]'
|
||||||
|
download-dist:
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
DOWNLOAD_DIST: ${{ inputs.download-dist }}
|
||||||
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: provision-gradle-versions-${{ inputs.cache-key-prefix }}
|
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: provision-gradle-versions-${{ inputs.cache-key-prefix }}
|
||||||
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
||||||
|
|
||||||
@ -26,7 +30,9 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
- name: Setup Gradle with v6.9
|
- name: Setup Gradle with v6.9
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
@ -49,17 +55,6 @@ jobs:
|
|||||||
- name: Test use release-candidate
|
- name: Test use release-candidate
|
||||||
working-directory: .github/workflow-samples/no-wrapper
|
working-directory: .github/workflow-samples/no-wrapper
|
||||||
run: gradle help
|
run: gradle help
|
||||||
- name: Setup Gradle with current
|
|
||||||
id: gradle-current
|
|
||||||
uses: ./
|
|
||||||
with:
|
|
||||||
gradle-version: current
|
|
||||||
- name: Check current version output parameter
|
|
||||||
if: ${{ !startsWith(steps.gradle-current.outputs.gradle-version , '8.') }}
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
core.setFailed('Gradle version parameter not set correctly: value was "${{ steps.gradle-current.outputs.gradle-version }}"')
|
|
||||||
|
|
||||||
gradle-versions:
|
gradle-versions:
|
||||||
strategy:
|
strategy:
|
||||||
@ -76,33 +71,28 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
- name: Setup Java
|
- name: Setup Java
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
distribution: temurin
|
distribution: temurin
|
||||||
java-version: 8
|
java-version: 8
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
id: setup-gradle
|
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
cache-read-only: false # For testing, allow writing cache entries on non-default branches
|
cache-read-only: false # For testing, allow writing cache entries on non-default branches
|
||||||
gradle-version: ${{ matrix.gradle }}
|
gradle-version: ${{ matrix.gradle }}
|
||||||
- name: Check output parameter
|
|
||||||
if: ${{ steps.setup-gradle.outputs.gradle-version != matrix.gradle }}
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
core.setFailed('Gradle version parameter not set correctly: value was "${{ steps.setup-gradle.outputs.gradle-version }}"')
|
|
||||||
- name: Run Gradle build
|
- name: Run Gradle build
|
||||||
id: gradle
|
id: gradle
|
||||||
working-directory: .github/workflow-samples/no-wrapper${{ matrix.build-root-suffix }}
|
working-directory: .github/workflow-samples/no-wrapper${{ matrix.build-root-suffix }}
|
||||||
run: gradle help "-DgradleVersionCheck=${{matrix.gradle}}"
|
run: gradle help "-DgradleVersionCheck=${{matrix.gradle}}"
|
||||||
- name: Check Build Scan url
|
- name: Check build scan url
|
||||||
if: ${{ !steps.gradle.outputs.build-scan-url }}
|
if: ${{ !steps.gradle.outputs.build-scan-url }}
|
||||||
uses: actions/github-script@v7
|
uses: actions/github-script@v6
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
core.setFailed('No Build Scan detected')
|
core.setFailed('No build scan detected')
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,11 +8,12 @@ on:
|
|||||||
runner-os:
|
runner-os:
|
||||||
type: string
|
type: string
|
||||||
default: '["ubuntu-latest", "windows-latest", "macos-latest"]'
|
default: '["ubuntu-latest", "windows-latest", "macos-latest"]'
|
||||||
secrets:
|
download-dist:
|
||||||
GRADLE_ENCRYPTION_KEY:
|
type: boolean
|
||||||
required: true
|
default: false
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
DOWNLOAD_DIST: ${{ inputs.download-dist }}
|
||||||
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: restore-configuration-cache-${{ inputs.cache-key-prefix }}
|
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: restore-configuration-cache-${{ inputs.cache-key-prefix }}
|
||||||
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
||||||
|
|
||||||
@ -26,21 +27,16 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
- name: Setup Java to ensure consistency
|
- name: Download distribution if required
|
||||||
uses: actions/setup-java@v4
|
uses: ./.github/actions/download-dist
|
||||||
with:
|
|
||||||
distribution: 'liberica'
|
|
||||||
java-version: '21'
|
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
cache-read-only: false # For testing, allow writing cache entries on non-default branches
|
cache-read-only: false # For testing, allow writing cache entries on non-default branches
|
||||||
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
|
|
||||||
gradle-version: 8.6-rc-1
|
|
||||||
- name: Groovy build with configuration-cache enabled
|
- name: Groovy build with configuration-cache enabled
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
working-directory: .github/workflow-samples/groovy-dsl
|
||||||
run: gradle test --configuration-cache
|
run: ./gradlew test --configuration-cache
|
||||||
|
|
||||||
verify-build-groovy:
|
verify-build-groovy:
|
||||||
env:
|
env:
|
||||||
@ -52,24 +48,19 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
- name: Setup Java to ensure consistency
|
- name: Download distribution if required
|
||||||
uses: actions/setup-java@v4
|
uses: ./.github/actions/download-dist
|
||||||
with:
|
|
||||||
distribution: 'liberica'
|
|
||||||
java-version: '21'
|
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
cache-read-only: true
|
cache-read-only: true
|
||||||
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
|
|
||||||
gradle-version: 8.6-rc-1
|
|
||||||
- name: Groovy build with configuration-cache enabled
|
- name: Groovy build with configuration-cache enabled
|
||||||
id: execute
|
id: execute
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
working-directory: .github/workflow-samples/groovy-dsl
|
||||||
run: gradle test --configuration-cache
|
run: ./gradlew test --configuration-cache
|
||||||
- name: Check that configuration-cache was used
|
- name: Check that configuration-cache was used
|
||||||
uses: actions/github-script@v7
|
uses: actions/github-script@v6
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
@ -88,23 +79,18 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
- name: Setup Java to ensure consistency
|
- name: Download distribution if required
|
||||||
uses: actions/setup-java@v4
|
uses: ./.github/actions/download-dist
|
||||||
with:
|
|
||||||
distribution: 'liberica'
|
|
||||||
java-version: '21'
|
|
||||||
- name: Setup Gradle with no extracted cache entries restored
|
- name: Setup Gradle with no extracted cache entries restored
|
||||||
uses: ./
|
uses: ./
|
||||||
env:
|
env:
|
||||||
GRADLE_BUILD_ACTION_SKIP_RESTORE: "generated-gradle-jars|wrapper-zips|java-toolchains|instrumented-jars|dependencies|kotlin-dsl"
|
GRADLE_BUILD_ACTION_SKIP_RESTORE: "generated-gradle-jars|wrapper-zips|java-toolchains|instrumented-jars|dependencies|kotlin-dsl"
|
||||||
with:
|
with:
|
||||||
cache-read-only: true
|
cache-read-only: true
|
||||||
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
|
|
||||||
gradle-version: 8.6-rc-1
|
|
||||||
- name: Check execute Gradle build with configuration cache enabled (but not restored)
|
- name: Check execute Gradle build with configuration cache enabled (but not restored)
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
working-directory: .github/workflow-samples/groovy-dsl
|
||||||
run: gradle test --configuration-cache
|
run: ./gradlew test --configuration-cache
|
||||||
|
|
||||||
seed-build-kotlin:
|
seed-build-kotlin:
|
||||||
env:
|
env:
|
||||||
@ -115,21 +101,16 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
- name: Setup Java to ensure consistency
|
- name: Download distribution if required
|
||||||
uses: actions/setup-java@v4
|
uses: ./.github/actions/download-dist
|
||||||
with:
|
|
||||||
distribution: 'liberica'
|
|
||||||
java-version: '21'
|
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
cache-read-only: false # For testing, allow writing cache entries on non-default branches
|
cache-read-only: false # For testing, allow writing cache entries on non-default branches
|
||||||
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
|
|
||||||
gradle-version: 8.6-rc-1
|
|
||||||
- name: Execute 'help' with configuration-cache enabled
|
- name: Execute 'help' with configuration-cache enabled
|
||||||
working-directory: .github/workflow-samples/kotlin-dsl
|
working-directory: .github/workflow-samples/kotlin-dsl
|
||||||
run: gradle help --configuration-cache
|
run: ./gradlew help --configuration-cache
|
||||||
|
|
||||||
modify-build-kotlin:
|
modify-build-kotlin:
|
||||||
env:
|
env:
|
||||||
@ -141,21 +122,16 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
- name: Setup Java to ensure consistency
|
- name: Download distribution if required
|
||||||
uses: actions/setup-java@v4
|
uses: ./.github/actions/download-dist
|
||||||
with:
|
|
||||||
distribution: 'liberica'
|
|
||||||
java-version: '21'
|
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
cache-read-only: false # For testing, allow writing cache entries on non-default branches
|
cache-read-only: false # For testing, allow writing cache entries on non-default branches
|
||||||
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
|
|
||||||
gradle-version: 8.6-rc-1
|
|
||||||
- name: Execute 'test' with configuration-cache enabled
|
- name: Execute 'test' with configuration-cache enabled
|
||||||
working-directory: .github/workflow-samples/kotlin-dsl
|
working-directory: .github/workflow-samples/kotlin-dsl
|
||||||
run: gradle test --configuration-cache
|
run: ./gradlew test --configuration-cache
|
||||||
|
|
||||||
# Test restore configuration-cache from the third build invocation
|
# Test restore configuration-cache from the third build invocation
|
||||||
verify-build-kotlin:
|
verify-build-kotlin:
|
||||||
@ -168,24 +144,19 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
- name: Setup Java to ensure consistency
|
- name: Download distribution if required
|
||||||
uses: actions/setup-java@v4
|
uses: ./.github/actions/download-dist
|
||||||
with:
|
|
||||||
distribution: 'liberica'
|
|
||||||
java-version: '21'
|
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
cache-read-only: true
|
cache-read-only: true
|
||||||
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
|
|
||||||
gradle-version: 8.6-rc-1
|
|
||||||
- name: Execute 'test' again with configuration-cache enabled
|
- name: Execute 'test' again with configuration-cache enabled
|
||||||
id: execute
|
id: execute
|
||||||
working-directory: .github/workflow-samples/kotlin-dsl
|
working-directory: .github/workflow-samples/kotlin-dsl
|
||||||
run: gradle test --configuration-cache
|
run: ./gradlew test --configuration-cache
|
||||||
- name: Check that configuration-cache was used
|
- name: Check that configuration-cache was used
|
||||||
uses: actions/github-script@v7
|
uses: actions/github-script@v6
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
|
@ -5,8 +5,12 @@ on:
|
|||||||
inputs:
|
inputs:
|
||||||
cache-key-prefix:
|
cache-key-prefix:
|
||||||
type: string
|
type: string
|
||||||
|
download-dist:
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
DOWNLOAD_DIST: ${{ inputs.download-dist }}
|
||||||
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: restore-custom-gradle-home-${{ inputs.cache-key-prefix }}
|
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: restore-custom-gradle-home-${{ inputs.cache-key-prefix }}
|
||||||
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
||||||
|
|
||||||
@ -16,9 +20,11 @@ jobs:
|
|||||||
container: fedora:latest
|
container: fedora:latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
- name: Setup Java
|
- name: Setup Java
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
java-version: 11
|
java-version: 11
|
||||||
distribution: temurin
|
distribution: temurin
|
||||||
@ -37,9 +43,11 @@ jobs:
|
|||||||
container: fedora:latest
|
container: fedora:latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
- name: Setup Java
|
- name: Setup Java
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
java-version: 11
|
java-version: 11
|
||||||
distribution: temurin
|
distribution: temurin
|
||||||
|
@ -5,8 +5,12 @@ on:
|
|||||||
inputs:
|
inputs:
|
||||||
cache-key-prefix:
|
cache-key-prefix:
|
||||||
type: string
|
type: string
|
||||||
|
download-dist:
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
DOWNLOAD_DIST: ${{ inputs.download-dist }}
|
||||||
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: restore-custom-gradle-home-${{ inputs.cache-key-prefix }}
|
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: restore-custom-gradle-home-${{ inputs.cache-key-prefix }}
|
||||||
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
||||||
|
|
||||||
@ -19,7 +23,9 @@ jobs:
|
|||||||
mkdir -p $GITHUB_WORKSPACE/gradle-user-home
|
mkdir -p $GITHUB_WORKSPACE/gradle-user-home
|
||||||
echo "GRADLE_USER_HOME=$GITHUB_WORKSPACE/gradle-user-home" >> $GITHUB_ENV
|
echo "GRADLE_USER_HOME=$GITHUB_WORKSPACE/gradle-user-home" >> $GITHUB_ENV
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
@ -38,7 +44,9 @@ jobs:
|
|||||||
mkdir -p $GITHUB_WORKSPACE/gradle-user-home
|
mkdir -p $GITHUB_WORKSPACE/gradle-user-home
|
||||||
echo "GRADLE_USER_HOME=$GITHUB_WORKSPACE/gradle-user-home" >> $GITHUB_ENV
|
echo "GRADLE_USER_HOME=$GITHUB_WORKSPACE/gradle-user-home" >> $GITHUB_ENV
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
@ -57,7 +65,9 @@ jobs:
|
|||||||
mkdir -p $GITHUB_WORKSPACE/gradle-user-home
|
mkdir -p $GITHUB_WORKSPACE/gradle-user-home
|
||||||
echo "GRADLE_USER_HOME=$GITHUB_WORKSPACE/gradle-user-home" >> $GITHUB_ENV
|
echo "GRADLE_USER_HOME=$GITHUB_WORKSPACE/gradle-user-home" >> $GITHUB_ENV
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
|
@ -8,8 +8,12 @@ on:
|
|||||||
runner-os:
|
runner-os:
|
||||||
type: string
|
type: string
|
||||||
default: '["ubuntu-latest", "windows-latest", "macos-latest"]'
|
default: '["ubuntu-latest", "windows-latest", "macos-latest"]'
|
||||||
|
download-dist:
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
DOWNLOAD_DIST: ${{ inputs.download-dist }}
|
||||||
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: restore-gradle-home-${{ inputs.cache-key-prefix }}
|
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: restore-gradle-home-${{ inputs.cache-key-prefix }}
|
||||||
GRADLE_BUILD_ACTION_CACHE_KEY_JOB: restore-gradle-home
|
GRADLE_BUILD_ACTION_CACHE_KEY_JOB: restore-gradle-home
|
||||||
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
||||||
@ -22,7 +26,9 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
@ -40,7 +46,9 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
@ -58,7 +66,9 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
@ -76,7 +86,9 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
- name: Setup Gradle with no extracted cache entries restored
|
- name: Setup Gradle with no extracted cache entries restored
|
||||||
uses: ./
|
uses: ./
|
||||||
env:
|
env:
|
||||||
@ -87,38 +99,3 @@ jobs:
|
|||||||
working-directory: .github/workflow-samples/groovy-dsl
|
working-directory: .github/workflow-samples/groovy-dsl
|
||||||
run: ./gradlew test
|
run: ./gradlew test
|
||||||
|
|
||||||
# Test that a pre-existing gradle-user-home can be overwritten by the restored cache
|
|
||||||
pre-existing-gradle-home:
|
|
||||||
needs: seed-build
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
os: ${{fromJSON(inputs.runner-os)}}
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout sources
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Pre-create Gradle User Home
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
mkdir -p ~/.gradle/caches
|
|
||||||
touch ~/.gradle/gradle.properties
|
|
||||||
touch ~/.gradle/caches/dummy.txt
|
|
||||||
- name: Setup Gradle
|
|
||||||
uses: ./
|
|
||||||
with:
|
|
||||||
cache-read-only: true
|
|
||||||
cache-overwrite-existing: true
|
|
||||||
- name: Check that pre-existing content still exists
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
if [ ! -e ~/.gradle/caches/dummy.txt ]; then
|
|
||||||
echo "::error ::Should find dummy.txt after cache restore"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
if [ ! -e ~/.gradle/gradle.properties ]; then
|
|
||||||
echo "::error ::Should find gradle.properties after cache restore"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
- name: Execute Gradle build with --offline
|
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
|
||||||
run: ./gradlew test --offline
|
|
||||||
|
@ -8,8 +8,12 @@ on:
|
|||||||
runner-os:
|
runner-os:
|
||||||
type: string
|
type: string
|
||||||
default: '["ubuntu-latest", "windows-latest", "macos-latest"]'
|
default: '["ubuntu-latest", "windows-latest", "macos-latest"]'
|
||||||
|
download-dist:
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
DOWNLOAD_DIST: ${{ inputs.download-dist }}
|
||||||
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: restore-java-toolchain-${{ inputs.cache-key-prefix }}
|
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: restore-java-toolchain-${{ inputs.cache-key-prefix }}
|
||||||
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
||||||
|
|
||||||
@ -21,7 +25,9 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
@ -39,7 +45,9 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
|
@ -8,8 +8,12 @@ on:
|
|||||||
runner-os:
|
runner-os:
|
||||||
type: string
|
type: string
|
||||||
default: '["ubuntu-latest", "windows-latest", "macos-latest"]'
|
default: '["ubuntu-latest", "windows-latest", "macos-latest"]'
|
||||||
|
download-dist:
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
DOWNLOAD_DIST: ${{ inputs.download-dist }}
|
||||||
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: sample-gradle-plugin-${{ inputs.cache-key-prefix }}
|
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: sample-gradle-plugin-${{ inputs.cache-key-prefix }}
|
||||||
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
||||||
|
|
||||||
@ -21,7 +25,9 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
@ -38,7 +44,9 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
|
@ -8,8 +8,12 @@ on:
|
|||||||
runner-os:
|
runner-os:
|
||||||
type: string
|
type: string
|
||||||
default: '["ubuntu-latest", "windows-latest", "macos-latest"]'
|
default: '["ubuntu-latest", "windows-latest", "macos-latest"]'
|
||||||
|
download-dist:
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
DOWNLOAD_DIST: ${{ inputs.download-dist }}
|
||||||
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: sample-kotlin-dsl-${{ inputs.cache-key-prefix }}
|
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: sample-kotlin-dsl-${{ inputs.cache-key-prefix }}
|
||||||
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
||||||
|
|
||||||
@ -21,7 +25,9 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
@ -38,7 +44,9 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
|
28
.github/workflows/purge-old-workflow-runs.yml
vendored
Normal file
28
.github/workflows/purge-old-workflow-runs.yml
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
name: Purge old workflow runs
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
days:
|
||||||
|
description: 'Purge runs older than days'
|
||||||
|
required: true
|
||||||
|
default: 30
|
||||||
|
minimum_runs:
|
||||||
|
description: 'The minimum runs to keep for each workflow.'
|
||||||
|
required: true
|
||||||
|
default: 6
|
||||||
|
delete_workflow_pattern:
|
||||||
|
description: 'The name of the workflow. if not set then it will target all workflows.'
|
||||||
|
required: false
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
del_runs:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Purge workflow runs
|
||||||
|
uses: Mattraks/delete-workflow-runs@v2
|
||||||
|
with:
|
||||||
|
token: ${{ github.token }}
|
||||||
|
repository: ${{ github.repository }}
|
||||||
|
retain_days: ${{ github.event.inputs.days }}
|
||||||
|
keep_minimum_runs: ${{ github.event.inputs.minimum_runs }}
|
||||||
|
delete_workflow_pattern: ${{ github.event.inputs.delete_workflow_pattern }}
|
3
.prettierignore
Normal file
3
.prettierignore
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
dist/
|
||||||
|
lib/
|
||||||
|
node_modules/
|
11
.prettierrc.json
Normal file
11
.prettierrc.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"printWidth": 120,
|
||||||
|
"tabWidth": 4,
|
||||||
|
"useTabs": false,
|
||||||
|
"semi": false,
|
||||||
|
"singleQuote": true,
|
||||||
|
"trailingComma": "none",
|
||||||
|
"bracketSpacing": false,
|
||||||
|
"arrowParens": "avoid",
|
||||||
|
"parser": "typescript"
|
||||||
|
}
|
3
.tool-versions
Normal file
3
.tool-versions
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Configuration file for asdf version manager
|
||||||
|
nodejs 16.18.1
|
||||||
|
gradle 7.6.1
|
14
CONTRIBUTING.md
Normal file
14
CONTRIBUTING.md
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
### How to merge a Dependabot PR
|
||||||
|
|
||||||
|
The "distribution" for a GitHub Action is checked into the repository itself.
|
||||||
|
In the case of the `gradle-build-action`, 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. Run `npm install` to download and the new dependencies and install locally
|
||||||
|
3. 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
|
2
LICENSE
2
LICENSE
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2023 Gradle Inc.
|
Copyright (c) 2018 GitHub, Inc. and contributors
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
418
README.md
418
README.md
@ -1,40 +1,400 @@
|
|||||||
> [!IMPORTANT]
|
# Execute Gradle builds in GitHub Actions workflows
|
||||||
> As of `v3` this action has been superceded by `gradle/actions/setup-gradle`.
|
|
||||||
> Any workflow that uses `gradle/gradle-build-action@v3` will transparently delegate to `gradle/actions/setup-gradle@v3`.
|
|
||||||
>
|
|
||||||
> Users are encouraged to update their workflows, replacing:
|
|
||||||
> ```
|
|
||||||
> uses: gradle/gradle-build-action@v3
|
|
||||||
> ```
|
|
||||||
>
|
|
||||||
> with
|
|
||||||
> ```
|
|
||||||
> uses: gradle/actions/setup-gradle@v3
|
|
||||||
> ```
|
|
||||||
>
|
|
||||||
> See the [setup-gradle documentation](https://github.com/gradle/actions/tree/main/setup-gradle) for up-to-date documentation for `gradle/actions/setup-gradle`.
|
|
||||||
|
|
||||||
# Setup Gradle for use in GitHub Actions workflows
|
This GitHub Action can be used to configure Gradle and optionally execute a Gradle build on any platform supported by GitHub Actions.
|
||||||
|
|
||||||
This GitHub Action can be used to configure Gradle on any platform supported by GitHub Actions.
|
## Use the action to setup Gradle
|
||||||
|
|
||||||
## Example usage
|
If you have an existing workflow invoking Gradle, you can add an initial "Setup Gradle" Step to benefit from caching,
|
||||||
|
build-scan capture and other features of the gradle-build-action.
|
||||||
|
|
||||||
|
All subsequent Gradle invocations will benefit from this initial setup, via `init` scripts added to the Gradle User Home.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
name: Build
|
name: Run Gradle on PRs
|
||||||
|
on: pull_request
|
||||||
on: [ push ]
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
gradle:
|
||||||
runs-on: ubuntu-latest
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- uses: actions/checkout@v3
|
||||||
uses: actions/checkout@v4
|
- uses: actions/setup-java@v3
|
||||||
|
with:
|
||||||
|
distribution: temurin
|
||||||
|
java-version: 11
|
||||||
|
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: gradle/actions/setup-gradle@v3
|
uses: gradle/gradle-build-action@v2
|
||||||
- name: Build with Gradle
|
|
||||||
|
- name: Execute Gradle build
|
||||||
run: ./gradlew build
|
run: ./gradlew build
|
||||||
```
|
```
|
||||||
|
|
||||||
See the [full setup-gradle documentation](https://github.com/gradle/actions/tree/main/setup-gradle) for more advanced usage scenarios.
|
## Why use the `gradle-build-action`?
|
||||||
|
|
||||||
|
It is possible to directly invoke Gradle in your workflow, and the `actions/setup-java@v3` action provides a simple way to cache Gradle dependencies.
|
||||||
|
|
||||||
|
However, the `gradle-build-action` offers a number of advantages over this approach:
|
||||||
|
|
||||||
|
- Easily [run the build with different versions of Gradle](#use-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).
|
||||||
|
- Detailed reporting of cache usage and cache configuration options allow you to [optimize the use of the GitHub actions cache](#optimizing-cache-effectiveness).
|
||||||
|
- [Automatic capture of build scan links](#build-scans) from the build, making these easier to locate for workflow run.
|
||||||
|
|
||||||
|
The `gradle-build-action` is designed to provide these benefits with minimal configuration.
|
||||||
|
These features work both when Gradle is executed via the `gradle-build-action` and for any Gradle execution in subsequent steps.
|
||||||
|
|
||||||
|
When using `gradle-build-action` we recommend that you _not_ use `actions/cache` or `actions/setup-java@v3` to explicitly cache the Gradle User Home. Doing so may interfere with the caching provided by this action.
|
||||||
|
|
||||||
|
## Use a specific Gradle version
|
||||||
|
|
||||||
|
The `gradle-build-action` can download and install a specified Gradle version, adding this installed version to the PATH.
|
||||||
|
Downloaded Gradle versions are stored in the GitHub Actions cache, to avoid requiring downloading again later.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: gradle/gradle-build-action@v2
|
||||||
|
with:
|
||||||
|
gradle-version: 6.5
|
||||||
|
```
|
||||||
|
|
||||||
|
The `gradle-version` parameter can be set to any valid Gradle version.
|
||||||
|
|
||||||
|
Moreover, you can use the following aliases:
|
||||||
|
|
||||||
|
| Alias | Selects |
|
||||||
|
| --- |---|
|
||||||
|
| `wrapper` | The Gradle wrapper's version (default, useful for matrix builds) |
|
||||||
|
| `current` | The current [stable release](https://gradle.org/install/) |
|
||||||
|
| `release-candidate` | The current [release candidate](https://gradle.org/release-candidate/) if any, otherwise fallback to `current` |
|
||||||
|
| `nightly` | The latest [nightly](https://gradle.org/nightly/), fails if none. |
|
||||||
|
| `release-nightly` | The latest [release nightly](https://gradle.org/release-nightly/), fails if none. |
|
||||||
|
|
||||||
|
This can be handy to automatically verify your build works with the latest release candidate of Gradle:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: Test latest Gradle RC
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: 0 0 * * * # daily
|
||||||
|
jobs:
|
||||||
|
gradle-rc:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: actions/setup-java@v3
|
||||||
|
with:
|
||||||
|
distribution: temurin
|
||||||
|
java-version: 11
|
||||||
|
- uses: gradle/gradle-build-action@v2
|
||||||
|
with:
|
||||||
|
gradle-version: release-candidate
|
||||||
|
- run: gradle build --dry-run # just test build configuration
|
||||||
|
```
|
||||||
|
|
||||||
|
## Gradle Execution
|
||||||
|
|
||||||
|
If the action is configured with an `arguments` input, then Gradle will execute a Gradle build with the arguments provided.
|
||||||
|
|
||||||
|
If no `arguments` are provided, the action will not execute Gradle, but will still cache Gradle state and configure build-scan capture for all subsequent Gradle executions.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: Run Gradle on PRs
|
||||||
|
on: pull_request
|
||||||
|
jobs:
|
||||||
|
gradle:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: actions/setup-java@v3
|
||||||
|
with:
|
||||||
|
distribution: temurin
|
||||||
|
java-version: 11
|
||||||
|
|
||||||
|
- name: Setup and execute Gradle 'test' task
|
||||||
|
uses: gradle/gradle-build-action@v2
|
||||||
|
with:
|
||||||
|
arguments: test
|
||||||
|
```
|
||||||
|
|
||||||
|
### Multiple Gradle executions in the same Job
|
||||||
|
|
||||||
|
It is possible to configure multiple Gradle executions to run sequentially in the same job.
|
||||||
|
The initial Action step will perform the Gradle setup.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: gradle/gradle-build-action@v2
|
||||||
|
with:
|
||||||
|
arguments: assemble
|
||||||
|
- uses: gradle/gradle-build-action@v2
|
||||||
|
with:
|
||||||
|
arguments: check
|
||||||
|
```
|
||||||
|
|
||||||
|
### Gradle command-line arguments
|
||||||
|
|
||||||
|
The `arguments` input can be used to pass arbitrary arguments to the `gradle` command line.
|
||||||
|
Arguments can be supplied in a single line, or as a multi-line input.
|
||||||
|
|
||||||
|
Here are some valid examples:
|
||||||
|
```yaml
|
||||||
|
arguments: build
|
||||||
|
arguments: check --scan
|
||||||
|
arguments: some arbitrary tasks
|
||||||
|
arguments: build -PgradleProperty=foo
|
||||||
|
arguments: |
|
||||||
|
build
|
||||||
|
--scan
|
||||||
|
-PgradleProperty=foo
|
||||||
|
-DsystemProperty=bar
|
||||||
|
```
|
||||||
|
|
||||||
|
If you need to pass environment variables, use the GitHub Actions workflow syntax:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: gradle/gradle-build-action@v2
|
||||||
|
env:
|
||||||
|
CI: true
|
||||||
|
with:
|
||||||
|
arguments: build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Gradle build located in a subdirectory
|
||||||
|
|
||||||
|
By default, the action will execute Gradle in the root directory of your project.
|
||||||
|
Use the `build-root-directory` input to target a Gradle build in a subdirectory.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: gradle/gradle-build-action@v2
|
||||||
|
with:
|
||||||
|
arguments: build
|
||||||
|
build-root-directory: some/subdirectory
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using a specific Gradle executable
|
||||||
|
|
||||||
|
The action will first look for a Gradle wrapper script in the root directory of your project.
|
||||||
|
If not found, `gradle` will be executed from the PATH.
|
||||||
|
Use the `gradle-executable` input to execute using a specific Gradle installation.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: gradle/gradle-build-action@v2
|
||||||
|
with:
|
||||||
|
arguments: build
|
||||||
|
gradle-executable: /path/to/installed/gradle
|
||||||
|
```
|
||||||
|
|
||||||
|
This mechanism can also be used to target a Gradle wrapper script that is located in a non-default location.
|
||||||
|
|
||||||
|
## Caching
|
||||||
|
|
||||||
|
By default, this action aims to cache any and all reusable state that may be speed up a subsequent build invocation.
|
||||||
|
|
||||||
|
The state that is cached includes:
|
||||||
|
- Any distributions downloaded to satisfy a `gradle-version` parameter ;
|
||||||
|
- A subset of the Gradle User Home directory, including downloaded dependencies, wrapper distributions, and the local build cache ;
|
||||||
|
|
||||||
|
To reduce the space required for caching, this action makes a best effort to reduce duplication in cache entries.
|
||||||
|
|
||||||
|
Caching is enabled by default. You can disable caching for the action as follows:
|
||||||
|
```yaml
|
||||||
|
cache-disabled: true
|
||||||
|
```
|
||||||
|
### Cache keys
|
||||||
|
|
||||||
|
Distributions downloaded to satisfy a `gradle-version` parameter are stored outside of Gradle User Home and cached separately. The cache key is unique to the downloaded distribution and will not change over time.
|
||||||
|
|
||||||
|
The state of the Gradle User Home is highly dependent on the Gradle execution, so the cache key is composed of the current commit hash and the GitHub actions job id.
|
||||||
|
As such, the cache key is likely to change on each subsequent run of GitHub actions.
|
||||||
|
This allows the most recent state to always be available in the GitHub actions cache.
|
||||||
|
|
||||||
|
To reduce duplication between cache entries, certain artifacts are cached independently based on their identity.
|
||||||
|
Artifacts that are cached independently include downloaded dependencies, downloaded wrapper distributions and generated Gradle API jars.
|
||||||
|
For example, this means that all jobs executing a particular version of the Gradle wrapper will share common entries for wrapper distributions and for generated Gradle API jars.
|
||||||
|
|
||||||
|
### Using the caches read-only
|
||||||
|
|
||||||
|
By default, the `gradle-build-action` will only write to the cache from Jobs on the default (`main`/`master`) branch.
|
||||||
|
Jobs on other branches will read entries from the cache but will not write updated entries.
|
||||||
|
See [Optimizing cache effectiveness](#optimizing-cache-effectiveness) for a more detailed explanation.
|
||||||
|
|
||||||
|
In some circumstances it makes sense to change this default, and to configure a workflow Job to read existing cache entries but not to write changes back.
|
||||||
|
|
||||||
|
You can configure read-only caching for the `gradle-build-action` as follows:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# Only write to the cache for builds on the 'main' and 'release' branches. (Default is 'main' only.)
|
||||||
|
# Builds on other branches will only read existing entries from the cache.
|
||||||
|
cache-read-only: ${{ github.ref != 'refs/heads/main' && github.ref != 'refs/heads/release' }}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Stopping the Gradle daemon
|
||||||
|
|
||||||
|
By default, the action will stop all running Gradle daemons in the post-action step, prior to saving the Gradle User Home state.
|
||||||
|
This allows for any Gradle User Home cleanup to occur, and avoid file-locking issues on Windows.
|
||||||
|
|
||||||
|
If caching is unavailable or the cache is in read-only mode, the daemon will not be stopped and will continue running after the job is completed.
|
||||||
|
|
||||||
|
### Gradle User Home cache tuning
|
||||||
|
|
||||||
|
As well as any wrapper distributions, the action will attempt to save and restore the `caches` and `notifications` directories from Gradle User Home.
|
||||||
|
|
||||||
|
The contents to be cached can be fine tuned by including and excluding certain paths with Gradle User Home.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# Cache downloaded JDKs in addition to the default directories.
|
||||||
|
gradle-home-cache-includes: |
|
||||||
|
caches
|
||||||
|
notifications
|
||||||
|
jdks
|
||||||
|
# Exclude the local build-cache and keyrings from the directories cached.
|
||||||
|
gradle-home-cache-excludes: |
|
||||||
|
caches/build-cache-1
|
||||||
|
caches/keyrings
|
||||||
|
```
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
### Cache debugging and analysis
|
||||||
|
|
||||||
|
Gradle User Home state will be restored from the cache during the first `gradle-build-action` step for any workflow job.
|
||||||
|
This state will be saved back to the cache at the end of the job, after all Gradle executions have completed.
|
||||||
|
A report of all cache entries restored and saved is printed to the Job Summary when saving the cache entries.
|
||||||
|
This report can provide valuable insignt into how much cache space is being used.
|
||||||
|
|
||||||
|
It is possible to enable additional debug logging for cache operations. You do via the `GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED` environment variable:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
env:
|
||||||
|
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that this setting will also prevent certain cache operations from running in parallel, further assisting with debugging.
|
||||||
|
|
||||||
|
### Optimizing cache effectiveness
|
||||||
|
|
||||||
|
Cache storage space for GitHub actions is limited, and writing new cache entries can trigger the deletion of existing entries.
|
||||||
|
Eviction of shared cache entries can reduce cache effectiveness, slowing down your `gradle-build-action` steps.
|
||||||
|
|
||||||
|
There are a number of actions you can take if your cache use is less effective due to entry eviction.
|
||||||
|
|
||||||
|
#### Select branches that should write to the cache
|
||||||
|
|
||||||
|
GitHub cache entries are not shared between builds on different branches.
|
||||||
|
This means that each PR branch will have it's own Gradle User Home cache, and will not benefit from cache entries written by other PR branches.
|
||||||
|
An exception to this is that cache entries written in parent and upstream branches are visible to child branches, and cache entries for the default (`master`/`main`) branch can be read by actions invoked for any other branch.
|
||||||
|
|
||||||
|
By default, the `gradle-build-action` will only _write_ to the cache for builds run on the default (`master`/`main`) branch.
|
||||||
|
Jobs run on other branches will only read from the cache. In most cases, this is the desired behaviour,
|
||||||
|
because Jobs run against other branches will benefit from the cache Gradle User Home from `main`,
|
||||||
|
without writing private cache entries that could lead to evicting shared entries.
|
||||||
|
|
||||||
|
If you have other long-lived development branches that would benefit from writing to the cache,
|
||||||
|
you can configure these by overriding the `cache-read-only` action parameter.
|
||||||
|
See [Using the caches read-only](#using-the-caches-read-only) for more details.
|
||||||
|
|
||||||
|
Similarly, you could use `cache-read-only` for certain jobs in the workflow, and instead have these jobs reuse the cache content from upstream jobs.
|
||||||
|
|
||||||
|
#### Exclude content from Gradle User Home cache
|
||||||
|
|
||||||
|
Each build is different, and some builds produce more Gradle User Home content than others.
|
||||||
|
[Cache debugging ](#cache-debugging-and-analysis) can provide insight into which cache entries are the largest,
|
||||||
|
and you can selectively [exclude content using `gradle-home-cache-exclude`](#gradle-user-home-cache-tuning).
|
||||||
|
|
||||||
|
#### Removing unused files from Gradle User Home before saving to cache
|
||||||
|
|
||||||
|
The Gradle User Home directory has a tendency 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.
|
||||||
|
|
||||||
|
In order to avoid this situation, the `gradle-build-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,
|
||||||
|
prior to saving the Gradle User Home to the GitHub Actions cache.
|
||||||
|
|
||||||
|
Gradle Home cache cleanup is disabled by default. You can enable this feature for the action as follows:
|
||||||
|
```yaml
|
||||||
|
gradle-home-cache-cleanup: true
|
||||||
|
```
|
||||||
|
|
||||||
|
## Saving build outputs
|
||||||
|
|
||||||
|
By default, a GitHub Actions workflow using `gradle-build-action` 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:
|
||||||
|
gradle:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout project sources
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Setup Gradle
|
||||||
|
uses: gradle/gradle-build-action@v2
|
||||||
|
- name: Run build with Gradle wrapper
|
||||||
|
run: ./gradlew build --scan
|
||||||
|
- name: Upload build reports
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: build-reports
|
||||||
|
path: build/reports/
|
||||||
|
```
|
||||||
|
|
||||||
|
## Build scans
|
||||||
|
|
||||||
|
If your build publishes a [build scan](https://gradle.com/build-scans/) the `gradle-build-action` action will:
|
||||||
|
- Add a notice with the link to the GitHub Actions user interface
|
||||||
|
- For each step that executes Gradle, adds the link to the published build scan as a Step output named `build-scan-url`.
|
||||||
|
|
||||||
|
You can then use that link in subsequent actions of your workflow. For example:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# .github/workflows/gradle-build-pr.yml
|
||||||
|
name: Run Gradle on PRs
|
||||||
|
on: pull_request
|
||||||
|
jobs:
|
||||||
|
gradle:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout project sources
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Setup Gradle
|
||||||
|
uses: gradle/gradle-build-action@v2
|
||||||
|
- name: Run build with Gradle wrapper
|
||||||
|
id: gradle
|
||||||
|
run: ./gradlew build --scan
|
||||||
|
- name: "Add build scan URL as PR comment"
|
||||||
|
uses: actions/github-script@v5
|
||||||
|
if: github.event_name == 'pull_request' && failure()
|
||||||
|
with:
|
||||||
|
github-token: ${{secrets.GITHUB_TOKEN}}
|
||||||
|
script: |
|
||||||
|
github.rest.issues.createComment({
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
body: '❌ ${{ github.workflow }} failed: ${{ steps.gradle.outputs.build-scan-url }}'
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that the build scan capturing utilizes the [Initialization Script](https://docs.gradle.org/current/userguide/init_scripts.html#sec:using_an_init_script)
|
||||||
|
in the `USER_HOME/.gradle/init.d/` directory, with the file named `build-result-capture.init.gradle`.
|
||||||
|
So, if you are using the init scripts for the [Gradle Enterprise Gradle Plugin](https://plugins.gradle.org/plugin/com.gradle.enterprise) like
|
||||||
|
[`scans-init.gradle` or `gradle-enterprise-init.gradle`](https://docs.gradle.com/enterprise/gradle-plugin/#scans_gradle_com),
|
||||||
|
make sure that its file names have earlier alphabetical order to the `build-result-capture.init.gradle`,
|
||||||
|
since configuring capture requires Gradle Enterprise Gradle Plugin to be applied already.
|
||||||
|
|
||||||
|
## Support for GitHub Enterprise Server (GHES)
|
||||||
|
|
||||||
|
You can use the `gradle-build-action` on GitHub Enterprise Server, and benefit from the improved integration with Gradle. Depending on the version of GHES you are running, certain features may be limited:
|
||||||
|
- Build scan links are captured and displayed in the GitHub Actions UI
|
||||||
|
- Easily run your build with different versions of Gradle
|
||||||
|
- Save/restore of Gradle User Home (requires GHES v3.5+ : GitHub Actions cache was introduced in GHES 3.5)
|
||||||
|
- Support for GitHub Actions Job Summary (requires GHES 3.6+ : GitHub Actions Job Summary support was introduced in GHES 3.6). In earlier versions of GHES the build-results summary and caching report will be written to the workflow log, as part of the post-action step.
|
||||||
|
226
action.yml
226
action.yml
@ -1,14 +1,13 @@
|
|||||||
name: setup-gradle
|
name: "Gradle Build Action"
|
||||||
description: 'Configures Gradle for GitHub actions, caching state and generating a dependency graph via Dependency Submission.'
|
description: 'Configures Gradle for use in GitHub actions, caching useful state in the GitHub actions cache'
|
||||||
|
|
||||||
|
# https://help.github.com/en/articles/metadata-syntax-for-github-actions
|
||||||
|
|
||||||
inputs:
|
inputs:
|
||||||
gradle-version:
|
gradle-version:
|
||||||
description: |
|
description: Gradle version to use
|
||||||
Gradle version to use. If specified, this Gradle version will be downloaded, added to the PATH and used for invoking Gradle.
|
|
||||||
If not provided, it is assumed that the project uses the Gradle Wrapper.
|
|
||||||
required: false
|
required: false
|
||||||
|
|
||||||
# Cache configuration
|
|
||||||
cache-disabled:
|
cache-disabled:
|
||||||
description: When 'true', all caching is disabled. No entries will be written to or read from the cache.
|
description: When 'true', all caching is disabled. No entries will be written to or read from the cache.
|
||||||
required: false
|
required: false
|
||||||
@ -28,18 +27,6 @@ inputs:
|
|||||||
required: false
|
required: false
|
||||||
default: false
|
default: false
|
||||||
|
|
||||||
cache-overwrite-existing:
|
|
||||||
description: When 'true', a pre-existing Gradle User Home will not prevent the cache from being restored.
|
|
||||||
required: false
|
|
||||||
default: false
|
|
||||||
|
|
||||||
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 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
|
|
||||||
|
|
||||||
gradle-home-cache-includes:
|
gradle-home-cache-includes:
|
||||||
description: Paths within Gradle User Home to cache.
|
description: Paths within Gradle User Home to cache.
|
||||||
required: false
|
required: false
|
||||||
@ -50,219 +37,52 @@ inputs:
|
|||||||
gradle-home-cache-excludes:
|
gradle-home-cache-excludes:
|
||||||
description: Paths within Gradle User Home to exclude from cache.
|
description: Paths within Gradle User Home to exclude from cache.
|
||||||
required: false
|
required: false
|
||||||
|
# e.g. Use the following setting to prevent the local build cache from being saved/restored
|
||||||
|
# gradle-home-cache-excludes: |
|
||||||
|
# caches/build-cache-1
|
||||||
|
|
||||||
gradle-home-cache-cleanup:
|
arguments:
|
||||||
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.
|
description: Gradle command line arguments (supports multi-line input)
|
||||||
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'.
|
|
||||||
required: false
|
|
||||||
default: 'always'
|
|
||||||
|
|
||||||
add-job-summary-as-pr-comment:
|
|
||||||
description: Specifies when each Job Summary should be added as a PR comment. Valid values are 'never' (default), 'always', and 'on-failure'. No action will be taken if the workflow was not triggered from a pull request.
|
|
||||||
required: false
|
|
||||||
default: 'never'
|
|
||||||
|
|
||||||
# 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'.
|
|
||||||
required: false
|
|
||||||
default: 'disabled'
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
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
|
required: false
|
||||||
|
|
||||||
# Build Scan configuration
|
build-root-directory:
|
||||||
build-scan-publish:
|
description: Path to the root directory of the build
|
||||||
description: |
|
|
||||||
Set to 'true' to automatically publish build results as a Build Scan on scans.gradle.com.
|
|
||||||
For publication to succeed without user input, you must also provide values for `build-scan-terms-of-use-url` and 'build-scan-terms-of-use-agree'.
|
|
||||||
required: false
|
|
||||||
default: false
|
|
||||||
|
|
||||||
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
|
required: false
|
||||||
|
|
||||||
build-scan-terms-of-use-agree:
|
gradle-executable:
|
||||||
description: Indicate that you agree to the Build Scan® terms of use. This input value must be "yes".
|
description: Path to the Gradle executable
|
||||||
required: false
|
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.
|
|
||||||
If the wrapper checksums are not valid, the action will fail.
|
|
||||||
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:
|
generate-job-summary:
|
||||||
description: When 'false', no Job Summary will be generated for the Job.
|
description: When 'false', no Job Summary will be generated for the Job.
|
||||||
required: false
|
required: false
|
||||||
default: true
|
default: true
|
||||||
deprecation-message: Superceded by the new 'add-job-summary' and 'add-job-summary-as-pr-comment' parameters.
|
|
||||||
|
|
||||||
arguments:
|
# EXPERIMENTAL & INTERNAL ACTION INPUTS
|
||||||
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.
|
|
||||||
|
|
||||||
# EXPERIMENTAL ACTION INPUTS
|
|
||||||
# The following action properties allow fine-grained tweaking of the action caching behaviour.
|
# The following action properties allow fine-grained tweaking of the action caching behaviour.
|
||||||
# These properties are experimental and not (yet) designed for production use, and may change without notice in a subsequent release of `setup-gradle`.
|
# These properties are experimental and not (yet) designed for production use, and may change without notice in a subsequent release of `gradle-build-action`.
|
||||||
# Use at your own risk!
|
# Use at your own risk!
|
||||||
gradle-home-cache-strict-match:
|
gradle-home-cache-strict-match:
|
||||||
description: When 'true', the action will not attempt to restore the Gradle User Home entries from other Jobs.
|
description: When 'true', the action will not attempt to restore the Gradle User Home entries from other Jobs.
|
||||||
required: false
|
required: false
|
||||||
default: 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:
|
workflow-job-context:
|
||||||
description: Used to uniquely identify the current job invocation. Defaults to the matrix values for this job; this should not be overridden by users (INTERNAL).
|
description: Used to uniquely identify the current job invocation. Defaults to the matrix values for this job; this should not be overridden by users (INTERNAL).
|
||||||
required: false
|
required: false
|
||||||
default: ${{ toJSON(matrix) }}
|
default: ${{ toJSON(matrix) }}
|
||||||
|
gradle-home-cache-cleanup:
|
||||||
github-token:
|
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.
|
||||||
description: The GitHub token used to authenticate when submitting via the Dependency Submission API.
|
|
||||||
default: ${{ github.token }}
|
|
||||||
required: false
|
required: false
|
||||||
|
default: false
|
||||||
|
|
||||||
outputs:
|
outputs:
|
||||||
build-scan-url:
|
build-scan-url:
|
||||||
description: Link to the Build Scan® generated by a Gradle build. Note that this output applies to a Step executing Gradle, not to the `setup-gradle` Step itself.
|
description: Link to the build scan if any
|
||||||
value: ${{ steps.setup-gradle.outputs.build-scan-url }}
|
|
||||||
dependency-graph-file:
|
|
||||||
description: Path to the GitHub Dependency Graph snapshot file generated by a Gradle build. Note that this output applies to a Step executing Gradle, not to the `setup-gradle` Step itself.
|
|
||||||
value: ${{ steps.setup-gradle.outputs.dependency-graph-file }}
|
|
||||||
gradle-version:
|
|
||||||
description: Version of Gradle that was setup by the action
|
|
||||||
value: ${{ steps.setup-gradle.outputs.gradle-version }}
|
|
||||||
|
|
||||||
runs:
|
runs:
|
||||||
using: "composite"
|
using: 'node16'
|
||||||
steps:
|
main: 'dist/main/index.js'
|
||||||
- name: Setup Gradle
|
post: 'dist/post/index.js'
|
||||||
id: setup-gradle
|
|
||||||
uses: gradle/actions/setup-gradle@v3.5.0
|
|
||||||
with:
|
|
||||||
gradle-version: ${{ inputs.gradle-version }}
|
|
||||||
cache-disabled: ${{ inputs.cache-disabled }}
|
|
||||||
cache-read-only: ${{ inputs.cache-read-only }}
|
|
||||||
cache-write-only: ${{ inputs.cache-write-only }}
|
|
||||||
cache-overwrite-existing: ${{ inputs.cache-overwrite-existing }}
|
|
||||||
cache-encryption-key: ${{ inputs.cache-encryption-key }}
|
|
||||||
gradle-home-cache-includes: ${{ inputs.gradle-home-cache-includes }}
|
|
||||||
gradle-home-cache-excludes: ${{ inputs.gradle-home-cache-excludes }}
|
|
||||||
gradle-home-cache-cleanup: ${{ inputs.gradle-home-cache-cleanup }}
|
|
||||||
add-job-summary: ${{ inputs.add-job-summary }}
|
|
||||||
add-job-summary-as-pr-comment: ${{ inputs.add-job-summary-as-pr-comment }}
|
|
||||||
dependency-graph: ${{ inputs.dependency-graph }}
|
|
||||||
dependency-graph-continue-on-failure: ${{ inputs.dependency-graph-continue-on-failure }}
|
|
||||||
artifact-retention-days: ${{ inputs.artifact-retention-days }}
|
|
||||||
build-scan-publish: ${{ inputs.build-scan-publish }}
|
|
||||||
build-scan-terms-of-use-url: ${{ inputs.build-scan-terms-of-use-url }}
|
|
||||||
build-scan-terms-of-use-agree: ${{ inputs.build-scan-terms-of-use-agree }}
|
|
||||||
validate-wrappers: ${{ inputs.validate-wrappers }}
|
|
||||||
build-scan-terms-of-service-url: ${{ inputs.build-scan-terms-of-service-url }}
|
|
||||||
build-scan-terms-of-service-agree: ${{ inputs.build-scan-terms-of-service-agree }}
|
|
||||||
generate-job-summary: ${{ inputs.generate-job-summary }}
|
|
||||||
arguments: ${{ inputs.arguments }}
|
|
||||||
build-root-directory: ${{ inputs.build-root-directory }}
|
|
||||||
gradle-home-cache-strict-match: ${{ inputs.gradle-home-cache-strict-match }}
|
|
||||||
workflow-job-context: ${{ inputs.workflow-job-context }}
|
|
||||||
github-token: ${{ inputs.github-token }}
|
|
||||||
develocity-access-key: ${{ inputs.develocity-access-key }}
|
|
||||||
develocity-token-expiry: ${{ inputs.develocity-token-expiry }}
|
|
||||||
develocity-injection-enabled: ${{ inputs.develocity-injection-enabled }}
|
|
||||||
develocity-url: ${{ inputs.develocity-url }}
|
|
||||||
develocity-allow-untrusted-server: ${{ inputs.develocity-allow-untrusted-server }}
|
|
||||||
develocity-capture-file-fingerprints: ${{ inputs.develocity-capture-file-fingerprints }}
|
|
||||||
develocity-enforce-url: ${{ inputs.develocity-enforce-url }}
|
|
||||||
develocity-plugin-version: ${{ inputs.develocity-plugin-version }}
|
|
||||||
develocity-ccud-plugin-version: ${{ inputs.develocity-ccud-plugin-version }}
|
|
||||||
gradle-plugin-repository-url: ${{ inputs.gradle-plugin-repository-url }}
|
|
||||||
gradle-plugin-repository-username: ${{ inputs.gradle-plugin-repository-username }}
|
|
||||||
gradle-plugin-repository-password: ${{ inputs.gradle-plugin-repository-password }}
|
|
||||||
|
|
||||||
env:
|
|
||||||
GRADLE_ACTION_ID: gradle/gradle-build-action
|
|
||||||
|
|
||||||
branding:
|
branding:
|
||||||
icon: 'box'
|
icon: 'box'
|
||||||
|
65737
dist/main/index.js
vendored
Normal file
65737
dist/main/index.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/main/index.js.map
vendored
Normal file
1
dist/main/index.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
64421
dist/post/index.js
vendored
Normal file
64421
dist/post/index.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/post/index.js.map
vendored
Normal file
1
dist/post/index.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
10
jest.config.js
Normal file
10
jest.config.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
module.exports = {
|
||||||
|
clearMocks: true,
|
||||||
|
moduleFileExtensions: ['js', 'ts', 'json'],
|
||||||
|
testEnvironment: 'node',
|
||||||
|
testMatch: ['**/*.test.ts'],
|
||||||
|
transform: {
|
||||||
|
'^.+\\.ts$': 'ts-jest'
|
||||||
|
},
|
||||||
|
verbose: true
|
||||||
|
}
|
12784
package-lock.json
generated
Normal file
12784
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
54
package.json
Normal file
54
package.json
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
{
|
||||||
|
"name": "gradle-build-action",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"description": "Execute Gradle Build",
|
||||||
|
"scripts": {
|
||||||
|
"postinstall": "patch-package",
|
||||||
|
"format": "prettier --write **/*.ts",
|
||||||
|
"format-check": "prettier --check **/*.ts",
|
||||||
|
"lint": "eslint src/**/*.ts",
|
||||||
|
"compile": "ncc build src/main.ts --out dist/main --source-map --no-source-map-register && ncc build src/post.ts --out dist/post --source-map --no-source-map-register",
|
||||||
|
"test": "jest",
|
||||||
|
"check": "npm run format && npm run lint",
|
||||||
|
"build": "npm run check && npm run compile",
|
||||||
|
"all": "npm run build && npm test"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/gradle/gradle-build-action.git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"github",
|
||||||
|
"actions",
|
||||||
|
"github-actions",
|
||||||
|
"gradle"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@actions/cache": "3.2.1",
|
||||||
|
"@actions/core": "1.10.0",
|
||||||
|
"@actions/exec": "1.1.1",
|
||||||
|
"@actions/github": "5.1.1",
|
||||||
|
"@actions/glob": "0.4.0",
|
||||||
|
"@actions/http-client": "2.1.0",
|
||||||
|
"@actions/tool-cache": "2.0.1",
|
||||||
|
"string-argv": "0.3.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "16.11.21",
|
||||||
|
"@types/jest": "29.5.0",
|
||||||
|
"@types/unzipper": "0.10.5",
|
||||||
|
"@typescript-eslint/parser": "5.58.0",
|
||||||
|
"@vercel/ncc": "0.36.1",
|
||||||
|
"eslint": "8.38.0",
|
||||||
|
"eslint-plugin-github": "4.7.0",
|
||||||
|
"eslint-plugin-jest": "27.2.1",
|
||||||
|
"jest": "29.5.0",
|
||||||
|
"js-yaml": "4.1.0",
|
||||||
|
"patch-package": "6.5.1",
|
||||||
|
"prettier": "2.8.7",
|
||||||
|
"ts-jest": "29.1.0",
|
||||||
|
"typescript": "5.0.4"
|
||||||
|
}
|
||||||
|
}
|
113
patches/@actions+cache+3.2.1.patch
Normal file
113
patches/@actions+cache+3.2.1.patch
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
diff --git a/node_modules/@actions/cache/lib/cache.d.ts b/node_modules/@actions/cache/lib/cache.d.ts
|
||||||
|
index 4658366..b796e58 100644
|
||||||
|
--- a/node_modules/@actions/cache/lib/cache.d.ts
|
||||||
|
+++ b/node_modules/@actions/cache/lib/cache.d.ts
|
||||||
|
@@ -21,7 +21,7 @@ export declare function isFeatureAvailable(): boolean;
|
||||||
|
* @param enableCrossOsArchive an optional boolean enabled to restore on windows any cache created on any platform
|
||||||
|
* @returns string returns the key for the cache hit, otherwise returns undefined
|
||||||
|
*/
|
||||||
|
-export declare function restoreCache(paths: string[], primaryKey: string, restoreKeys?: string[], options?: DownloadOptions, enableCrossOsArchive?: boolean): Promise<string | undefined>;
|
||||||
|
+export declare function restoreCache(paths: string[], primaryKey: string, restoreKeys?: string[], options?: DownloadOptions, enableCrossOsArchive?: boolean): Promise<CacheEntry | undefined>;
|
||||||
|
/**
|
||||||
|
* Saves a list of files with the specified key
|
||||||
|
*
|
||||||
|
@@ -31,4 +31,12 @@ export declare function restoreCache(paths: string[], primaryKey: string, restor
|
||||||
|
* @param options cache upload options
|
||||||
|
* @returns number returns cacheId if the cache was saved successfully and throws an error if save fails
|
||||||
|
*/
|
||||||
|
-export declare function saveCache(paths: string[], key: string, options?: UploadOptions, enableCrossOsArchive?: boolean): Promise<number>;
|
||||||
|
+export declare function saveCache(paths: string[], key: string, options?: UploadOptions, enableCrossOsArchive?: boolean): Promise<CacheEntry>;
|
||||||
|
+
|
||||||
|
+// PATCHED: Add `CacheEntry` as return type for save/restore functions
|
||||||
|
+// This allows us to track and report on cache entry sizes.
|
||||||
|
+export declare class CacheEntry {
|
||||||
|
+ key: string;
|
||||||
|
+ size?: number;
|
||||||
|
+ constructor(key: string, size?: number);
|
||||||
|
+}
|
||||||
|
diff --git a/node_modules/@actions/cache/lib/cache.js b/node_modules/@actions/cache/lib/cache.js
|
||||||
|
index 9d636aa..a176bd7 100644
|
||||||
|
--- a/node_modules/@actions/cache/lib/cache.js
|
||||||
|
+++ b/node_modules/@actions/cache/lib/cache.js
|
||||||
|
@@ -127,18 +127,21 @@ function restoreCache(paths, primaryKey, restoreKeys, options, enableCrossOsArch
|
||||||
|
core.info(`Cache Size: ~${Math.round(archiveFileSize / (1024 * 1024))} MB (${archiveFileSize} B)`);
|
||||||
|
yield (0, tar_1.extractTar)(archivePath, compressionMethod);
|
||||||
|
core.info('Cache restored successfully');
|
||||||
|
- return cacheEntry.cacheKey;
|
||||||
|
- }
|
||||||
|
- catch (error) {
|
||||||
|
- const typedError = error;
|
||||||
|
- if (typedError.name === ValidationError.name) {
|
||||||
|
- throw error;
|
||||||
|
- }
|
||||||
|
- else {
|
||||||
|
- // Supress all non-validation cache related errors because caching should be optional
|
||||||
|
- core.warning(`Failed to restore: ${error.message}`);
|
||||||
|
- }
|
||||||
|
+
|
||||||
|
+ // PATCHED - Return more inforamtion about restored entry
|
||||||
|
+ return new CacheEntry(cacheEntry.cacheKey, archiveFileSize);;
|
||||||
|
}
|
||||||
|
+ // PATCHED - propagate errors
|
||||||
|
+ // catch (error) {
|
||||||
|
+ // const typedError = error;
|
||||||
|
+ // if (typedError.name === ValidationError.name) {
|
||||||
|
+ // throw error;
|
||||||
|
+ // }
|
||||||
|
+ // else {
|
||||||
|
+ // // Supress all non-validation cache related errors because caching should be optional
|
||||||
|
+ // core.warning(`Failed to restore: ${error.message}`);
|
||||||
|
+ // }
|
||||||
|
+ // }
|
||||||
|
finally {
|
||||||
|
// Try to delete the archive to save space
|
||||||
|
try {
|
||||||
|
@@ -206,19 +209,23 @@ function saveCache(paths, key, options, enableCrossOsArchive = false) {
|
||||||
|
}
|
||||||
|
core.debug(`Saving Cache (ID: ${cacheId})`);
|
||||||
|
yield cacheHttpClient.saveCache(cacheId, archivePath, options);
|
||||||
|
+
|
||||||
|
+ // PATCHED - Return more inforamtion about saved entry
|
||||||
|
+ return new CacheEntry(key, archiveFileSize);
|
||||||
|
}
|
||||||
|
- catch (error) {
|
||||||
|
- const typedError = error;
|
||||||
|
- if (typedError.name === ValidationError.name) {
|
||||||
|
- throw error;
|
||||||
|
- }
|
||||||
|
- else if (typedError.name === ReserveCacheError.name) {
|
||||||
|
- core.info(`Failed to save: ${typedError.message}`);
|
||||||
|
- }
|
||||||
|
- else {
|
||||||
|
- core.warning(`Failed to save: ${typedError.message}`);
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
+ // PATCHED - propagate errors
|
||||||
|
+ // catch (error) {
|
||||||
|
+ // const typedError = error;
|
||||||
|
+ // if (typedError.name === ValidationError.name) {
|
||||||
|
+ // throw error;
|
||||||
|
+ // }
|
||||||
|
+ // else if (typedError.name === ReserveCacheError.name) {
|
||||||
|
+ // core.info(`Failed to save: ${typedError.message}`);
|
||||||
|
+ // }
|
||||||
|
+ // else {
|
||||||
|
+ // core.warning(`Failed to save: ${typedError.message}`);
|
||||||
|
+ // }
|
||||||
|
+ // }
|
||||||
|
finally {
|
||||||
|
// Try to delete the archive to save space
|
||||||
|
try {
|
||||||
|
@@ -232,4 +239,11 @@ function saveCache(paths, key, options, enableCrossOsArchive = false) {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
exports.saveCache = saveCache;
|
||||||
|
+class CacheEntry {
|
||||||
|
+ constructor(key, size) {
|
||||||
|
+ this.key = key;
|
||||||
|
+ this.size = size;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+exports.CacheEntry = CacheEntry;
|
||||||
|
//# sourceMappingURL=cache.js.map
|
||||||
|
\ No newline at end of file
|
48
patches/@azure+logger+1.0.4.patch
Normal file
48
patches/@azure+logger+1.0.4.patch
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
diff --git a/node_modules/@azure/logger/dist-esm/src/debug.js b/node_modules/@azure/logger/dist-esm/src/debug.js
|
||||||
|
index d202779..30e8313 100644
|
||||||
|
--- a/node_modules/@azure/logger/dist-esm/src/debug.js
|
||||||
|
+++ b/node_modules/@azure/logger/dist-esm/src/debug.js
|
||||||
|
@@ -7,7 +7,7 @@ let enabledNamespaces = [];
|
||||||
|
let skippedNamespaces = [];
|
||||||
|
const debuggers = [];
|
||||||
|
if (debugEnvVariable) {
|
||||||
|
- enable(debugEnvVariable);
|
||||||
|
+ // enable(debugEnvVariable);
|
||||||
|
}
|
||||||
|
const debugObj = Object.assign((namespace) => {
|
||||||
|
return createDebugger(namespace);
|
||||||
|
diff --git a/node_modules/@azure/logger/dist-esm/src/index.js b/node_modules/@azure/logger/dist-esm/src/index.js
|
||||||
|
index cc25720..2925db5 100644
|
||||||
|
--- a/node_modules/@azure/logger/dist-esm/src/index.js
|
||||||
|
+++ b/node_modules/@azure/logger/dist-esm/src/index.js
|
||||||
|
@@ -20,7 +20,7 @@ if (logLevelFromEnv) {
|
||||||
|
setLogLevel(logLevelFromEnv);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
- console.error(`AZURE_LOG_LEVEL set to unknown log level '${logLevelFromEnv}'; logging is not enabled. Acceptable values: ${AZURE_LOG_LEVELS.join(", ")}.`);
|
||||||
|
+ console.error(`AZURE_LOG_LEVEL set to unknown log level; logging is not enabled. Acceptable values: ${AZURE_LOG_LEVELS.join(", ")}.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
diff --git a/node_modules/@azure/logger/dist/index.js b/node_modules/@azure/logger/dist/index.js
|
||||||
|
index 81e97c3..a415e2f 100644
|
||||||
|
--- a/node_modules/@azure/logger/dist/index.js
|
||||||
|
+++ b/node_modules/@azure/logger/dist/index.js
|
||||||
|
@@ -21,7 +21,7 @@ let enabledNamespaces = [];
|
||||||
|
let skippedNamespaces = [];
|
||||||
|
const debuggers = [];
|
||||||
|
if (debugEnvVariable) {
|
||||||
|
- enable(debugEnvVariable);
|
||||||
|
+ // enable(debugEnvVariable);
|
||||||
|
}
|
||||||
|
const debugObj = Object.assign((namespace) => {
|
||||||
|
return createDebugger(namespace);
|
||||||
|
@@ -125,7 +125,7 @@ if (logLevelFromEnv) {
|
||||||
|
setLogLevel(logLevelFromEnv);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
- console.error(`AZURE_LOG_LEVEL set to unknown log level '${logLevelFromEnv}'; logging is not enabled. Acceptable values: ${AZURE_LOG_LEVELS.join(", ")}.`);
|
||||||
|
+ console.error(`AZURE_LOG_LEVEL set to unknown log level; logging is not enabled. Acceptable values: ${AZURE_LOG_LEVELS.join(", ")}.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
0
release/changes.md
Normal file
0
release/changes.md
Normal file
27
src/build-results.ts
Normal file
27
src/build-results.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import * as fs from 'fs'
|
||||||
|
import * as path from 'path'
|
||||||
|
|
||||||
|
export interface BuildResult {
|
||||||
|
get rootProjectName(): string
|
||||||
|
get rootProjectDir(): string
|
||||||
|
get requestedTasks(): string
|
||||||
|
get gradleVersion(): string
|
||||||
|
get gradleHomeDir(): string
|
||||||
|
get buildFailed(): boolean
|
||||||
|
get buildScanUri(): string
|
||||||
|
get buildScanFailed(): boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export function loadBuildResults(): BuildResult[] {
|
||||||
|
const buildResultsDir = path.resolve(process.env['RUNNER_TEMP']!, '.build-results')
|
||||||
|
if (!fs.existsSync(buildResultsDir)) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
return fs.readdirSync(buildResultsDir).map(file => {
|
||||||
|
// Every file in the .build-results dir should be a BuildResults JSON
|
||||||
|
const filePath = path.join(buildResultsDir, file)
|
||||||
|
const content = fs.readFileSync(filePath, 'utf8')
|
||||||
|
return JSON.parse(content) as BuildResult
|
||||||
|
})
|
||||||
|
}
|
222
src/cache-base.ts
Normal file
222
src/cache-base.ts
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
import * as core from '@actions/core'
|
||||||
|
import * as exec from '@actions/exec'
|
||||||
|
import path from 'path'
|
||||||
|
import fs from 'fs'
|
||||||
|
import {CacheListener} from './cache-reporting'
|
||||||
|
import {saveCache, restoreCache, cacheDebug, isCacheDebuggingEnabled, tryDelete, generateCacheKey} from './cache-utils'
|
||||||
|
import {GradleHomeEntryExtractor} from './cache-extract-entries'
|
||||||
|
|
||||||
|
const RESTORED_CACHE_KEY_KEY = 'restored-cache-key'
|
||||||
|
|
||||||
|
export const META_FILE_DIR = '.gradle-build-action'
|
||||||
|
const INCLUDE_PATHS_PARAMETER = 'gradle-home-cache-includes'
|
||||||
|
const EXCLUDE_PATHS_PARAMETER = 'gradle-home-cache-excludes'
|
||||||
|
|
||||||
|
export class GradleStateCache {
|
||||||
|
private cacheName: string
|
||||||
|
private cacheDescription: string
|
||||||
|
|
||||||
|
protected readonly gradleUserHome: string
|
||||||
|
|
||||||
|
constructor(gradleUserHome: string) {
|
||||||
|
this.gradleUserHome = gradleUserHome
|
||||||
|
this.cacheName = 'gradle'
|
||||||
|
this.cacheDescription = 'Gradle User Home'
|
||||||
|
}
|
||||||
|
|
||||||
|
init(): void {
|
||||||
|
const actionCacheDir = path.resolve(this.gradleUserHome, '.gradle-build-action')
|
||||||
|
fs.mkdirSync(actionCacheDir, {recursive: true})
|
||||||
|
|
||||||
|
const initScriptsDir = path.resolve(this.gradleUserHome, 'init.d')
|
||||||
|
fs.mkdirSync(initScriptsDir, {recursive: true})
|
||||||
|
|
||||||
|
this.initializeGradleUserHome(this.gradleUserHome, initScriptsDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
cacheOutputExists(): boolean {
|
||||||
|
const cachesDir = path.resolve(this.gradleUserHome, 'caches')
|
||||||
|
if (fs.existsSync(cachesDir)) {
|
||||||
|
cacheDebug(`Cache output exists at ${cachesDir}`)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restores the cache entry, finding the closest match to the currently running job.
|
||||||
|
*/
|
||||||
|
async restore(listener: CacheListener): Promise<void> {
|
||||||
|
const entryListener = listener.entry(this.cacheDescription)
|
||||||
|
|
||||||
|
const cacheKey = generateCacheKey(this.cacheName)
|
||||||
|
|
||||||
|
cacheDebug(
|
||||||
|
`Requesting ${this.cacheDescription} with
|
||||||
|
key:${cacheKey.key}
|
||||||
|
restoreKeys:[${cacheKey.restoreKeys}]`
|
||||||
|
)
|
||||||
|
|
||||||
|
const cacheResult = await restoreCache(this.getCachePath(), cacheKey.key, cacheKey.restoreKeys, entryListener)
|
||||||
|
if (!cacheResult) {
|
||||||
|
core.info(`${this.cacheDescription} cache not found. Will initialize empty.`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
core.saveState(RESTORED_CACHE_KEY_KEY, cacheResult.key)
|
||||||
|
|
||||||
|
core.info(`Restored ${this.cacheDescription} from cache key: ${cacheResult.key}`)
|
||||||
|
|
||||||
|
try {
|
||||||
|
await this.afterRestore(listener)
|
||||||
|
} catch (error) {
|
||||||
|
core.warning(`Restore ${this.cacheDescription} failed in 'afterRestore': ${error}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore any extracted cache entries after the main Gradle User Home entry is restored.
|
||||||
|
*/
|
||||||
|
async afterRestore(listener: CacheListener): Promise<void> {
|
||||||
|
await this.debugReportGradleUserHomeSize('as restored from cache')
|
||||||
|
await new GradleHomeEntryExtractor(this.gradleUserHome).restore(listener)
|
||||||
|
// await new ConfigurationCacheEntryExtractor(this.gradleUserHome).restore(listener)
|
||||||
|
await this.debugReportGradleUserHomeSize('after restoring common artifacts')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves the cache entry based on the current cache key unless the cache was restored with the exact key,
|
||||||
|
* in which case we cannot overwrite it.
|
||||||
|
*
|
||||||
|
* If the cache entry was restored with a partial match on a restore key, then
|
||||||
|
* it is saved with the exact key.
|
||||||
|
*/
|
||||||
|
async save(listener: CacheListener): Promise<void> {
|
||||||
|
const cacheKey = generateCacheKey(this.cacheName).key
|
||||||
|
const restoredCacheKey = core.getState(RESTORED_CACHE_KEY_KEY)
|
||||||
|
const gradleHomeEntryListener = listener.entry(this.cacheDescription)
|
||||||
|
|
||||||
|
if (restoredCacheKey && cacheKey === restoredCacheKey) {
|
||||||
|
core.info(`Cache hit occurred on the cache key ${cacheKey}, not saving cache.`)
|
||||||
|
|
||||||
|
for (const entryListener of listener.cacheEntries) {
|
||||||
|
if (entryListener === gradleHomeEntryListener) {
|
||||||
|
entryListener.markNotSaved('cache key not changed')
|
||||||
|
} else {
|
||||||
|
entryListener.markNotSaved(`referencing '${this.cacheDescription}' cache entry not saved`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await this.beforeSave(listener)
|
||||||
|
} catch (error) {
|
||||||
|
core.warning(`Save ${this.cacheDescription} failed in 'beforeSave': ${error}`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
core.info(`Caching ${this.cacheDescription} with cache key: ${cacheKey}`)
|
||||||
|
const cachePath = this.getCachePath()
|
||||||
|
await saveCache(cachePath, cacheKey, gradleHomeEntryListener)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract and save any defined extracted cache entries prior to the main Gradle User Home entry being saved.
|
||||||
|
*/
|
||||||
|
async beforeSave(listener: CacheListener): Promise<void> {
|
||||||
|
await this.debugReportGradleUserHomeSize('before saving common artifacts')
|
||||||
|
this.deleteExcludedPaths()
|
||||||
|
await Promise.all([
|
||||||
|
new GradleHomeEntryExtractor(this.gradleUserHome).extract(listener)
|
||||||
|
// new ConfigurationCacheEntryExtractor(this.gradleUserHome).extract(listener)
|
||||||
|
])
|
||||||
|
await this.debugReportGradleUserHomeSize(
|
||||||
|
"after extracting common artifacts (only 'caches' and 'notifications' will be stored)"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete any file paths that are excluded by the `gradle-home-cache-excludes` parameter.
|
||||||
|
*/
|
||||||
|
private deleteExcludedPaths(): void {
|
||||||
|
const rawPaths: string[] = core.getMultilineInput(EXCLUDE_PATHS_PARAMETER)
|
||||||
|
const resolvedPaths = rawPaths.map(x => path.resolve(this.gradleUserHome, x))
|
||||||
|
|
||||||
|
for (const p of resolvedPaths) {
|
||||||
|
cacheDebug(`Deleting excluded path: ${p}`)
|
||||||
|
tryDelete(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the paths within Gradle User Home to cache.
|
||||||
|
* By default, this is the 'caches' and 'notifications' directories,
|
||||||
|
* but this can be overridden by the `gradle-home-cache-includes` parameter.
|
||||||
|
*/
|
||||||
|
protected getCachePath(): string[] {
|
||||||
|
const rawPaths: string[] = core.getMultilineInput(INCLUDE_PATHS_PARAMETER)
|
||||||
|
rawPaths.push(META_FILE_DIR)
|
||||||
|
const resolvedPaths = rawPaths.map(x => this.resolveCachePath(x))
|
||||||
|
cacheDebug(`Using cache paths: ${resolvedPaths}`)
|
||||||
|
return resolvedPaths
|
||||||
|
}
|
||||||
|
|
||||||
|
private resolveCachePath(rawPath: string): string {
|
||||||
|
if (rawPath.startsWith('!')) {
|
||||||
|
const resolved = this.resolveCachePath(rawPath.substring(1))
|
||||||
|
return `!${resolved}`
|
||||||
|
}
|
||||||
|
return path.resolve(this.gradleUserHome, rawPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
private initializeGradleUserHome(gradleUserHome: string, initScriptsDir: string): void {
|
||||||
|
const initScriptFilenames = ['build-result-capture.init.gradle', 'build-result-capture-service.plugin.groovy']
|
||||||
|
for (const initScriptFilename of initScriptFilenames) {
|
||||||
|
const initScriptContent = this.readInitScriptAsString(initScriptFilename)
|
||||||
|
const initScriptPath = path.resolve(initScriptsDir, initScriptFilename)
|
||||||
|
fs.writeFileSync(initScriptPath, initScriptContent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private readInitScriptAsString(resource: string): string {
|
||||||
|
// Resolving relative to __dirname will allow node to find the resource at runtime
|
||||||
|
const absolutePath = path.resolve(__dirname, '..', '..', 'src', 'resources', 'init-scripts', resource)
|
||||||
|
return fs.readFileSync(absolutePath, 'utf8')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When cache debugging is enabled, this method will give a detailed report
|
||||||
|
* of the Gradle User Home contents.
|
||||||
|
*/
|
||||||
|
private async debugReportGradleUserHomeSize(label: string): Promise<void> {
|
||||||
|
if (!isCacheDebuggingEnabled()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!fs.existsSync(this.gradleUserHome)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const result = await exec.getExecOutput('du', ['-h', '-c', '-t', '5M'], {
|
||||||
|
cwd: this.gradleUserHome,
|
||||||
|
silent: true,
|
||||||
|
ignoreReturnCode: true
|
||||||
|
})
|
||||||
|
|
||||||
|
core.info(`Gradle User Home (directories >5M): ${label}`)
|
||||||
|
|
||||||
|
core.info(
|
||||||
|
result.stdout
|
||||||
|
.trimEnd()
|
||||||
|
.replace(/\t/g, ' ')
|
||||||
|
.split('\n')
|
||||||
|
.map(it => {
|
||||||
|
return ` ${it}`
|
||||||
|
})
|
||||||
|
.join('\n')
|
||||||
|
)
|
||||||
|
|
||||||
|
core.info('-----------------------')
|
||||||
|
}
|
||||||
|
}
|
68
src/cache-cleaner.ts
Normal file
68
src/cache-cleaner.ts
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
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'
|
||||||
|
|
||||||
|
export class CacheCleaner {
|
||||||
|
private readonly gradleUserHome: string
|
||||||
|
private readonly tmpDir: string
|
||||||
|
|
||||||
|
constructor(gradleUserHome: string, tmpDir: string) {
|
||||||
|
this.gradleUserHome = gradleUserHome
|
||||||
|
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 forceCleanup(): Promise<void> {
|
||||||
|
// Age all 'gc' files so that cache cleanup will run immediately.
|
||||||
|
await this.ageAllFiles('gc.properties')
|
||||||
|
|
||||||
|
// Run a dummy Gradle build to trigger cache cleanup
|
||||||
|
const cleanupProjectDir = path.resolve(this.tmpDir, 'dummy-cleanup-project')
|
||||||
|
fs.mkdirSync(cleanupProjectDir, {recursive: true})
|
||||||
|
fs.writeFileSync(
|
||||||
|
path.resolve(cleanupProjectDir, 'settings.gradle'),
|
||||||
|
'rootProject.name = "dummy-cleanup-project"'
|
||||||
|
)
|
||||||
|
fs.writeFileSync(path.resolve(cleanupProjectDir, 'build.gradle'), 'task("noop") {}')
|
||||||
|
|
||||||
|
await exec.exec(`gradle -g ${this.gradleUserHome} --no-daemon --build-cache --no-scan --quiet noop`, [], {
|
||||||
|
cwd: 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 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
|
||||||
|
})
|
||||||
|
for await (const file of globber.globGenerator()) {
|
||||||
|
fs.utimesSync(file, timestamp, timestamp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
393
src/cache-extract-entries.ts
Normal file
393
src/cache-extract-entries.ts
Normal file
@ -0,0 +1,393 @@
|
|||||||
|
import path from 'path'
|
||||||
|
import fs from 'fs'
|
||||||
|
import * as core from '@actions/core'
|
||||||
|
import * as glob from '@actions/glob'
|
||||||
|
|
||||||
|
import {META_FILE_DIR} from './cache-base'
|
||||||
|
import {CacheEntryListener, CacheListener} from './cache-reporting'
|
||||||
|
import {
|
||||||
|
cacheDebug,
|
||||||
|
getCacheKeyPrefix,
|
||||||
|
hashFileNames,
|
||||||
|
isCacheDebuggingEnabled,
|
||||||
|
restoreCache,
|
||||||
|
saveCache,
|
||||||
|
tryDelete
|
||||||
|
} from './cache-utils'
|
||||||
|
import {loadBuildResults} from './build-results'
|
||||||
|
|
||||||
|
const SKIP_RESTORE_VAR = 'GRADLE_BUILD_ACTION_SKIP_RESTORE'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the result of attempting to load or store an extracted cache entry.
|
||||||
|
* An undefined cacheKey indicates that the operation did not succeed.
|
||||||
|
* The collected results are then used to populate the `cache-metadata.json` file for later use.
|
||||||
|
*/
|
||||||
|
class ExtractedCacheEntry {
|
||||||
|
artifactType: string
|
||||||
|
pattern: string
|
||||||
|
cacheKey: string | undefined
|
||||||
|
|
||||||
|
constructor(artifactType: string, pattern: string, cacheKey: string | undefined) {
|
||||||
|
this.artifactType = artifactType
|
||||||
|
this.pattern = pattern
|
||||||
|
this.cacheKey = cacheKey
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Representation of all of the extracted cache entries for this Gradle User Home.
|
||||||
|
* This object is persisted to JSON file in the Gradle User Home directory for storing,
|
||||||
|
* and subsequently used to restore the Gradle User Home.
|
||||||
|
*/
|
||||||
|
class ExtractedCacheEntryMetadata {
|
||||||
|
entries: ExtractedCacheEntry[] = []
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The specification for a type of extracted cache entry.
|
||||||
|
*/
|
||||||
|
class ExtractedCacheEntryDefinition {
|
||||||
|
artifactType: string
|
||||||
|
pattern: string
|
||||||
|
bundle: boolean
|
||||||
|
uniqueFileNames = true
|
||||||
|
|
||||||
|
constructor(artifactType: string, pattern: string, bundle: boolean) {
|
||||||
|
this.artifactType = artifactType
|
||||||
|
this.pattern = pattern
|
||||||
|
this.bundle = bundle
|
||||||
|
}
|
||||||
|
|
||||||
|
withNonUniqueFileNames(): ExtractedCacheEntryDefinition {
|
||||||
|
this.uniqueFileNames = false
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Caches and restores the entire Gradle User Home directory, extracting entries containing common artifacts
|
||||||
|
* for more efficient storage.
|
||||||
|
*/
|
||||||
|
abstract class AbstractEntryExtractor {
|
||||||
|
protected readonly gradleUserHome: string
|
||||||
|
private extractorName: string
|
||||||
|
|
||||||
|
constructor(gradleUserHome: string, extractorName: string) {
|
||||||
|
this.gradleUserHome = gradleUserHome
|
||||||
|
this.extractorName = extractorName
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restores any artifacts that were cached separately, based on the information in the `cache-metadata.json` file.
|
||||||
|
* Each extracted cache entry is restored in parallel, except when debugging is enabled.
|
||||||
|
*/
|
||||||
|
async restore(listener: CacheListener): Promise<void> {
|
||||||
|
const previouslyExtractedCacheEntries = this.loadExtractedCacheEntries()
|
||||||
|
|
||||||
|
const processes: Promise<ExtractedCacheEntry>[] = []
|
||||||
|
|
||||||
|
for (const cacheEntry of previouslyExtractedCacheEntries) {
|
||||||
|
const artifactType = cacheEntry.artifactType
|
||||||
|
const entryListener = listener.entry(cacheEntry.pattern)
|
||||||
|
|
||||||
|
// Handle case where the extracted-cache-entry definitions have been changed
|
||||||
|
const skipRestore = process.env[SKIP_RESTORE_VAR] || ''
|
||||||
|
if (skipRestore.includes(artifactType)) {
|
||||||
|
core.info(`Not restoring extracted cache entry for ${artifactType}`)
|
||||||
|
entryListener.markRequested('SKIP_RESTORE')
|
||||||
|
} else {
|
||||||
|
processes.push(
|
||||||
|
this.awaitForDebugging(
|
||||||
|
this.restoreExtractedCacheEntry(
|
||||||
|
artifactType,
|
||||||
|
cacheEntry.cacheKey!,
|
||||||
|
cacheEntry.pattern,
|
||||||
|
entryListener
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.saveMetadataForCacheResults(await Promise.all(processes))
|
||||||
|
}
|
||||||
|
|
||||||
|
private async restoreExtractedCacheEntry(
|
||||||
|
artifactType: string,
|
||||||
|
cacheKey: string,
|
||||||
|
pattern: string,
|
||||||
|
listener: CacheEntryListener
|
||||||
|
): Promise<ExtractedCacheEntry> {
|
||||||
|
const restoredEntry = await restoreCache([pattern], cacheKey, [], listener)
|
||||||
|
if (restoredEntry) {
|
||||||
|
core.info(`Restored ${artifactType} with key ${cacheKey} to ${pattern}`)
|
||||||
|
return new ExtractedCacheEntry(artifactType, pattern, cacheKey)
|
||||||
|
} else {
|
||||||
|
core.info(`Did not restore ${artifactType} with key ${cacheKey} to ${pattern}`)
|
||||||
|
return new ExtractedCacheEntry(artifactType, pattern, undefined)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves any artifacts that are configured to be cached separately, based on the extracted cache entry definitions.
|
||||||
|
* Each entry is extracted and saved in parallel, except when debugging is enabled.
|
||||||
|
*/
|
||||||
|
async extract(listener: CacheListener): Promise<void> {
|
||||||
|
// Load the cache entry definitions (from config) and the previously restored entries (from persisted metadata file)
|
||||||
|
const cacheEntryDefinitions = this.getExtractedCacheEntryDefinitions()
|
||||||
|
cacheDebug(
|
||||||
|
`Extracting cache entries for ${this.extractorName}: ${JSON.stringify(cacheEntryDefinitions, null, 2)}`
|
||||||
|
)
|
||||||
|
|
||||||
|
const previouslyRestoredEntries = this.loadExtractedCacheEntries()
|
||||||
|
const cacheActions: Promise<ExtractedCacheEntry>[] = []
|
||||||
|
|
||||||
|
// For each cache entry definition, determine if it has already been restored, and if not, extract it
|
||||||
|
for (const cacheEntryDefinition of cacheEntryDefinitions) {
|
||||||
|
const artifactType = cacheEntryDefinition.artifactType
|
||||||
|
const pattern = cacheEntryDefinition.pattern
|
||||||
|
|
||||||
|
// Find all matching files for this cache entry definition
|
||||||
|
const globber = await glob.create(pattern, {
|
||||||
|
implicitDescendants: false
|
||||||
|
})
|
||||||
|
const matchingFiles = await globber.glob()
|
||||||
|
|
||||||
|
if (matchingFiles.length === 0) {
|
||||||
|
cacheDebug(`No files found to cache for ${artifactType}`)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cacheEntryDefinition.bundle) {
|
||||||
|
// For an extracted "bundle", use the defined pattern and cache all matching files in a single entry.
|
||||||
|
cacheActions.push(
|
||||||
|
this.awaitForDebugging(
|
||||||
|
this.saveExtractedCacheEntry(
|
||||||
|
matchingFiles,
|
||||||
|
artifactType,
|
||||||
|
pattern,
|
||||||
|
cacheEntryDefinition.uniqueFileNames,
|
||||||
|
previouslyRestoredEntries,
|
||||||
|
listener.entry(pattern)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
// Otherwise cache each matching file in a separate entry, using the complete file path as the cache pattern.
|
||||||
|
for (const cacheFile of matchingFiles) {
|
||||||
|
cacheActions.push(
|
||||||
|
this.awaitForDebugging(
|
||||||
|
this.saveExtractedCacheEntry(
|
||||||
|
[cacheFile],
|
||||||
|
artifactType,
|
||||||
|
cacheFile,
|
||||||
|
cacheEntryDefinition.uniqueFileNames,
|
||||||
|
previouslyRestoredEntries,
|
||||||
|
listener.entry(cacheFile)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.saveMetadataForCacheResults(await Promise.all(cacheActions))
|
||||||
|
}
|
||||||
|
|
||||||
|
private async saveExtractedCacheEntry(
|
||||||
|
matchingFiles: string[],
|
||||||
|
artifactType: string,
|
||||||
|
pattern: string,
|
||||||
|
uniqueFileNames: boolean,
|
||||||
|
previouslyRestoredEntries: ExtractedCacheEntry[],
|
||||||
|
entryListener: CacheEntryListener
|
||||||
|
): Promise<ExtractedCacheEntry> {
|
||||||
|
const cacheKey = uniqueFileNames
|
||||||
|
? this.createCacheKeyFromFileNames(artifactType, matchingFiles)
|
||||||
|
: await this.createCacheKeyFromFileContents(artifactType, pattern)
|
||||||
|
const previouslyRestoredKey = previouslyRestoredEntries.find(
|
||||||
|
x => x.artifactType === artifactType && x.pattern === pattern
|
||||||
|
)?.cacheKey
|
||||||
|
|
||||||
|
if (previouslyRestoredKey === cacheKey) {
|
||||||
|
cacheDebug(`No change to previously restored ${artifactType}. Not saving.`)
|
||||||
|
entryListener.markNotSaved('contents unchanged')
|
||||||
|
} else {
|
||||||
|
core.info(`Caching ${artifactType} with path '${pattern}' and cache key: ${cacheKey}`)
|
||||||
|
await saveCache([pattern], cacheKey, entryListener)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const file of matchingFiles) {
|
||||||
|
tryDelete(file)
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ExtractedCacheEntry(artifactType, pattern, cacheKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected createCacheKeyFromFileNames(artifactType: string, files: string[]): string {
|
||||||
|
const cacheKeyPrefix = getCacheKeyPrefix()
|
||||||
|
const relativeFiles = files.map(x => path.relative(this.gradleUserHome, x))
|
||||||
|
const key = hashFileNames(relativeFiles)
|
||||||
|
|
||||||
|
cacheDebug(`Generating cache key for ${artifactType} from file names: ${relativeFiles}`)
|
||||||
|
|
||||||
|
return `${cacheKeyPrefix}${artifactType}-${key}`
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async createCacheKeyFromFileContents(artifactType: string, pattern: string): Promise<string> {
|
||||||
|
const cacheKeyPrefix = getCacheKeyPrefix()
|
||||||
|
const key = await glob.hashFiles(pattern)
|
||||||
|
|
||||||
|
cacheDebug(`Generating cache key for ${artifactType} from files matching: ${pattern}`)
|
||||||
|
|
||||||
|
return `${cacheKeyPrefix}${artifactType}-${key}`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run actions sequentially if debugging is enabled
|
||||||
|
private async awaitForDebugging(p: Promise<ExtractedCacheEntry>): Promise<ExtractedCacheEntry> {
|
||||||
|
if (isCacheDebuggingEnabled()) {
|
||||||
|
await p
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load information about the extracted cache entries previously restored/saved. This is loaded from the 'cache-metadata.json' file.
|
||||||
|
*/
|
||||||
|
protected loadExtractedCacheEntries(): ExtractedCacheEntry[] {
|
||||||
|
const cacheMetadataFile = this.getCacheMetadataFile()
|
||||||
|
if (!fs.existsSync(cacheMetadataFile)) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
const filedata = fs.readFileSync(cacheMetadataFile, 'utf-8')
|
||||||
|
cacheDebug(`Loaded cache metadata: ${filedata}`)
|
||||||
|
const extractedCacheEntryMetadata = JSON.parse(filedata) as ExtractedCacheEntryMetadata
|
||||||
|
return extractedCacheEntryMetadata.entries
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves information about the extracted cache entries into the 'cache-metadata.json' file.
|
||||||
|
*/
|
||||||
|
private saveMetadataForCacheResults(results: ExtractedCacheEntry[]): void {
|
||||||
|
const extractedCacheEntryMetadata = new ExtractedCacheEntryMetadata()
|
||||||
|
extractedCacheEntryMetadata.entries = results.filter(x => x.cacheKey !== undefined)
|
||||||
|
|
||||||
|
const filedata = JSON.stringify(extractedCacheEntryMetadata)
|
||||||
|
cacheDebug(`Saving cache metadata: ${filedata}`)
|
||||||
|
|
||||||
|
fs.writeFileSync(this.getCacheMetadataFile(), filedata, 'utf-8')
|
||||||
|
}
|
||||||
|
|
||||||
|
private getCacheMetadataFile(): string {
|
||||||
|
const actionMetadataDirectory = path.resolve(this.gradleUserHome, META_FILE_DIR)
|
||||||
|
fs.mkdirSync(actionMetadataDirectory, {recursive: true})
|
||||||
|
|
||||||
|
return path.resolve(actionMetadataDirectory, `${this.extractorName}-entry-metadata.json`)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract getExtractedCacheEntryDefinitions(): ExtractedCacheEntryDefinition[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export class GradleHomeEntryExtractor extends AbstractEntryExtractor {
|
||||||
|
constructor(gradleUserHome: string) {
|
||||||
|
super(gradleUserHome, 'gradle-home')
|
||||||
|
}
|
||||||
|
|
||||||
|
async extract(listener: CacheListener): Promise<void> {
|
||||||
|
await this.deleteWrapperZips()
|
||||||
|
return super.extract(listener)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete any downloaded wrapper zip files that are not needed after extraction.
|
||||||
|
* These files are cleaned up by Gradle >= 7.5, but for older versions we remove them manually.
|
||||||
|
*/
|
||||||
|
private async deleteWrapperZips(): Promise<void> {
|
||||||
|
const wrapperZips = path.resolve(this.gradleUserHome, 'wrapper/dists/*/*/*.zip')
|
||||||
|
const globber = await glob.create(wrapperZips, {
|
||||||
|
implicitDescendants: false
|
||||||
|
})
|
||||||
|
|
||||||
|
for (const wrapperZip of await globber.glob()) {
|
||||||
|
cacheDebug(`Deleting wrapper zip: ${wrapperZip}`)
|
||||||
|
await tryDelete(wrapperZip)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the extracted cache entry definitions, which determine which artifacts will be cached
|
||||||
|
* separately from the rest of the Gradle User Home cache entry.
|
||||||
|
*/
|
||||||
|
protected getExtractedCacheEntryDefinitions(): ExtractedCacheEntryDefinition[] {
|
||||||
|
const entryDefinition = (
|
||||||
|
artifactType: string,
|
||||||
|
patterns: string[],
|
||||||
|
bundle: boolean
|
||||||
|
): ExtractedCacheEntryDefinition => {
|
||||||
|
const resolvedPatterns = patterns
|
||||||
|
.map(x => {
|
||||||
|
const isDir = x.endsWith('/')
|
||||||
|
const resolved = path.resolve(this.gradleUserHome, x)
|
||||||
|
return isDir ? `${resolved}/` : resolved // Restore trailing '/' removed by path.resolve()
|
||||||
|
})
|
||||||
|
.join('\n')
|
||||||
|
return new ExtractedCacheEntryDefinition(artifactType, resolvedPatterns, bundle)
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
entryDefinition('generated-gradle-jars', ['caches/*/generated-gradle-jars/*.jar'], false),
|
||||||
|
entryDefinition('wrapper-zips', ['wrapper/dists/*/*/'], false), // Each wrapper directory cached separately
|
||||||
|
entryDefinition('java-toolchains', ['jdks/*/'], false), // Each extracted JDK cached separately
|
||||||
|
entryDefinition('dependencies', ['caches/modules-*/files-*/*/*/*/*'], true),
|
||||||
|
entryDefinition('instrumented-jars', ['caches/jars-*/*'], true),
|
||||||
|
entryDefinition('kotlin-dsl', ['caches/*/kotlin-dsl/*/*'], true)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ConfigurationCacheEntryExtractor extends AbstractEntryExtractor {
|
||||||
|
constructor(gradleUserHome: string) {
|
||||||
|
super(gradleUserHome, 'configuration-cache')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the case where Gradle User Home has not been fully restored, so that the configuration-cache
|
||||||
|
* entry is not reusable.
|
||||||
|
*/
|
||||||
|
async restore(listener: CacheListener): Promise<void> {
|
||||||
|
if (listener.fullyRestored) {
|
||||||
|
return super.restore(listener)
|
||||||
|
}
|
||||||
|
|
||||||
|
core.info('Not restoring configuration-cache state, as Gradle User Home was not fully restored')
|
||||||
|
for (const cacheEntry of this.loadExtractedCacheEntries()) {
|
||||||
|
listener.entry(cacheEntry.pattern).markRequested('NOT_RESTORED')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract cache entries for the configuration cache in each project.
|
||||||
|
*/
|
||||||
|
protected getExtractedCacheEntryDefinitions(): ExtractedCacheEntryDefinition[] {
|
||||||
|
return this.getProjectRoots().map(projectRoot => {
|
||||||
|
const configCachePath = path.resolve(projectRoot, '.gradle/configuration-cache')
|
||||||
|
return new ExtractedCacheEntryDefinition(
|
||||||
|
'configuration-cache',
|
||||||
|
configCachePath,
|
||||||
|
true
|
||||||
|
).withNonUniqueFileNames()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For every Gradle invocation, we record the project root directory. This method returns the entire
|
||||||
|
* set of project roots, to allow saving of configuration-cache entries for each.
|
||||||
|
*/
|
||||||
|
private getProjectRoots(): string[] {
|
||||||
|
const buildResults = loadBuildResults()
|
||||||
|
const projectRootDirs = buildResults.map(x => x.rootProjectDir)
|
||||||
|
return [...new Set(projectRootDirs)] // Remove duplicates
|
||||||
|
}
|
||||||
|
}
|
228
src/cache-reporting.ts
Normal file
228
src/cache-reporting.ts
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
import * as core from '@actions/core'
|
||||||
|
import * as cache from '@actions/cache'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collects information on what entries were saved and restored during the action.
|
||||||
|
* This information is used to generate a summary of the cache usage.
|
||||||
|
*/
|
||||||
|
export class CacheListener {
|
||||||
|
cacheEntries: CacheEntryListener[] = []
|
||||||
|
cacheReadOnly = false
|
||||||
|
cacheWriteOnly = false
|
||||||
|
cacheDisabled = false
|
||||||
|
|
||||||
|
get fullyRestored(): boolean {
|
||||||
|
return this.cacheEntries.every(x => !x.wasRequestedButNotRestored())
|
||||||
|
}
|
||||||
|
|
||||||
|
get cacheStatus(): string {
|
||||||
|
if (!cache.isFeatureAvailable()) return 'not available'
|
||||||
|
if (this.cacheDisabled) return 'disabled'
|
||||||
|
if (this.cacheWriteOnly) return 'write-only'
|
||||||
|
if (this.cacheReadOnly) return 'read-only'
|
||||||
|
return 'enabled'
|
||||||
|
}
|
||||||
|
|
||||||
|
entry(name: string): CacheEntryListener {
|
||||||
|
for (const entry of this.cacheEntries) {
|
||||||
|
if (entry.entryName === name) {
|
||||||
|
return entry
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const newEntry = new CacheEntryListener(name)
|
||||||
|
this.cacheEntries.push(newEntry)
|
||||||
|
return newEntry
|
||||||
|
}
|
||||||
|
|
||||||
|
stringify(): string {
|
||||||
|
return JSON.stringify(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
static rehydrate(stringRep: string): CacheListener {
|
||||||
|
if (stringRep === '') {
|
||||||
|
return new CacheListener()
|
||||||
|
}
|
||||||
|
const rehydrated: CacheListener = Object.assign(new CacheListener(), JSON.parse(stringRep))
|
||||||
|
const entries = rehydrated.cacheEntries
|
||||||
|
for (let index = 0; index < entries.length; index++) {
|
||||||
|
const rawEntry = entries[index]
|
||||||
|
entries[index] = Object.assign(new CacheEntryListener(rawEntry.entryName), rawEntry)
|
||||||
|
}
|
||||||
|
return rehydrated
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collects information on the state of a single cache entry.
|
||||||
|
*/
|
||||||
|
export class CacheEntryListener {
|
||||||
|
entryName: string
|
||||||
|
requestedKey: string | undefined
|
||||||
|
requestedRestoreKeys: string[] | undefined
|
||||||
|
restoredKey: string | undefined
|
||||||
|
restoredSize: number | undefined
|
||||||
|
notRestored: string | undefined
|
||||||
|
|
||||||
|
savedKey: string | undefined
|
||||||
|
savedSize: number | undefined
|
||||||
|
notSaved: string | undefined
|
||||||
|
|
||||||
|
constructor(entryName: string) {
|
||||||
|
this.entryName = entryName
|
||||||
|
}
|
||||||
|
|
||||||
|
wasRequestedButNotRestored(): boolean {
|
||||||
|
return this.requestedKey !== undefined && this.restoredKey === undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
markRequested(key: string, restoreKeys: string[] = []): CacheEntryListener {
|
||||||
|
this.requestedKey = key
|
||||||
|
this.requestedRestoreKeys = restoreKeys
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
markRestored(key: string, size: number | undefined): CacheEntryListener {
|
||||||
|
this.restoredKey = key
|
||||||
|
this.restoredSize = size
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
markNotRestored(message: string): CacheEntryListener {
|
||||||
|
this.notRestored = message
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
markSaved(key: string, size: number | undefined): CacheEntryListener {
|
||||||
|
this.savedKey = key
|
||||||
|
this.savedSize = size
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
markAlreadyExists(key: string): CacheEntryListener {
|
||||||
|
this.savedKey = key
|
||||||
|
this.savedSize = 0
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
markNotSaved(message: string): CacheEntryListener {
|
||||||
|
this.notSaved = message
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function writeCachingReport(listener: CacheListener): void {
|
||||||
|
const entries = listener.cacheEntries
|
||||||
|
|
||||||
|
core.summary.addRaw(
|
||||||
|
`\n<details><summary><h4>Caching for gradle-build-action was ${listener.cacheStatus} - expand for details</h4></summary>\n`
|
||||||
|
)
|
||||||
|
|
||||||
|
core.summary.addTable([
|
||||||
|
[
|
||||||
|
{data: '', header: true},
|
||||||
|
{data: 'Count', header: true},
|
||||||
|
{data: 'Total Size (Mb)', header: true}
|
||||||
|
],
|
||||||
|
['Entries Restored', `${getCount(entries, e => e.restoredSize)}`, `${getSize(entries, e => e.restoredSize)}`],
|
||||||
|
['Entries Saved', `${getCount(entries, e => e.savedSize)}`, `${getSize(entries, e => e.savedSize)}`]
|
||||||
|
])
|
||||||
|
|
||||||
|
core.summary.addHeading('Cache Entry Details', 5)
|
||||||
|
|
||||||
|
const entryDetails = renderEntryDetails(listener)
|
||||||
|
core.summary.addRaw(`<pre>
|
||||||
|
${entryDetails}
|
||||||
|
</pre>
|
||||||
|
</details>
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function logCachingReport(listener: CacheListener): void {
|
||||||
|
const entries = listener.cacheEntries
|
||||||
|
|
||||||
|
core.startGroup(`Caching for gradle-build-action was ${listener.cacheStatus} - expand for details`)
|
||||||
|
|
||||||
|
core.info(
|
||||||
|
`Entries Restored: ${getCount(entries, e => e.restoredSize)} (${getSize(entries, e => e.restoredSize)} Mb)`
|
||||||
|
)
|
||||||
|
core.info(`Entries Saved : ${getCount(entries, e => e.savedSize)} (${getSize(entries, e => e.savedSize)} Mb)`)
|
||||||
|
|
||||||
|
core.info(`Cache Entry Details`)
|
||||||
|
core.info(renderEntryDetails(listener))
|
||||||
|
|
||||||
|
core.endGroup()
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderEntryDetails(listener: CacheListener): string {
|
||||||
|
return listener.cacheEntries
|
||||||
|
.map(
|
||||||
|
entry => `Entry: ${entry.entryName}
|
||||||
|
Requested Key : ${entry.requestedKey ?? ''}
|
||||||
|
Restored Key : ${entry.restoredKey ?? ''}
|
||||||
|
Size: ${formatSize(entry.restoredSize)}
|
||||||
|
${getRestoredMessage(entry, listener.cacheWriteOnly)}
|
||||||
|
Saved Key : ${entry.savedKey ?? ''}
|
||||||
|
Size: ${formatSize(entry.savedSize)}
|
||||||
|
${getSavedMessage(entry, listener.cacheReadOnly)}
|
||||||
|
`
|
||||||
|
)
|
||||||
|
.join('---\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRestoredMessage(entry: CacheEntryListener, cacheWriteOnly: boolean): string {
|
||||||
|
if (entry.notRestored) {
|
||||||
|
return `(Entry not restored: ${entry.notRestored})`
|
||||||
|
}
|
||||||
|
if (cacheWriteOnly) {
|
||||||
|
return '(Entry not restored: cache is write-only)'
|
||||||
|
}
|
||||||
|
if (entry.requestedKey === undefined) {
|
||||||
|
return '(Entry not restored: not requested)'
|
||||||
|
}
|
||||||
|
if (entry.restoredKey === undefined) {
|
||||||
|
return '(Entry not restored: no match found)'
|
||||||
|
}
|
||||||
|
if (entry.restoredKey === entry.requestedKey) {
|
||||||
|
return '(Entry restored: exact match found)'
|
||||||
|
}
|
||||||
|
return '(Entry restored: partial match found)'
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSavedMessage(entry: CacheEntryListener, cacheReadOnly: boolean): string {
|
||||||
|
if (entry.notSaved) {
|
||||||
|
return `(Entry not saved: ${entry.notSaved})`
|
||||||
|
}
|
||||||
|
if (entry.savedKey === undefined) {
|
||||||
|
if (cacheReadOnly) {
|
||||||
|
return '(Entry not saved: cache is read-only)'
|
||||||
|
}
|
||||||
|
return '(Entry not saved: reason unknown)'
|
||||||
|
}
|
||||||
|
if (entry.savedSize === 0) {
|
||||||
|
return '(Entry not saved: entry with key already exists)'
|
||||||
|
}
|
||||||
|
return '(Entry saved)'
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCount(
|
||||||
|
cacheEntries: CacheEntryListener[],
|
||||||
|
predicate: (value: CacheEntryListener) => number | undefined
|
||||||
|
): number {
|
||||||
|
return cacheEntries.filter(e => predicate(e)).length
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSize(
|
||||||
|
cacheEntries: CacheEntryListener[],
|
||||||
|
predicate: (value: CacheEntryListener) => number | undefined
|
||||||
|
): number {
|
||||||
|
const bytes = cacheEntries.map(e => predicate(e) ?? 0).reduce((p, v) => p + v, 0)
|
||||||
|
return Math.round(bytes / (1024 * 1024))
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatSize(bytes: number | undefined): string {
|
||||||
|
if (bytes === undefined || bytes === 0) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
return `${Math.round(bytes / (1024 * 1024))} MB (${bytes} B)`
|
||||||
|
}
|
252
src/cache-utils.ts
Normal file
252
src/cache-utils.ts
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
import * as core from '@actions/core'
|
||||||
|
import * as cache from '@actions/cache'
|
||||||
|
import * as github from '@actions/github'
|
||||||
|
import * as exec from '@actions/exec'
|
||||||
|
|
||||||
|
import * as crypto from 'crypto'
|
||||||
|
import * as path from 'path'
|
||||||
|
import * as fs from 'fs'
|
||||||
|
|
||||||
|
import {CacheEntryListener} from './cache-reporting'
|
||||||
|
|
||||||
|
const CACHE_PROTOCOL_VERSION = 'v7-'
|
||||||
|
|
||||||
|
const JOB_CONTEXT_PARAMETER = 'workflow-job-context'
|
||||||
|
const CACHE_DISABLED_PARAMETER = 'cache-disabled'
|
||||||
|
const CACHE_READONLY_PARAMETER = 'cache-read-only'
|
||||||
|
const CACHE_WRITEONLY_PARAMETER = 'cache-write-only'
|
||||||
|
const STRICT_CACHE_MATCH_PARAMETER = 'gradle-home-cache-strict-match'
|
||||||
|
const CACHE_CLEANUP_ENABLED_PARAMETER = 'gradle-home-cache-cleanup'
|
||||||
|
const CACHE_DEBUG_VAR = 'GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED'
|
||||||
|
|
||||||
|
const CACHE_KEY_PREFIX_VAR = 'GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX'
|
||||||
|
const CACHE_KEY_OS_VAR = 'GRADLE_BUILD_ACTION_CACHE_KEY_ENVIRONMENT'
|
||||||
|
const CACHE_KEY_JOB_VAR = 'GRADLE_BUILD_ACTION_CACHE_KEY_JOB'
|
||||||
|
const CACHE_KEY_JOB_INSTANCE_VAR = 'GRADLE_BUILD_ACTION_CACHE_KEY_JOB_INSTANCE'
|
||||||
|
const CACHE_KEY_JOB_EXECUTION_VAR = 'GRADLE_BUILD_ACTION_CACHE_KEY_JOB_EXECUTION'
|
||||||
|
|
||||||
|
const SEGMENT_DOWNLOAD_TIMEOUT_VAR = 'SEGMENT_DOWNLOAD_TIMEOUT_MINS'
|
||||||
|
const SEGMENT_DOWNLOAD_TIMEOUT_DEFAULT = 10 * 60 * 1000 // 10 minutes
|
||||||
|
|
||||||
|
export function isCacheDisabled(): boolean {
|
||||||
|
if (!cache.isFeatureAvailable()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return core.getBooleanInput(CACHE_DISABLED_PARAMETER)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isCacheReadOnly(): boolean {
|
||||||
|
return !isCacheWriteOnly() && core.getBooleanInput(CACHE_READONLY_PARAMETER)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isCacheWriteOnly(): boolean {
|
||||||
|
return core.getBooleanInput(CACHE_WRITEONLY_PARAMETER)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isCacheDebuggingEnabled(): boolean {
|
||||||
|
return process.env[CACHE_DEBUG_VAR] ? true : false
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isCacheCleanupEnabled(): boolean {
|
||||||
|
return core.getBooleanInput(CACHE_CLEANUP_ENABLED_PARAMETER)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a key used to restore a cache entry.
|
||||||
|
* The Github Actions cache will first try for an exact match on the key.
|
||||||
|
* If that fails, it will try for a prefix match on any of the restoreKeys.
|
||||||
|
*/
|
||||||
|
export class CacheKey {
|
||||||
|
key: string
|
||||||
|
restoreKeys: string[]
|
||||||
|
|
||||||
|
constructor(key: string, restoreKeys: string[]) {
|
||||||
|
this.key = key
|
||||||
|
this.restoreKeys = restoreKeys
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a cache key specific to the current job execution.
|
||||||
|
* The key is constructed from the following inputs (with some user overrides):
|
||||||
|
* - The cache protocol version
|
||||||
|
* - The name of the cache
|
||||||
|
* - The runner operating system
|
||||||
|
* - The name of the Job being executed
|
||||||
|
* - The matrix values for the Job being executed (job context)
|
||||||
|
* - The SHA of the commit being executed
|
||||||
|
*
|
||||||
|
* Caches are restored by trying to match the these key prefixes in order:
|
||||||
|
* - The full key with SHA
|
||||||
|
* - A previous key for this Job + matrix
|
||||||
|
* - Any previous key for this Job (any matrix)
|
||||||
|
* - Any previous key for this cache on the current OS
|
||||||
|
*/
|
||||||
|
export function generateCacheKey(cacheName: string): CacheKey {
|
||||||
|
const cacheKeyBase = `${getCacheKeyPrefix()}${CACHE_PROTOCOL_VERSION}${cacheName}`
|
||||||
|
|
||||||
|
// At the most general level, share caches for all executions on the same OS
|
||||||
|
const cacheKeyForEnvironment = `${cacheKeyBase}|${getCacheKeyEnvironment()}`
|
||||||
|
|
||||||
|
// Prefer caches that run this job
|
||||||
|
const cacheKeyForJob = `${cacheKeyForEnvironment}|${getCacheKeyJob()}`
|
||||||
|
|
||||||
|
// Prefer (even more) jobs that run this job with the same context (matrix)
|
||||||
|
const cacheKeyForJobContext = `${cacheKeyForJob}[${getCacheKeyJobInstance()}]`
|
||||||
|
|
||||||
|
// Exact match on Git SHA
|
||||||
|
const cacheKey = `${cacheKeyForJobContext}-${getCacheKeyJobExecution()}`
|
||||||
|
|
||||||
|
if (core.getBooleanInput(STRICT_CACHE_MATCH_PARAMETER)) {
|
||||||
|
return new CacheKey(cacheKey, [cacheKeyForJobContext])
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CacheKey(cacheKey, [cacheKeyForJobContext, cacheKeyForJob, cacheKeyForEnvironment])
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCacheKeyPrefix(): string {
|
||||||
|
// Prefix can be used to force change all cache keys (defaults to cache protocol version)
|
||||||
|
return process.env[CACHE_KEY_PREFIX_VAR] || ''
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCacheKeyEnvironment(): string {
|
||||||
|
const runnerOs = process.env['RUNNER_OS'] || ''
|
||||||
|
return process.env[CACHE_KEY_OS_VAR] || runnerOs
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCacheKeyJob(): string {
|
||||||
|
// Prefix can be used to force change all cache keys (defaults to cache protocol version)
|
||||||
|
return process.env[CACHE_KEY_JOB_VAR] || github.context.job
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCacheKeyJobInstance(): string {
|
||||||
|
const override = process.env[CACHE_KEY_JOB_INSTANCE_VAR]
|
||||||
|
if (override) {
|
||||||
|
return override
|
||||||
|
}
|
||||||
|
|
||||||
|
// By default, we hash the full `matrix` data for the run, to uniquely identify this job invocation
|
||||||
|
// The only way we can obtain the `matrix` data is via the `workflow-job-context` parameter in action.yml.
|
||||||
|
const workflowJobContext = core.getInput(JOB_CONTEXT_PARAMETER)
|
||||||
|
return hashStrings([workflowJobContext])
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCacheKeyJobExecution(): string {
|
||||||
|
// Used to associate a cache key with a particular execution (default is bound to the git commit sha)
|
||||||
|
return process.env[CACHE_KEY_JOB_EXECUTION_VAR] || github.context.sha
|
||||||
|
}
|
||||||
|
|
||||||
|
export function hashFileNames(fileNames: string[]): string {
|
||||||
|
return hashStrings(fileNames.map(x => x.replace(new RegExp(`\\${path.sep}`, 'g'), '/')))
|
||||||
|
}
|
||||||
|
|
||||||
|
export function hashStrings(values: string[]): string {
|
||||||
|
const hash = crypto.createHash('md5')
|
||||||
|
for (const value of values) {
|
||||||
|
hash.update(value)
|
||||||
|
}
|
||||||
|
return hash.digest('hex')
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function restoreCache(
|
||||||
|
cachePath: string[],
|
||||||
|
cacheKey: string,
|
||||||
|
cacheRestoreKeys: string[],
|
||||||
|
listener: CacheEntryListener
|
||||||
|
): Promise<cache.CacheEntry | undefined> {
|
||||||
|
listener.markRequested(cacheKey, cacheRestoreKeys)
|
||||||
|
try {
|
||||||
|
// Only override the read timeout if the SEGMENT_DOWNLOAD_TIMEOUT_MINS env var has NOT been set
|
||||||
|
const cacheRestoreOptions = process.env[SEGMENT_DOWNLOAD_TIMEOUT_VAR]
|
||||||
|
? {}
|
||||||
|
: {segmentTimeoutInMs: SEGMENT_DOWNLOAD_TIMEOUT_DEFAULT}
|
||||||
|
const restoredEntry = await cache.restoreCache(cachePath, cacheKey, cacheRestoreKeys, cacheRestoreOptions)
|
||||||
|
if (restoredEntry !== undefined) {
|
||||||
|
listener.markRestored(restoredEntry.key, restoredEntry.size)
|
||||||
|
}
|
||||||
|
return restoredEntry
|
||||||
|
} catch (error) {
|
||||||
|
listener.markNotRestored((error as Error).message)
|
||||||
|
handleCacheFailure(error, `Failed to restore ${cacheKey}`)
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function saveCache(cachePath: string[], cacheKey: string, listener: CacheEntryListener): Promise<void> {
|
||||||
|
try {
|
||||||
|
const savedEntry = await cache.saveCache(cachePath, cacheKey)
|
||||||
|
listener.markSaved(savedEntry.key, savedEntry.size)
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof cache.ReserveCacheError) {
|
||||||
|
listener.markAlreadyExists(cacheKey)
|
||||||
|
} else {
|
||||||
|
listener.markNotSaved((error as Error).message)
|
||||||
|
}
|
||||||
|
handleCacheFailure(error, `Failed to save cache entry with path '${cachePath}' and key: ${cacheKey}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function cacheDebug(message: string): void {
|
||||||
|
if (isCacheDebuggingEnabled()) {
|
||||||
|
core.info(message)
|
||||||
|
} else {
|
||||||
|
core.debug(message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function handleCacheFailure(error: unknown, message: string): void {
|
||||||
|
if (error instanceof cache.ValidationError) {
|
||||||
|
// Fail on cache validation errors
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
if (error instanceof cache.ReserveCacheError) {
|
||||||
|
// Reserve cache errors are expected if the artifact has been previously cached
|
||||||
|
core.info(`${message}: ${error}`)
|
||||||
|
} else {
|
||||||
|
// Warn on all other errors
|
||||||
|
core.warning(`${message}: ${error}`)
|
||||||
|
if (error instanceof Error && error.stack) {
|
||||||
|
cacheDebug(error.stack)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to delete a file or directory, waiting to allow locks to be released
|
||||||
|
*/
|
||||||
|
export async function tryDelete(file: string): Promise<void> {
|
||||||
|
const maxAttempts = 5
|
||||||
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
||||||
|
if (!fs.existsSync(file)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const stat = fs.lstatSync(file)
|
||||||
|
if (stat.isDirectory()) {
|
||||||
|
fs.rmSync(file, {recursive: true})
|
||||||
|
} else {
|
||||||
|
fs.unlinkSync(file)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
} catch (error) {
|
||||||
|
if (attempt === maxAttempts) {
|
||||||
|
core.warning(`Failed to delete ${file}, which will impact caching.
|
||||||
|
It is likely locked by another process. Output of 'jps -ml':
|
||||||
|
${await getJavaProcesses()}`)
|
||||||
|
throw error
|
||||||
|
} else {
|
||||||
|
cacheDebug(`Attempt to delete ${file} failed. Will try again.`)
|
||||||
|
await delay(1000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function delay(ms: number): Promise<void> {
|
||||||
|
return new Promise(resolve => setTimeout(resolve, ms))
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getJavaProcesses(): Promise<string> {
|
||||||
|
const jpsOutput = await exec.getExecOutput('jps', ['-lm'])
|
||||||
|
return jpsOutput.stdout
|
||||||
|
}
|
88
src/caches.ts
Normal file
88
src/caches.ts
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
import * as core from '@actions/core'
|
||||||
|
import {isCacheCleanupEnabled, isCacheDisabled, isCacheReadOnly, isCacheWriteOnly} from './cache-utils'
|
||||||
|
import {CacheListener} from './cache-reporting'
|
||||||
|
import {DaemonController} from './daemon-controller'
|
||||||
|
import {GradleStateCache} from './cache-base'
|
||||||
|
import {CacheCleaner} from './cache-cleaner'
|
||||||
|
|
||||||
|
const CACHE_RESTORED_VAR = 'GRADLE_BUILD_ACTION_CACHE_RESTORED'
|
||||||
|
|
||||||
|
export async function restore(gradleUserHome: string, cacheListener: CacheListener): Promise<void> {
|
||||||
|
// Bypass restore cache on all but first action step in workflow.
|
||||||
|
if (process.env[CACHE_RESTORED_VAR]) {
|
||||||
|
core.info('Cache only restored on first action step.')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
core.exportVariable(CACHE_RESTORED_VAR, true)
|
||||||
|
|
||||||
|
const gradleStateCache = new GradleStateCache(gradleUserHome)
|
||||||
|
|
||||||
|
if (isCacheDisabled()) {
|
||||||
|
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
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gradleStateCache.cacheOutputExists()) {
|
||||||
|
core.info('Gradle User Home already exists: will not restore from cache.')
|
||||||
|
// Initialize pre-existing Gradle User Home.
|
||||||
|
gradleStateCache.init()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
gradleStateCache.init()
|
||||||
|
// Mark the state as restored so that post-action will perform save.
|
||||||
|
core.saveState(CACHE_RESTORED_VAR, true)
|
||||||
|
|
||||||
|
if (isCacheWriteOnly()) {
|
||||||
|
core.info('Cache is write-only: will not restore from cache.')
|
||||||
|
cacheListener.cacheWriteOnly = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
await core.group('Restore Gradle state from cache', async () => {
|
||||||
|
await gradleStateCache.restore(cacheListener)
|
||||||
|
})
|
||||||
|
|
||||||
|
if (isCacheCleanupEnabled() && !isCacheReadOnly()) {
|
||||||
|
core.info('Preparing cache for cleanup.')
|
||||||
|
const cacheCleaner = new CacheCleaner(gradleUserHome, process.env['RUNNER_TEMP']!)
|
||||||
|
await cacheCleaner.prepare()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function save(
|
||||||
|
gradleUserHome: string,
|
||||||
|
cacheListener: CacheListener,
|
||||||
|
daemonController: DaemonController
|
||||||
|
): Promise<void> {
|
||||||
|
if (isCacheDisabled()) {
|
||||||
|
core.info('Cache is disabled: will not save state for later builds.')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!core.getState(CACHE_RESTORED_VAR)) {
|
||||||
|
core.info('Cache will not be saved: not restored in main action step.')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isCacheReadOnly()) {
|
||||||
|
core.info('Cache is read-only: will not save state for use in subsequent builds.')
|
||||||
|
cacheListener.cacheReadOnly = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
await daemonController.stopAllDaemons()
|
||||||
|
|
||||||
|
if (isCacheCleanupEnabled()) {
|
||||||
|
core.info('Forcing cache cleanup.')
|
||||||
|
const cacheCleaner = new CacheCleaner(gradleUserHome, process.env['RUNNER_TEMP']!)
|
||||||
|
await cacheCleaner.forceCleanup()
|
||||||
|
}
|
||||||
|
|
||||||
|
await core.group('Caching Gradle state', async () => {
|
||||||
|
return new GradleStateCache(gradleUserHome).save(cacheListener)
|
||||||
|
})
|
||||||
|
}
|
36
src/daemon-controller.ts
Normal file
36
src/daemon-controller.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import * as core from '@actions/core'
|
||||||
|
import * as exec from '@actions/exec'
|
||||||
|
import * as fs from 'fs'
|
||||||
|
import * as path from 'path'
|
||||||
|
import {BuildResult} from './build-results'
|
||||||
|
|
||||||
|
export class DaemonController {
|
||||||
|
private readonly gradleHomes
|
||||||
|
|
||||||
|
constructor(buildResults: BuildResult[]) {
|
||||||
|
const allHomes = buildResults.map(buildResult => buildResult.gradleHomeDir)
|
||||||
|
this.gradleHomes = Array.from(new Set(allHomes))
|
||||||
|
}
|
||||||
|
|
||||||
|
async stopAllDaemons(): Promise<void> {
|
||||||
|
core.info('Stopping all Gradle daemons before saving Gradle User Home state')
|
||||||
|
|
||||||
|
const executions: Promise<number>[] = []
|
||||||
|
const args = ['--stop']
|
||||||
|
|
||||||
|
for (const gradleHome of this.gradleHomes) {
|
||||||
|
const executable = path.resolve(gradleHome, 'bin', 'gradle')
|
||||||
|
if (!fs.existsSync(executable)) {
|
||||||
|
core.warning(`Gradle executable not found at ${executable}. Could not stop Gradle daemons.`)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
core.info(`Stopping Gradle daemons for ${gradleHome}`)
|
||||||
|
executions.push(
|
||||||
|
exec.exec(executable, args, {
|
||||||
|
ignoreReturnCode: true
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
await Promise.all(executions)
|
||||||
|
}
|
||||||
|
}
|
26
src/execution.ts
Normal file
26
src/execution.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import * as core from '@actions/core'
|
||||||
|
import * as exec from '@actions/exec'
|
||||||
|
import fs from 'fs'
|
||||||
|
import * as gradlew from './gradlew'
|
||||||
|
|
||||||
|
export async function executeGradleBuild(executable: string | undefined, root: string, args: string[]): Promise<void> {
|
||||||
|
// Use the provided executable, or look for a Gradle wrapper script to run
|
||||||
|
const toExecute = executable ?? gradlew.locateGradleWrapperScript(root)
|
||||||
|
verifyIsExecutableScript(toExecute)
|
||||||
|
const status: number = await exec.exec(toExecute, args, {
|
||||||
|
cwd: root,
|
||||||
|
ignoreReturnCode: true
|
||||||
|
})
|
||||||
|
|
||||||
|
if (status !== 0) {
|
||||||
|
core.setFailed(`Gradle build failed: see console output for details`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function verifyIsExecutableScript(toExecute: string): void {
|
||||||
|
try {
|
||||||
|
fs.accessSync(toExecute, fs.constants.X_OK)
|
||||||
|
} catch (err) {
|
||||||
|
throw new Error(`Gradle script '${toExecute}' is not executable.`)
|
||||||
|
}
|
||||||
|
}
|
26
src/gradlew.ts
Normal file
26
src/gradlew.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import * as path from 'path'
|
||||||
|
import fs from 'fs'
|
||||||
|
|
||||||
|
const IS_WINDOWS = process.platform === 'win32'
|
||||||
|
|
||||||
|
export function wrapperScriptFilename(): string {
|
||||||
|
return IS_WINDOWS ? 'gradlew.bat' : 'gradlew'
|
||||||
|
}
|
||||||
|
|
||||||
|
export function installScriptFilename(): string {
|
||||||
|
return IS_WINDOWS ? 'gradle.bat' : 'gradle'
|
||||||
|
}
|
||||||
|
|
||||||
|
export function locateGradleWrapperScript(buildRootDirectory: string): string {
|
||||||
|
validateGradleWrapper(buildRootDirectory)
|
||||||
|
return path.resolve(buildRootDirectory, wrapperScriptFilename())
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateGradleWrapper(buildRootDirectory: string): void {
|
||||||
|
const wrapperProperties = path.resolve(buildRootDirectory, 'gradle/wrapper/gradle-wrapper.properties')
|
||||||
|
if (!fs.existsSync(wrapperProperties)) {
|
||||||
|
throw new Error(
|
||||||
|
`Cannot locate a Gradle wrapper properties file at '${wrapperProperties}'. Specify 'gradle-version' or 'gradle-executable' for projects without Gradle wrapper configured.`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
94
src/job-summary.ts
Normal file
94
src/job-summary.ts
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
import * as core from '@actions/core'
|
||||||
|
import {BuildResult} from './build-results'
|
||||||
|
import {writeCachingReport, CacheListener, logCachingReport} from './cache-reporting'
|
||||||
|
|
||||||
|
export async function writeJobSummary(buildResults: BuildResult[], cacheListener: CacheListener): Promise<void> {
|
||||||
|
core.info('Writing job summary')
|
||||||
|
|
||||||
|
if (buildResults.length === 0) {
|
||||||
|
core.debug('No Gradle build results found. Summary table will not be generated.')
|
||||||
|
} else {
|
||||||
|
writeSummaryTable(buildResults)
|
||||||
|
}
|
||||||
|
|
||||||
|
writeCachingReport(cacheListener)
|
||||||
|
|
||||||
|
await core.summary.write()
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function logJobSummary(buildResults: BuildResult[], cacheListener: CacheListener): Promise<void> {
|
||||||
|
if (buildResults.length === 0) {
|
||||||
|
core.debug('No Gradle build results found. Summary table will not be logged.')
|
||||||
|
} else {
|
||||||
|
logSummaryTable(buildResults)
|
||||||
|
}
|
||||||
|
|
||||||
|
logCachingReport(cacheListener)
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeSummaryTable(results: BuildResult[]): void {
|
||||||
|
core.summary.addHeading('Gradle Builds', 3)
|
||||||
|
|
||||||
|
core.summary.addRaw(`
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Root Project</th>
|
||||||
|
<th>Requested Tasks</th>
|
||||||
|
<th>Gradle Version</th>
|
||||||
|
<th>Build Outcome</th>
|
||||||
|
<th>Build Scan™</th>
|
||||||
|
</tr>${results.map(result => renderBuildResultRow(result)).join('')}
|
||||||
|
</table>
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderBuildResultRow(result: BuildResult): string {
|
||||||
|
return `
|
||||||
|
<tr>
|
||||||
|
<td>${result.rootProjectName}</td>
|
||||||
|
<td>${result.requestedTasks}</td>
|
||||||
|
<td align='center'>${result.gradleVersion}</td>
|
||||||
|
<td align='center'>${renderOutcome(result)}</td>
|
||||||
|
<td>${renderBuildScan(result)}</td>
|
||||||
|
</tr>`
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderOutcome(result: BuildResult): string {
|
||||||
|
return result.buildFailed ? ':x:' : ':white_check_mark:'
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderBuildScan(result: BuildResult): string {
|
||||||
|
if (result.buildScanFailed) {
|
||||||
|
return renderBuildScanBadge(
|
||||||
|
'PUBLISH_FAILED',
|
||||||
|
'orange',
|
||||||
|
'https://docs.gradle.com/enterprise/gradle-plugin/#troubleshooting'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (result.buildScanUri) {
|
||||||
|
return renderBuildScanBadge('PUBLISHED', '06A0CE', result.buildScanUri)
|
||||||
|
}
|
||||||
|
return renderBuildScanBadge('NOT_PUBLISHED', 'lightgrey', 'https://scans.gradle.com')
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderBuildScanBadge(outcomeText: string, outcomeColor: string, targetUrl: string): string {
|
||||||
|
const badgeUrl = `https://img.shields.io/badge/Build%20Scan%E2%84%A2-${outcomeText}-${outcomeColor}?logo=Gradle`
|
||||||
|
const badgeHtml = `<img src="${badgeUrl}" alt="Build Scan ${outcomeText}" />`
|
||||||
|
return `<a href="${targetUrl}" rel="nofollow">${badgeHtml}</a>`
|
||||||
|
}
|
||||||
|
|
||||||
|
function logSummaryTable(results: BuildResult[]): void {
|
||||||
|
core.info('============================')
|
||||||
|
core.info('Gradle Builds')
|
||||||
|
core.info('----------------------------')
|
||||||
|
core.info('Root Project | Requested Tasks | Gradle Version | Build Outcome | Build Scan™')
|
||||||
|
core.info('----------------------------')
|
||||||
|
for (const result of results) {
|
||||||
|
core.info(
|
||||||
|
`${result.rootProjectName} | ${result.requestedTasks} | ${result.gradleVersion} | ${
|
||||||
|
result.buildFailed ? 'FAILED' : 'SUCCESS'
|
||||||
|
} | ${result.buildScanFailed ? 'Publish failed' : result.buildScanUri}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
core.info('============================')
|
||||||
|
}
|
64
src/main.ts
Normal file
64
src/main.ts
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
import * as core from '@actions/core'
|
||||||
|
import * as path from 'path'
|
||||||
|
import {parseArgsStringToArgv} from 'string-argv'
|
||||||
|
|
||||||
|
import * as setupGradle from './setup-gradle'
|
||||||
|
import * as execution from './execution'
|
||||||
|
import * as provision from './provision'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The main entry point for the action, called by Github Actions for the step.
|
||||||
|
*/
|
||||||
|
export async function run(): Promise<void> {
|
||||||
|
try {
|
||||||
|
const workspaceDirectory = process.env[`GITHUB_WORKSPACE`] || ''
|
||||||
|
const buildRootDirectory = resolveBuildRootDirectory(workspaceDirectory)
|
||||||
|
|
||||||
|
await setupGradle.setup(buildRootDirectory)
|
||||||
|
|
||||||
|
const executable = await provisionGradle(workspaceDirectory)
|
||||||
|
// executable will be undefined if using Gradle wrapper
|
||||||
|
if (executable !== undefined) {
|
||||||
|
core.addPath(path.dirname(executable))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only execute if arguments have been provided
|
||||||
|
const args: string[] = parseCommandLineArguments()
|
||||||
|
if (args.length > 0) {
|
||||||
|
await execution.executeGradleBuild(executable, buildRootDirectory, args)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
core.setFailed(String(error))
|
||||||
|
if (error instanceof Error && error.stack) {
|
||||||
|
core.info(error.stack)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
run()
|
||||||
|
|
||||||
|
async function provisionGradle(workspaceDirectory: string): Promise<string | undefined> {
|
||||||
|
const gradleVersion = core.getInput('gradle-version')
|
||||||
|
if (gradleVersion !== '' && gradleVersion !== 'wrapper') {
|
||||||
|
return path.resolve(await provision.gradleVersion(gradleVersion))
|
||||||
|
}
|
||||||
|
|
||||||
|
const gradleExecutable = core.getInput('gradle-executable')
|
||||||
|
if (gradleExecutable !== '') {
|
||||||
|
return path.resolve(workspaceDirectory, gradleExecutable)
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveBuildRootDirectory(baseDirectory: string): string {
|
||||||
|
const buildRootDirectory = core.getInput('build-root-directory')
|
||||||
|
const resolvedBuildRootDirectory =
|
||||||
|
buildRootDirectory === '' ? path.resolve(baseDirectory) : path.resolve(baseDirectory, buildRootDirectory)
|
||||||
|
return resolvedBuildRootDirectory
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseCommandLineArguments(): string[] {
|
||||||
|
const input = core.getInput('arguments')
|
||||||
|
return parseArgsStringToArgv(input)
|
||||||
|
}
|
27
src/post.ts
Normal file
27
src/post.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import * as core from '@actions/core'
|
||||||
|
import * as setupGradle from './setup-gradle'
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// throw an uncaught exception. Instead of failing this action, just warn.
|
||||||
|
process.on('uncaughtException', e => handleFailure(e))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The post-execution entry point for the action, called by Github Actions after completing all steps for the Job.
|
||||||
|
*/
|
||||||
|
export async function run(): Promise<void> {
|
||||||
|
try {
|
||||||
|
await setupGradle.complete()
|
||||||
|
} catch (error) {
|
||||||
|
handleFailure(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleFailure(error: unknown): void {
|
||||||
|
core.warning(`Unhandled error in Gradle post-action - job will continue: ${error}`)
|
||||||
|
if (error instanceof Error && error.stack) {
|
||||||
|
core.info(error.stack)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
run()
|
161
src/provision.ts
Normal file
161
src/provision.ts
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
import * as fs from 'fs'
|
||||||
|
import * as os from 'os'
|
||||||
|
import * as path from 'path'
|
||||||
|
import * as httpm from '@actions/http-client'
|
||||||
|
import * as core from '@actions/core'
|
||||||
|
import * as cache from '@actions/cache'
|
||||||
|
import * as toolCache from '@actions/tool-cache'
|
||||||
|
|
||||||
|
import * as gradlew from './gradlew'
|
||||||
|
import {handleCacheFailure, isCacheDisabled, isCacheReadOnly} from './cache-utils'
|
||||||
|
|
||||||
|
const gradleVersionsBaseUrl = 'https://services.gradle.org/versions'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Gradle executable path
|
||||||
|
*/
|
||||||
|
export async function gradleVersion(version: string): Promise<string> {
|
||||||
|
switch (version) {
|
||||||
|
case 'current':
|
||||||
|
return gradleCurrent()
|
||||||
|
case 'rc':
|
||||||
|
core.warning(`Specifying gradle-version 'rc' has been deprecated. Use 'release-candidate' instead.`)
|
||||||
|
return gradleReleaseCandidate()
|
||||||
|
case 'release-candidate':
|
||||||
|
return gradleReleaseCandidate()
|
||||||
|
case 'nightly':
|
||||||
|
return gradleNightly()
|
||||||
|
case 'release-nightly':
|
||||||
|
return gradleReleaseNightly()
|
||||||
|
default:
|
||||||
|
return gradle(version)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function gradleCurrent(): Promise<string> {
|
||||||
|
const versionInfo = await gradleVersionDeclaration(`${gradleVersionsBaseUrl}/current`)
|
||||||
|
return provisionGradle(versionInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function gradleReleaseCandidate(): Promise<string> {
|
||||||
|
const versionInfo = await gradleVersionDeclaration(`${gradleVersionsBaseUrl}/release-candidate`)
|
||||||
|
if (versionInfo && versionInfo.version && versionInfo.downloadUrl) {
|
||||||
|
return provisionGradle(versionInfo)
|
||||||
|
}
|
||||||
|
core.info('No current release-candidate found, will fallback to current')
|
||||||
|
return gradleCurrent()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function gradleNightly(): Promise<string> {
|
||||||
|
const versionInfo = await gradleVersionDeclaration(`${gradleVersionsBaseUrl}/nightly`)
|
||||||
|
return provisionGradle(versionInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function gradleReleaseNightly(): Promise<string> {
|
||||||
|
const versionInfo = await gradleVersionDeclaration(`${gradleVersionsBaseUrl}/release-nightly`)
|
||||||
|
return provisionGradle(versionInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function gradle(version: string): Promise<string> {
|
||||||
|
const versionInfo = await findGradleVersionDeclaration(version)
|
||||||
|
if (!versionInfo) {
|
||||||
|
throw new Error(`Gradle version ${version} does not exists`)
|
||||||
|
}
|
||||||
|
return provisionGradle(versionInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function gradleVersionDeclaration(url: string): Promise<GradleVersionInfo> {
|
||||||
|
return await httpGetGradleVersion(url)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function findGradleVersionDeclaration(version: string): Promise<GradleVersionInfo | undefined> {
|
||||||
|
const gradleVersions = await httpGetGradleVersions(`${gradleVersionsBaseUrl}/all`)
|
||||||
|
return gradleVersions.find((entry: GradleVersionInfo) => {
|
||||||
|
return entry.version === version
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function provisionGradle(versionInfo: GradleVersionInfo): Promise<string> {
|
||||||
|
return core.group(`Provision Gradle ${versionInfo.version}`, async () => {
|
||||||
|
return locateGradleAndDownloadIfRequired(versionInfo)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function locateGradleAndDownloadIfRequired(versionInfo: GradleVersionInfo): Promise<string> {
|
||||||
|
const installsDir = path.join(os.homedir(), 'gradle-installations/installs')
|
||||||
|
const installDir = path.join(installsDir, `gradle-${versionInfo.version}`)
|
||||||
|
if (fs.existsSync(installDir)) {
|
||||||
|
core.info(`Gradle installation already exists at ${installDir}`)
|
||||||
|
return executableFrom(installDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
const downloadPath = await downloadAndCacheGradleDistribution(versionInfo)
|
||||||
|
await toolCache.extractZip(downloadPath, installsDir)
|
||||||
|
core.info(`Extracted Gradle ${versionInfo.version} to ${installDir}`)
|
||||||
|
|
||||||
|
const executable = executableFrom(installDir)
|
||||||
|
fs.chmodSync(executable, '755')
|
||||||
|
core.info(`Provisioned Gradle executable ${executable}`)
|
||||||
|
|
||||||
|
return executable
|
||||||
|
}
|
||||||
|
|
||||||
|
async function downloadAndCacheGradleDistribution(versionInfo: GradleVersionInfo): Promise<string> {
|
||||||
|
const downloadPath = path.join(os.homedir(), `gradle-installations/downloads/gradle-${versionInfo.version}-bin.zip`)
|
||||||
|
|
||||||
|
if (isCacheDisabled()) {
|
||||||
|
await downloadGradleDistribution(versionInfo, downloadPath)
|
||||||
|
return downloadPath
|
||||||
|
}
|
||||||
|
|
||||||
|
const cacheKey = `gradle-${versionInfo.version}`
|
||||||
|
try {
|
||||||
|
const restoreKey = await cache.restoreCache([downloadPath], cacheKey)
|
||||||
|
if (restoreKey) {
|
||||||
|
core.info(`Restored Gradle distribution ${cacheKey} from cache to ${downloadPath}`)
|
||||||
|
return downloadPath
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
handleCacheFailure(error, `Restore Gradle distribution ${versionInfo.version} failed`)
|
||||||
|
}
|
||||||
|
|
||||||
|
core.info(`Gradle distribution ${versionInfo.version} not found in cache. Will download.`)
|
||||||
|
await downloadGradleDistribution(versionInfo, downloadPath)
|
||||||
|
|
||||||
|
if (!isCacheReadOnly()) {
|
||||||
|
try {
|
||||||
|
await cache.saveCache([downloadPath], cacheKey)
|
||||||
|
} catch (error) {
|
||||||
|
handleCacheFailure(error, `Save Gradle distribution ${versionInfo.version} failed`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return downloadPath
|
||||||
|
}
|
||||||
|
|
||||||
|
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})`)
|
||||||
|
}
|
||||||
|
|
||||||
|
function executableFrom(installDir: string): string {
|
||||||
|
return path.join(installDir, 'bin', `${gradlew.installScriptFilename()}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function httpGetGradleVersion(url: string): Promise<GradleVersionInfo> {
|
||||||
|
return JSON.parse(await httpGetString(url))
|
||||||
|
}
|
||||||
|
|
||||||
|
async function httpGetGradleVersions(url: string): Promise<GradleVersionInfo[]> {
|
||||||
|
return JSON.parse(await httpGetString(url))
|
||||||
|
}
|
||||||
|
|
||||||
|
async function httpGetString(url: string): Promise<string> {
|
||||||
|
const httpClient = new httpm.HttpClient('gradle/gradle-build-action')
|
||||||
|
const response = await httpClient.get(url)
|
||||||
|
return response.readBody()
|
||||||
|
}
|
||||||
|
|
||||||
|
interface GradleVersionInfo {
|
||||||
|
version: string
|
||||||
|
downloadUrl: string
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
import org.gradle.tooling.events.*
|
||||||
|
import org.gradle.tooling.events.task.*
|
||||||
|
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 {
|
||||||
|
def projectTracker = gradle.sharedServices.registerIfAbsent("gradle-build-action-buildResultsRecorder", BuildResultsRecorder, { spec ->
|
||||||
|
spec.getParameters().getRootProjectName().set(gradle.rootProject.name)
|
||||||
|
spec.getParameters().getRootProjectDir().set(gradle.rootProject.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)
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class BuildResultsRecorder implements BuildService<BuildResultsRecorder.Params>, OperationCompletionListener, AutoCloseable {
|
||||||
|
private boolean buildFailed = false
|
||||||
|
interface Params extends BuildServiceParameters {
|
||||||
|
Property<String> getRootProjectName()
|
||||||
|
Property<String> getRootProjectDir()
|
||||||
|
Property<String> getRequestedTasks()
|
||||||
|
Property<String> getGradleHomeDir()
|
||||||
|
Property<String> getInvocationId()
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onFinish(FinishEvent finishEvent) {
|
||||||
|
if (finishEvent instanceof TaskFinishEvent && finishEvent.result instanceof TaskFailureResult) {
|
||||||
|
buildFailed = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
def buildResults = [
|
||||||
|
rootProjectName: getParameters().getRootProjectName().get(),
|
||||||
|
rootProjectDir: getParameters().getRootProjectDir().get(),
|
||||||
|
requestedTasks: getParameters().getRequestedTasks().get(),
|
||||||
|
gradleVersion: GradleVersion.current().version,
|
||||||
|
gradleHomeDir: getParameters().getGradleHomeDir().get(),
|
||||||
|
buildFailed: buildFailed,
|
||||||
|
buildScanUri: null,
|
||||||
|
buildScanFailed: false
|
||||||
|
]
|
||||||
|
|
||||||
|
def runnerTempDir = System.getenv("RUNNER_TEMP")
|
||||||
|
def githubActionStep = System.getenv("GITHUB_ACTION")
|
||||||
|
if (!runnerTempDir || !githubActionStep) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
def buildResultsDir = new File(runnerTempDir, ".build-results")
|
||||||
|
buildResultsDir.mkdirs()
|
||||||
|
def buildResultsFile = new File(buildResultsDir, githubActionStep + getParameters().getInvocationId().get() + ".json")
|
||||||
|
if (!buildResultsFile.exists()) {
|
||||||
|
buildResultsFile << groovy.json.JsonOutput.toJson(buildResults)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
134
src/resources/init-scripts/build-result-capture.init.gradle
Normal file
134
src/resources/init-scripts/build-result-capture.init.gradle
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
/*
|
||||||
|
* Capture information for each executed Gradle build to display in the job summary.
|
||||||
|
*/
|
||||||
|
import org.gradle.util.GradleVersion
|
||||||
|
|
||||||
|
// Only run against root build. Do not run against included builds.
|
||||||
|
def isTopLevelBuild = gradle.getParent() == null
|
||||||
|
if (isTopLevelBuild) {
|
||||||
|
def version = GradleVersion.current().baseVersion
|
||||||
|
|
||||||
|
def atLeastGradle3 = version >= GradleVersion.version("3.0")
|
||||||
|
def atLeastGradle6 = version >= GradleVersion.version("6.0")
|
||||||
|
|
||||||
|
def invocationId = "-${System.currentTimeMillis()}"
|
||||||
|
|
||||||
|
if (atLeastGradle6) {
|
||||||
|
def useBuildService = version >= GradleVersion.version("6.6")
|
||||||
|
settingsEvaluated { settings ->
|
||||||
|
// The `buildScanPublished` hook is the only way to capture the build scan URI.
|
||||||
|
if (settings.pluginManager.hasPlugin("com.gradle.enterprise")) {
|
||||||
|
captureUsingBuildScanPublished(settings.extensions["gradleEnterprise"].buildScan, settings.rootProject, invocationId)
|
||||||
|
}
|
||||||
|
// We also need to add hooks in case the plugin is applied but no build scan is published
|
||||||
|
// The `buildScanPublished` results will NOT be overwritten by these calls
|
||||||
|
if (useBuildService) {
|
||||||
|
captureUsingBuildService(settings, invocationId)
|
||||||
|
} else {
|
||||||
|
captureUsingBuildFinished(gradle, invocationId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (atLeastGradle3) {
|
||||||
|
projectsEvaluated { gradle ->
|
||||||
|
if (gradle.rootProject.pluginManager.hasPlugin("com.gradle.build-scan")) {
|
||||||
|
captureUsingBuildScanPublished(gradle.rootProject.extensions["buildScan"], gradle.rootProject, invocationId)
|
||||||
|
}
|
||||||
|
// Always attempt to capture in buildFinished in case the plugin is applied but no build scan is published
|
||||||
|
// The `buildScanPublished` results will NOT be overwritten by this call
|
||||||
|
captureUsingBuildFinished(gradle, invocationId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def captureUsingBuildScanPublished(buildScanExtension, rootProject, invocationId) {
|
||||||
|
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 githubOutput = System.getenv("GITHUB_OUTPUT")
|
||||||
|
if (githubOutput) {
|
||||||
|
new File(githubOutput) << "build-scan-url=${buildScan.buildScanUri}\n"
|
||||||
|
} else {
|
||||||
|
// Retained for compatibility with older GitHub Enterprise versions
|
||||||
|
println("::set-output name=build-scan-url::${buildScan.buildScanUri}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onError { error ->
|
||||||
|
buildResults.setBuildScanFailed()
|
||||||
|
buildResults.writeToResultsFile(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def captureUsingBuildFinished(gradle, invocationId) {
|
||||||
|
gradle.buildFinished { result ->
|
||||||
|
def buildResults = new BuildResults(invocationId, gradle, gradle.rootProject)
|
||||||
|
buildResults.setBuildResult(result)
|
||||||
|
buildResults.writeToResultsFile(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def captureUsingBuildService(settings, invocationId) {
|
||||||
|
gradle.ext.invocationId = invocationId
|
||||||
|
apply from: 'build-result-capture-service.plugin.groovy'
|
||||||
|
}
|
||||||
|
|
||||||
|
class BuildResults {
|
||||||
|
def invocationId
|
||||||
|
def buildResults
|
||||||
|
|
||||||
|
BuildResults(String invocationId, def gradle, def rootProject) {
|
||||||
|
this.invocationId = invocationId
|
||||||
|
buildResults = [
|
||||||
|
rootProjectName: rootProject.name,
|
||||||
|
rootProjectDir: rootProject.projectDir.absolutePath,
|
||||||
|
requestedTasks: gradle.startParameter.taskNames.join(" "),
|
||||||
|
gradleVersion: GradleVersion.current().version,
|
||||||
|
gradleHomeDir: gradle.gradleHomeDir.absolutePath,
|
||||||
|
buildFailed: false,
|
||||||
|
buildScanUri: null,
|
||||||
|
buildScanFailed: false
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
def setBuildResult(def result) {
|
||||||
|
buildResults['buildFailed'] = result.failure != null
|
||||||
|
}
|
||||||
|
|
||||||
|
def setBuildScanUri(def buildScanUrl) {
|
||||||
|
buildResults['buildScanUri'] = buildScanUrl
|
||||||
|
}
|
||||||
|
|
||||||
|
def setBuildScanFailed() {
|
||||||
|
buildResults['buildScanFailed'] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
def writeToResultsFile(boolean overwrite) {
|
||||||
|
def runnerTempDir = System.getenv("RUNNER_TEMP")
|
||||||
|
def githubActionStep = System.getenv("GITHUB_ACTION")
|
||||||
|
if (!runnerTempDir || !githubActionStep) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
def buildResultsDir = new File(runnerTempDir, ".build-results")
|
||||||
|
buildResultsDir.mkdirs()
|
||||||
|
def buildResultsFile = new File(buildResultsDir, githubActionStep + invocationId + ".json")
|
||||||
|
|
||||||
|
// Overwrite any contents written by buildFinished or build service, since this result is a superset.
|
||||||
|
if (buildResultsFile.exists()) {
|
||||||
|
if (overwrite) {
|
||||||
|
buildResultsFile.text = groovy.json.JsonOutput.toJson(buildResults)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
buildResultsFile << groovy.json.JsonOutput.toJson(buildResults)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
95
src/setup-gradle.ts
Normal file
95
src/setup-gradle.ts
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
import * as core from '@actions/core'
|
||||||
|
import * as exec from '@actions/exec'
|
||||||
|
import {SUMMARY_ENV_VAR} from '@actions/core/lib/summary'
|
||||||
|
import * as path from 'path'
|
||||||
|
import * as os from 'os'
|
||||||
|
import * as caches from './caches'
|
||||||
|
|
||||||
|
import {logJobSummary, writeJobSummary} from './job-summary'
|
||||||
|
import {loadBuildResults} from './build-results'
|
||||||
|
import {CacheListener} from './cache-reporting'
|
||||||
|
import {DaemonController} from './daemon-controller'
|
||||||
|
|
||||||
|
const GRADLE_SETUP_VAR = 'GRADLE_BUILD_ACTION_SETUP_COMPLETED'
|
||||||
|
const GRADLE_USER_HOME = 'GRADLE_USER_HOME'
|
||||||
|
const CACHE_LISTENER = 'CACHE_LISTENER'
|
||||||
|
const JOB_SUMMARY_ENABLED_PARAMETER = 'generate-job-summary'
|
||||||
|
|
||||||
|
function shouldGenerateJobSummary(): boolean {
|
||||||
|
// Check if Job Summary is supported on this platform
|
||||||
|
if (!process.env[SUMMARY_ENV_VAR]) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return core.getBooleanInput(JOB_SUMMARY_ENABLED_PARAMETER)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function setup(buildRootDirectory: string): Promise<void> {
|
||||||
|
const gradleUserHome = await determineGradleUserHome(buildRootDirectory)
|
||||||
|
|
||||||
|
// Bypass setup on all but first action step in workflow.
|
||||||
|
if (process.env[GRADLE_SETUP_VAR]) {
|
||||||
|
core.info('Gradle setup only performed on first gradle-build-action step in workflow.')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Record setup complete: visible to all subsequent actions and prevents duplicate setup
|
||||||
|
core.exportVariable(GRADLE_SETUP_VAR, true)
|
||||||
|
// Record setup complete: visible in post-action, to control action completion
|
||||||
|
core.saveState(GRADLE_SETUP_VAR, true)
|
||||||
|
|
||||||
|
// Save the Gradle User Home for use in the post-action step.
|
||||||
|
core.saveState(GRADLE_USER_HOME, gradleUserHome)
|
||||||
|
|
||||||
|
const cacheListener = new CacheListener()
|
||||||
|
await caches.restore(gradleUserHome, cacheListener)
|
||||||
|
|
||||||
|
core.saveState(CACHE_LISTENER, cacheListener.stringify())
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function complete(): Promise<void> {
|
||||||
|
if (!core.getState(GRADLE_SETUP_VAR)) {
|
||||||
|
core.info('Gradle setup post-action only performed for first gradle-build-action step in workflow.')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
core.info('In final post-action step, saving state and writing summary')
|
||||||
|
|
||||||
|
const buildResults = loadBuildResults()
|
||||||
|
|
||||||
|
const gradleUserHome = core.getState(GRADLE_USER_HOME)
|
||||||
|
const cacheListener: CacheListener = CacheListener.rehydrate(core.getState(CACHE_LISTENER))
|
||||||
|
const daemonController = new DaemonController(buildResults)
|
||||||
|
|
||||||
|
await caches.save(gradleUserHome, cacheListener, daemonController)
|
||||||
|
|
||||||
|
if (shouldGenerateJobSummary()) {
|
||||||
|
await writeJobSummary(buildResults, cacheListener)
|
||||||
|
} else {
|
||||||
|
logJobSummary(buildResults, cacheListener)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function determineGradleUserHome(rootDir: string): Promise<string> {
|
||||||
|
const customGradleUserHome = process.env['GRADLE_USER_HOME']
|
||||||
|
if (customGradleUserHome) {
|
||||||
|
return path.resolve(rootDir, customGradleUserHome)
|
||||||
|
}
|
||||||
|
|
||||||
|
return path.resolve(await determineUserHome(), '.gradle')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Different values can be returned by os.homedir() in Javascript and System.getProperty('user.home') in Java.
|
||||||
|
* In order to determine the correct Gradle User Home, we ask Java for the user home instead of using os.homedir().
|
||||||
|
*/
|
||||||
|
async function determineUserHome(): Promise<string> {
|
||||||
|
const output = await exec.getExecOutput('java', ['-XshowSettings:properties', '-version'], {silent: true})
|
||||||
|
const regex = /user\.home = (\S*)/i
|
||||||
|
const found = output.stderr.match(regex)
|
||||||
|
if (found == null || found.length <= 1) {
|
||||||
|
core.info('Could not determine user.home from java -version output. Using os.homedir().')
|
||||||
|
return os.homedir()
|
||||||
|
}
|
||||||
|
const userHome = found[1]
|
||||||
|
core.debug(`Determined user.home from java -version output: '${userHome}'`)
|
||||||
|
return userHome
|
||||||
|
}
|
2
test/init-scripts/.gitignore
vendored
Normal file
2
test/init-scripts/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
build
|
||||||
|
.gradle
|
29
test/init-scripts/build.gradle
Normal file
29
test/init-scripts/build.gradle
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
plugins {
|
||||||
|
id 'groovy'
|
||||||
|
}
|
||||||
|
|
||||||
|
java {
|
||||||
|
toolchain {
|
||||||
|
languageVersion = JavaLanguageVersion.of(8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
testImplementation gradleTestKit()
|
||||||
|
testImplementation 'org.spockframework:spock-core:2.3-groovy-3.0'
|
||||||
|
testImplementation('org.spockframework:spock-junit4:2.3-groovy-3.0')
|
||||||
|
|
||||||
|
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.14.2'
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
test {
|
||||||
|
useJUnitPlatform()
|
||||||
|
}
|
BIN
test/init-scripts/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
test/init-scripts/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
5
test/init-scripts/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
5
test/init-scripts/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
234
test/init-scripts/gradlew
vendored
Executable file
234
test/init-scripts/gradlew
vendored
Executable file
@ -0,0 +1,234 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright © 2015-2021 the original authors.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
#
|
||||||
|
# Gradle start up script for POSIX generated by Gradle.
|
||||||
|
#
|
||||||
|
# Important for running:
|
||||||
|
#
|
||||||
|
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||||
|
# noncompliant, but you have some other compliant shell such as ksh or
|
||||||
|
# bash, then to run this script, type that shell name before the whole
|
||||||
|
# command line, like:
|
||||||
|
#
|
||||||
|
# ksh Gradle
|
||||||
|
#
|
||||||
|
# Busybox and similar reduced shells will NOT work, because this script
|
||||||
|
# requires all of these POSIX shell features:
|
||||||
|
# * functions;
|
||||||
|
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||||
|
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||||
|
# * compound commands having a testable exit status, especially «case»;
|
||||||
|
# * various built-in commands including «command», «set», and «ulimit».
|
||||||
|
#
|
||||||
|
# Important for patching:
|
||||||
|
#
|
||||||
|
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||||
|
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||||
|
#
|
||||||
|
# The "traditional" practice of packing multiple parameters into a
|
||||||
|
# space-separated string is a well documented source of bugs and security
|
||||||
|
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||||
|
# options in "$@", and eventually passing that to Java.
|
||||||
|
#
|
||||||
|
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||||
|
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||||
|
# see the in-line comments for details.
|
||||||
|
#
|
||||||
|
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||||
|
# Darwin, MinGW, and NonStop.
|
||||||
|
#
|
||||||
|
# (3) This script is generated from the Groovy template
|
||||||
|
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||||
|
# within the Gradle project.
|
||||||
|
#
|
||||||
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
|
#
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Attempt to set APP_HOME
|
||||||
|
|
||||||
|
# Resolve links: $0 may be a link
|
||||||
|
app_path=$0
|
||||||
|
|
||||||
|
# Need this for daisy-chained symlinks.
|
||||||
|
while
|
||||||
|
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||||
|
[ -h "$app_path" ]
|
||||||
|
do
|
||||||
|
ls=$( ls -ld "$app_path" )
|
||||||
|
link=${ls#*' -> '}
|
||||||
|
case $link in #(
|
||||||
|
/*) app_path=$link ;; #(
|
||||||
|
*) app_path=$APP_HOME$link ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||||
|
|
||||||
|
APP_NAME="Gradle"
|
||||||
|
APP_BASE_NAME=${0##*/}
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
|
MAX_FD=maximum
|
||||||
|
|
||||||
|
warn () {
|
||||||
|
echo "$*"
|
||||||
|
} >&2
|
||||||
|
|
||||||
|
die () {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
} >&2
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
nonstop=false
|
||||||
|
case "$( uname )" in #(
|
||||||
|
CYGWIN* ) cygwin=true ;; #(
|
||||||
|
Darwin* ) darwin=true ;; #(
|
||||||
|
MSYS* | MINGW* ) msys=true ;; #(
|
||||||
|
NONSTOP* ) nonstop=true ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
|
# Determine the Java command to use to start the JVM.
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||||
|
else
|
||||||
|
JAVACMD=$JAVA_HOME/bin/java
|
||||||
|
fi
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD=java
|
||||||
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Increase the maximum file descriptors if we can.
|
||||||
|
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||||
|
case $MAX_FD in #(
|
||||||
|
max*)
|
||||||
|
MAX_FD=$( ulimit -H -n ) ||
|
||||||
|
warn "Could not query maximum file descriptor limit"
|
||||||
|
esac
|
||||||
|
case $MAX_FD in #(
|
||||||
|
'' | soft) :;; #(
|
||||||
|
*)
|
||||||
|
ulimit -n "$MAX_FD" ||
|
||||||
|
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Collect all arguments for the java command, stacking in reverse order:
|
||||||
|
# * args from the command line
|
||||||
|
# * the main class name
|
||||||
|
# * -classpath
|
||||||
|
# * -D...appname settings
|
||||||
|
# * --module-path (only if needed)
|
||||||
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||||
|
|
||||||
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||||
|
if "$cygwin" || "$msys" ; then
|
||||||
|
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||||
|
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||||
|
|
||||||
|
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||||
|
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
for arg do
|
||||||
|
if
|
||||||
|
case $arg in #(
|
||||||
|
-*) false ;; # don't mess with options #(
|
||||||
|
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||||
|
[ -e "$t" ] ;; #(
|
||||||
|
*) false ;;
|
||||||
|
esac
|
||||||
|
then
|
||||||
|
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||||
|
fi
|
||||||
|
# Roll the args list around exactly as many times as the number of
|
||||||
|
# args, so each arg winds up back in the position where it started, but
|
||||||
|
# possibly modified.
|
||||||
|
#
|
||||||
|
# NB: a `for` loop captures its iteration list before it begins, so
|
||||||
|
# changing the positional parameters here affects neither the number of
|
||||||
|
# iterations, nor the values presented in `arg`.
|
||||||
|
shift # remove old arg
|
||||||
|
set -- "$@" "$arg" # push replacement arg
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Collect all arguments for the java command;
|
||||||
|
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||||
|
# shell script including quotes and variable substitutions, so put them in
|
||||||
|
# double quotes to make sure that they get re-expanded; and
|
||||||
|
# * put everything else in single quotes, so that it's not re-expanded.
|
||||||
|
|
||||||
|
set -- \
|
||||||
|
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||||
|
-classpath "$CLASSPATH" \
|
||||||
|
org.gradle.wrapper.GradleWrapperMain \
|
||||||
|
"$@"
|
||||||
|
|
||||||
|
# Use "xargs" to parse quoted args.
|
||||||
|
#
|
||||||
|
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||||
|
#
|
||||||
|
# In Bash we could simply go:
|
||||||
|
#
|
||||||
|
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||||
|
# set -- "${ARGS[@]}" "$@"
|
||||||
|
#
|
||||||
|
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||||
|
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||||
|
# character that might be a shell metacharacter, then use eval to reverse
|
||||||
|
# that process (while maintaining the separation between arguments), and wrap
|
||||||
|
# the whole thing up as a single "set" statement.
|
||||||
|
#
|
||||||
|
# This will of course break if any of these variables contains a newline or
|
||||||
|
# an unmatched quote.
|
||||||
|
#
|
||||||
|
|
||||||
|
eval "set -- $(
|
||||||
|
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||||
|
xargs -n1 |
|
||||||
|
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||||
|
tr '\n' ' '
|
||||||
|
)" '"$@"'
|
||||||
|
|
||||||
|
exec "$JAVACMD" "$@"
|
89
test/init-scripts/gradlew.bat
vendored
Normal file
89
test/init-scripts/gradlew.bat
vendored
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
@rem
|
||||||
|
@rem Copyright 2015 the original author or authors.
|
||||||
|
@rem
|
||||||
|
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@rem you may not use this file except in compliance with the License.
|
||||||
|
@rem You may obtain a copy of the License at
|
||||||
|
@rem
|
||||||
|
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
@rem
|
||||||
|
@rem Unless required by applicable law or agreed to in writing, software
|
||||||
|
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@rem See the License for the specific language governing permissions and
|
||||||
|
@rem limitations under the License.
|
||||||
|
@rem
|
||||||
|
|
||||||
|
@if "%DEBUG%" == "" @echo off
|
||||||
|
@rem ##########################################################################
|
||||||
|
@rem
|
||||||
|
@rem Gradle startup script for Windows
|
||||||
|
@rem
|
||||||
|
@rem ##########################################################################
|
||||||
|
|
||||||
|
@rem Set local scope for the variables with windows NT shell
|
||||||
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
|
set DIRNAME=%~dp0
|
||||||
|
if "%DIRNAME%" == "" set DIRNAME=.
|
||||||
|
set APP_BASE_NAME=%~n0
|
||||||
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||||
|
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||||
|
|
||||||
|
@rem Find java.exe
|
||||||
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
|
set JAVA_EXE=java.exe
|
||||||
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
|
if "%ERRORLEVEL%" == "0" goto 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.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:findJavaFromJavaHome
|
||||||
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
|
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.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:execute
|
||||||
|
@rem Setup the command line
|
||||||
|
|
||||||
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
|
@rem Execute Gradle
|
||||||
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||||
|
|
||||||
|
:end
|
||||||
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||||
|
|
||||||
|
:fail
|
||||||
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
|
rem the _cmd.exe /c_ return code!
|
||||||
|
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||||
|
exit /b 1
|
||||||
|
|
||||||
|
:mainEnd
|
||||||
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
|
:omega
|
14
test/init-scripts/settings.gradle
Normal file
14
test/init-scripts/settings.gradle
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
plugins {
|
||||||
|
id "com.gradle.enterprise" version "3.12.6"
|
||||||
|
id "com.gradle.common-custom-user-data-gradle-plugin" version "1.10"
|
||||||
|
}
|
||||||
|
|
||||||
|
gradleEnterprise {
|
||||||
|
buildScan {
|
||||||
|
termsOfServiceUrl = "https://gradle.com/terms-of-service"
|
||||||
|
termsOfServiceAgree = "yes"
|
||||||
|
publishAlways()
|
||||||
|
uploadInBackground = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rootProject.name = 'test-init-scripts'
|
@ -0,0 +1,246 @@
|
|||||||
|
package com.gradle.gradlebuildaction
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonFactory
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
|
import com.fasterxml.jackson.dataformat.smile.SmileFactory
|
||||||
|
import org.gradle.testkit.runner.BuildResult
|
||||||
|
import org.gradle.testkit.runner.GradleRunner
|
||||||
|
import org.gradle.testkit.runner.internal.DefaultGradleRunner
|
||||||
|
import org.gradle.util.GradleVersion
|
||||||
|
import ratpack.groovy.test.embed.GroovyEmbeddedApp
|
||||||
|
import spock.lang.AutoCleanup
|
||||||
|
import spock.lang.Specification
|
||||||
|
import spock.lang.TempDir
|
||||||
|
|
||||||
|
import java.nio.file.Files
|
||||||
|
import java.util.zip.GZIPOutputStream
|
||||||
|
|
||||||
|
class BaseInitScriptTest extends Specification {
|
||||||
|
|
||||||
|
static final TestGradleVersion GRADLE_3_X = new TestGradleVersion(GradleVersion.version('3.5.1'), 7, 9)
|
||||||
|
static final TestGradleVersion GRADLE_4_X = new TestGradleVersion(GradleVersion.version('4.10.3'), 7, 10)
|
||||||
|
static final TestGradleVersion GRADLE_5_X = new TestGradleVersion(GradleVersion.version('5.6.4'), 8, 12)
|
||||||
|
static final TestGradleVersion GRADLE_6_NO_BUILD_SERVICE = new TestGradleVersion(GradleVersion.version('6.5.1'), 8, 14)
|
||||||
|
static final TestGradleVersion GRADLE_6_X = new TestGradleVersion(GradleVersion.version('6.9.4'), 8, 15)
|
||||||
|
static final TestGradleVersion GRADLE_7_X = new TestGradleVersion(GradleVersion.version('7.6.1'), 8, 19)
|
||||||
|
static final TestGradleVersion GRADLE_8_X = new TestGradleVersion(GradleVersion.version('8.0.2'), 8, 19)
|
||||||
|
|
||||||
|
static final List<TestGradleVersion> ALL_VERSIONS = [
|
||||||
|
GRADLE_3_X, // First version where TestKit supports environment variables
|
||||||
|
GRADLE_4_X,
|
||||||
|
GRADLE_5_X,
|
||||||
|
GRADLE_6_NO_BUILD_SERVICE, // Last version without build service support
|
||||||
|
GRADLE_6_X,
|
||||||
|
GRADLE_7_X,
|
||||||
|
GRADLE_8_X,
|
||||||
|
]
|
||||||
|
|
||||||
|
static final List<TestGradleVersion> CONFIGURATION_CACHE_VERSIONS =
|
||||||
|
[GRADLE_7_X, GRADLE_8_X]
|
||||||
|
|
||||||
|
static final String PUBLIC_BUILD_SCAN_ID = 'i2wepy2gr7ovw'
|
||||||
|
static final String DEFAULT_SCAN_UPLOAD_TOKEN = 'scan-upload-token'
|
||||||
|
static final String ROOT_PROJECT_NAME = 'test-init-script'
|
||||||
|
boolean failScanUpload = false
|
||||||
|
|
||||||
|
File settingsFile
|
||||||
|
File buildFile
|
||||||
|
|
||||||
|
@TempDir
|
||||||
|
File testProjectDir
|
||||||
|
|
||||||
|
@AutoCleanup
|
||||||
|
def mockScansServer = GroovyEmbeddedApp.of {
|
||||||
|
def jsonWriter = new ObjectMapper(new JsonFactory()).writer()
|
||||||
|
def smileWriter = new ObjectMapper(new SmileFactory()).writer()
|
||||||
|
|
||||||
|
handlers {
|
||||||
|
post('in/:gradleVersion/:pluginVersion') {
|
||||||
|
if (failScanUpload) {
|
||||||
|
context.response.status(401).send()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
def scanUrlString = "${mockScansServer.address}s/$PUBLIC_BUILD_SCAN_ID"
|
||||||
|
def body = [
|
||||||
|
id : PUBLIC_BUILD_SCAN_ID,
|
||||||
|
scanUrl: scanUrlString.toString(),
|
||||||
|
]
|
||||||
|
def out = new ByteArrayOutputStream()
|
||||||
|
new GZIPOutputStream(out).withStream { smileWriter.writeValue(it, body) }
|
||||||
|
context.response
|
||||||
|
.contentType('application/vnd.gradle.scan-ack')
|
||||||
|
.send(out.toByteArray())
|
||||||
|
}
|
||||||
|
prefix('scans/publish') {
|
||||||
|
post('gradle/:pluginVersion/token') {
|
||||||
|
if (failScanUpload) {
|
||||||
|
context.response.status(401).send()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
def pluginVersion = context.pathTokens.pluginVersion
|
||||||
|
def scanUrlString = "${mockScansServer.address}s/$PUBLIC_BUILD_SCAN_ID"
|
||||||
|
def body = [
|
||||||
|
id : PUBLIC_BUILD_SCAN_ID,
|
||||||
|
scanUrl : scanUrlString.toString(),
|
||||||
|
scanUploadUrl : "${mockScansServer.address.toString()}scans/publish/gradle/$pluginVersion/upload".toString(),
|
||||||
|
scanUploadToken: DEFAULT_SCAN_UPLOAD_TOKEN
|
||||||
|
]
|
||||||
|
context.response
|
||||||
|
.contentType('application/vnd.gradle.scan-ack+json')
|
||||||
|
.send(jsonWriter.writeValueAsBytes(body))
|
||||||
|
}
|
||||||
|
post('gradle/:pluginVersion/upload') {
|
||||||
|
if (failScanUpload) {
|
||||||
|
context.response.status(401).send()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
context.request.getBody(1024 * 1024 * 10).then {
|
||||||
|
context.response
|
||||||
|
.contentType('application/vnd.gradle.scan-upload-ack+json')
|
||||||
|
.send()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
notFound()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def setup() {
|
||||||
|
settingsFile = new File(testProjectDir, 'settings.gradle')
|
||||||
|
buildFile = new File(testProjectDir, 'build.gradle')
|
||||||
|
|
||||||
|
File srcInitScriptsDir = new File("../../src/resources/init-scripts")
|
||||||
|
File targetInitScriptsDir = new File(testProjectDir, "initScripts")
|
||||||
|
targetInitScriptsDir.mkdirs()
|
||||||
|
|
||||||
|
for (File srcInitScript : srcInitScriptsDir.listFiles()) {
|
||||||
|
File targetInitScript = new File(targetInitScriptsDir, srcInitScript.name)
|
||||||
|
Files.copy(srcInitScript.toPath(), targetInitScript.toPath())
|
||||||
|
}
|
||||||
|
settingsFile << "rootProject.name = '${ROOT_PROJECT_NAME}'\n"
|
||||||
|
buildFile << ''
|
||||||
|
}
|
||||||
|
|
||||||
|
def declareGePluginApplication(GradleVersion gradleVersion) {
|
||||||
|
settingsFile.text = maybeAddPluginsToSettings(gradleVersion) + settingsFile.text
|
||||||
|
buildFile.text = maybeAddPluginsToRootProject(gradleVersion) + buildFile.text
|
||||||
|
}
|
||||||
|
|
||||||
|
String maybeAddPluginsToSettings(GradleVersion gradleVersion) {
|
||||||
|
if (gradleVersion < GradleVersion.version('5.0')) {
|
||||||
|
'' // applied in build.gradle
|
||||||
|
} else if (gradleVersion < GradleVersion.version('6.0')) {
|
||||||
|
'' // applied in build.gradle
|
||||||
|
} else {
|
||||||
|
"""
|
||||||
|
plugins {
|
||||||
|
id 'com.gradle.enterprise' version '3.12.6'
|
||||||
|
}
|
||||||
|
gradleEnterprise {
|
||||||
|
server = '$mockScansServer.address'
|
||||||
|
buildScan {
|
||||||
|
publishAlways()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String maybeAddPluginsToRootProject(GradleVersion gradleVersion) {
|
||||||
|
if (gradleVersion < GradleVersion.version('5.0')) {
|
||||||
|
"""
|
||||||
|
plugins {
|
||||||
|
id 'com.gradle.build-scan' version '1.16'
|
||||||
|
}
|
||||||
|
buildScan {
|
||||||
|
server = '$mockScansServer.address'
|
||||||
|
publishAlways()
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
} else if (gradleVersion < GradleVersion.version('6.0')) {
|
||||||
|
"""
|
||||||
|
plugins {
|
||||||
|
id 'com.gradle.build-scan' version '3.12.6'
|
||||||
|
}
|
||||||
|
gradleEnterprise {
|
||||||
|
server = '$mockScansServer.address'
|
||||||
|
buildScan {
|
||||||
|
publishAlways()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
} else {
|
||||||
|
'' // applied in settings.gradle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def addFailingTaskToBuild() {
|
||||||
|
buildFile << '''
|
||||||
|
task expectFailure {
|
||||||
|
doLast {
|
||||||
|
throw new RuntimeException("Expected to fail")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'''
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildResult run(List<String> args, String initScript, GradleVersion gradleVersion = GradleVersion.current(), List<String> jvmArgs = [], Map<String, String> envVars = [:]) {
|
||||||
|
createRunner(initScript, args, gradleVersion, jvmArgs, envVars).build()
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildResult runAndFail(List<String> args, String initScript, GradleVersion gradleVersion = GradleVersion.current(), List<String> jvmArgs = [], Map<String, String> envVars = [:]) {
|
||||||
|
createRunner(initScript, args, gradleVersion, jvmArgs, envVars).buildAndFail()
|
||||||
|
}
|
||||||
|
|
||||||
|
GradleRunner createRunner(String initScript, List<String> args, GradleVersion gradleVersion = GradleVersion.current(), List<String> jvmArgs = [], Map<String, String> envVars = [:]) {
|
||||||
|
File initScriptsDir = new File(testProjectDir, "initScripts")
|
||||||
|
args << '-I' << new File(initScriptsDir, initScript).absolutePath
|
||||||
|
|
||||||
|
envVars.putIfAbsent('RUNNER_TEMP', testProjectDir.absolutePath)
|
||||||
|
envVars.putIfAbsent('GITHUB_ACTION', 'github-step-id')
|
||||||
|
|
||||||
|
def runner = ((DefaultGradleRunner) GradleRunner.create())
|
||||||
|
.withJvmArguments(jvmArgs)
|
||||||
|
.withGradleVersion(gradleVersion.version)
|
||||||
|
.withProjectDir(testProjectDir)
|
||||||
|
.withArguments(args)
|
||||||
|
.withEnvironment(envVars)
|
||||||
|
.forwardOutput()
|
||||||
|
|
||||||
|
runner
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class TestGradleVersion {
|
||||||
|
|
||||||
|
final GradleVersion gradleVersion
|
||||||
|
private final Integer jdkMin
|
||||||
|
private final Integer jdkMax
|
||||||
|
|
||||||
|
TestGradleVersion(GradleVersion gradleVersion, Integer jdkMin, Integer jdkMax) {
|
||||||
|
this.gradleVersion = gradleVersion
|
||||||
|
this.jdkMin = jdkMin
|
||||||
|
this.jdkMax = jdkMax
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isCompatibleWithCurrentJvm() {
|
||||||
|
def jvmVersion = getJvmVersion()
|
||||||
|
jdkMin <= jvmVersion && jvmVersion <= jdkMax
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getJvmVersion() {
|
||||||
|
String version = System.getProperty('java.version')
|
||||||
|
if (version.startsWith('1.')) {
|
||||||
|
Integer.parseInt(version.substring(2, 3))
|
||||||
|
} else {
|
||||||
|
Integer.parseInt(version.substring(0, version.indexOf('.')))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String toString() {
|
||||||
|
return "Gradle " + gradleVersion.version
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,172 @@
|
|||||||
|
package com.gradle.gradlebuildaction
|
||||||
|
|
||||||
|
import groovy.json.JsonSlurper
|
||||||
|
|
||||||
|
import static org.junit.Assume.assumeTrue
|
||||||
|
|
||||||
|
class TestBuildResultRecorder extends BaseInitScriptTest {
|
||||||
|
def initScript = 'build-result-capture.init.gradle'
|
||||||
|
|
||||||
|
def "produces build results file for build with #testGradleVersion"() {
|
||||||
|
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
||||||
|
|
||||||
|
when:
|
||||||
|
run(['help'], initScript, testGradleVersion.gradleVersion)
|
||||||
|
|
||||||
|
then:
|
||||||
|
assertResults('help', testGradleVersion, false, false)
|
||||||
|
|
||||||
|
where:
|
||||||
|
testGradleVersion << ALL_VERSIONS
|
||||||
|
}
|
||||||
|
|
||||||
|
def "produces build results file for failing build with #testGradleVersion"() {
|
||||||
|
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
||||||
|
|
||||||
|
when:
|
||||||
|
addFailingTaskToBuild()
|
||||||
|
runAndFail(['expectFailure'], initScript, testGradleVersion.gradleVersion)
|
||||||
|
|
||||||
|
then:
|
||||||
|
assertResults('expectFailure', testGradleVersion, true, false)
|
||||||
|
|
||||||
|
where:
|
||||||
|
testGradleVersion << ALL_VERSIONS
|
||||||
|
}
|
||||||
|
|
||||||
|
def "produces build results file for build with --configuration-cache on #testGradleVersion"() {
|
||||||
|
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
||||||
|
|
||||||
|
when:
|
||||||
|
run(['help', '--configuration-cache'], initScript, testGradleVersion.gradleVersion)
|
||||||
|
|
||||||
|
then:
|
||||||
|
assertResults('help', testGradleVersion, false, false)
|
||||||
|
assert buildResultFile.delete()
|
||||||
|
|
||||||
|
when:
|
||||||
|
run(['help', '--configuration-cache'], initScript, testGradleVersion.gradleVersion)
|
||||||
|
|
||||||
|
then:
|
||||||
|
assertResults('help', testGradleVersion, false, false)
|
||||||
|
|
||||||
|
where:
|
||||||
|
testGradleVersion << CONFIGURATION_CACHE_VERSIONS
|
||||||
|
}
|
||||||
|
|
||||||
|
def "produces build results file for #testGradleVersion with build scan published"() {
|
||||||
|
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
||||||
|
|
||||||
|
when:
|
||||||
|
declareGePluginApplication(testGradleVersion.gradleVersion)
|
||||||
|
run(['help'], initScript, testGradleVersion.gradleVersion)
|
||||||
|
|
||||||
|
then:
|
||||||
|
assertResults('help', testGradleVersion, false, true)
|
||||||
|
|
||||||
|
where:
|
||||||
|
testGradleVersion << ALL_VERSIONS
|
||||||
|
}
|
||||||
|
|
||||||
|
def "produces build results file for #testGradleVersion with ge-plugin and no build scan published"() {
|
||||||
|
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
||||||
|
|
||||||
|
when:
|
||||||
|
declareGePluginApplication(testGradleVersion.gradleVersion)
|
||||||
|
run(['help', '--no-scan'], initScript, testGradleVersion.gradleVersion)
|
||||||
|
|
||||||
|
then:
|
||||||
|
assertResults('help', testGradleVersion, false, false)
|
||||||
|
|
||||||
|
where:
|
||||||
|
testGradleVersion << ALL_VERSIONS
|
||||||
|
}
|
||||||
|
|
||||||
|
def "produces build results file for failing build on #testGradleVersion with build scan published"() {
|
||||||
|
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
||||||
|
|
||||||
|
when:
|
||||||
|
declareGePluginApplication(testGradleVersion.gradleVersion)
|
||||||
|
addFailingTaskToBuild()
|
||||||
|
runAndFail(['expectFailure'], initScript, testGradleVersion.gradleVersion)
|
||||||
|
|
||||||
|
then:
|
||||||
|
assertResults('expectFailure', testGradleVersion, true, true)
|
||||||
|
|
||||||
|
where:
|
||||||
|
testGradleVersion << ALL_VERSIONS
|
||||||
|
}
|
||||||
|
|
||||||
|
def "produces build results file for build with --configuration-cache on #testGradleVersion with build scan published"() {
|
||||||
|
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
||||||
|
|
||||||
|
when:
|
||||||
|
declareGePluginApplication(testGradleVersion.gradleVersion)
|
||||||
|
run(['help', '--configuration-cache'], initScript, testGradleVersion.gradleVersion)
|
||||||
|
|
||||||
|
then:
|
||||||
|
assertResults('help', testGradleVersion, false, true)
|
||||||
|
assert buildResultFile.delete()
|
||||||
|
|
||||||
|
when:
|
||||||
|
run(['help', '--configuration-cache'], initScript, testGradleVersion.gradleVersion)
|
||||||
|
|
||||||
|
then:
|
||||||
|
assertResults('help', testGradleVersion, false, true)
|
||||||
|
|
||||||
|
where:
|
||||||
|
testGradleVersion << CONFIGURATION_CACHE_VERSIONS
|
||||||
|
}
|
||||||
|
|
||||||
|
def "produces build results file for failing build on #testGradleVersion when build scan publish fails"() {
|
||||||
|
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
||||||
|
|
||||||
|
when:
|
||||||
|
declareGePluginApplication(testGradleVersion.gradleVersion)
|
||||||
|
addFailingTaskToBuild()
|
||||||
|
failScanUpload = true
|
||||||
|
runAndFail(['expectFailure'], initScript, testGradleVersion.gradleVersion)
|
||||||
|
|
||||||
|
then:
|
||||||
|
assertResults('expectFailure', testGradleVersion, true, false, true)
|
||||||
|
|
||||||
|
where:
|
||||||
|
testGradleVersion << ALL_VERSIONS
|
||||||
|
}
|
||||||
|
|
||||||
|
def "produces no build results file when GitHub env vars not set with #testGradleVersion"() {
|
||||||
|
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
||||||
|
|
||||||
|
when:
|
||||||
|
run(['help'], initScript, testGradleVersion.gradleVersion, [], [RUNNER_TEMP: '', GITHUB_ACTION: ''])
|
||||||
|
|
||||||
|
then:
|
||||||
|
def buildResultsDir = new File(testProjectDir, '.build-results')
|
||||||
|
assert !buildResultsDir.exists()
|
||||||
|
|
||||||
|
where:
|
||||||
|
testGradleVersion << ALL_VERSIONS
|
||||||
|
}
|
||||||
|
|
||||||
|
void assertResults(String task, TestGradleVersion testGradleVersion, boolean hasFailure, boolean hasBuildScan, boolean scanUploadFailed = false) {
|
||||||
|
def results = new JsonSlurper().parse(buildResultFile)
|
||||||
|
assert results['rootProjectName'] == ROOT_PROJECT_NAME
|
||||||
|
assert results['rootProjectDir'] == testProjectDir.canonicalPath
|
||||||
|
assert results['requestedTasks'] == task
|
||||||
|
assert results['gradleVersion'] == testGradleVersion.gradleVersion.version
|
||||||
|
assert results['gradleHomeDir'] != null
|
||||||
|
assert results['buildFailed'] == hasFailure
|
||||||
|
assert results['buildScanUri'] == (hasBuildScan ? "${mockScansServer.address}s/${PUBLIC_BUILD_SCAN_ID}" : null)
|
||||||
|
assert results['buildScanFailed'] == scanUploadFailed
|
||||||
|
}
|
||||||
|
|
||||||
|
private File getBuildResultFile() {
|
||||||
|
def buildResultsDir = new File(testProjectDir, '.build-results')
|
||||||
|
assert buildResultsDir.directory
|
||||||
|
assert buildResultsDir.listFiles().size() == 1
|
||||||
|
def resultsFile = buildResultsDir.listFiles()[0]
|
||||||
|
assert resultsFile.name.startsWith('github-step-id')
|
||||||
|
assert resultsFile.text.count('rootProjectName') == 1
|
||||||
|
return resultsFile
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user