This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch GROOVY-12019
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/GROOVY-12019 by this push:
new 8908904dc4 Enhance task handling in SharedConfiguration for
documentation and Apache publishing
8908904dc4 is described below
commit 8908904dc49854cebb79b39cf44ef0d2a7f8ff91
Author: Daniel Sun <[email protected]>
AuthorDate: Thu May 28 02:12:36 2026 +0900
Enhance task handling in SharedConfiguration for documentation and Apache
publishing
---
.../src/main/groovy/org.apache.groovy-base.gradle | 6 +-
.../main/groovy/org.apache.groovy-library.gradle | 8 +-
.../org.apache.groovy-published-library.gradle | 4 +-
.../org/apache/groovy/gradle/JarJarTask.groovy | 24 +++--
.../groovy/gradle/SharedConfiguration.groovy | 102 ++++++++++++++++++++-
5 files changed, 129 insertions(+), 15 deletions(-)
diff --git a/build-logic/src/main/groovy/org.apache.groovy-base.gradle
b/build-logic/src/main/groovy/org.apache.groovy-base.gradle
index 22784c8e60..9386ea793a 100644
--- a/build-logic/src/main/groovy/org.apache.groovy-base.gradle
+++ b/build-logic/src/main/groovy/org.apache.groovy-base.gradle
@@ -47,9 +47,9 @@ if (sharedConfiguration.hasCodeCoverage.get()) {
}
if (sharedConfiguration.isDocumentationBuild &&
layout.projectDirectory.dir('src/spec/doc').asFile.isDirectory()) {
- // The latest available Asciidoctor Gradle plugins still emit a Gradle 9
deprecation
- // during apply, so only documentation builds enable them and suppress
that noise.
- gradle.startParameter.warningMode =
org.gradle.api.logging.configuration.WarningMode.None
+ // asciidoctor-gradle-jvm 4.0.5 still emits a Gradle 9 deprecation during
apply.
+ // Keep docs builds opt-in, but leave warnings enabled so unrelated
deprecations stay visible.
+ // TODO: Drop this note once the build can move to asciidoctor-gradle-jvm
4.0.6+.
pluginManager.apply('org.apache.groovy-asciidoctor')
}
diff --git a/build-logic/src/main/groovy/org.apache.groovy-library.gradle
b/build-logic/src/main/groovy/org.apache.groovy-library.gradle
index ae7618ddcd..860b14392d 100644
--- a/build-logic/src/main/groovy/org.apache.groovy-library.gradle
+++ b/build-logic/src/main/groovy/org.apache.groovy-library.gradle
@@ -37,11 +37,11 @@ tasks.named('jarjar') { JarJarTask jjt ->
jjt.bndInstruction('Fragment-Host', 'groovy') // GROOVY-9402, GROOVY-11570
def folder = file("${projectDir}/src/main/resources/META-INF/services")
if (folder.exists() && folder.listFiles().count { it.name ==~
/^(?!(org.codehaus.groovy.transform.ASTTransformation)$).*$/ } > 0) {
- jjt.bndInstruction('Require-Capability',
'osgi.extender;filter:="(osgi.extender=osgi.serviceloader.processor)"')
- jjt.bndInstruction('Require-Capability',
'osgi.extender;filter:="(osgi.extender=osgi.serviceloader.registrar)"')
+ jjt.appendBndInstruction('Require-Capability',
'osgi.extender;filter:="(osgi.extender=osgi.serviceloader.processor)"')
+ jjt.appendBndInstruction('Require-Capability',
'osgi.extender;filter:="(osgi.extender=osgi.serviceloader.registrar)"')
folder.eachFileMatch(~/^(?!(org.codehaus.groovy.transform.ASTTransformation)$).*$/)
{
- jjt.bndInstruction('Require-Capability',
"osgi.serviceloader;filter:=\"(osgi.serviceloader=${it.name})\";cardinality:=multiple")
- jjt.bndInstruction('Provide-Capability',
"osgi.serviceloader;osgi.serviceloader=\"${it.name}\"")
+ jjt.appendBndInstruction('Require-Capability',
"osgi.serviceloader;filter:=\"(osgi.serviceloader=${it.name})\";cardinality:=multiple")
+ jjt.appendBndInstruction('Provide-Capability',
"osgi.serviceloader;osgi.serviceloader=\"${it.name}\"")
}
}
}
diff --git
a/build-logic/src/main/groovy/org.apache.groovy-published-library.gradle
b/build-logic/src/main/groovy/org.apache.groovy-published-library.gradle
index b7e0e90aa4..4804167999 100644
--- a/build-logic/src/main/groovy/org.apache.groovy-published-library.gradle
+++ b/build-logic/src/main/groovy/org.apache.groovy-published-library.gradle
@@ -828,7 +828,9 @@ signing {
}
gradle.taskGraph.whenReady { taskGraph ->
- if (sharedConfiguration.signing.shouldSign()) {
+ boolean shouldSign = sharedConfiguration.signing.shouldSign(taskGraph)
+ signing.required = shouldSign
+ if (shouldSign) {
// Use Java 6's console or Swing to read input (not suitable for CI)
if (!sharedConfiguration.signing.hasAllKeyDetails()) {
printf '\n\nWe have to sign some things in this build.' +
diff --git
a/build-logic/src/main/groovy/org/apache/groovy/gradle/JarJarTask.groovy
b/build-logic/src/main/groovy/org/apache/groovy/gradle/JarJarTask.groovy
index 65be072eb8..ce199744d0 100644
--- a/build-logic/src/main/groovy/org/apache/groovy/gradle/JarJarTask.groovy
+++ b/build-logic/src/main/groovy/org/apache/groovy/gradle/JarJarTask.groovy
@@ -97,9 +97,8 @@ class JarJarTask extends DefaultTask {
/**
* BND instructions used when generating the OSGi manifest.
- * Keys that are added multiple times are accumulated with
comma-separators,
- * which is the correct BND syntax for multi-value headers such as
- * {@code Require-Capability} and {@code Provide-Capability}.
+ * Entries override the default analyzer properties unless explicitly
appended
+ * through {@link #appendBndInstruction(String, String)}.
*/
@Input
Map<String, String> bndInstructions = [:]
@@ -118,11 +117,24 @@ class JarJarTask extends DefaultTask {
}
/**
- * Adds (or accumulates) a BND manifest instruction.
- * If {@code key} already has a value, the new {@code value} is appended
- * with a comma separator — matching BND's multi-value header syntax.
+ * Sets a BND manifest instruction, replacing any previous value for
{@code key}.
*/
void bndInstruction(String key, String value) {
+ setBndInstruction(key, value)
+ }
+
+ /**
+ * Sets a BND manifest instruction, replacing any previous value for
{@code key}.
+ */
+ void setBndInstruction(String key, String value) {
+ bndInstructions[key] = value
+ }
+
+ /**
+ * Appends a BND manifest instruction using a comma separator, matching
BND's
+ * syntax for multi-value headers such as {@code Require-Capability}.
+ */
+ void appendBndInstruction(String key, String value) {
def existing = bndInstructions.get(key)
bndInstructions[key] = existing != null ? "${existing},${value}" :
value
}
diff --git
a/build-logic/src/main/groovy/org/apache/groovy/gradle/SharedConfiguration.groovy
b/build-logic/src/main/groovy/org/apache/groovy/gradle/SharedConfiguration.groovy
index 1158b3292d..b18030bcfa 100644
---
a/build-logic/src/main/groovy/org/apache/groovy/gradle/SharedConfiguration.groovy
+++
b/build-logic/src/main/groovy/org/apache/groovy/gradle/SharedConfiguration.groovy
@@ -20,6 +20,7 @@ package org.apache.groovy.gradle
import groovy.transform.CompileStatic
import org.gradle.StartParameter
+import org.gradle.api.execution.TaskExecutionGraph
import org.gradle.api.file.Directory
import org.gradle.api.file.ProjectLayout
import org.gradle.api.file.RegularFile
@@ -32,6 +33,24 @@ import org.gradle.api.tasks.Nested
@CompileStatic
class SharedConfiguration {
+ private static final List<String> DOCUMENTATION_TASK_NAMES = [
+ 'asciidocAll',
+ 'asciidoctor',
+ 'asciidoctorPdf',
+ 'doc',
+ 'docGDK',
+ 'dist',
+ 'distBin',
+ 'distDoc',
+ 'distSdk',
+ 'groovydocAll',
+ 'javadocAll'
+ ]
+ private static final List<String> APACHE_PUBLISH_TASK_PATHS = [
+ ':artifactoryPublish',
+ ':publishAllPublicationsToApacheRepository'
+ ]
+
final Provider<String> groovyVersion
final Provider<Boolean> isReleaseVersion
final Provider<Date> buildDate
@@ -114,7 +133,8 @@ class SharedConfiguration {
normalized.contains('docgdk') ||
normalized == 'dist' ||
normalized.startsWith('dist') ||
- normalized.contains(':dist')
+ normalized.contains(':dist') ||
+ matchesTaskAbbreviation(taskName, DOCUMENTATION_TASK_NAMES)
}
private static boolean isApachePublishTask(String taskName) {
@@ -125,6 +145,79 @@ class SharedConfiguration {
normalized.endsWith(':publishAllPublicationsToApacheRepository')
}
+ // Gradle keeps the originally requested selector in
startParameter.taskNames and expands
+ // task abbreviations only later, after configuration. Recognize
camel-case prefixes here
+ // so requests like `jA` still opt into the documentation wiring they
resolve to.
+ private static boolean matchesTaskAbbreviation(String taskName,
List<String> candidateTaskNames) {
+ String selector = taskSelector(taskName)
+ selector && candidateTaskNames.any { String candidateTaskName ->
+ matchesTaskSelector(selector, candidateTaskName)
+ }
+ }
+
+ private static String taskSelector(String taskName) {
+ String normalized = taskName.trim()
+ int lastSeparator = normalized.lastIndexOf(':')
+ lastSeparator >= 0 ? normalized.substring(lastSeparator + 1) :
normalized
+ }
+
+ private static boolean matchesTaskSelector(String requestedTaskName,
String actualTaskName) {
+ if (actualTaskName.regionMatches(true, 0, requestedTaskName, 0,
requestedTaskName.length())) {
+ return true
+ }
+
+ List<String> requestedSegments = taskNameSegments(requestedTaskName)
+ List<String> actualSegments = taskNameSegments(actualTaskName)
+ if (requestedSegments.size() > actualSegments.size()) {
+ return false
+ }
+
+ for (int i = 0; i < requestedSegments.size(); i += 1) {
+ String requestedSegment =
requestedSegments.get(i).toLowerCase(Locale.ROOT)
+ String actualSegment =
actualSegments.get(i).toLowerCase(Locale.ROOT)
+ if (!actualSegment.startsWith(requestedSegment)) {
+ return false
+ }
+ }
+ true
+ }
+
+ private static List<String> taskNameSegments(String taskName) {
+ List<String> segments = []
+ StringBuilder currentSegment = new StringBuilder()
+ for (int i = 0; i < taskName.length(); i += 1) {
+ char current = taskName.charAt(i)
+ if (current in ['-', '_', '.']) {
+ if (currentSegment.length() > 0) {
+ segments.add(currentSegment.toString())
+ currentSegment.setLength(0)
+ }
+ continue
+ }
+ if (currentSegment.length() > 0 && startsNewSegment(taskName, i,
currentSegment.charAt(currentSegment.length() - 1))) {
+ segments.add(currentSegment.toString())
+ currentSegment.setLength(0)
+ }
+ currentSegment.append(current)
+ }
+ if (currentSegment.length() > 0) {
+ segments.add(currentSegment.toString())
+ }
+ segments
+ }
+
+ private static boolean startsNewSegment(String taskName, int index, char
previous) {
+ char current = taskName.charAt(index)
+ if (!Character.isUpperCase(current)) {
+ return false
+ }
+ if (Character.isLowerCase(previous)) {
+ return true
+ }
+ int nextIndex = index + 1
+ nextIndex < taskName.length() &&
Character.isLowerCase(taskName.charAt(nextIndex))
+ }
+
static class Artifactory {
final Provider<String> username
final Provider<String> password
@@ -199,6 +292,13 @@ class SharedConfiguration {
(forceSign.get() || apachePublishRequested))
}
+ boolean shouldSign(TaskExecutionGraph taskGraph) {
+ trySign.get() || (config.isReleaseVersion.get() &&
+ (forceSign.get() || apachePublishRequested ||
APACHE_PUBLISH_TASK_PATHS.any {
+ taskGraph.hasTask(it)
+ }))
+ }
+
boolean hasAllKeyDetails() {
return useGpgCmd.get() ||
keyId.present && secretKeyRingFile.present &&
password.present