
org.apache.maven.plugins.deploy.DeployMojo Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of maven-deploy-plugin Show documentation
Show all versions of maven-deploy-plugin Show documentation
Uploads the project artifacts to the internal remote repository.
The newest version!
/*
* 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.
*/
package org.apache.maven.plugins.deploy;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.maven.api.Artifact;
import org.apache.maven.api.MojoExecution;
import org.apache.maven.api.ProducedArtifact;
import org.apache.maven.api.Project;
import org.apache.maven.api.RemoteRepository;
import org.apache.maven.api.di.Inject;
import org.apache.maven.api.model.DistributionManagement;
import org.apache.maven.api.model.Plugin;
import org.apache.maven.api.model.PluginExecution;
import org.apache.maven.api.plugin.MojoException;
import org.apache.maven.api.plugin.annotations.Mojo;
import org.apache.maven.api.plugin.annotations.Parameter;
import org.apache.maven.api.services.ArtifactDeployer;
import org.apache.maven.api.services.ArtifactDeployerRequest;
import org.apache.maven.api.services.ArtifactManager;
import org.apache.maven.api.services.ProjectManager;
/**
* Deploys an artifact to remote repository.
*
* @author Emmanuel Venisse
* @author John Casey (refactoring only)
*/
@Mojo(name = "deploy", defaultPhase = "deploy")
public class DeployMojo extends AbstractDeployMojo {
private static final Pattern ALT_LEGACY_REPO_SYNTAX_PATTERN = Pattern.compile("(.+?)::(.+?)::(.+)");
private static final Pattern ALT_REPO_SYNTAX_PATTERN = Pattern.compile("(.+?)::(.+)");
@Inject
private Project project;
@Inject
private MojoExecution mojoExecution;
/**
* 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
*/
@Parameter(defaultValue = "true", property = "deployAtEnd")
private boolean deployAtEnd;
/**
* Specifies an alternative repository to which the project artifacts should be deployed (other than those specified
* in <distributionManagement>).
* Format: id::url
*
* - id
* - The id can be used to pick up the correct credentials from the settings.xml
* - url
* - The location of the repository
*
* Note: In version 2.x, the format was id::layout::url
where layout
* could be default
(ie. Maven 2) or legacy
(ie. Maven 1), but since 3.0.0 the layout part
* has been removed because Maven 3 only supports Maven 2 repository layout.
*/
@Parameter(property = "altDeploymentRepository")
private String altDeploymentRepository;
/**
* The alternative repository to use when the project has a snapshot version.
*
* Note: In version 2.x, the format was id::layout::url
where layout
* could be default
(ie. Maven 2) or legacy
(ie. Maven 1), but since 3.0.0 the layout part
* has been removed because Maven 3 only supports Maven 2 repository layout.
* @since 2.8
* @see DeployMojo#altDeploymentRepository
*/
@Parameter(property = "altSnapshotDeploymentRepository")
private String altSnapshotDeploymentRepository;
/**
* The alternative repository to use when the project has a final version.
*
* Note: In version 2.x, the format was id::layout::url
where layout
* could be default
(ie. Maven 2) or legacy
(ie. Maven 1), but since 3.0.0 the layout part
* has been removed because Maven 3 only supports Maven 2 repository layout.
* @since 2.8
* @see DeployMojo#altDeploymentRepository
*/
@Parameter(property = "altReleaseDeploymentRepository")
private String altReleaseDeploymentRepository;
/**
* Set this to 'true' to bypass artifact deploy
* Since 3.0.0-M2 it's not anymore a real boolean as it can have more than 2 values:
*
* true
: will skip as usual
* releases
: will skip if current version of the project is a release
* snapshots
: will skip if current version of the project is a snapshot
* - any other values will be considered as
false
*
* @since 2.4
*/
@Parameter(property = "maven.deploy.skip", defaultValue = "false")
private String skip = Boolean.FALSE.toString();
/**
* Set this to true
to allow incomplete project processing. By default, such projects are forbidden
* and Mojo will fail to process them. Incomplete project is a Maven Project that has any other packaging than
* "pom" and has no main artifact packaged. In the majority of cases, what user really wants here is a project
* with "pom" packaging and some classified artifact attached (typical example is some assembly being packaged
* and attached with classifier).
*
* @since 3.1.1
*/
@Parameter(defaultValue = "false", property = "allowIncompleteProjects")
private boolean allowIncompleteProjects;
private enum State {
SKIPPED,
DEPLOYED,
TO_BE_DEPLOYED
}
public DeployMojo() {}
private void putState(State state) {
session.getPluginContext(project).put(State.class.getName(), state);
}
private void putState(ArtifactDeployerRequest request) {
session.getPluginContext(project).put(ArtifactDeployerRequest.class.getName(), request);
}
private State getState(Project project) {
return (State) session.getPluginContext(project).get(State.class.getName());
}
private boolean hasState(Project project) {
return session.getPluginContext(project).containsKey(State.class.getName());
}
public void execute() {
if (Boolean.parseBoolean(skip)
|| ("releases".equals(skip) && !session.isVersionSnapshot(project.getVersion()))
|| ("snapshots".equals(skip) && session.isVersionSnapshot(project.getVersion()))) {
getLog().info("Skipping artifact deployment");
putState(State.SKIPPED);
} else {
failIfOffline();
warnIfAffectedPackagingAndMaven(project.getPackaging().id());
if (!deployAtEnd) {
getLog().info("Deploying deploy for " + project.getGroupId() + ":" + project.getArtifactId() + ":"
+ project.getVersion() + " at end");
deploy(createDeployerRequest());
putState(State.DEPLOYED);
} else {
// compute the request
putState(State.TO_BE_DEPLOYED);
putState(createDeployerRequest());
if (!allProjectsMarked()) {
getLog().info("Deferring deploy for " + project.getGroupId() + ":" + project.getArtifactId() + ":"
+ project.getVersion() + " at end");
}
}
}
if (allProjectsMarked()) {
deployAllAtOnce();
}
}
private boolean allProjectsMarked() {
return session.getProjects().stream().allMatch(p -> hasState(p) || !hasDeployExecution(p));
}
private boolean hasDeployExecution(Project p) {
String key = mojoExecution.getPlugin().getModel().getKey();
Plugin plugin = p.getBuild().getPluginsAsMap().get(key);
if (plugin != null) {
for (PluginExecution execution : plugin.getExecutions()) {
if (!execution.getGoals().isEmpty() && !"none".equalsIgnoreCase(execution.getPhase())) {
return true;
}
}
}
return false;
}
private void deployAllAtOnce() {
Map>> flattenedRequests = new LinkedHashMap<>();
// flatten requests, grouping by remote repository and number of retries
for (Project reactorProject : session.getProjects()) {
State state = getState(reactorProject);
if (state == State.TO_BE_DEPLOYED) {
ArtifactDeployerRequest request = (ArtifactDeployerRequest)
session.getPluginContext(reactorProject).get(ArtifactDeployerRequest.class.getName());
flattenedRequests
.computeIfAbsent(request.getRepository(), r -> new LinkedHashMap<>())
.computeIfAbsent(request.getRetryFailedDeploymentCount(), i -> new ArrayList<>())
.addAll(request.getArtifacts());
}
}
// Re-group all requests
List requests = new ArrayList<>();
for (Map.Entry>> entry1 : flattenedRequests.entrySet()) {
for (Map.Entry> entry2 :
entry1.getValue().entrySet()) {
requests.add(ArtifactDeployerRequest.builder()
.session(session)
.repository(entry1.getKey())
.retryFailedDeploymentCount(entry2.getKey())
.artifacts(entry2.getValue())
.build());
}
}
// Deploy
if (!requests.isEmpty()) {
requests.forEach(this::deploy);
} else {
getLog().info("No actual deploy requests");
}
}
private void deploy(ArtifactDeployerRequest request) {
try {
getLog().info("Deploying artifacts " + request.getArtifacts().toString() + " to repository "
+ request.getRepository());
getArtifactDeployer().deploy(request);
} catch (MojoException e) {
throw e;
} catch (Exception e) {
throw new MojoException(e.getMessage(), e);
}
}
private ArtifactDeployerRequest createDeployerRequest() {
ProjectManager projectManager = getProjectManager();
Collection deployables = projectManager.getAllArtifacts(project);
Collection attachedArtifacts = projectManager.getAttachedArtifacts(project);
ArtifactManager artifactManager = getArtifactManager();
if (artifactManager.getPath(project.getPomArtifact()).isEmpty()) {
artifactManager.setPath(project.getPomArtifact(), project.getPomPath());
}
for (Artifact deployable : deployables) {
if (!isValidPath(deployable)) {
if (deployable == project.getMainArtifact().orElse(null)) {
if (attachedArtifacts.isEmpty()) {
throw new MojoException(
"The packaging for this project did not assign a file to the build artifact");
} else {
if (allowIncompleteProjects) {
getLog().warn("");
getLog().warn("The packaging plugin for this project did not assign");
getLog().warn(
"a main file to the project but it has attachments. Change packaging to 'pom'.");
getLog().warn("");
getLog().warn("Incomplete projects like this will fail in future Maven versions!");
getLog().warn("");
} else {
throw new MojoException("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 MojoException("The packaging for this project did not assign "
+ "a file to the attached artifact: " + deployable);
}
}
}
ArtifactDeployerRequest request = ArtifactDeployerRequest.builder()
.session(session)
.repository(getDeploymentRepository(session.isVersionSnapshot(project.getVersion())))
.artifacts((Collection) deployables)
.retryFailedDeploymentCount(Math.max(1, Math.min(10, getRetryFailedDeploymentCount())))
.build();
return request;
}
/**
* Visible for testing.
*/
RemoteRepository getDeploymentRepository(boolean isSnapshot) throws MojoException {
RemoteRepository repo = null;
String altDeploymentRepo;
if (isSnapshot && altSnapshotDeploymentRepository != null) {
altDeploymentRepo = altSnapshotDeploymentRepository;
} else if (!isSnapshot && altReleaseDeploymentRepository != null) {
altDeploymentRepo = altReleaseDeploymentRepository;
} else {
altDeploymentRepo = altDeploymentRepository;
}
if (altDeploymentRepo != null) {
getLog().info("Using alternate deployment repository " + altDeploymentRepo);
Matcher matcher = ALT_LEGACY_REPO_SYNTAX_PATTERN.matcher(altDeploymentRepo);
if (matcher.matches()) {
String id = matcher.group(1).trim();
String layout = matcher.group(2).trim();
String url = matcher.group(3).trim();
if ("default".equals(layout)) {
getLog().warn("Using legacy syntax for alternative repository. " + "Use \"" + id + "::" + url
+ "\" instead.");
repo = createDeploymentArtifactRepository(id, url);
} else {
throw new MojoException(
altDeploymentRepo,
"Invalid legacy syntax and layout for repository.",
"Invalid legacy syntax and layout for alternative repository. Use \"" + id + "::" + url
+ "\" instead, and only default layout is supported.");
}
} else {
matcher = ALT_REPO_SYNTAX_PATTERN.matcher(altDeploymentRepo);
if (!matcher.matches()) {
throw new MojoException(
altDeploymentRepo,
"Invalid syntax for repository.",
"Invalid syntax for alternative repository. Use \"id::url\".");
} else {
String id = matcher.group(1).trim();
String url = matcher.group(2).trim();
repo = createDeploymentArtifactRepository(id, url);
}
}
}
if (repo == null) {
DistributionManagement dm = project.getModel().getDistributionManagement();
if (dm != null) {
if (isSnapshot
&& dm.getSnapshotRepository() != null
&& isNotEmpty(dm.getSnapshotRepository().getId())
&& isNotEmpty(dm.getSnapshotRepository().getUrl())) {
repo = session.createRemoteRepository(dm.getSnapshotRepository());
} else if (dm.getRepository() != null
&& isNotEmpty(dm.getRepository().getId())
&& isNotEmpty(dm.getRepository().getUrl())) {
repo = session.createRemoteRepository(dm.getRepository());
}
}
}
if (repo == null) {
String msg = "Deployment failed: repository element was not specified in the POM inside"
+ " distributionManagement element or in -DaltDeploymentRepository=id::url parameter";
throw new MojoException(msg);
}
return repo;
}
private boolean isValidPath(Artifact a) {
return getArtifactManager().getPath(a).filter(Files::isRegularFile).isPresent();
}
private static boolean isNotEmpty(String str) {
return str != null && !str.isEmpty();
}
private ArtifactDeployer getArtifactDeployer() {
return session.getService(ArtifactDeployer.class);
}
private ArtifactManager getArtifactManager() {
return session.getService(ArtifactManager.class);
}
private ProjectManager getProjectManager() {
return session.getService(ProjectManager.class);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy