mirror of
				https://hub.gitmirror.com/https://github.com/gradle/gradle-build-action
				synced 2025-11-01 02:20:05 +08:00 
			
		
		
		
	Compare commits
	
		
			No commits in common. "main" and "v2.4.1" 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 | ||||
| distributionPath=wrapper/dists | ||||
| distributionSha256Sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d | ||||
| distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip | ||||
| distributionSha256Sum=ff7bf6a86f09b9b2c40bb8f48b25fc19cf2b2664fd1d220cd7ab833ec758d0d7 | ||||
| distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip | ||||
| networkTimeout=10000 | ||||
| validateDistributionUrl=true | ||||
| zipStoreBase=GRADLE_USER_HOME | ||||
| 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 | ||||
| # shellcheck disable=SC2034 | ||||
| APP_BASE_NAME=${0##*/} | ||||
| # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) | ||||
| APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit | ||||
| APP_HOME=$( cd "${APP_HOME:-./}" && 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. | ||||
| MAX_FD=maximum | ||||
| @ -131,13 +133,10 @@ location of your Java installation." | ||||
|     fi | ||||
| else | ||||
|     JAVACMD=java | ||||
|     if ! command -v java >/dev/null 2>&1 | ||||
|     then | ||||
|         die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. | ||||
|     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 | ||||
| fi | ||||
| 
 | ||||
| # Increase the maximum file descriptors if we can. | ||||
| @ -145,7 +144,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then | ||||
|     case $MAX_FD in #( | ||||
|       max*) | ||||
|         # 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 ) || | ||||
|             warn "Could not query maximum file descriptor limit" | ||||
|     esac | ||||
| @ -153,7 +152,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then | ||||
|       '' | soft) :;; #( | ||||
|       *) | ||||
|         # 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" || | ||||
|             warn "Could not set maximum file descriptor limit to $MAX_FD" | ||||
|     esac | ||||
| @ -198,15 +197,11 @@ if "$cygwin" || "$msys" ; then | ||||
|     done | ||||
| fi | ||||
| 
 | ||||
| 
 | ||||
| # 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"' | ||||
| 
 | ||||
| # Collect all arguments for the java command: | ||||
| #   * 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. | ||||
| # 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" \ | ||||
|  | ||||
| @ -43,11 +43,11 @@ set JAVA_EXE=java.exe | ||||
| %JAVA_EXE% -version >NUL 2>&1 | ||||
| if %ERRORLEVEL% equ 0 goto execute | ||||
| 
 | ||||
| echo. 1>&2 | ||||
| echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 | ||||
| echo. 1>&2 | ||||
| echo Please set the JAVA_HOME variable in your environment to match the 1>&2 | ||||
| echo location of your Java installation. 1>&2 | ||||
| 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 | ||||
| 
 | ||||
| @ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe | ||||
| 
 | ||||
| if exist "%JAVA_EXE%" goto execute | ||||
| 
 | ||||
| echo. 1>&2 | ||||
| echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 | ||||
| echo. 1>&2 | ||||
| echo Please set the JAVA_HOME variable in your environment to match the 1>&2 | ||||
| echo location of your Java installation. 1>&2 | ||||
| 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 | ||||
| 
 | ||||
|  | ||||
										
											Binary file not shown.
										
									
								
							| @ -1,8 +1,7 @@ | ||||
| distributionBase=GRADLE_USER_HOME | ||||
| distributionPath=wrapper/dists | ||||
| distributionSha256Sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d | ||||
| distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip | ||||
| distributionSha256Sum=ff7bf6a86f09b9b2c40bb8f48b25fc19cf2b2664fd1d220cd7ab833ec758d0d7 | ||||
| distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip | ||||
| networkTimeout=10000 | ||||
| validateDistributionUrl=true | ||||
| zipStoreBase=GRADLE_USER_HOME | ||||
| 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 | ||||
| # shellcheck disable=SC2034 | ||||
| APP_BASE_NAME=${0##*/} | ||||
| # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) | ||||
| APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit | ||||
| APP_HOME=$( cd "${APP_HOME:-./}" && 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. | ||||
| MAX_FD=maximum | ||||
| @ -131,13 +133,10 @@ location of your Java installation." | ||||
|     fi | ||||
| else | ||||
|     JAVACMD=java | ||||
|     if ! command -v java >/dev/null 2>&1 | ||||
|     then | ||||
|         die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. | ||||
|     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 | ||||
| fi | ||||
| 
 | ||||
| # Increase the maximum file descriptors if we can. | ||||
| @ -145,7 +144,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then | ||||
|     case $MAX_FD in #( | ||||
|       max*) | ||||
|         # 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 ) || | ||||
|             warn "Could not query maximum file descriptor limit" | ||||
|     esac | ||||
| @ -153,7 +152,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then | ||||
|       '' | soft) :;; #( | ||||
|       *) | ||||
|         # 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" || | ||||
|             warn "Could not set maximum file descriptor limit to $MAX_FD" | ||||
|     esac | ||||
| @ -198,15 +197,11 @@ if "$cygwin" || "$msys" ; then | ||||
|     done | ||||
| fi | ||||
| 
 | ||||
| 
 | ||||
| # 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"' | ||||
| 
 | ||||
| # Collect all arguments for the java command: | ||||
| #   * 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. | ||||
| # 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" \ | ||||
|  | ||||
							
								
								
									
										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 | ||||
| if %ERRORLEVEL% equ 0 goto execute | ||||
| 
 | ||||
| echo. 1>&2 | ||||
| echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 | ||||
| echo. 1>&2 | ||||
| echo Please set the JAVA_HOME variable in your environment to match the 1>&2 | ||||
| echo location of your Java installation. 1>&2 | ||||
| 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 | ||||
| 
 | ||||
| @ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe | ||||
| 
 | ||||
| if exist "%JAVA_EXE%" goto execute | ||||
| 
 | ||||
| echo. 1>&2 | ||||
| echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 | ||||
| echo. 1>&2 | ||||
| echo Please set the JAVA_HOME variable in your environment to match the 1>&2 | ||||
| echo location of your Java installation. 1>&2 | ||||
| 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 | ||||
| 
 | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| plugins { | ||||
|     id "com.gradle.enterprise" version "3.16.2" | ||||
|     id "com.gradle.common-custom-user-data-gradle-plugin" version "1.13" | ||||
|     id "com.gradle.enterprise" version "3.12.6" | ||||
|     id "com.gradle.common-custom-user-data-gradle-plugin" version "1.10" | ||||
| } | ||||
| 
 | ||||
| gradleEnterprise { | ||||
|  | ||||
										
											Binary file not shown.
										
									
								
							| @ -1,8 +1,7 @@ | ||||
| distributionBase=GRADLE_USER_HOME | ||||
| distributionPath=wrapper/dists | ||||
| distributionSha256Sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d | ||||
| distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip | ||||
| distributionSha256Sum=ff7bf6a86f09b9b2c40bb8f48b25fc19cf2b2664fd1d220cd7ab833ec758d0d7 | ||||
| distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip | ||||
| networkTimeout=10000 | ||||
| validateDistributionUrl=true | ||||
| zipStoreBase=GRADLE_USER_HOME | ||||
| 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 | ||||
| # shellcheck disable=SC2034 | ||||
| APP_BASE_NAME=${0##*/} | ||||
| # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) | ||||
| APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit | ||||
| APP_HOME=$( cd "${APP_HOME:-./}" && 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. | ||||
| MAX_FD=maximum | ||||
| @ -131,13 +133,10 @@ location of your Java installation." | ||||
|     fi | ||||
| else | ||||
|     JAVACMD=java | ||||
|     if ! command -v java >/dev/null 2>&1 | ||||
|     then | ||||
|         die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. | ||||
|     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 | ||||
| fi | ||||
| 
 | ||||
| # Increase the maximum file descriptors if we can. | ||||
| @ -145,7 +144,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then | ||||
|     case $MAX_FD in #( | ||||
|       max*) | ||||
|         # 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 ) || | ||||
|             warn "Could not query maximum file descriptor limit" | ||||
|     esac | ||||
| @ -153,7 +152,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then | ||||
|       '' | soft) :;; #( | ||||
|       *) | ||||
|         # 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" || | ||||
|             warn "Could not set maximum file descriptor limit to $MAX_FD" | ||||
|     esac | ||||
| @ -198,15 +197,11 @@ if "$cygwin" || "$msys" ; then | ||||
|     done | ||||
| fi | ||||
| 
 | ||||
| 
 | ||||
| # 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"' | ||||
| 
 | ||||
| # Collect all arguments for the java command: | ||||
| #   * 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. | ||||
| # 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" \ | ||||
|  | ||||
| @ -43,11 +43,11 @@ set JAVA_EXE=java.exe | ||||
| %JAVA_EXE% -version >NUL 2>&1 | ||||
| if %ERRORLEVEL% equ 0 goto execute | ||||
| 
 | ||||
| echo. 1>&2 | ||||
| echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 | ||||
| echo. 1>&2 | ||||
| echo Please set the JAVA_HOME variable in your environment to match the 1>&2 | ||||
| echo location of your Java installation. 1>&2 | ||||
| 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 | ||||
| 
 | ||||
| @ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe | ||||
| 
 | ||||
| if exist "%JAVA_EXE%" goto execute | ||||
| 
 | ||||
| echo. 1>&2 | ||||
| echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 | ||||
| echo. 1>&2 | ||||
| echo Please set the JAVA_HOME variable in your environment to match the 1>&2 | ||||
| echo location of your Java installation. 1>&2 | ||||
| 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 | ||||
| 
 | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| 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' | ||||
|  | ||||
| @ -8,9 +8,9 @@ repositories { | ||||
| 
 | ||||
| dependencies { | ||||
|     api("org.apache.commons:commons-math3:3.6.1") | ||||
|     implementation("com.google.guava:guava:33.1.0-jre") | ||||
|     implementation("com.google.guava:guava:31.1-jre") | ||||
| 
 | ||||
|     testImplementation("org.junit.jupiter:junit-jupiter:5.10.2") | ||||
|     testImplementation("org.junit.jupiter:junit-jupiter:5.9.2") | ||||
| } | ||||
| 
 | ||||
| tasks.test { | ||||
|  | ||||
										
											Binary file not shown.
										
									
								
							| @ -1,8 +1,7 @@ | ||||
| distributionBase=GRADLE_USER_HOME | ||||
| distributionPath=wrapper/dists | ||||
| distributionSha256Sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d | ||||
| distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip | ||||
| distributionSha256Sum=ff7bf6a86f09b9b2c40bb8f48b25fc19cf2b2664fd1d220cd7ab833ec758d0d7 | ||||
| distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip | ||||
| networkTimeout=10000 | ||||
| validateDistributionUrl=true | ||||
| zipStoreBase=GRADLE_USER_HOME | ||||
| 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 | ||||
| # shellcheck disable=SC2034 | ||||
| APP_BASE_NAME=${0##*/} | ||||
| # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) | ||||
| APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit | ||||
| APP_HOME=$( cd "${APP_HOME:-./}" && 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. | ||||
| MAX_FD=maximum | ||||
| @ -131,13 +133,10 @@ location of your Java installation." | ||||
|     fi | ||||
| else | ||||
|     JAVACMD=java | ||||
|     if ! command -v java >/dev/null 2>&1 | ||||
|     then | ||||
|         die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. | ||||
|     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 | ||||
| fi | ||||
| 
 | ||||
| # Increase the maximum file descriptors if we can. | ||||
| @ -145,7 +144,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then | ||||
|     case $MAX_FD in #( | ||||
|       max*) | ||||
|         # 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 ) || | ||||
|             warn "Could not query maximum file descriptor limit" | ||||
|     esac | ||||
| @ -153,7 +152,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then | ||||
|       '' | soft) :;; #( | ||||
|       *) | ||||
|         # 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" || | ||||
|             warn "Could not set maximum file descriptor limit to $MAX_FD" | ||||
|     esac | ||||
| @ -198,15 +197,11 @@ if "$cygwin" || "$msys" ; then | ||||
|     done | ||||
| fi | ||||
| 
 | ||||
| 
 | ||||
| # 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"' | ||||
| 
 | ||||
| # Collect all arguments for the java command: | ||||
| #   * 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. | ||||
| # 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" \ | ||||
|  | ||||
							
								
								
									
										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 | ||||
| if %ERRORLEVEL% equ 0 goto execute | ||||
| 
 | ||||
| echo. 1>&2 | ||||
| echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 | ||||
| echo. 1>&2 | ||||
| echo Please set the JAVA_HOME variable in your environment to match the 1>&2 | ||||
| echo location of your Java installation. 1>&2 | ||||
| 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 | ||||
| 
 | ||||
| @ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe | ||||
| 
 | ||||
| if exist "%JAVA_EXE%" goto execute | ||||
| 
 | ||||
| echo. 1>&2 | ||||
| echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 | ||||
| echo. 1>&2 | ||||
| echo Please set the JAVA_HOME variable in your environment to match the 1>&2 | ||||
| echo location of your Java installation. 1>&2 | ||||
| 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 | ||||
| 
 | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| plugins { | ||||
|     id("com.gradle.enterprise") version "3.16.2" | ||||
|     id("com.gradle.common-custom-user-data-gradle-plugin") version "1.13" | ||||
|     id("com.gradle.enterprise") version "3.12.6" | ||||
|     id("com.gradle.common-custom-user-data-gradle-plugin") version "1.10" | ||||
| } | ||||
| 
 | ||||
| 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 { | ||||
|     id "com.gradle.build-scan" version "3.16.2" | ||||
|     id "com.gradle.build-scan" version "3.12.6"  | ||||
| } | ||||
| 
 | ||||
| gradleEnterprise { | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| plugins { | ||||
|     id "com.gradle.enterprise" version "3.16.2" | ||||
|     id "com.gradle.enterprise" version "3.12.6" | ||||
| } | ||||
| 
 | ||||
| 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 | ||||
							
								
								
									
										43
									
								
								.github/workflows/ci-full-check.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										43
									
								
								.github/workflows/ci-full-check.yml
									
									
									
									
										vendored
									
									
								
							| @ -2,6 +2,16 @@ name: CI-full-check | ||||
| 
 | ||||
| on: | ||||
|   workflow_dispatch: | ||||
|   pull_request: | ||||
|     types: | ||||
|       - assigned | ||||
|       - review_requested | ||||
|   push: | ||||
|     branches:  | ||||
|       - main | ||||
|     paths: | ||||
|       - '.github/**' | ||||
|       - 'dist/**' | ||||
| 
 | ||||
| jobs: | ||||
|   action-inputs: | ||||
| @ -9,20 +19,13 @@ jobs: | ||||
|     with: | ||||
|       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: | ||||
|     uses: ./.github/workflows/integ-test-caching-config.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 | ||||
|     uses: ./.github/workflows/integ-test-action-inputs-caching.yml | ||||
|     with: | ||||
|       cache-key-prefix: ${{github.run_number}}- | ||||
| 
 | ||||
| @ -36,13 +39,6 @@ jobs: | ||||
|     with: | ||||
|       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: | ||||
|     uses: ./.github/workflows/integ-test-provision-gradle-versions.yml | ||||
|     with: | ||||
| @ -52,8 +48,6 @@ jobs: | ||||
|     uses: ./.github/workflows/integ-test-restore-configuration-cache.yml | ||||
|     with: | ||||
|       cache-key-prefix: ${{github.run_number}}- | ||||
|     secrets: | ||||
|       GRADLE_ENCRYPTION_KEY: ${{ secrets.GRADLE_ENCRYPTION_KEY }} | ||||
| 
 | ||||
|   restore-custom-gradle-home: | ||||
|     uses: ./.github/workflows/integ-test-restore-custom-gradle-home.yml | ||||
| @ -84,8 +78,3 @@ jobs: | ||||
|     uses: ./.github/workflows/integ-test-sample-gradle-plugin.yml | ||||
|     with: | ||||
|       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 | ||||
							
								
								
									
										85
									
								
								.github/workflows/ci-quick-check.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										85
									
								
								.github/workflows/ci-quick-check.yml
									
									
									
									
										vendored
									
									
								
							| @ -3,86 +3,117 @@ name: CI-quick-check | ||||
| on: | ||||
|   workflow_dispatch: | ||||
|   push: | ||||
|     branches-ignore: main | ||||
| 
 | ||||
| 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: | ||||
|     needs: build-distribution | ||||
|     uses: ./.github/workflows/integ-test-action-inputs.yml | ||||
|     with: | ||||
|       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: | ||||
|     uses: ./.github/workflows/integ-test-caching-config.yml | ||||
|     with: | ||||
|       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 | ||||
|     needs: build-distribution | ||||
|     uses: ./.github/workflows/integ-test-action-inputs-caching.yml | ||||
|     with: | ||||
|       runner-os: '["ubuntu-latest"]' | ||||
|       download-dist: true | ||||
| 
 | ||||
|   execution-with-caching: | ||||
|     needs: build-distribution | ||||
|     uses: ./.github/workflows/integ-test-execution-with-caching.yml | ||||
|     with: | ||||
|       runner-os: '["ubuntu-latest"]' | ||||
|       download-dist: true | ||||
| 
 | ||||
|   execution: | ||||
|     needs: build-distribution | ||||
|     uses: ./.github/workflows/integ-test-execution.yml | ||||
|     with: | ||||
|       runner-os: '["ubuntu-latest"]' | ||||
| 
 | ||||
|   develocity-injection: | ||||
|     uses: ./.github/workflows/integ-test-inject-develocity.yml | ||||
|     with: | ||||
|       runner-os: '["ubuntu-latest"]' | ||||
|     secrets: | ||||
|       DEVELOCITY_ACCESS_KEY: ${{ secrets.GE_SOLUTIONS_ACCESS_TOKEN }} | ||||
|       download-dist: true | ||||
| 
 | ||||
|   provision-gradle-versions: | ||||
|     needs: build-distribution | ||||
|     uses: ./.github/workflows/integ-test-provision-gradle-versions.yml | ||||
|     with: | ||||
|       runner-os: '["ubuntu-latest"]' | ||||
|       download-dist: true | ||||
| 
 | ||||
|   restore-configuration-cache: | ||||
|     needs: build-distribution | ||||
|     uses: ./.github/workflows/integ-test-restore-configuration-cache.yml | ||||
|     with: | ||||
|       runner-os: '["ubuntu-latest"]' | ||||
|     secrets: | ||||
|       GRADLE_ENCRYPTION_KEY: ${{ secrets.GRADLE_ENCRYPTION_KEY }} | ||||
|       download-dist: true | ||||
| 
 | ||||
|   restore-containerized-gradle-home: | ||||
|     needs: build-distribution | ||||
|     uses: ./.github/workflows/integ-test-restore-containerized-gradle-home.yml | ||||
|     with: | ||||
|       download-dist: true | ||||
| 
 | ||||
|   restore-custom-gradle-home: | ||||
|     needs: build-distribution | ||||
|     uses: ./.github/workflows/integ-test-restore-custom-gradle-home.yml | ||||
|     with: | ||||
|       download-dist: true | ||||
| 
 | ||||
|   restore-gradle-home: | ||||
|     needs: build-distribution | ||||
|     uses: ./.github/workflows/integ-test-restore-gradle-home.yml | ||||
|     with: | ||||
|       runner-os: '["ubuntu-latest"]' | ||||
|       download-dist: true | ||||
| 
 | ||||
|   restore-java-toolchain: | ||||
|     needs: build-distribution | ||||
|     uses: ./.github/workflows/integ-test-restore-java-toolchain.yml | ||||
|     with: | ||||
|       runner-os: '["ubuntu-latest"]' | ||||
|       download-dist: true | ||||
| 
 | ||||
|   sample-kotlin-dsl: | ||||
|     needs: build-distribution | ||||
|     uses: ./.github/workflows/integ-test-sample-kotlin-dsl.yml | ||||
|     with: | ||||
|       runner-os: '["ubuntu-latest"]' | ||||
|       download-dist: true | ||||
| 
 | ||||
|   sample-gradle-plugin: | ||||
|     needs: build-distribution | ||||
|     uses: ./.github/workflows/integ-test-sample-gradle-plugin.yml | ||||
|     with: | ||||
|       runner-os: '["ubuntu-latest"]' | ||||
| 
 | ||||
|   toolchain-detection: | ||||
|     uses: ./.github/workflows/integ-test-detect-java-toolchains.yml | ||||
|     with: | ||||
|       runner-os: '["ubuntu-latest"]' | ||||
|       download-dist: true | ||||
|  | ||||
							
								
								
									
										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 | ||||
|     steps: | ||||
|     - name: Checkout sources | ||||
|       uses: actions/checkout@v4 | ||||
|       uses: actions/checkout@v3 | ||||
|     - name: Test build failure | ||||
|       uses: ./ | ||||
|       continue-on-error: true | ||||
| @ -21,7 +21,7 @@ jobs: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|     - name: Checkout sources | ||||
|       uses: actions/checkout@v4 | ||||
|       uses: actions/checkout@v3 | ||||
|     - name: Test wrapper missing | ||||
|       uses: ./ | ||||
|       continue-on-error: true | ||||
| @ -33,7 +33,7 @@ jobs: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|     - name: Checkout sources | ||||
|       uses: actions/checkout@v4 | ||||
|       uses: actions/checkout@v3 | ||||
|     - name: Test bad config value | ||||
|       uses: ./ | ||||
|       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: | ||||
|   workflow_dispatch: | ||||
| @ -8,20 +8,25 @@ env: | ||||
|   GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true | ||||
| 
 | ||||
| jobs: | ||||
|   many-gradle-builds: | ||||
|   run-gradle-builds: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|     - 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 | ||||
|       uses: ./ | ||||
|     - name: Build kotlin-dsl project | ||||
|       working-directory: .github/workflow-samples/kotlin-dsl | ||||
|       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 | ||||
|       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 | ||||
|       run: ./gradlew check -Dgradle.enterprise.url=https://not.valid.server | ||||
|     - name: Build groovy-dsl project | ||||
| @ -36,36 +41,3 @@ jobs: | ||||
|       working-directory: .github/workflow-samples/groovy-dsl | ||||
|       continue-on-error: true | ||||
|       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: | ||||
|   pull_request: | ||||
|     types: [assigned, review_requested] | ||||
| 
 | ||||
| permissions: | ||||
|   pull-requests: write | ||||
| 
 | ||||
| jobs: | ||||
|   successful-build-with-always-comment: | ||||
|   gradle: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|     - name: Checkout project sources | ||||
|       uses: actions/checkout@v4 | ||||
|       uses: actions/checkout@v3 | ||||
|     - name: Setup Gradle | ||||
|       uses: ./ | ||||
|       with: | ||||
|         add-job-summary-as-pr-comment: always | ||||
|     - name: Run build with Gradle wrapper | ||||
|       id: gradle | ||||
|       working-directory: .github/workflow-samples/kotlin-dsl | ||||
|       run: ./gradlew build --scan | ||||
| 
 | ||||
|   successful-build-with-comment-on-failure: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|     - name: Checkout project sources | ||||
|       uses: actions/checkout@v4 | ||||
|     - name: Setup Gradle | ||||
|       uses: ./ | ||||
|     - name: "Add build scan URL as PR comment" | ||||
|       uses: actions/github-script@v6 | ||||
|       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 build --scan | ||||
| 
 | ||||
|   failing-build-with-comment-on-failure: | ||||
|     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 | ||||
|         github-token: ${{secrets.GITHUB_TOKEN}} | ||||
|         script: | | ||||
|           github.rest.issues.createComment({ | ||||
|             issue_number: context.issue.number, | ||||
|             owner: context.repo.owner, | ||||
|             repo: context.repo.repo, | ||||
|             body: 'PR ready for review: ${{ steps.gradle.outputs.build-scan-url }}' | ||||
|           }) | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| name: Test caching configuration | ||||
| name: Test action inputs for caching | ||||
| 
 | ||||
| on: | ||||
|   workflow_call: | ||||
| @ -8,8 +8,12 @@ on: | ||||
|       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: action-inputs-caching-${{ inputs.cache-key-prefix }} | ||||
|   GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true | ||||
| 
 | ||||
| @ -21,7 +25,9 @@ jobs: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     steps: | ||||
|     - name: Checkout sources | ||||
|       uses: actions/checkout@v4 | ||||
|       uses: actions/checkout@v3 | ||||
|     - name: Download distribution if required | ||||
|       uses: ./.github/actions/download-dist | ||||
|     - name: Setup Gradle | ||||
|       uses: ./ | ||||
|       with: | ||||
| @ -32,8 +38,7 @@ jobs: | ||||
|             enterprise | ||||
|         # Exclude build-cache from main cache entry | ||||
|         gradle-home-cache-excludes: | | ||||
|             caches/build-cache-* | ||||
|             caches/*/executionHistory | ||||
|             caches/build-cache-1 | ||||
|     - name: Build using Gradle wrapper | ||||
|       working-directory: .github/workflow-samples/groovy-dsl | ||||
|       run: ./gradlew test | ||||
| @ -47,7 +52,9 @@ jobs: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     steps: | ||||
|     - name: Checkout sources | ||||
|       uses: actions/checkout@v4 | ||||
|       uses: actions/checkout@v3 | ||||
|     - name: Download distribution if required | ||||
|       uses: ./.github/actions/download-dist | ||||
|     - name: Setup Gradle | ||||
|       uses: ./ | ||||
|       with: | ||||
| @ -56,8 +63,7 @@ jobs: | ||||
|             caches | ||||
|             enterprise | ||||
|         gradle-home-cache-excludes: | | ||||
|             caches/build-cache-* | ||||
|             caches/*/executionHistory | ||||
|             caches/build-cache-1 | ||||
|         cache-read-only: true | ||||
|     - name: Execute Gradle build with --offline | ||||
|       working-directory: .github/workflow-samples/groovy-dsl | ||||
| @ -71,7 +77,9 @@ jobs: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     steps: | ||||
|     - name: Checkout sources | ||||
|       uses: actions/checkout@v4 | ||||
|       uses: actions/checkout@v3 | ||||
|     - name: Download distribution if required | ||||
|       uses: ./.github/actions/download-dist | ||||
|     - name: Setup Gradle | ||||
|       uses: ./ | ||||
|       with: | ||||
| @ -80,19 +88,21 @@ jobs: | ||||
|       id: gradle | ||||
|       working-directory: .github/workflow-samples/no-wrapper${{ matrix.build-root-suffix }} | ||||
|       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 }} | ||||
|       uses: actions/github-script@v7 | ||||
|       uses: actions/github-script@v6 | ||||
|       with: | ||||
|         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 | ||||
|   cache-disabled-pre-existing-gradle-home: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|     - 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 | ||||
|       run: mkdir -p ~/.gradle/caches | ||||
|     - name: Setup Gradle | ||||
| @ -101,12 +111,12 @@ jobs: | ||||
|       id: gradle | ||||
|       working-directory: .github/workflow-samples/no-wrapper${{ matrix.build-root-suffix }} | ||||
|       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 }} | ||||
|       uses: actions/github-script@v7 | ||||
|       uses: actions/github-script@v6 | ||||
|       with: | ||||
|         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 | ||||
|   seed-build-write-only: | ||||
| @ -118,7 +128,9 @@ jobs: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     steps: | ||||
|     - name: Checkout sources | ||||
|       uses: actions/checkout@v4 | ||||
|       uses: actions/checkout@v3 | ||||
|     - name: Download distribution if required | ||||
|       uses: ./.github/actions/download-dist | ||||
|     - name: Setup Gradle | ||||
|       uses: ./ | ||||
|       with: | ||||
| @ -137,7 +149,9 @@ jobs: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     steps: | ||||
|     - name: Checkout sources | ||||
|       uses: actions/checkout@v4 | ||||
|       uses: actions/checkout@v3 | ||||
|     - name: Download distribution if required | ||||
|       uses: ./.github/actions/download-dist | ||||
|     - name: Setup Gradle | ||||
|       uses: ./ | ||||
|       with: | ||||
| @ -8,8 +8,12 @@ on: | ||||
|       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: action-inputs-${{ inputs.cache-key-prefix }} | ||||
|   GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true | ||||
| 
 | ||||
| @ -21,7 +25,9 @@ jobs: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     steps: | ||||
|     - 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 | ||||
|       uses: ./ | ||||
|       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: | ||||
|         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: execution-with-caching-${{ inputs.cache-key-prefix }} | ||||
|   GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true | ||||
| 
 | ||||
| @ -21,7 +25,9 @@ jobs: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     steps: | ||||
|     - 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 | ||||
|       uses: ./ | ||||
|       with: | ||||
| @ -38,7 +44,9 @@ jobs: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     steps: | ||||
|     - 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 | ||||
|       uses: ./ | ||||
|       with: | ||||
|  | ||||
							
								
								
									
										26
									
								
								.github/workflows/integ-test-execution.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								.github/workflows/integ-test-execution.yml
									
									
									
									
										vendored
									
									
								
							| @ -8,8 +8,12 @@ on: | ||||
|       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: execution-${{ inputs.cache-key-prefix }} | ||||
|   GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true | ||||
| 
 | ||||
| @ -26,7 +30,9 @@ jobs: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     steps: | ||||
|     - 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 | ||||
|       uses: ./ | ||||
|       with: | ||||
| @ -40,6 +46,12 @@ jobs: | ||||
|         gradle-version: release-candidate | ||||
|         build-root-directory: .github/workflow-samples/no-wrapper | ||||
|         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: | ||||
|     strategy: | ||||
| @ -56,9 +68,11 @@ jobs: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     steps: | ||||
|     - name: Checkout sources | ||||
|       uses: actions/checkout@v4 | ||||
|       uses: actions/checkout@v3 | ||||
|     - name: Download distribution if required | ||||
|       uses: ./.github/actions/download-dist | ||||
|     - name: Setup Java | ||||
|       uses: actions/setup-java@v4 | ||||
|       uses: actions/setup-java@v3 | ||||
|       with: | ||||
|         distribution: temurin | ||||
|         java-version: 8 | ||||
| @ -70,11 +84,11 @@ jobs: | ||||
|         gradle-version: ${{matrix.gradle}} | ||||
|         build-root-directory: .github/workflow-samples/no-wrapper${{ matrix.build-root-suffix }} | ||||
|         arguments: help -DgradleVersionCheck=${{matrix.gradle}} | ||||
|     - name: Check Build Scan url | ||||
|     - name: Check build scan url | ||||
|       if: ${{ !steps.gradle.outputs.build-scan-url }} | ||||
|       uses: actions/github-script@v7 | ||||
|       uses: actions/github-script@v6 | ||||
|       with: | ||||
|         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: | ||||
|         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: provision-gradle-versions-${{ inputs.cache-key-prefix }} | ||||
|   GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true | ||||
| 
 | ||||
| @ -26,7 +30,9 @@ jobs: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     steps: | ||||
|     - 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 | ||||
|       uses: ./ | ||||
|       with: | ||||
| @ -49,17 +55,6 @@ jobs: | ||||
|     - name: Test use release-candidate | ||||
|       working-directory: .github/workflow-samples/no-wrapper | ||||
|       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: | ||||
|     strategy: | ||||
| @ -76,33 +71,28 @@ jobs: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     steps: | ||||
|     - name: Checkout sources | ||||
|       uses: actions/checkout@v4 | ||||
|       uses: actions/checkout@v3 | ||||
|     - name: Download distribution if required | ||||
|       uses: ./.github/actions/download-dist | ||||
|     - name: Setup Java | ||||
|       uses: actions/setup-java@v4 | ||||
|       uses: actions/setup-java@v3 | ||||
|       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: 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 | ||||
|       id: gradle | ||||
|       working-directory: .github/workflow-samples/no-wrapper${{ matrix.build-root-suffix }} | ||||
|       run: gradle help "-DgradleVersionCheck=${{matrix.gradle}}" | ||||
|     - name: Check Build Scan url | ||||
|     - name: Check build scan url | ||||
|       if: ${{ !steps.gradle.outputs.build-scan-url }} | ||||
|       uses: actions/github-script@v7 | ||||
|       uses: actions/github-script@v6 | ||||
|       with: | ||||
|         script: | | ||||
|           core.setFailed('No Build Scan detected')     | ||||
|           core.setFailed('No build scan detected')     | ||||
|    | ||||
|     | ||||
|  | ||||
| @ -8,11 +8,12 @@ on: | ||||
|       runner-os: | ||||
|         type: string | ||||
|         default: '["ubuntu-latest", "windows-latest", "macos-latest"]' | ||||
|     secrets: | ||||
|       GRADLE_ENCRYPTION_KEY: | ||||
|         required: true | ||||
|       download-dist: | ||||
|         type: boolean | ||||
|         default: false | ||||
| 
 | ||||
| env: | ||||
|   DOWNLOAD_DIST: ${{ inputs.download-dist }} | ||||
|   GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: restore-configuration-cache-${{ inputs.cache-key-prefix }} | ||||
|   GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true | ||||
| 
 | ||||
| @ -26,21 +27,16 @@ jobs: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     steps: | ||||
|     - name: Checkout sources | ||||
|       uses: actions/checkout@v4 | ||||
|     - name: Setup Java to ensure consistency | ||||
|       uses: actions/setup-java@v4 | ||||
|       with: | ||||
|         distribution: 'liberica' | ||||
|         java-version: '21' | ||||
|       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 | ||||
|         cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }} | ||||
|         gradle-version: 8.6-rc-1 | ||||
|     - name: Groovy build with configuration-cache enabled | ||||
|       working-directory: .github/workflow-samples/groovy-dsl | ||||
|       run: gradle test --configuration-cache | ||||
|       run: ./gradlew test --configuration-cache | ||||
| 
 | ||||
|   verify-build-groovy: | ||||
|     env: | ||||
| @ -52,24 +48,19 @@ jobs: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     steps: | ||||
|     - name: Checkout sources | ||||
|       uses: actions/checkout@v4 | ||||
|     - name: Setup Java to ensure consistency | ||||
|       uses: actions/setup-java@v4 | ||||
|       with: | ||||
|         distribution: 'liberica' | ||||
|         java-version: '21' | ||||
|       uses: actions/checkout@v3 | ||||
|     - name: Download distribution if required | ||||
|       uses: ./.github/actions/download-dist | ||||
|     - name: Setup Gradle | ||||
|       uses: ./ | ||||
|       with: | ||||
|         cache-read-only: true | ||||
|         cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }} | ||||
|         gradle-version: 8.6-rc-1 | ||||
|     - name: Groovy build with configuration-cache enabled | ||||
|       id: execute | ||||
|       working-directory: .github/workflow-samples/groovy-dsl | ||||
|       run: gradle test --configuration-cache | ||||
|       run: ./gradlew test --configuration-cache | ||||
|     - name: Check that configuration-cache was used | ||||
|       uses: actions/github-script@v7 | ||||
|       uses: actions/github-script@v6 | ||||
|       with: | ||||
|         script: | | ||||
|           const fs = require('fs') | ||||
| @ -88,23 +79,18 @@ jobs: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     steps: | ||||
|     - name: Checkout sources | ||||
|       uses: actions/checkout@v4 | ||||
|     - name: Setup Java to ensure consistency | ||||
|       uses: actions/setup-java@v4 | ||||
|       with: | ||||
|         distribution: 'liberica' | ||||
|         java-version: '21' | ||||
|       uses: actions/checkout@v3 | ||||
|     - name: Download distribution if required | ||||
|       uses: ./.github/actions/download-dist | ||||
|     - name: Setup Gradle with no extracted cache entries restored | ||||
|       uses: ./ | ||||
|       env:  | ||||
|         GRADLE_BUILD_ACTION_SKIP_RESTORE: "generated-gradle-jars|wrapper-zips|java-toolchains|instrumented-jars|dependencies|kotlin-dsl" | ||||
|       with: | ||||
|         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) | ||||
|       working-directory: .github/workflow-samples/groovy-dsl | ||||
|       run: gradle test --configuration-cache | ||||
|       run: ./gradlew test --configuration-cache | ||||
| 
 | ||||
|   seed-build-kotlin: | ||||
|     env: | ||||
| @ -115,21 +101,16 @@ jobs: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     steps: | ||||
|     - name: Checkout sources | ||||
|       uses: actions/checkout@v4 | ||||
|     - name: Setup Java to ensure consistency | ||||
|       uses: actions/setup-java@v4 | ||||
|       with: | ||||
|         distribution: 'liberica' | ||||
|         java-version: '21' | ||||
|       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 | ||||
|         cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }} | ||||
|         gradle-version: 8.6-rc-1 | ||||
|     - name: Execute 'help' with configuration-cache enabled | ||||
|       working-directory: .github/workflow-samples/kotlin-dsl | ||||
|       run: gradle help --configuration-cache | ||||
|       run: ./gradlew help --configuration-cache | ||||
| 
 | ||||
|   modify-build-kotlin: | ||||
|     env: | ||||
| @ -141,21 +122,16 @@ jobs: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     steps: | ||||
|     - name: Checkout sources | ||||
|       uses: actions/checkout@v4 | ||||
|     - name: Setup Java to ensure consistency | ||||
|       uses: actions/setup-java@v4 | ||||
|       with: | ||||
|         distribution: 'liberica' | ||||
|         java-version: '21' | ||||
|       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 | ||||
|         cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }} | ||||
|         gradle-version: 8.6-rc-1 | ||||
|     - name: Execute 'test' with configuration-cache enabled | ||||
|       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 | ||||
|   verify-build-kotlin: | ||||
| @ -168,24 +144,19 @@ jobs: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     steps: | ||||
|     - name: Checkout sources | ||||
|       uses: actions/checkout@v4 | ||||
|     - name: Setup Java to ensure consistency | ||||
|       uses: actions/setup-java@v4 | ||||
|       with: | ||||
|         distribution: 'liberica' | ||||
|         java-version: '21' | ||||
|       uses: actions/checkout@v3 | ||||
|     - name: Download distribution if required | ||||
|       uses: ./.github/actions/download-dist | ||||
|     - name: Setup Gradle | ||||
|       uses: ./ | ||||
|       with: | ||||
|         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 | ||||
|       id: execute | ||||
|       working-directory: .github/workflow-samples/kotlin-dsl | ||||
|       run: gradle test --configuration-cache | ||||
|       run: ./gradlew test --configuration-cache | ||||
|     - name: Check that configuration-cache was used | ||||
|       uses: actions/github-script@v7 | ||||
|       uses: actions/github-script@v6 | ||||
|       with: | ||||
|         script: | | ||||
|           const fs = require('fs') | ||||
|  | ||||
| @ -5,8 +5,12 @@ on: | ||||
|     inputs: | ||||
|       cache-key-prefix: | ||||
|         type: string | ||||
|       download-dist: | ||||
|         type: boolean | ||||
|         default: false | ||||
| 
 | ||||
| env: | ||||
|   DOWNLOAD_DIST: ${{ inputs.download-dist }} | ||||
|   GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: restore-custom-gradle-home-${{ inputs.cache-key-prefix }} | ||||
|   GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true | ||||
| 
 | ||||
| @ -16,9 +20,11 @@ jobs: | ||||
|     container: fedora:latest | ||||
|     steps: | ||||
|     - name: Checkout sources | ||||
|       uses: actions/checkout@v4 | ||||
|       uses: actions/checkout@v3 | ||||
|     - name: Download distribution if required | ||||
|       uses: ./.github/actions/download-dist | ||||
|     - name: Setup Java | ||||
|       uses: actions/setup-java@v4 | ||||
|       uses: actions/setup-java@v3 | ||||
|       with: | ||||
|         java-version: 11 | ||||
|         distribution: temurin | ||||
| @ -37,9 +43,11 @@ jobs: | ||||
|     container: fedora:latest | ||||
|     steps: | ||||
|     - name: Checkout sources | ||||
|       uses: actions/checkout@v4 | ||||
|       uses: actions/checkout@v3 | ||||
|     - name: Download distribution if required | ||||
|       uses: ./.github/actions/download-dist | ||||
|     - name: Setup Java | ||||
|       uses: actions/setup-java@v4 | ||||
|       uses: actions/setup-java@v3 | ||||
|       with: | ||||
|         java-version: 11 | ||||
|         distribution: temurin | ||||
|  | ||||
| @ -5,8 +5,12 @@ on: | ||||
|     inputs: | ||||
|       cache-key-prefix: | ||||
|         type: string | ||||
|       download-dist: | ||||
|         type: boolean | ||||
|         default: false | ||||
| 
 | ||||
| env: | ||||
|   DOWNLOAD_DIST: ${{ inputs.download-dist }} | ||||
|   GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: restore-custom-gradle-home-${{ inputs.cache-key-prefix }} | ||||
|   GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true | ||||
| 
 | ||||
| @ -19,7 +23,9 @@ jobs: | ||||
|         mkdir -p $GITHUB_WORKSPACE/gradle-user-home | ||||
|         echo "GRADLE_USER_HOME=$GITHUB_WORKSPACE/gradle-user-home" >> $GITHUB_ENV | ||||
|     - name: Checkout sources | ||||
|       uses: actions/checkout@v4 | ||||
|       uses: actions/checkout@v3 | ||||
|     - name: Download distribution if required | ||||
|       uses: ./.github/actions/download-dist | ||||
|     - name: Setup Gradle | ||||
|       uses: ./ | ||||
|       with: | ||||
| @ -38,7 +44,9 @@ jobs: | ||||
|         mkdir -p $GITHUB_WORKSPACE/gradle-user-home | ||||
|         echo "GRADLE_USER_HOME=$GITHUB_WORKSPACE/gradle-user-home" >> $GITHUB_ENV | ||||
|     - name: Checkout sources | ||||
|       uses: actions/checkout@v4 | ||||
|       uses: actions/checkout@v3 | ||||
|     - name: Download distribution if required | ||||
|       uses: ./.github/actions/download-dist | ||||
|     - name: Setup Gradle | ||||
|       uses: ./ | ||||
|       with: | ||||
| @ -57,7 +65,9 @@ jobs: | ||||
|         mkdir -p $GITHUB_WORKSPACE/gradle-user-home | ||||
|         echo "GRADLE_USER_HOME=$GITHUB_WORKSPACE/gradle-user-home" >> $GITHUB_ENV | ||||
|     - name: Checkout sources | ||||
|       uses: actions/checkout@v4 | ||||
|       uses: actions/checkout@v3 | ||||
|     - name: Download distribution if required | ||||
|       uses: ./.github/actions/download-dist | ||||
|     - name: Setup Gradle | ||||
|       uses: ./ | ||||
|       with: | ||||
|  | ||||
| @ -8,8 +8,12 @@ on: | ||||
|       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: restore-gradle-home-${{ inputs.cache-key-prefix }} | ||||
|   GRADLE_BUILD_ACTION_CACHE_KEY_JOB: restore-gradle-home | ||||
|   GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true | ||||
| @ -22,7 +26,9 @@ jobs: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     steps: | ||||
|     - name: Checkout sources | ||||
|       uses: actions/checkout@v4 | ||||
|       uses: actions/checkout@v3 | ||||
|     - name: Download distribution if required | ||||
|       uses: ./.github/actions/download-dist | ||||
|     - name: Setup Gradle | ||||
|       uses: ./ | ||||
|       with: | ||||
| @ -40,7 +46,9 @@ jobs: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     steps: | ||||
|     - name: Checkout sources | ||||
|       uses: actions/checkout@v4 | ||||
|       uses: actions/checkout@v3 | ||||
|     - name: Download distribution if required | ||||
|       uses: ./.github/actions/download-dist | ||||
|     - name: Setup Gradle | ||||
|       uses: ./ | ||||
|       with: | ||||
| @ -58,7 +66,9 @@ jobs: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     steps: | ||||
|     - name: Checkout sources | ||||
|       uses: actions/checkout@v4 | ||||
|       uses: actions/checkout@v3 | ||||
|     - name: Download distribution if required | ||||
|       uses: ./.github/actions/download-dist | ||||
|     - name: Setup Gradle | ||||
|       uses: ./ | ||||
|       with: | ||||
| @ -76,7 +86,9 @@ jobs: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     steps: | ||||
|     - 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 | ||||
|       uses: ./ | ||||
|       env:  | ||||
| @ -87,38 +99,3 @@ jobs: | ||||
|       working-directory: .github/workflow-samples/groovy-dsl | ||||
|       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: | ||||
|         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: restore-java-toolchain-${{ inputs.cache-key-prefix }} | ||||
|   GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true | ||||
| 
 | ||||
| @ -21,7 +25,9 @@ jobs: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     steps: | ||||
|     - name: Checkout sources | ||||
|       uses: actions/checkout@v4 | ||||
|       uses: actions/checkout@v3 | ||||
|     - name: Download distribution if required | ||||
|       uses: ./.github/actions/download-dist | ||||
|     - name: Setup Gradle | ||||
|       uses: ./ | ||||
|       with: | ||||
| @ -39,7 +45,9 @@ jobs: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     steps: | ||||
|     - name: Checkout sources | ||||
|       uses: actions/checkout@v4 | ||||
|       uses: actions/checkout@v3 | ||||
|     - name: Download distribution if required | ||||
|       uses: ./.github/actions/download-dist | ||||
|     - name: Setup Gradle | ||||
|       uses: ./ | ||||
|       with: | ||||
|  | ||||
| @ -8,8 +8,12 @@ on: | ||||
|       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: sample-gradle-plugin-${{ inputs.cache-key-prefix }} | ||||
|   GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true | ||||
| 
 | ||||
| @ -21,7 +25,9 @@ jobs: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     steps: | ||||
|     - name: Checkout sources | ||||
|       uses: actions/checkout@v4 | ||||
|       uses: actions/checkout@v3 | ||||
|     - name: Download distribution if required | ||||
|       uses: ./.github/actions/download-dist | ||||
|     - name: Setup Gradle | ||||
|       uses: ./ | ||||
|       with: | ||||
| @ -38,7 +44,9 @@ jobs: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     steps: | ||||
|     - name: Checkout sources | ||||
|       uses: actions/checkout@v4 | ||||
|       uses: actions/checkout@v3 | ||||
|     - name: Download distribution if required | ||||
|       uses: ./.github/actions/download-dist | ||||
|     - name: Setup Gradle | ||||
|       uses: ./ | ||||
|       with: | ||||
|  | ||||
| @ -8,8 +8,12 @@ on: | ||||
|       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: sample-kotlin-dsl-${{ inputs.cache-key-prefix }} | ||||
|   GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true | ||||
| 
 | ||||
| @ -21,7 +25,9 @@ jobs: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     steps: | ||||
|     - name: Checkout sources | ||||
|       uses: actions/checkout@v4 | ||||
|       uses: actions/checkout@v3 | ||||
|     - name: Download distribution if required | ||||
|       uses: ./.github/actions/download-dist | ||||
|     - name: Setup Gradle | ||||
|       uses: ./ | ||||
|       with: | ||||
| @ -38,7 +44,9 @@ jobs: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     steps: | ||||
|     - name: Checkout sources | ||||
|       uses: actions/checkout@v4 | ||||
|       uses: actions/checkout@v3 | ||||
|     - name: Download distribution if required | ||||
|       uses: ./.github/actions/download-dist | ||||
|     - name: Setup Gradle | ||||
|       uses: ./ | ||||
|       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) | ||||
| 
 | ||||
| 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 | ||||
| of this software and associated documentation files (the "Software"), to deal | ||||
|  | ||||
							
								
								
									
										418
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										418
									
								
								README.md
									
									
									
									
									
								
							| @ -1,40 +1,400 @@ | ||||
| > [!IMPORTANT] | ||||
| > 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`.  | ||||
| # Execute Gradle builds in GitHub Actions workflows | ||||
| 
 | ||||
| # 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 | ||||
| name: Build | ||||
| 
 | ||||
| on: [ push ] | ||||
| 
 | ||||
| name: Run Gradle on PRs | ||||
| on: pull_request | ||||
| jobs: | ||||
|   build: | ||||
|     runs-on: ubuntu-latest | ||||
|   gradle: | ||||
|     strategy: | ||||
|       matrix: | ||||
|         os: [ubuntu-latest, macos-latest, windows-latest] | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     steps: | ||||
|     - name: Checkout sources | ||||
|       uses: actions/checkout@v4 | ||||
|     - uses: actions/checkout@v3 | ||||
|     - uses: actions/setup-java@v3 | ||||
|       with: | ||||
|         distribution: temurin | ||||
|         java-version: 11 | ||||
|          | ||||
|     - name: Setup Gradle | ||||
|       uses: gradle/actions/setup-gradle@v3 | ||||
|     - name: Build with Gradle | ||||
|       uses: gradle/gradle-build-action@v2 | ||||
|      | ||||
|     - name: Execute Gradle 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 ; | ||||
| - Any [configuration-cache](https://docs.gradle.org/nightly/userguide/configuration_cache.html) data stored in the project `.gradle` directory. (Only supported for Gradle 7 or higher.) | ||||
| 
 | ||||
| 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 and configuration-cache are highly dependent on the Gradle execution, so the cache key is composed of the current commit hash and the GitHub actions job id. | ||||
| As such, the cache key is likely to change on each subsequent run of GitHub actions.  | ||||
| This allows the most recent state to always be available in the GitHub actions cache. | ||||
| 
 | ||||
| To reduce duplication between cache entries, certain artifacts are cached independently based on their identity. | ||||
| Artifacts that are cached independently include downloaded dependencies, downloaded wrapper distributions and generated Gradle API jars. | ||||
| For example, this means that all jobs executing a particular version of the Gradle wrapper will share common entries for wrapper distributions and for generated Gradle API jars. | ||||
| 
 | ||||
| ### Using the caches read-only | ||||
| 
 | ||||
| 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 from the directories cached. | ||||
| gradle-home-cache-excludes: | | ||||
|     caches/build-cache-1 | ||||
| ``` | ||||
| 
 | ||||
| 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. | ||||
|  | ||||
							
								
								
									
										228
									
								
								action.yml
									
									
									
									
									
								
							
							
						
						
									
										228
									
								
								action.yml
									
									
									
									
									
								
							| @ -1,14 +1,13 @@ | ||||
| name: setup-gradle | ||||
| description: 'Configures Gradle for GitHub actions, caching state and generating a dependency graph via Dependency Submission.' | ||||
| name: "Gradle Build Action" | ||||
| 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: | ||||
|   gradle-version: | ||||
|     description: | | ||||
|       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. | ||||
|     description: Gradle version to use | ||||
|     required: false | ||||
| 
 | ||||
|   # Cache configuration | ||||
|   cache-disabled: | ||||
|     description: When 'true', all caching is disabled. No entries will be written to or read from the cache. | ||||
|     required: false | ||||
| @ -23,23 +22,11 @@ inputs: | ||||
| 
 | ||||
|   cache-write-only: | ||||
|     description: | | ||||
|       When 'true', entries will not be restored from the cache but will be saved at the end of the Job. | ||||
|       When 'true', entries will not be restored from the cache but will be saved at the end of the Job.  | ||||
|       Setting this to 'true' implies cache-read-only will be 'false'. | ||||
|     required: false | ||||
|     default: false | ||||
| 
 | ||||
|   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: | ||||
|     description: Paths within Gradle User Home to cache. | ||||
|     required: false | ||||
| @ -50,219 +37,52 @@ inputs: | ||||
|   gradle-home-cache-excludes: | ||||
|     description: Paths within Gradle User Home to exclude from cache. | ||||
|     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: | ||||
|     description: When 'true', the action will attempt to remove any stale/unused entries from the Gradle User Home prior to saving to the GitHub Actions cache. | ||||
|     required: false | ||||
|     default: false | ||||
| 
 | ||||
|   # Job summary configuration | ||||
|   add-job-summary: | ||||
|     description: Specifies when a Job Summary should be inluded in the action results. Valid values are 'never', 'always' (default), and 'on-failure'. | ||||
|     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. | ||||
|   arguments: | ||||
|     description: Gradle command line arguments (supports multi-line input) | ||||
|     required: false | ||||
| 
 | ||||
|   # Build Scan configuration | ||||
|   build-scan-publish: | ||||
|     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'. | ||||
|   build-root-directory: | ||||
|     description: Path to the root directory of the build | ||||
|     required: false | ||||
| 
 | ||||
|   build-scan-terms-of-use-agree: | ||||
|     description: Indicate that you agree to the Build Scan® terms of use. This input value must be "yes". | ||||
|   gradle-executable: | ||||
|     description: Path to the Gradle executable | ||||
|     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: | ||||
|     description: When 'false', no Job Summary will be generated for the Job. | ||||
|     required: false | ||||
|     default: true | ||||
|     deprecation-message: Superceded by the new 'add-job-summary' and 'add-job-summary-as-pr-comment' parameters. | ||||
| 
 | ||||
|   arguments: | ||||
|     description: Gradle command line arguments (supports multi-line input) | ||||
|     required: false | ||||
|     deprecation-message: Using the action to execute Gradle directly is deprecated in favor of using the action to setup Gradle, and executing Gradle in a subsequent Step. | ||||
| 
 | ||||
|   build-root-directory: | ||||
|     description: Path to the root directory of the build. Default is the root of the GitHub workspace. | ||||
|     required: false | ||||
|     deprecation-message: Using the action to execute Gradle directly is deprecated in favor of using the action to setup Gradle, and executing Gradle in a subsequent Step. | ||||
| 
 | ||||
|   # EXPERIMENTAL ACTION INPUTS | ||||
|   # EXPERIMENTAL & INTERNAL ACTION INPUTS | ||||
|   # 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! | ||||
|   gradle-home-cache-strict-match: | ||||
|     description: When 'true', the action will not attempt to restore the Gradle User Home entries from other Jobs. | ||||
|     required: false | ||||
|     default: false | ||||
| 
 | ||||
|   # INTERNAL ACTION INPUTS | ||||
|   # These inputs should not be configured directly, and are only used to pass environmental information to the action | ||||
|   workflow-job-context: | ||||
|     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 | ||||
|     default: ${{ toJSON(matrix) }} | ||||
| 
 | ||||
|   github-token: | ||||
|     description: The GitHub token used to authenticate when submitting via the Dependency Submission API. | ||||
|     default: ${{ github.token }} | ||||
|   gradle-home-cache-cleanup: | ||||
|     description: When 'true', the action will attempt to remove any stale/unused entries from the Gradle User Home prior to saving to the GitHub Actions cache. | ||||
|     required: false | ||||
|     default: false | ||||
| 
 | ||||
| outputs: | ||||
|   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. | ||||
|     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 }} | ||||
|     description: Link to the build scan if any | ||||
| 
 | ||||
| runs: | ||||
|   using: "composite" | ||||
|   steps: | ||||
|     - name: Setup Gradle | ||||
|       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 | ||||
|   using: 'node16' | ||||
|   main: 'dist/main/index.js' | ||||
|   post: 'dist/post/index.js' | ||||
| 
 | ||||
| branding: | ||||
|   icon: 'box' | ||||
|  | ||||
							
								
								
									
										65739
									
								
								dist/main/index.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										65739
									
								
								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
											
										
									
								
							
							
								
								
									
										64423
									
								
								dist/post/index.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										64423
									
								
								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 {ConfigurationCacheEntryExtractor, 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 = 'v6-' | ||||
| 
 | ||||
| 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