codeconsole commented on code in PR #43:
URL:
https://github.com/apache/grails-gradle-publish/pull/43#discussion_r4189817686
##########
plugin/src/main/groovy/org/apache/grails/gradle/publish/GrailsPublishGradlePlugin.groovy:
##########
@@ -1080,20 +1056,65 @@ Note: properties are read as Gradle properties (the
root project's gradle.proper
}.join('\n') + '\n'
}
- /** The versions of the artifacts resolved by the named configurations,
keyed by `group:name` */
+ /**
+ * The versions of the components resolved by the named configurations,
keyed by `group:name`. Nothing is resolved
+ * until the provider is queried, and nothing at all while
`transitiveDependencies` is disabled. A task action reads
+ * the versions through this provider instead of the project: with the
configuration cache, the provider is
+ * evaluated when the cache entry is stored, and a build reusing the entry
reads the stored versions.
+ */
+ protected static Provider<Map<String, String>>
resolvedVersionsProvider(Project project, Provider<Boolean> enabled,
List<String> configurationNames) {
+ ConfigurationContainer configurations = project.configurations
+ List<String> names = new ArrayList<>(configurationNames)
+ project.provider {
+ enabled.get() ? resolvedVersions(configurations, names) : [:] as
Map<String, String>
+ }
+ }
+
+ /** The versions of the components resolved by the named configurations,
keyed by `group:name` */
protected static Map<String, String> resolvedVersions(Project project,
List<String> configurationNames) {
+ resolvedVersions(project.configurations, configurationNames)
+ }
+
+ /**
+ * The versions of the components resolved by the named configurations,
keyed by `group:name`; for a module
+ * resolved by more than one of them, the version of the configuration
listed first. Configurations that do not
+ * exist are skipped.
+ */
+ protected static Map<String, String>
resolvedVersions(ConfigurationContainer configurations, List<String>
configurationNames) {
Map<String, String> versions = [:]
for (String configurationName : configurationNames) {
- def configuration =
project.configurations.findByName(configurationName)
+ Configuration configuration =
configurations.findByName(configurationName)
if (configuration != null) {
- for (ResolvedArtifact artifact :
configuration.resolvedConfiguration.resolvedArtifacts) {
-
versions.putIfAbsent("${artifact.moduleVersion.id.group}:${artifact.moduleVersion.id.name}"
as String, artifact.moduleVersion.id.version)
- }
+
collectResolvedVersions(configuration.incoming.resolutionResult.rootComponent.get(),
versions)
}
}
versions
}
+ /** Adds the version of every component the root component depends on,
directly or transitively */
+ private static void collectResolvedVersions(ResolvedComponentResult root,
Map<String, String> versions) {
+ Set<ResolvedComponentResult> visited = [] as
Set<ResolvedComponentResult>
+ Deque<ResolvedComponentResult> pending = new ArrayDeque<>()
+ pending.add(root)
+ while (!pending.isEmpty()) {
+ ResolvedComponentResult component = pending.poll()
+ for (DependencyResult dependency : component.dependencies) {
+ if (!(dependency instanceof ResolvedDependencyResult)) {
Review Comment:
**Unresolved dependencies are now skipped without any error, and with the
configuration cache a temporary failure can get stored in the entry**
The old code used `resolvedConfiguration.resolvedArtifacts`, which threw a
`ResolveException` when any edge failed. `incoming.resolutionResult` does not
throw on failed edges. It reports them as `UnresolvedDependencyResult`, and
this loop skips them.
Example: the repository is down (or returns 401) when the configuration
cache entry for `publish` is stored. A platform managed `testFixturesApi
'org.apache.groovy:groovy-json'` is unresolved and gets skipped, and the stored
map has no entry for it. The pom task then fails with `No version found for
dependency org.apache.groovy:groovy-json.`, which hides the real resolution
error. The entry is stored before execution, and unresolved edges do not appear
to be tracked as a cache input. So later builds can reuse the same incomplete
map and keep failing after the repository is back. With the old strict
resolution, storing the entry would itself have failed and nothing would have
been cached.
A second effect: a resolution failure on any of the four classpaths used to
stop the publish. It now passes silently whenever every pom dependency already
has a version.
Possible fix: collect the `UnresolvedDependencyResult` failures and rethrow
them (or at least report them) when a version lookup misses.
##########
plugin/src/functionalTest/resources/publish-projects/other-artifacts/gradle-plugin-project/build.gradle:
##########
@@ -79,4 +79,13 @@ if (System.getenv('PUBLISH_SHARED_ARTIFACTS')) {
publicationName = 'maven'
addComponents = true
}
+
+ // Both publications write the same coordinates, each with its own pom.
With the configuration cache, tasks of a
+ // project run in parallel, so publish one after the other, keeping the
files of one publication from being mixed
+ // with the signatures of the other
+ tasks.withType(AbstractPublishToMaven).configureEach { task ->
Review Comment:
**This fixes the parallel publish race only in the test fixture, not in the
plugin**
With the configuration cache, tasks of the same project run in parallel. Two
publications that write the same coordinates can then interleave their files
and signatures. The plugin itself says it supports this setup
(`GrailsPublishGradlePlugin` lines 523-529: "a build can still add one to
several publications") and already orders publish tasks after `Sign` for it.
But the ordering between the publish tasks is only added here, in the test
build script.
Example: a user build shaped like `PUBLISH_SHARED_ARTIFACTS` turns on the
configuration cache, as the new README section invites.
`publishPluginMavenPublicationTo*` and `publishMavenPublicationTo*` run at the
same time. The published `.pom`/`.module` can end up next to the `.asc` of the
other publication, and signature verification fails in the staging repository.
Possible fix: add the ordering in the plugin, for publications that share
coordinates or for all `AbstractPublishToMaven` tasks of the project that
target the same repository.
##########
plugin/src/functionalTest/groovy/org/apache/grails/gradle/publish/examples/ContainerizedReleaseSpec.groovy:
##########
@@ -106,7 +106,10 @@ class ContainerizedReleaseSpec extends
ExampleProjectSpecification {
ExecResult build = container.execInContainer(ExecConfig.builder()
.workDir('/project')
.envVars(environment)
- .command((['gradle', '--no-daemon', '--stacktrace',
'--init-script', '/init/local-plugin.init.gradle']
+ // the container has its own Gradle user home, so the
configuration cache is enabled here, as it is for
+ // the builds run by the test kit (see GradleSpecification)
+ .command((['gradle', '--no-daemon', '--stacktrace',
'--configuration-cache', '--configuration-cache-problems=fail',
Review Comment:
**This build can never store a configuration cache entry, so the
configuration cache flags here test nothing**
This invocation runs `closeSonatypeStagingRepository`, which this PR marks
`notCompatibleWithConfigurationCache`. It also publishes with explicit Nexus
credentials, which Gradle degrades on ("Explicit credentials are unsupported
with the Configuration Cache"). So the build always runs without storing an
entry, and none of the release path task state (Sign,
InitializeNexusStagingRepository, the Nexus publish tasks) is ever serialized.
Example: a later change makes one of those tasks hold state that cannot be
serialized, such as a closure capturing the project. This test still passes,
which contradicts the comment above and the PR description ("fails on any
problem, including the containerized release").
Possible fix: assert on the configuration cache outcome you expect (for
example, that the transition task is the only reported degradation reason), or
drop the claim.
##########
plugin/src/main/groovy/org/apache/grails/gradle/publish/GrailsPublishGradlePlugin.groovy:
##########
@@ -351,6 +357,14 @@ Note: properties are read as Gradle properties (the root
project's gradle.proper
}
}
+ // The close and release tasks of the Nexus publish plugin (2.0.0)
cannot be stored in the configuration
+ // cache when they run without its publishing tasks, as in a
release closing the staging repository in a
+ // separate build: their transition check options reach the Nexus
extension, and through it the project.
+ // Gradle then runs such a build without storing a configuration
cache entry instead of failing it.
+
project.rootProject.tasks.withType(AbstractTransitionNexusStagingRepositoryTask).configureEach
{ AbstractTransitionNexusStagingRepositoryTask task ->
Review Comment:
**This marking is added again by every subproject, unconditionally, and it
configures another project's tasks**
`project.rootProject.tasks.withType(...).configureEach` runs once for each
subproject that applies the plugin with Nexus publishing. In a build shaped
like grails-core, every transition task gets N identical
`notCompatibleWithConfigurationCache` actions. The marking also applies to
combined `publishToSonatype close...` builds, which the comment above says can
be stored. It also adds another cross-project configuration of the root
project. Isolated Projects reports that as a violation, and the plugin
otherwise guards against it (`findProjectProperty`, line 219).
Possible fix: register the marking once, for example only where
`rootProjectPluginManager.apply(NexusPublishPlugin)` runs, or behind a flag on
the root project.
##########
plugin/src/main/groovy/org/apache/grails/gradle/publish/GrailsPublishGradlePlugin.groovy:
##########
@@ -801,7 +791,24 @@ Note: properties are read as Gradle properties (the root
project's gradle.proper
}
}
+ /**
+ * Sets the versions of the pom dependencies declared without one from the
versions resolved by the named
+ * configurations of the project.
+ *
+ * @deprecated reads the project when the pom is generated, which the
configuration cache does not allow; the
+ * plugin itself uses {@link #setDependencyVersions(Node,
Provider)}
+ */
+ @Deprecated
protected void setDependencyVersions(Node pomNode, Project project,
List<String> configurationNames) {
Review Comment:
**Subclasses that override this method are now silently bypassed**
The plugin no longer calls `setDependencyVersions(Node, Project, List)`.
`PomXmlAction` calls the new `static setDependencyVersions(Node, Provider)`
directly, and a static method cannot be overridden. This class is meant to be
extended (protected hooks, and the injected getter is there "so plugins
extending this one keep working").
Example: a subclass overrides this method to pick versions differently or to
tolerate missing ones. After this change its override never runs, the published
pom changes (or the build fails with `No version found`), and the subclass gets
no compile error. The only warning is the `@Deprecated` marker, and that only
shows up when the method is called, which no longer happens.
##########
plugin/src/main/groovy/org/apache/grails/gradle/publish/GrailsPublishGradlePlugin.groovy:
##########
@@ -1233,5 +1254,114 @@ Note: properties are read as Gradle properties (the
root project's gradle.proper
}
}
}
-}
+ /**
+ * Completes the generated pom: removes the dependencyManagement section
(unless the project is a platform),
+ * applies the pom customization, and fills in the versions of
dependencies declared without one.
+ *
+ * The action is part of the state of the pom generation task, so it only
holds values and providers, which keeps
+ * it compatible with the configuration cache. The versions are read from
a provider, which the configuration
+ * cache evaluates when it stores the task.
+ */
+ @PackageScope
+ static class PomXmlAction implements Action<XmlProvider> {
+
+ private final MavenPom pom
+ private final boolean javaPlatform
+ private final Provider<Closure> pomCustomization
+ private final Provider<Boolean> transitiveDependencies
+ private final Provider<Map<String, String>> resolvedVersions
+
+ PomXmlAction(MavenPom pom, boolean javaPlatform, Provider<Closure>
pomCustomization,
+ Provider<Boolean> transitiveDependencies,
Provider<Map<String, String>> resolvedVersions) {
+ this.pom = pom
+ this.javaPlatform = javaPlatform
+ this.pomCustomization = pomCustomization
+ this.transitiveDependencies = transitiveDependencies
+ this.resolvedVersions = resolvedVersions
+ }
+
+ @Override
+ void execute(XmlProvider xml) {
+ Node pomNode = xml.asNode()
+
+ if (!javaPlatform) {
+ // Spring boot dependency management plugin will add the
dependencyManagement section,
+ // we do not want to publish this information as we will
determine the specific versions
+ // and set them instead
+ NodeList dependencyManagement = (NodeList)
pomNode.get('dependencyManagement')
+ if (dependencyManagement) {
+ dependencyManagement.replaceNode {}
+ }
+ }
+
+ if (pomCustomization.isPresent()) {
+ Closure customization = pomCustomization.get()
+ customization.delegate = pom
+ customization.resolveStrategy = Closure.DELEGATE_FIRST
+ customization.call(xml)
+ }
+
+ // fix dependencies without a version, this can occur when the
spring dependency management plugin is used
+ // disabling that plugin will cause gradle to fail on any
unresolved, or by disabling the check with:
+ // https://github.com/gradle/gradle/issues/23030
+ //tasks.withType(GenerateModuleMetadata).configureEach {
+ //
suppressedValidationErrors.add('dependencies-without-versions')
+ //}
+ if (transitiveDependencies.get()) {
+ setDependencyVersions(pomNode, resolvedVersions)
+ }
+ }
+ }
+
+ /**
+ * Fills in the versions the Gradle module metadata is missing, see
+ * {@link #configureModuleMetadataVersions(Project,
GrailsPublishExtension, String, List)}.
+ *
+ * The action is part of the state of the module metadata task, so it only
holds values and providers, which keeps
+ * it compatible with the configuration cache. The versions are read from
a provider, which the configuration
+ * cache evaluates when it stores the task.
+ */
+ @PackageScope
+ static class ModuleMetadataVersionsAction implements Action<Task> {
+
+ private final String publicationName
+ private final Provider<Boolean> transitiveDependencies
+ private final Provider<Map<String, String>> resolvedVersions
+
+ ModuleMetadataVersionsAction(String publicationName, Provider<Boolean>
transitiveDependencies,
+ Provider<Map<String, String>>
resolvedVersions) {
+ this.publicationName = publicationName
+ this.transitiveDependencies = transitiveDependencies
+ this.resolvedVersions = resolvedVersions
+ }
+
+ @Override
+ void execute(Task task) {
+ if (!transitiveDependencies.get()) {
+ return
+ }
+ File moduleFile = ((GenerateModuleMetadata)
task).outputFile.get().asFile
+ Map<String, String> versions = resolvedVersions.get()
+ Map module = new JsonSlurper().parse(moduleFile, 'UTF-8') as Map
+ boolean changed = false
+ for (Map variant : (module.variants ?: []) as List<Map>) {
+ for (Map dependency : (variant.dependencies ?: []) as
List<Map>) {
+ Map version = dependency.version as Map
+ if (version?.requires || version?.strictly ||
version?.prefers) {
+ continue
+ }
+ String resolved =
versions["${dependency.group}:${dependency.module}" as String]
+ if (resolved == null) {
+ throw new InvalidUserDataException("No version found
for dependency ${dependency.group}:${dependency.module} of variant
${variant.name} in the module metadata of publication ${publicationName}.")
+ }
+ dependency.version = [requires: resolved]
Review Comment:
**Filling in a missing version replaces the whole `version` object, so
`rejects` is lost**
The skip check only looks at `requires`, `strictly` and `prefers`. A
dependency whose version object has only `rejects` is therefore treated as
missing a version, and `dependency.version = [requires: resolved]` overwrites
the whole object.
Example: `testFixturesApi('org.example:lib') { version { reject '1.0.0' }
}`, managed by a platform. Gradle writes `"version": {"rejects": ["1.0.0"]}`.
This action replaces it with `{"requires": "1.1.0"}`, and consumers lose the
reject.
Possible fix: merge into the existing map (`(version ?: [:]) + [requires:
resolved]`).
##########
README.md:
##########
@@ -270,6 +270,28 @@ capability, so consumers that do not explicitly request
the capability are unaff
tree is also what allows Gradle to resolve a project dependency (including a
self dependency such as
`cliApi project(path)`) on a project with multiple publications.
+### Configuration Cache
+
+The plugin is compatible with the [configuration
cache](https://docs.gradle.org/current/userguide/configuration_cache.html),
+publishing included. The versions written into the pom and the Gradle module
metadata for dependencies declared without
+one (when `transitiveDependencies` is enabled, the default) are resolved when
the configuration cache entry is stored,
+and a build reusing the entry publishes them without resolving the
configurations again.
+
+The `pomCustomization` closure is stored with the task generating the pom, so
it must only use its `XmlProvider`
+argument and the pom it is delegated to, not the project or other state of the
build script. Read any other value it
+needs into a local variable beforehand, as the
[bom](examples/bom/build.gradle) example does.
+
+Some builds still cannot store a configuration cache entry, because of the
plugins this one works with:
+
+- Gradle does not store publishing tasks of a repository with explicit
credentials (the `MAVEN_PUBLISH_` and
Review Comment:
**Credentialed publishing, the common case, still never stores an entry,
partly because of how the plugin sets credentials**
The plugin sets the `MAVEN_PUBLISH_*` credentials explicitly
(`repo.credentials { credentials.username = ...; credentials.password = ... }`,
lines 409-412). That is exactly what Gradle degrades on
(`MavenPublishPlugin.usingExplicitCredentials`: "Explicit credentials are
unsupported with the Configuration Cache"). So every real snapshot or release
publish to an authenticated repository still runs without storing an entry.
Only repositories without credentials store one, as in the new tests.
Possible fix at the root cause, at least for the plugin's own `maven`
repository: use Gradle's identity based
`repo.credentials(PasswordCredentials)`, which reads the
`mavenUsername`/`mavenPassword` Gradle properties (for example
`ORG_GRADLE_PROJECT_mavenUsername`), and keep the explicit environment variable
path as a fallback.
##########
plugin/src/main/groovy/org/apache/grails/gradle/publish/GrailsPublishGradlePlugin.groovy:
##########
@@ -1035,36 +1032,15 @@ Note: properties are read as Gradle properties (the
root project's gradle.proper
* resolved classpaths the pom is completed from.
*/
protected void configureModuleMetadataVersions(Project project,
GrailsPublishExtension gpe, String publicationName, List<String>
configurationNames) {
+ // the action runs when the module metadata is generated, so it is
given values and providers only: with the
+ // configuration cache, neither the project nor this extension is
available then
+ Provider<Boolean> transitiveDependencies = gpe.transitiveDependencies
+ Provider<Map<String, String>> resolvedVersions =
resolvedVersionsProvider(project, transitiveDependencies, configurationNames)
Review Comment:
**Each publication gets two separate resolved-version providers**
`configurePom` (line 675) and this method each call
`resolvedVersionsProvider` for the same configurations. With the configuration
cache, both providers are evaluated when the entry is stored. That walks up to
four resolution graphs twice per publication and stores two copies of the full
transitive version map in the entry.
Possible fix: create one provider per publication in the `afterEvaluate`
block and pass it to both `configurePom` and `configureModuleMetadataVersions`.
##########
plugin/src/main/groovy/org/apache/grails/gradle/publish/GrailsPublishGradlePlugin.groovy:
##########
@@ -815,26 +822,16 @@ Note: properties are read as Gradle properties (the root
project's gradle.proper
}
NodeList dependencyNodes = (nodes.get(0) as
Node).getAt(dependencyQName) as NodeList
- LinkedHashSet<ResolvedArtifact> resolvedArtifacts = []
- for (String configurationName : configurationNames) {
- def configuration =
project.configurations.findByName(configurationName)
- if (configuration != null) {
-
resolvedArtifacts.addAll(configuration.resolvedConfiguration.resolvedArtifacts)
- }
- }
-
- dependencyNodes.findAll { dependencyNode ->
+ Map<String, String> versions = resolvedVersions.get()
Review Comment:
**`resolvedVersions.get()` runs before the code checks whether any
dependency is missing a version**
The same happens at line 1345 for the module metadata. Without the
configuration cache (the default for most builds), every pom and module
generation resolves up to four classpaths, even when version mapping already
wrote every version, which is the usual case. The javadoc says "only queried
when the pom has dependencies", which promises more laziness than the code
delivers.
Possible fix: call `get()` only once `dependenciesWithoutVersion` is
non-empty, and in the module action, only on the first dependency without a
version.
##########
plugin/src/main/groovy/org/apache/grails/gradle/publish/GrailsPublishGradlePlugin.groovy:
##########
@@ -1233,5 +1254,114 @@ Note: properties are read as Gradle properties (the
root project's gradle.proper
}
}
}
-}
+ /**
+ * Completes the generated pom: removes the dependencyManagement section
(unless the project is a platform),
+ * applies the pom customization, and fills in the versions of
dependencies declared without one.
+ *
+ * The action is part of the state of the pom generation task, so it only
holds values and providers, which keeps
+ * it compatible with the configuration cache. The versions are read from
a provider, which the configuration
+ * cache evaluates when it stores the task.
+ */
+ @PackageScope
+ static class PomXmlAction implements Action<XmlProvider> {
+
+ private final MavenPom pom
+ private final boolean javaPlatform
+ private final Provider<Closure> pomCustomization
+ private final Provider<Boolean> transitiveDependencies
+ private final Provider<Map<String, String>> resolvedVersions
+
+ PomXmlAction(MavenPom pom, boolean javaPlatform, Provider<Closure>
pomCustomization,
+ Provider<Boolean> transitiveDependencies,
Provider<Map<String, String>> resolvedVersions) {
+ this.pom = pom
+ this.javaPlatform = javaPlatform
+ this.pomCustomization = pomCustomization
+ this.transitiveDependencies = transitiveDependencies
+ this.resolvedVersions = resolvedVersions
+ }
+
+ @Override
+ void execute(XmlProvider xml) {
+ Node pomNode = xml.asNode()
+
+ if (!javaPlatform) {
+ // Spring boot dependency management plugin will add the
dependencyManagement section,
+ // we do not want to publish this information as we will
determine the specific versions
+ // and set them instead
+ NodeList dependencyManagement = (NodeList)
pomNode.get('dependencyManagement')
+ if (dependencyManagement) {
+ dependencyManagement.replaceNode {}
+ }
+ }
+
+ if (pomCustomization.isPresent()) {
+ Closure customization = pomCustomization.get()
+ customization.delegate = pom
+ customization.resolveStrategy = Closure.DELEGATE_FIRST
+ customization.call(xml)
+ }
+
+ // fix dependencies without a version, this can occur when the
spring dependency management plugin is used
+ // disabling that plugin will cause gradle to fail on any
unresolved, or by disabling the check with:
+ // https://github.com/gradle/gradle/issues/23030
+ //tasks.withType(GenerateModuleMetadata).configureEach {
+ //
suppressedValidationErrors.add('dependencies-without-versions')
+ //}
+ if (transitiveDependencies.get()) {
+ setDependencyVersions(pomNode, resolvedVersions)
+ }
+ }
+ }
+
+ /**
+ * Fills in the versions the Gradle module metadata is missing, see
+ * {@link #configureModuleMetadataVersions(Project,
GrailsPublishExtension, String, List)}.
+ *
+ * The action is part of the state of the module metadata task, so it only
holds values and providers, which keeps
+ * it compatible with the configuration cache. The versions are read from
a provider, which the configuration
+ * cache evaluates when it stores the task.
+ */
+ @PackageScope
+ static class ModuleMetadataVersionsAction implements Action<Task> {
+
+ private final String publicationName
+ private final Provider<Boolean> transitiveDependencies
+ private final Provider<Map<String, String>> resolvedVersions
+
+ ModuleMetadataVersionsAction(String publicationName, Provider<Boolean>
transitiveDependencies,
+ Provider<Map<String, String>>
resolvedVersions) {
+ this.publicationName = publicationName
+ this.transitiveDependencies = transitiveDependencies
+ this.resolvedVersions = resolvedVersions
+ }
+
+ @Override
+ void execute(Task task) {
+ if (!transitiveDependencies.get()) {
+ return
+ }
+ File moduleFile = ((GenerateModuleMetadata)
task).outputFile.get().asFile
+ Map<String, String> versions = resolvedVersions.get()
+ Map module = new JsonSlurper().parse(moduleFile, 'UTF-8') as Map
+ boolean changed = false
+ for (Map variant : (module.variants ?: []) as List<Map>) {
+ for (Map dependency : (variant.dependencies ?: []) as
List<Map>) {
+ Map version = dependency.version as Map
+ if (version?.requires || version?.strictly ||
version?.prefers) {
+ continue
+ }
+ String resolved =
versions["${dependency.group}:${dependency.module}" as String]
+ if (resolved == null) {
Review Comment:
**The pom and module paths handle an empty resolved version differently**
The pom path fails on `!managedVersion` (null or empty, line 835). This
check only fails on `null`, so an empty version is written into the module
metadata as `"requires": ""`.
Example: a project dependency on a sibling whose version resolves to `''`.
Pom generation fails with `No version found`, while the module metadata
publishes an empty version without any error. Use the same check (`if
(!resolved)`) in both places.
##########
plugin/src/main/groovy/org/apache/grails/gradle/publish/GrailsPublishGradlePlugin.groovy:
##########
@@ -1233,5 +1254,114 @@ Note: properties are read as Gradle properties (the
root project's gradle.proper
}
}
}
-}
+ /**
+ * Completes the generated pom: removes the dependencyManagement section
(unless the project is a platform),
+ * applies the pom customization, and fills in the versions of
dependencies declared without one.
+ *
+ * The action is part of the state of the pom generation task, so it only
holds values and providers, which keeps
+ * it compatible with the configuration cache. The versions are read from
a provider, which the configuration
+ * cache evaluates when it stores the task.
+ */
+ @PackageScope
+ static class PomXmlAction implements Action<XmlProvider> {
+
+ private final MavenPom pom
+ private final boolean javaPlatform
+ private final Provider<Closure> pomCustomization
+ private final Provider<Boolean> transitiveDependencies
+ private final Provider<Map<String, String>> resolvedVersions
+
+ PomXmlAction(MavenPom pom, boolean javaPlatform, Provider<Closure>
pomCustomization,
+ Provider<Boolean> transitiveDependencies,
Provider<Map<String, String>> resolvedVersions) {
+ this.pom = pom
+ this.javaPlatform = javaPlatform
+ this.pomCustomization = pomCustomization
+ this.transitiveDependencies = transitiveDependencies
+ this.resolvedVersions = resolvedVersions
+ }
+
+ @Override
+ void execute(XmlProvider xml) {
+ Node pomNode = xml.asNode()
+
+ if (!javaPlatform) {
+ // Spring boot dependency management plugin will add the
dependencyManagement section,
+ // we do not want to publish this information as we will
determine the specific versions
+ // and set them instead
+ NodeList dependencyManagement = (NodeList)
pomNode.get('dependencyManagement')
+ if (dependencyManagement) {
+ dependencyManagement.replaceNode {}
+ }
+ }
+
+ if (pomCustomization.isPresent()) {
+ Closure customization = pomCustomization.get()
+ customization.delegate = pom
+ customization.resolveStrategy = Closure.DELEGATE_FIRST
+ customization.call(xml)
+ }
+
+ // fix dependencies without a version, this can occur when the
spring dependency management plugin is used
+ // disabling that plugin will cause gradle to fail on any
unresolved, or by disabling the check with:
+ // https://github.com/gradle/gradle/issues/23030
+ //tasks.withType(GenerateModuleMetadata).configureEach {
Review Comment:
**Commented-out code moved into the new action**
The commented `tasks.withType(GenerateModuleMetadata)...` snippet came along
into `PomXmlAction`. There is no `tasks` in scope here, and reaching project
state from this action is exactly what the class exists to avoid. Consider
deleting it, together with the trailing "or by disabling the check with:", or
moving the note to `configureModuleMetadataVersions`.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]