Skip to content

Conversation

chonton
Copy link
Member

@chonton chonton commented Dec 10, 2017

MDEPLOY-226: DeployAtEnd fails when module has extension
MDEPLOY-225: DeployAtEnd fails when overriding skip
MDEPLOY-224: Overriding deployAtEnd fails

@chonton
Copy link
Member Author

chonton commented Dec 10, 2017

Same PR as apache/maven-plugins#138.

@robseidel
Copy link

Great work. The Deploy Maven Plugin 2.8.2 deployAtEnd feature is not working with Maven 3 due to the different class realms (http://maven.apache.org/guides/mini/guide-maven-classloading.html) - so the static instance variables are useless.
Hopefully this gets merged and released soon (since 2.8.2 was released before more than 3 years).

@lhein
Copy link

lhein commented Jan 30, 2018

I referenced this PR on https://issues.apache.org/jira/browse/MDEPLOY-200.
Maybe one of you guys should leave a comment on the Jira with further explanations.

@mattnelson
Copy link

Same PR as apache/maven-plugins#138.

Interested in getting this fix merged.

@khmarbaise Which repo should be used? I have an open PR myself on apache/maven-plugins because I didn't realize this repo existed.

@chonton
Copy link
Member Author

chonton commented Apr 12, 2018

Unfortunately, this technique interferes with surefire/failsafe. The user properties must contain String properties. I could make the pojos into json encoding.

Or, what other places can a plugin save information across invocations? It appears that plugin context is also tied to the ClassLoader.

@robseidel
Copy link

robseidel commented May 4, 2018

The serialization seems the easiest approach. I've written a quick & dirty modification to serialize/deserialize with XMLEncoder/XMLDecoder - which works with surefire.
For the serialization of the MavenProject I've used simply the filename and retrieve the correct MavenProject from the reactorProjects at deserialization.

@brenuart
Copy link

brenuart commented Sep 7, 2018

Any chance this PR is accepted one day?

@khmarbaise
Copy link
Member

The point is, as already @chonton has stated it will not work without influences in other areas which is unfortunately not good...
Currently there is only one real solution which I have made a longer time ago https://github.com/khmarbaise/maven-deployer-extension which is written as an extension...

The other solution would be to change the Maven Core to handle such things differently which is not very easy MNG-5666 and keeping compatibility...

@robseidel
Copy link

As I've written before, this PR can be fixed without breaking other stuff by using any form of serialization:

Just use the following class:

DeployRequestList

package org.apache.maven.plugin.deploy;

import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

import org.apache.maven.project.MavenProject;

/**

  • unique global list of deploy requests which are to be executed at the end of a multimodule project

*/
public class DeployRequestList implements Serializable {

private List<DeployRequest> list;

public DeployRequestList(Integer initialListSize) {
	list = new ArrayList<DeployRequest>(initialListSize);
}

public DeployRequestList(List<DeployRequest> deployRequests) {
	this.list = deployRequests;
}

public List<DeployRequest> getList() {
	return list;
}

public String serialize() {
	ByteArrayOutputStream baos = new ByteArrayOutputStream();
	XMLEncoder encoder = new XMLEncoder(new BufferedOutputStream(baos));
	encoder.writeObject(getList().size());
	for (DeployRequest request : getList()) {
		if (request == null) {
			encoder.writeObject(null);
		} else {
			request.serializeIn(encoder);
		}
	}
	encoder.close();
	String result = new String(baos.toByteArray(), StandardCharsets.UTF_8);
	return result;
}

public static DeployRequestList deserialize(String serializedDeployRequestList, List<MavenProject> reactorProjects) {
	ByteArrayInputStream bais = new ByteArrayInputStream(serializedDeployRequestList.getBytes(StandardCharsets.UTF_8));
	
	XMLDecoder decoder = new XMLDecoder(new BufferedInputStream(bais));
	Integer listSize = (Integer) decoder.readObject();
	
	DeployRequestList result = new DeployRequestList(listSize);
	for (int i=0; i < listSize; i++) {
		String projectFile = (String) decoder.readObject();
		if (projectFile == null) {
			result.getList().add(null);
		} else {
			result.getList().add(DeployRequest.deserialize(decoder, reactorProjects, projectFile));
		}
	}

	decoder.close();
    
    return result;
}

}

And add serialize/deserialize functions to DeployRequest:

public void serializeIn(XMLEncoder encoder) {
encoder.writeObject(getProject().getFile().getAbsolutePath());
encoder.writeObject(updateReleaseInfo);
encoder.writeObject(getRetryFailedDeploymentCount());
encoder.writeObject(getAltDeploymentRepository());
encoder.writeObject(getAltSnapshotDeploymentRepository());
encoder.writeObject(getAltReleaseDeploymentRepository());
}

public static DeployRequest deserialize(XMLDecoder decoder, List<MavenProject> reactorProjects,
		String projectFile) {
	MavenProject project = null;
	for (MavenProject reactorProject : reactorProjects) {
		if (projectFile.equals(reactorProject.getFile().getAbsolutePath())) {
			project = reactorProject;
			break;
		}
	}
	if (project==null) {
		throw new RuntimeException("Project for file '" + projectFile + "' could not be found within reactorprojects.");
	}
	
	boolean read_isUpdateReleaseInfo = (Boolean) decoder.readObject();
	int read_retryFailedDeploymentCount = (Integer) decoder.readObject();
	String read_altDeploymentRepository = (String) decoder.readObject();
	String read_altSnapshotDeploymentRepository = (String) decoder.readObject();
	String read_altReleaseDeploymentRepository = (String) decoder.readObject();
	
	return new DeployRequest().setProject( project ).setUpdateReleaseInfo( read_isUpdateReleaseInfo ).setRetryFailedDeploymentCount( read_retryFailedDeploymentCount ).setAltReleaseDeploymentRepository( read_altReleaseDeploymentRepository ).setAltSnapshotDeploymentRepository( read_altSnapshotDeploymentRepository ).setAltDeploymentRepository( read_altDeploymentRepository );
}

Then you can easily serialize the list into the property string. I don't think Maven Core will change its concept of different class loaders. So to hang up shared stuff in a shared variable is the way to go.

@digulla
Copy link

digulla commented Jan 22, 2019

Wouldn't it be possible to add a Map<String, Object> to MavenProject? Plugins could put data there under the key of one of their class names and get the data again later.

Note: You can't use the class itself as key because the classloader is part of the hashCode/equals.

@brianwyka
Copy link

Can this be revisited to be merged?

if ( reqs == null )
{
reqs = new ArrayList<ProjectDeployerRequest>( reactorProjects.size() );
projectProperties.put( propertyKey, reqs );

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about serializing the value reqs here (and deserialize on line 215)

@klaraward
Copy link

Any update on this?

@chonton
Copy link
Member Author

chonton commented May 31, 2021

Since implementation is difficult without changes to core, I've modified this pull request to be documentation only.

MerisierTac pushed a commit to TousAntiCovid/robert-server that referenced this pull request Jul 19, 2021
Having multiple submodules declaring extensions cause the
maven-deploy-plugin to not deploy artifacts when using -DdeployAtEnd=true.
See apache/maven-deploy-plugin#1
@slawekjaranowski
Copy link
Member

I will verify it again, thanks for efforts

@NersesAM
Copy link

I wish this had been merged and was available in documentation. Spent hours only to figure out that having one of the modules skip deployments makes the whole deployAtEnd silently fail to deploy anything at all

@cstamas
Copy link
Member

cstamas commented Oct 23, 2023

Does that happen with latest m-deploy-p as well?

@NersesAM
Copy link

NersesAM commented Oct 24, 2023

yes v3.1.1

@cstamas
Copy link
Member

cstamas commented Oct 24, 2023

And how is the module skipped? Using the <skip>?

@cstamas
Copy link
Member

cstamas commented Oct 24, 2023

Can you create a simple reproducer and post it on GitHub (or wherever)?

@cstamas
Copy link
Member

cstamas commented Oct 24, 2023

I see nothing in JIRA (all similar issues were reported against older versions, that yes, had known issues w/ skip). 3.1.1 should not have these issues (unless whole plugin is left out from execution, which is kinda "illegal" and could cause this): essentially, plugin should be always invoked (invoking it with skip=true also counts) to signal to plugin state "i am done" (even if did not anything as I was skipped).

This PR is totally irrelevant and not applicable to m-deploy-p 3.1.1 FTR. Same for doco changes.

So, if you have some issue with deployAtEnd, I'd like to see a reproducer for it.

@NersesAM
Copy link

I tried to create small reproducible case but I am not able to.
I started playing a bit more with my project and I noticed that github actions runner was using maven version 3.8.8, same project running with 3.9.5 works just fine! I have no idea what has changed in between the 2.

the project I am trying to deploy is https://github.com/ExpediaGroup/styx

in github actions I run

./mvnw --settings /home/settings.xml deploy -DskipTests=true -Prelease -Dlibs.release.url=${{env.MAVEN_URL}}/maven-release-local -Dlibs.snapshot.url=${{env.MAVEN_URL}}/maven-snapshot-local -DdeployAtEnd=true -Dlicense.skip=true

If you have local server repo server to deploy and can try against. you can skip tests to make the build faster

3.8.8

[INFO] --- maven-deploy-plugin:3.1.1:deploy (default-deploy) @ styx-distribution ---
[INFO] Deferring deploy for com.hotels.styx:styx-distribution:1.0-SNAPSHOT at end
[INFO] 
[INFO] --- maven-deploy-plugin:3.1.1:deploy-file (deploy-file) @ styx-distribution ---
[INFO] pom.xml not found in styx-1.0-SNAPSHOT.zip
Downloading from central: https://artfactory/com/hotels/styx/styx/1.0-SNAPSHOT/maven-metadata.xml
[WARNING] Could not transfer metadata com.hotels.styx:styx:1.0-SNAPSHOT/maven-metadata.xml from/to central (https://artifactory): authentication failed for https://artifactory/com/hotels/styx/styx/1.0-SNAPSHOT/maven-metadata.xml, status: 401 Unauthorized

vs
3.9.5

[INFO] --- deploy:3.1.1:deploy (default-deploy) @ styx-distribution ---
Downloading from snapshots: https://artifactory/com/hotels/styx/styx-parent/1.0-SNAPSHOT/maven-metadata.xml
[WARNING] Could not transfer metadata com.hotels.styx:styx-parent:1.0-SNAPSHOT/maven-metadata.xml from/to snapshots (https://artifactory): status code: 401, reason phrase: Unauthorized (401)

Ignore it fails, but you can see with 3.8.8 it is failing at deploy:deploy-file skipping deploy:deploy while with 3.9.5 it is actually failing at deploy:deploy phase which was supposed to do deployment of all the modules

another interesting thing is if you remove one of the modules with -pl !plugin-examples it works with 3.8.8

@cstamas
Copy link
Member

cstamas commented Oct 24, 2023

Well,...

  • 3.8.x should be left for oblivion, use 3.9.x
  • your best bet is wrapper, as you fully control Maven in use, and not rely on any 3rd party things like GH Action, some preinstalled software, or whatever. Always keep yourself in control 😄
  • -pl and friends in Maven 3 can have unexpected (side) effects, especially when project observed "as whole" (is what deployAtEnd tries to do)/

@NersesAM
Copy link

I thought GH uses latest maven! lessons learned I guess :) I agree controlling the version is the best. Thanks for your help

@jira-importer
Copy link

Resolve #365

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.