This is an automated email from the ASF dual-hosted git repository.
mridulpathak pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git
The following commit(s) were added to refs/heads/trunk by this push:
new 17bbbc662c Improved: Upgrade Gradle to 9.8.2 and CodeNarc to 4.0.0
(OFBIZ-13208)
17bbbc662c is described below
commit 17bbbc662cec6ee7c908d90201d874e77e8e52f8
Author: Mridul Pathak <[email protected]>
AuthorDate: Fri Oct 23 13:16:42 2026 +0530
Improved: Upgrade Gradle to 9.8.2 and CodeNarc to 4.0.0 (OFBIZ-13208)
- Bump the Gradle wrapper from 8.14.6 to 9.8.2 and regenerate gradlew and
gradlew.bat with the 9.8.2 wrapper task.
- Import groovy.xml.XmlParser in build.gradle and common.gradle, since
Gradle 9 embeds Groovy 4, which no longer provides groovy.util.XmlParser.
- Run external processes from task actions through an injected
ExecOperations (terminateOfbiz, gitInfoFooter, generateDBPassword,
generateEncryptedSecret, reEncryptAllSecrets and pullPlugin), since Gradle 9
removed Project.exec and Project.javaexec.
- Read git output at configuration time through providers.exec instead of
String.execute(), which Gradle 9.8 deprecates at configuration time.
- Collect the cleanAll dependencies from tasks.names, since
DomainObjectCollection.findAll(Closure) is deprecated.
- Bump CodeNarc from 3.7.0-groovy-4.0 to 4.0.0, which is built on Groovy 5
and runs on Java 17. The plain version also lets Dependabot propose future
CodeNarc updates, which it skipped while the current version carried the
-groovy-4.0 suffix.
The Java source and target compatibility stay at 17.
---
build.gradle | 51 ++++++++++++++-----
common.gradle | 1 +
gradle/libs.versions.toml | 5 +-
gradle/wrapper/gradle-wrapper.properties | 4 +-
gradlew | 11 ++--
gradlew.bat | 86 +++++++++++++++++++-------------
6 files changed, 101 insertions(+), 57 deletions(-)
diff --git a/build.gradle b/build.gradle
index 88a02e105a..5200d349d0 100644
--- a/build.gradle
+++ b/build.gradle
@@ -17,9 +17,12 @@
* under the License.
*/
import groovy.xml.MarkupBuilder
+import groovy.xml.XmlParser
import groovy.xml.XmlSlurper
+import javax.inject.Inject
import org.apache.tools.ant.filters.ReplaceTokens
import org.asciidoctor.gradle.jvm.AsciidoctorTask
+import org.gradle.process.ExecOperations
/* ========================================================
* Project setup
@@ -242,7 +245,16 @@ processResources {
// Only used for release branches
def getCurrentGitBranch() {
- return "git branch --show-current".execute().text.trim()
+ return gitOutput('branch', '--show-current')
+}
+
+// Returns the trimmed standard output of a git command, or an empty string if
it fails
+// (e.g. when building from a source release that is not a git checkout).
+def gitOutput(String... gitArgs) {
+ return providers.exec {
+ commandLine(['git', '-C', rootDir.path] + gitArgs.toList())
+ ignoreExitValue = true
+ }.standardOutput.asText.get().trim()
}
// defines the footer files for git info
@@ -387,7 +399,7 @@ checkstyle {
gitHooks {
// Resolve the real .git dir so this also works from a linked worktree,
// where "$rootDir/.git" (the plugin's default) is a gitlink file, not a
directory.
- def gitCommonDir = "git -C ${rootDir} rev-parse
--git-common-dir".execute().text.trim()
+ def gitCommonDir = gitOutput('rev-parse', '--git-common-dir')
hooksDirectory.set(new File(rootDir,
gitCommonDir).toPath().resolve('hooks').toFile())
hooks = ['pre-push': 'checkstyleMain checkstyleTest codenarcMain
codenarcTest']
}
@@ -703,20 +715,28 @@ task testIntegration(group: ofbizServer) {
description = 'Run OFBiz integration tests; You must run loadAll before
running this task'
}
+// Gives tasks access to ExecOperations, which replaces Project.exec and
Project.javaexec
+// (removed in Gradle 9) for running external processes from a task action.
+interface InjectedExecOps {
+ @Inject
+ ExecOperations getExecOps()
+}
+
task terminateOfbiz(group: ofbizServer,
description: 'Force termination of any running OFBiz servers, only use if
\"--shutdown\" command fails') {
+ def execOps = objects.newInstance(InjectedExecOps).execOps
doLast {
if (os.contains('windows')) {
Runtime.getRuntime().exec("wmic process where \"CommandLine Like
\'%org.apache.ofbiz.base.start.Start%\'\" Call Terminate")
} else {
def processOutput = new ByteArrayOutputStream()
- exec {
+ execOps.exec {
commandLine 'ps', 'ax'
standardOutput = processOutput
}
processOutput.toString().split(System.lineSeparator()).each { line
->
if (line ==~ /.*org\.apache\.ofbiz\.base\.start\.Start.*/) {
- exec { commandLine 'kill', '-9', line.tokenize().first() }
+ execOps.exec { commandLine 'kill', '-9',
line.tokenize().first() }
}
}
}
@@ -1000,6 +1020,7 @@ task generateAllPluginsDocumentation(group: docsGroup,
// (applied above) - kept out of this file since they're self-contained and
sizable.
task gitInfoFooter(group: sysadminGroup, description: 'Update the Git
Branch-revision info in the footer if Git is used') {
+ def execOps = objects.newInstance(InjectedExecOps).execOps
doLast {
def branch
def revision
@@ -1012,13 +1033,13 @@ task gitInfoFooter(group: sysadminGroup, description:
'Update the Git Branch-rev
}
def branchOutput = new ByteArrayOutputStream()
- exec {
+ execOps.exec {
commandLine 'git', 'rev-parse', '--abbrev-ref', 'HEAD'
standardOutput = branchOutput
}
branch = branchOutput.toString()
def revisionOutput = new ByteArrayOutputStream()
- exec {
+ execOps.exec {
commandLine 'git', 'rev-parse', 'HEAD'
standardOutput = revisionOutput
}
@@ -1080,13 +1101,14 @@ task generateDBPassword(group: sysadminGroup,
+ 'If -PdbPassword is omitted, you will be prompted for it via
masked console input '
+ '(run with --no-daemon --console=plain). The master key is
taken from -PmasterKey, '
+ 'falling back to the OFBIZ_MASTER_KEY environment
variable.') {
+ def execOps = objects.newInstance(InjectedExecOps).execOps
doLast {
def secret = project.hasProperty('dbPassword') ?
project.property('dbPassword')
: promptSecret('Enter database password: ')
def masterKey = project.hasProperty('masterKey') ?
project.property('masterKey') : System.getenv('OFBIZ_MASTER_KEY')
if (masterKey) {
def output = new java.io.ByteArrayOutputStream()
- javaexec {
+ execOps.javaexec {
classpath = sourceSets.main.runtimeClasspath
mainClass = 'org.apache.ofbiz.base.crypto.ConfigCryptoUtil'
args masterKey, secret
@@ -1112,6 +1134,7 @@ task generateEncryptedSecret(group: sysadminGroup,
+ 'Any of -PsecretPassword/-PlookupKey/-PmasterKey may be
omitted to be prompted for '
+ 'interactively (run with --no-daemon --console=plain); the
master key also falls back '
+ 'to the OFBIZ_MASTER_KEY environment variable.') {
+ def execOps = objects.newInstance(InjectedExecOps).execOps
doLast {
def secret = project.hasProperty('secretPassword') ?
project.property('secretPassword')
: promptSecret('Enter secret value: ')
@@ -1129,7 +1152,7 @@ task generateEncryptedSecret(group: sysadminGroup,
}
def output = new java.io.ByteArrayOutputStream()
- javaexec {
+ execOps.javaexec {
classpath = sourceSets.main.runtimeClasspath
mainClass = 'org.apache.ofbiz.base.crypto.ConfigCryptoUtil'
args masterKey, secret
@@ -1147,13 +1170,14 @@ task reEncryptAllSecrets(group: sysadminGroup,
+ 'Keys may also be supplied via the OFBIZ_OLD_MASTER_KEY /
OFBIZ_NEW_MASTER_KEY env vars '
+ 'or entered interactively (run with --no-daemon
--console=plain).') {
dependsOn classes
+ def execOps = objects.newInstance(InjectedExecOps).execOps
doLast {
def oldKey = project.hasProperty('oldMasterKey') ?
project.property('oldMasterKey')
: (System.getenv('OFBIZ_OLD_MASTER_KEY') ?:
promptSecret('Enter OLD master key: '))
def newKey = project.hasProperty('newMasterKey') ?
project.property('newMasterKey')
: (System.getenv('OFBIZ_NEW_MASTER_KEY') ?:
promptSecret('Enter NEW master key: '))
def dryRun = project.hasProperty('dryRun') ?
project.property('dryRun') : 'false'
- javaexec {
+ execOps.javaexec {
classpath = sourceSets.main.runtimeClasspath
mainClass = 'org.apache.ofbiz.base.crypto.ReEncryptSecretsMain'
args oldKey, newKey, dryRun
@@ -1363,6 +1387,7 @@ task pushPlugin(group: ofbizPlugin, description: 'push an
existing plugin to loc
}
task pullPlugin(group: ofbizPlugin, description: 'Download and install a
plugin with all dependencies') {
+ def execOps = objects.newInstance(InjectedExecOps).execOps
doLast {
if (!project.hasProperty('dependencyId')) {
throw new GradleException('You must pass the dependencyId of the
plugin')
@@ -1400,7 +1425,7 @@ task pullPlugin(group: ofbizPlugin, description:
'Download and install a plugin
from zipTree(pluginArchive)
into "${pluginsDir}/${pluginId}"
}
- gradlewSubprocess(['installPlugin', "-PpluginId=${pluginId}"])
+ gradlewSubprocess(execOps, ['installPlugin',
"-PpluginId=${pluginId}"])
}
}
}
@@ -1453,7 +1478,7 @@ task cleanFooterFiles(group: cleanupGroup, description:
'clean generated footer
* declaration is important because it means that it will automatically
* run whenever the task cleanAll executes (dependency matched by regex)
*/
-def cleanTasks = tasks.findAll { it.name ==~ /^clean.+/ }
+def cleanTasks = tasks.names.findAll { it ==~ /^clean.+/ }
task cleanAll(group: cleanupGroup, dependsOn: [cleanTasks, clean]) {
description = 'Execute all cleaning tasks.'
}
@@ -1588,8 +1613,8 @@ def taskExistsInproject(fullyQualifiedProject, taskName) {
.anyMatch { it.name == taskName }
}
-def gradlewSubprocess(commandList) {
- exec { commandLine(gradlew, '--no-daemon', *commandList) }
+def gradlewSubprocess(ExecOperations execOps, commandList) {
+ execOps.exec { commandLine(gradlew, '--no-daemon', *commandList) }
}
diff --git a/common.gradle b/common.gradle
index 3c7db5020d..17aaa761b1 100644
--- a/common.gradle
+++ b/common.gradle
@@ -16,6 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
+import groovy.xml.XmlParser
import java.util.stream.Stream
import java.util.stream.Collectors
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 2c3de3e0c6..ae5d61e876 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -98,8 +98,9 @@ barcode4j = "2.1"
avalon-framework-impl = "4.3.1"
h2 = "2.5.252"
geronimo-jaxrpc-spec = "2.1"
-# Specify last codenarc version for java 17 compliance.
-codenarc = "3.7.0-groovy-4.0"
+# Keep the plain CodeNarc version (built for Groovy 5), not a "-groovy-x.y"
variant: Dependabot
+# only proposes versions carrying the same suffix as the current one.
+codenarc = "4.0.0"
# CVE-2024-21742
apache-mime4j-core = "0.8.15"
# CVE-2024-29857, CVE-2024-30171, CVE-2024-30172, CVE-2024-34447
diff --git a/gradle/wrapper/gradle-wrapper.properties
b/gradle/wrapper/gradle-wrapper.properties
index d3f0219867..91c4fc64aa 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,7 +1,9 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.6-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-9.8.2-bin.zip
networkTimeout=10000
+retries=0
+retryBackOffMs=500
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
index 23d15a9367..249efbb032 100755
--- a/gradlew
+++ b/gradlew
@@ -1,7 +1,7 @@
#!/bin/sh
#
-# Copyright © 2015-2021 the original authors.
+# Copyright © 2015 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.
@@ -20,7 +20,7 @@
##############################################################################
#
-# Gradle start up script for POSIX generated by Gradle.
+# gradlew start up script for POSIX generated by Gradle.
#
# Important for running:
#
@@ -29,7 +29,7 @@
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
-# ksh Gradle
+# ksh gradlew
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
@@ -57,7 +57,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
-#
https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+#
https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
@@ -114,7 +114,6 @@ case "$( uname )" in #(
NONSTOP* ) nonstop=true ;;
esac
-CLASSPATH="\\\"\\\""
# Determine the Java command to use to start the JVM.
@@ -172,7 +171,6 @@ fi
# 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" )
@@ -212,7 +210,6 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
- -classpath "$CLASSPATH" \
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
"$@"
diff --git a/gradlew.bat b/gradlew.bat
index db3a6ac207..3185a43f78 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -19,12 +19,39 @@
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
-@rem Gradle startup script for Windows
+@rem gradlew startup script for Windows
@rem
@rem ##########################################################################
-@rem Set local scope for the variables with windows NT shell
-if "%OS%"=="Windows_NT" setlocal
+@rem Set local scope for the variables, and ensure extensions are enabled
+setlocal EnableExtensions
+
+@rem Catch executions from older scripts and ensure they exit cleanly.
+@rem This can be removed once we can be reasonably confident that few people
+@rem will be migrating directly to this new wrapper.
+goto afterSafetyNet
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+goto exitWithErrorLevel
+:afterSafetyNet
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@@ -45,13 +72,14 @@ 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
+1>&2 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.
-goto fail
+"%COMSPEC%" /c exit 1
+goto exitWithErrorLevel
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
@@ -59,36 +87,26 @@ 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
+1>&2 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.
-goto fail
+"%COMSPEC%" /c exit 1
+goto exitWithErrorLevel
:execute
@rem Setup the command line
-set CLASSPATH=
-@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS%
"-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar
"%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
+@rem Execute gradlew
+@rem endlocal doesn't take effect until after the line is parsed and variables
are expanded
+@rem which allows us to clear the local environment before executing the java
command
+endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS%
"-Dorg.gradle.appname=%APP_BASE_NAME%" -jar
"%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel &
goto exitWithErrorLevel
-:end
-@rem End local scope for the variables with windows NT shell
-if %ERRORLEVEL% equ 0 goto mainEnd
-
-:fail
-rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code
instead of
-rem the _cmd.exe /c_ return code!
-set EXIT_CODE=%ERRORLEVEL%
-if %EXIT_CODE% equ 0 set EXIT_CODE=1
-if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
-exit /b %EXIT_CODE%
-
-:mainEnd
-if "%OS%"=="Windows_NT" endlocal
-
-:omega
+@rem This label must not be changed. We rely on old scripts being able to jump
to this point.
+:exitWithErrorLevel
+@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts
+"%COMSPEC%" /c exit %ERRORLEVEL%