diff --git a/pom.xml b/pom.xml
index c6ec6c28..de5f87b5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -229,6 +229,12 @@ under the License.
verify
${project.build.directory}/local-repo
src/it/settings.xml
+
+ ${project.build.directory}/remote-repo
+
+
+ ${project.build.directory}/remote-repo
+
deploy
diff --git a/src/it/deploy-at-end-pass/module2/pom.xml b/src/it/deploy-at-end-pass/module2/pom.xml
new file mode 100644
index 00000000..827396fe
--- /dev/null
+++ b/src/it/deploy-at-end-pass/module2/pom.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+ 4.0.0
+
+
+ org.apache.maven.its.deploy.dae.pass
+ dae
+ 1.0
+
+ module2
+
+
+
+
+ org.apache.maven.plugins
+ maven-deploy-plugin
+
+
+ default-deploy
+ none
+
+
+
+
+
+
diff --git a/src/it/deploy-at-end-pass/module3/pom.xml b/src/it/deploy-at-end-pass/module3/pom.xml
new file mode 100644
index 00000000..48c9caa0
--- /dev/null
+++ b/src/it/deploy-at-end-pass/module3/pom.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+ 4.0.0
+
+
+ org.apache.maven.its.deploy.dae.pass
+ dae
+ 1.0
+
+ module3
+
+
diff --git a/src/it/deploy-at-end-pass/module4/pom.xml b/src/it/deploy-at-end-pass/module4/pom.xml
new file mode 100644
index 00000000..05f07629
--- /dev/null
+++ b/src/it/deploy-at-end-pass/module4/pom.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+ 4.0.0
+
+
+ org.apache.maven.its.deploy.dae.pass
+ dae
+ 1.0
+
+ module4
+
+
+ without-deploy
+
+
+
+
+ org.apache.maven.its.deploy.mock
+ mock-phase-maven-plugin
+ 1.0
+ true
+
+
+
+
diff --git a/src/it/deploy-at-end-pass/pom.xml b/src/it/deploy-at-end-pass/pom.xml
index 04250d5a..90ed655c 100644
--- a/src/it/deploy-at-end-pass/pom.xml
+++ b/src/it/deploy-at-end-pass/pom.xml
@@ -38,7 +38,7 @@ under the License.
it
- file:///${basedir}/target/repo
+ file:///@remoteRepo@/deploy-at-end-pass
@@ -95,5 +95,8 @@ under the License.
module1
+ module2
+ module3
+ module4
diff --git a/src/it/deploy-at-end-pass/verify.groovy b/src/it/deploy-at-end-pass/verify.groovy
index 634808a5..6aedbb57 100644
--- a/src/it/deploy-at-end-pass/verify.groovy
+++ b/src/it/deploy-at-end-pass/verify.groovy
@@ -17,10 +17,15 @@
* under the License.
*/
-assert new File( basedir, "target/repo/org/apache/maven/its/deploy/dae/pass/dae/1.0/dae-1.0.pom" ).exists()
-assert new File( basedir, "module1/target/repo/org/apache/maven/its/deploy/dae/pass/module1/1.0/module1-1.0.pom" ).exists()
+assert new File( remoteRepo, "deploy-at-end-pass/org/apache/maven/its/deploy/dae/pass/dae/1.0/dae-1.0.pom" ).exists()
+assert new File( remoteRepo, "deploy-at-end-pass/org/apache/maven/its/deploy/dae/pass/module1/1.0/module1-1.0.pom" ).exists()
+assert new File( remoteRepo, "deploy-at-end-pass/org/apache/maven/its/deploy/dae/pass/module1/1.0/module1-1.0.jar" ).exists()
+assert new File( remoteRepo, "deploy-at-end-pass/org/apache/maven/its/deploy/dae/pass/module3/1.0/module3-1.0.pom" ).exists()
+assert new File( remoteRepo, "deploy-at-end-pass/org/apache/maven/its/deploy/dae/pass/module3/1.0/module3-1.0.jar" ).exists()
File buildLog = new File( basedir, 'build.log' )
assert buildLog.exists()
assert buildLog.text.contains( "[INFO] Deferring deploy for org.apache.maven.its.deploy.dae.pass:dae:1.0 at end" )
+assert buildLog.text.contains( "[INFO] Deferring deploy for org.apache.maven.its.deploy.dae.pass:module1:1.0 at end" )
+assert buildLog.text.contains( "[INFO] Deferring deploy for org.apache.maven.its.deploy.dae.pass:module3:1.0 at end" )
diff --git a/src/it/setup-mock-phase-maven-plugin/invoker.properties b/src/it/setup-mock-phase-maven-plugin/invoker.properties
new file mode 100644
index 00000000..d5d6ca5d
--- /dev/null
+++ b/src/it/setup-mock-phase-maven-plugin/invoker.properties
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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
+#
+# http://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.
+
+invoker.goals = install
diff --git a/src/it/setup-mock-phase-maven-plugin/pom.xml b/src/it/setup-mock-phase-maven-plugin/pom.xml
new file mode 100644
index 00000000..4ebb8af5
--- /dev/null
+++ b/src/it/setup-mock-phase-maven-plugin/pom.xml
@@ -0,0 +1,57 @@
+
+
+
+
+
+ 4.0.0
+
+ org.apache.maven.its.deploy.mock
+ mock-phase-maven-plugin
+ 1.0
+ maven-plugin
+
+
+ @mavenVersion@
+
+
+ plugin with Maven phase without m-deploy-p
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-install-plugin
+ @mavenInstallPluginVersion@
+
+
+ org.apache.maven.plugins
+ maven-plugin-plugin
+ @mavenPluginToolsVersion@
+
+ true
+
+
+
+
+
+
+
diff --git a/src/it/setup-mock-phase-maven-plugin/src/main/resources/META-INF/plexus/components.xml b/src/it/setup-mock-phase-maven-plugin/src/main/resources/META-INF/plexus/components.xml
new file mode 100644
index 00000000..93e017ca
--- /dev/null
+++ b/src/it/setup-mock-phase-maven-plugin/src/main/resources/META-INF/plexus/components.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+ org.apache.maven.lifecycle.mapping.LifecycleMapping
+ without-deploy
+ org.apache.maven.lifecycle.mapping.DefaultLifecycleMapping
+
+
+
+ default
+
+ org.apache.maven.plugins:maven-resources-plugin:resources
+
+
+
+
+
+
+
diff --git a/src/main/java/org/apache/maven/plugins/deploy/AbstractDeployMojo.java b/src/main/java/org/apache/maven/plugins/deploy/AbstractDeployMojo.java
index 33ecad0b..2c5c1d9c 100644
--- a/src/main/java/org/apache/maven/plugins/deploy/AbstractDeployMojo.java
+++ b/src/main/java/org/apache/maven/plugins/deploy/AbstractDeployMojo.java
@@ -26,7 +26,6 @@
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.rtinfo.RuntimeInformation;
import org.eclipse.aether.RepositorySystem;
-import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.deployment.DeployRequest;
import org.eclipse.aether.deployment.DeploymentException;
import org.eclipse.aether.repository.RemoteRepository;
@@ -122,10 +121,13 @@ protected RemoteRepository getRemoteRepository(final String repositoryId, final
return result;
}
- /**
- * Handles high level retries (this was buried into MAT).
- */
- protected void deploy(RepositorySystemSession session, DeployRequest deployRequest) throws MojoExecutionException {
+ // I'm not sure if retries will work with deploying on client level ...
+ // Most repository managers block a duplicate artifacts.
+
+ // Eg, when we have an artifact list, even simple pom and jar in one request with released version,
+ // next try can fail due to duplicate.
+
+ protected void deploy(DeployRequest deployRequest) throws MojoExecutionException {
int retryFailedDeploymentCounter = Math.max(1, Math.min(10, retryFailedDeploymentCount));
DeploymentException exception = null;
for (int count = 0; count < retryFailedDeploymentCounter; count++) {
@@ -134,7 +136,7 @@ protected void deploy(RepositorySystemSession session, DeployRequest deployReque
getLog().info("Retrying deployment attempt " + (count + 1) + " of " + retryFailedDeploymentCounter);
}
- repositorySystem.deploy(session, deployRequest);
+ repositorySystem.deploy(session.getRepositorySession(), deployRequest);
exception = null;
break;
} catch (DeploymentException e) {
diff --git a/src/main/java/org/apache/maven/plugins/deploy/DeployMojo.java b/src/main/java/org/apache/maven/plugins/deploy/DeployMojo.java
index 09214174..806b3f33 100644
--- a/src/main/java/org/apache/maven/plugins/deploy/DeployMojo.java
+++ b/src/main/java/org/apache/maven/plugins/deploy/DeployMojo.java
@@ -19,6 +19,8 @@
package org.apache.maven.plugins.deploy;
import java.io.File;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
@@ -26,6 +28,8 @@
import org.apache.maven.RepositoryUtils;
import org.apache.maven.artifact.ArtifactUtils;
+import org.apache.maven.model.Plugin;
+import org.apache.maven.model.PluginExecution;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
@@ -34,10 +38,8 @@
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.artifact.ProjectArtifact;
-import org.apache.maven.project.artifact.ProjectArtifactMetadata;
import org.eclipse.aether.deployment.DeployRequest;
import org.eclipse.aether.repository.RemoteRepository;
-import org.eclipse.aether.util.artifact.SubArtifact;
/**
* Deploys an artifact to remote repository.
@@ -63,7 +65,6 @@ public class DeployMojo extends AbstractDeployMojo {
/**
* Whether every project should be deployed during its own deploy-phase or at the end of the multimodule build. If
* set to {@code true} and the build fails, none of the reactor projects is deployed.
- * (experimental)
*
* @since 2.8
*/
@@ -176,17 +177,21 @@ public void execute() throws MojoExecutionException, MojoFailureException {
warnIfAffectedPackagingAndMaven(project.getPackaging());
if (!deployAtEnd) {
- deploy(
- session.getRepositorySession(),
- processProject(
- project,
- altSnapshotDeploymentRepository,
- altReleaseDeploymentRepository,
- altDeploymentRepository));
+
+ RemoteRepository deploymentRepository = getDeploymentRepository(
+ project,
+ altSnapshotDeploymentRepository,
+ altReleaseDeploymentRepository,
+ altDeploymentRepository);
+
+ DeployRequest request = new DeployRequest();
+ request.setRepository(deploymentRepository);
+ processProject(project, request);
+ deploy(request);
putState(State.DEPLOYED);
} else {
- putPluginContextValue(DEPLOY_ALT_RELEASE_DEPLOYMENT_REPOSITORY, altReleaseDeploymentRepository);
putPluginContextValue(DEPLOY_ALT_SNAPSHOT_DEPLOYMENT_REPOSITORY, altSnapshotDeploymentRepository);
+ putPluginContextValue(DEPLOY_ALT_RELEASE_DEPLOYMENT_REPOSITORY, altReleaseDeploymentRepository);
putPluginContextValue(DEPLOY_ALT_DEPLOYMENT_REPOSITORY, altDeploymentRepository);
putState(State.TO_BE_DEPLOYED);
getLog().info("Deferring deploy for " + project.getGroupId() + ":" + project.getArtifactId() + ":"
@@ -194,32 +199,41 @@ public void execute() throws MojoExecutionException, MojoFailureException {
}
}
- if (allProjectsMarked()) {
- for (MavenProject reactorProject : reactorProjects) {
+ List allProjectsUsingPlugin = getAllProjectsUsingPlugin();
+
+ if (allProjectsMarked(allProjectsUsingPlugin)) {
+ Map requests = new LinkedHashMap<>();
+
+ // collect all arifacts from all modules to deploy
+ // requests are grouped by used remote repository
+ for (MavenProject reactorProject : allProjectsUsingPlugin) {
Map pluginContext = session.getPluginContext(pluginDescriptor, reactorProject);
State state = getState(pluginContext);
if (state == State.TO_BE_DEPLOYED) {
- String altReleaseDeploymentRepository =
- getPluginContextValue(pluginContext, DEPLOY_ALT_RELEASE_DEPLOYMENT_REPOSITORY);
- String altSnapshotDeploymentRepository =
- getPluginContextValue(pluginContext, DEPLOY_ALT_SNAPSHOT_DEPLOYMENT_REPOSITORY);
- String altDeploymentRepository =
- getPluginContextValue(pluginContext, DEPLOY_ALT_DEPLOYMENT_REPOSITORY);
-
- deploy(
- session.getRepositorySession(),
- processProject(
- reactorProject,
- altSnapshotDeploymentRepository,
- altReleaseDeploymentRepository,
- altDeploymentRepository));
+
+ RemoteRepository deploymentRepository = getDeploymentRepository(
+ reactorProject,
+ getPluginContextValue(pluginContext, DEPLOY_ALT_SNAPSHOT_DEPLOYMENT_REPOSITORY),
+ getPluginContextValue(pluginContext, DEPLOY_ALT_RELEASE_DEPLOYMENT_REPOSITORY),
+ getPluginContextValue(pluginContext, DEPLOY_ALT_DEPLOYMENT_REPOSITORY));
+
+ DeployRequest request = requests.computeIfAbsent(deploymentRepository, repo -> {
+ DeployRequest newRequest = new DeployRequest();
+ newRequest.setRepository(repo);
+ return newRequest;
+ });
+ processProject(reactorProject, request);
}
}
+ // finally execute all deployments request, lets resolver to optimize deployment
+ for (DeployRequest request : requests.values()) {
+ deploy(request);
+ }
}
}
- private boolean allProjectsMarked() {
- for (MavenProject reactorProject : reactorProjects) {
+ private boolean allProjectsMarked(List allProjectsUsingPlugin) {
+ for (MavenProject reactorProject : allProjectsUsingPlugin) {
if (!hasState(reactorProject)) {
return false;
}
@@ -227,61 +241,58 @@ private boolean allProjectsMarked() {
return true;
}
- private DeployRequest processProject(
- final MavenProject project,
- final String altSnapshotDeploymentRepository,
- final String altReleaseDeploymentRepository,
- final String altDeploymentRepository)
- throws MojoExecutionException, MojoFailureException {
- DeployRequest request = new DeployRequest();
- request.setRepository(getDeploymentRepository(
- project, altSnapshotDeploymentRepository, altReleaseDeploymentRepository, altDeploymentRepository));
+ private List getAllProjectsUsingPlugin() {
+ ArrayList result = new ArrayList<>();
+ for (MavenProject reactorProject : reactorProjects) {
+ if (hasExecution(reactorProject.getPlugin("org.apache.maven.plugins:maven-deploy-plugin"))) {
+ result.add(reactorProject);
+ }
+ }
+ return result;
+ }
+
+ private boolean hasExecution(Plugin plugin) {
+ if (plugin == null) {
+ return false;
+ }
+
+ for (PluginExecution execution : plugin.getExecutions()) {
+ if (!execution.getGoals().isEmpty() && !"none".equalsIgnoreCase(execution.getPhase())) {
+ return true;
+ }
+ }
+ return false;
+ }
- org.apache.maven.artifact.Artifact mavenMainArtifact = project.getArtifact();
- String packaging = project.getPackaging();
- File pomFile = project.getFile();
- boolean isPomArtifact = "pom".equals(packaging);
- boolean pomArtifactAttached = false;
+ private void processProject(final MavenProject project, DeployRequest request) throws MojoExecutionException {
- if (pomFile != null) {
+ if (isFile(project.getFile())) {
request.addArtifact(RepositoryUtils.toArtifact(new ProjectArtifact(project)));
- pomArtifactAttached = true;
+ } else {
+ throw new MojoExecutionException("The project POM could not be attached");
}
- if (!isPomArtifact) {
- File file = mavenMainArtifact.getFile();
- if (file != null && file.isFile()) {
- org.eclipse.aether.artifact.Artifact mainArtifact = RepositoryUtils.toArtifact(mavenMainArtifact);
- request.addArtifact(mainArtifact);
-
- if (!pomArtifactAttached) {
- for (Object metadata : mavenMainArtifact.getMetadataList()) {
- if (metadata instanceof ProjectArtifactMetadata) {
- request.addArtifact(new SubArtifact(mainArtifact, "", "pom")
- .setFile(((ProjectArtifactMetadata) metadata).getFile()));
- pomArtifactAttached = true;
- }
- }
- }
+ if (!"pom".equals(project.getPackaging())) {
+ org.apache.maven.artifact.Artifact mavenMainArtifact = project.getArtifact();
+ if (isFile(mavenMainArtifact.getFile())) {
+ request.addArtifact(RepositoryUtils.toArtifact(mavenMainArtifact));
} else if (!project.getAttachedArtifacts().isEmpty()) {
throw new MojoExecutionException("The packaging plugin for this project did not assign "
+ "a main file to the project but it has attachments. Change packaging to 'pom'.");
} else {
throw new MojoExecutionException(
- "The packaging for this project did not assign " + "a file to the build artifact");
+ "The packaging for this project did not assign a file to the build artifact");
}
}
- if (!pomArtifactAttached) {
- throw new MojoExecutionException("The POM could not be attached");
- }
-
for (org.apache.maven.artifact.Artifact attached : project.getAttachedArtifacts()) {
- getLog().debug("Attaching for install: " + attached.getId());
+ getLog().debug("Attaching for deploy: " + attached.getId());
request.addArtifact(RepositoryUtils.toArtifact(attached));
}
+ }
- return request;
+ private boolean isFile(File file) {
+ return file != null && file.isFile();
}
/**
diff --git a/src/test/java/org/apache/maven/plugins/deploy/stubs/MavenProjectStub.java b/src/test/java/org/apache/maven/plugins/deploy/stubs/MavenProjectStub.java
index ff97f913..646e09ad 100644
--- a/src/test/java/org/apache/maven/plugins/deploy/stubs/MavenProjectStub.java
+++ b/src/test/java/org/apache/maven/plugins/deploy/stubs/MavenProjectStub.java
@@ -18,7 +18,11 @@
*/
package org.apache.maven.plugins.deploy.stubs;
+import java.util.Collections;
+
import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.model.Build;
+import org.apache.maven.model.Plugin;
public class MavenProjectStub extends org.apache.maven.plugin.testing.stubs.MavenProjectStub {
@@ -27,4 +31,12 @@ public class MavenProjectStub extends org.apache.maven.plugin.testing.stubs.Mave
public ArtifactRepository getDistributionManagementArtifactRepository() {
return deploymentRepository;
}
+
+ @Override
+ public Build getBuild() {
+ Plugin plugin = new Plugin();
+ Build build = new Build();
+ build.setPlugins(Collections.singletonList(plugin));
+ return build;
+ }
}