Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MDEPLOY-193] Deploy At End feature (no extension) #20

Merged
merged 9 commits into from Jul 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/it/deploy-at-end-fail/verify.groovy
Expand Up @@ -22,5 +22,5 @@ assert !( new File( basedir, "module1/target/repo/org/apache/maven/its/deploy/da

File buildLog = new File( basedir, 'build.log' )
assert buildLog.exists()
assert buildLog.text.contains( "[INFO] Deploying org.apache.maven.its.deploy.dae.fail:dae:1.0 at end" )
assert buildLog.text.contains( "[INFO] Deferring deploy for org.apache.maven.its.deploy.dae.fail:dae:1.0 at end" )

2 changes: 1 addition & 1 deletion src/it/deploy-at-end-pass/verify.groovy
Expand Up @@ -22,5 +22,5 @@ assert new File( basedir, "module1/target/repo/org/apache/maven/its/deploy/dae/p

File buildLog = new File( basedir, 'build.log' )
assert buildLog.exists()
assert buildLog.text.contains( "[INFO] Deploying 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:dae:1.0 at end" )

147 changes: 107 additions & 40 deletions src/main/java/org/apache/maven/plugins/deploy/DeployMojo.java
Expand Up @@ -19,17 +19,16 @@
* under the License.
*/

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.maven.artifact.ArtifactUtils;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
Expand All @@ -55,23 +54,15 @@ public class DeployMojo

private static final Pattern ALT_REPO_SYNTAX_PATTERN = Pattern.compile( "(.+?)::(.+)" );

/**
* When building with multiple threads, reaching the last project doesn't have to mean that all projects are ready
* to be deployed
*/
private static final AtomicInteger READYPROJECTSCOUNTER = new AtomicInteger();

private static final List<ProjectDeployerRequest> DEPLOYREQUESTS =
Collections.synchronizedList( new ArrayList<ProjectDeployerRequest>() );

/**
*/
@Parameter( defaultValue = "${project}", readonly = true, required = true )
private MavenProject project;

@Parameter( defaultValue = "${reactorProjects}", required = true, readonly = true )
private List<MavenProject> reactorProjects;

@Parameter( defaultValue = "${plugin}", required = true, readonly = true )
private PluginDescriptor pluginDescriptor;

/**
* 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.
Expand Down Expand Up @@ -143,63 +134,139 @@ public class DeployMojo
@Component
private ProjectDeployer projectDeployer;

private enum State
{
SKIPPED, DEPLOYED, TO_BE_DEPLOYED
}

private static final String DEPLOY_PROCESSED_MARKER = DeployMojo.class.getName() + ".processed";

private static final String DEPLOY_ALT_RELEASE_DEPLOYMENT_REPOSITORY =
DeployMojo.class.getName() + ".altReleaseDeploymentRepository";

private static final String DEPLOY_ALT_SNAPSHOT_DEPLOYMENT_REPOSITORY =
DeployMojo.class.getName() + ".altSnapshotDeploymentRepository";

private static final String DEPLOY_ALT_DEPLOYMENT_REPOSITORY =
DeployMojo.class.getName() + ".altDeploymentRepository";

private void putState( State state )
{
getPluginContext().put( DEPLOY_PROCESSED_MARKER, state.name() );
}

private void putPluginContextValue( String key, String value )
{
if ( value != null )
{
getPluginContext().put( key, value );
}
}

private String getPluginContextValue( Map<String, Object> pluginContext, String key )
{
return (String) pluginContext.get( key );
}

private State getState( Map<String, Object> pluginContext )
{
return State.valueOf( getPluginContextValue( pluginContext, DEPLOY_PROCESSED_MARKER ) );
}

private boolean hasState( MavenProject project )
{
Map<String, Object> pluginContext = getSession().getPluginContext( pluginDescriptor, project );
return pluginContext.containsKey( DEPLOY_PROCESSED_MARKER );
}

public void execute()
throws MojoExecutionException, MojoFailureException
{
boolean addedDeployRequest = false;
if ( Boolean.parseBoolean( skip )
|| ( "releases".equals( skip ) && !ArtifactUtils.isSnapshot( project.getVersion() ) )
|| ( "snapshots".equals( skip ) && ArtifactUtils.isSnapshot( project.getVersion() ) )
)
{
getLog().info( "Skipping artifact deployment" );
putState( State.SKIPPED );
}
else
{
failIfOffline();

// CHECKSTYLE_OFF: LineLength
// @formatter:off
ProjectDeployerRequest pdr = new ProjectDeployerRequest()
.setProject( project )
.setRetryFailedDeploymentCount( getRetryFailedDeploymentCount() )
.setAltReleaseDeploymentRepository( altReleaseDeploymentRepository )
.setAltSnapshotDeploymentRepository( altSnapshotDeploymentRepository )
.setAltDeploymentRepository( altDeploymentRepository );
// @formatter:on
// CHECKSTYLE_ON: LineLength

ArtifactRepository repo = getDeploymentRepository( pdr );

if ( !deployAtEnd )
{
// CHECKSTYLE_OFF: LineLength
// @formatter:off
ProjectDeployerRequest pdr = new ProjectDeployerRequest()
.setProject( project )
.setRetryFailedDeploymentCount( getRetryFailedDeploymentCount() )
.setAltReleaseDeploymentRepository( altReleaseDeploymentRepository )
.setAltSnapshotDeploymentRepository( altSnapshotDeploymentRepository )
.setAltDeploymentRepository( altDeploymentRepository );
// @formatter:on
// CHECKSTYLE_ON: LineLength

ArtifactRepository repo = getDeploymentRepository( pdr );

deployProject( getSession().getProjectBuildingRequest(), pdr, repo );
putState( State.DEPLOYED );
}
else
{
DEPLOYREQUESTS.add( pdr );
addedDeployRequest = true;
putState( State.TO_BE_DEPLOYED );
putPluginContextValue( DEPLOY_ALT_RELEASE_DEPLOYMENT_REPOSITORY, altReleaseDeploymentRepository );
putPluginContextValue( DEPLOY_ALT_SNAPSHOT_DEPLOYMENT_REPOSITORY, altSnapshotDeploymentRepository );
putPluginContextValue( DEPLOY_ALT_DEPLOYMENT_REPOSITORY, altDeploymentRepository );
getLog().info( "Deferring deploy for " + getProjectReferenceId( project ) + " at end" );
}
}

boolean projectsReady = READYPROJECTSCOUNTER.incrementAndGet() == reactorProjects.size();
if ( projectsReady )
if ( allProjectsMarked() )
{
synchronized ( DEPLOYREQUESTS )
for ( MavenProject reactorProject : reactorProjects )
{
while ( !DEPLOYREQUESTS.isEmpty() )
Map<String, Object> pluginContext = getSession().getPluginContext( pluginDescriptor, reactorProject );
State state = getState( pluginContext );
if ( state == State.TO_BE_DEPLOYED )
{
ArtifactRepository repo = getDeploymentRepository( DEPLOYREQUESTS.get( 0 ) );

deployProject( getSession().getProjectBuildingRequest(), DEPLOYREQUESTS.remove( 0 ), repo );
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 );

ProjectDeployerRequest pdr = new ProjectDeployerRequest()
.setProject( reactorProject )
.setRetryFailedDeploymentCount( getRetryFailedDeploymentCount() )
.setAltReleaseDeploymentRepository( altReleaseDeploymentRepository )
.setAltSnapshotDeploymentRepository( altSnapshotDeploymentRepository )
.setAltDeploymentRepository( altDeploymentRepository );

ArtifactRepository repo = getDeploymentRepository( pdr );

deployProject( getSession().getProjectBuildingRequest(), pdr, repo );
}
}
}
else if ( addedDeployRequest )
}

private String getProjectReferenceId( MavenProject mavenProject )
{
return mavenProject.getGroupId() + ":" + mavenProject.getArtifactId() + ":" + mavenProject.getVersion();
}

private boolean allProjectsMarked()
{
for ( MavenProject reactorProject : reactorProjects )
{
getLog().info( "Deploying " + project.getGroupId() + ":" + project.getArtifactId() + ":"
+ project.getVersion() + " at end" );
if ( !hasState( reactorProject ) )
{
return false;
}
}
return true;
}

private void deployProject( ProjectBuildingRequest pbr, ProjectDeployerRequest pir, ArtifactRepository repo )
Expand Down
22 changes: 18 additions & 4 deletions src/test/java/org/apache/maven/plugins/deploy/DeployMojoTest.java
Expand Up @@ -19,6 +19,7 @@
* under the License.
*/

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
Expand All @@ -28,11 +29,13 @@
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.apache.maven.plugin.testing.AbstractMojoTestCase;
import org.apache.maven.plugin.testing.stubs.MavenProjectStub;
import org.apache.maven.plugins.deploy.stubs.ArtifactDeployerStub;
Expand Down Expand Up @@ -68,7 +71,6 @@ public class DeployMojoTest

MavenProjectStub project = new MavenProjectStub();

@Mock
private MavenSession session;

@InjectMocks
Expand All @@ -78,7 +80,11 @@ public void setUp()
throws Exception
{
super.setUp();


session = mock( MavenSession.class );
when( session.getPluginContext(any(PluginDescriptor.class), any(MavenProject.class)))
.thenReturn( new ConcurrentHashMap<String, Object>() );

remoteRepo = new File( REMOTE_REPO );

remoteRepo.mkdirs();
Expand Down Expand Up @@ -144,7 +150,8 @@ public void testBasicDeploy()
assertTrue( file.exists() );

MavenProject project = (MavenProject) getVariableValueFromObject( mojo, "project" );


setVariableValueToObject( mojo, "pluginContext", new ConcurrentHashMap<>() );
setVariableValueToObject( mojo, "reactorProjects", Collections.singletonList( project ) );

artifact = ( DeployArtifactStub ) project.getArtifact();
Expand Down Expand Up @@ -251,8 +258,11 @@ public void testSkippingDeploy()
assertTrue( file.exists() );

MavenProject project = (MavenProject) getVariableValueFromObject( mojo, "project" );


setVariableValueToObject( mojo, "pluginDescriptor", new PluginDescriptor() );
setVariableValueToObject( mojo, "pluginContext", new ConcurrentHashMap<>() );
setVariableValueToObject( mojo, "reactorProjects", Collections.singletonList( project ) );
setVariableValueToObject( mojo, "session", session );

artifact = (DeployArtifactStub) project.getArtifact();

Expand Down Expand Up @@ -316,6 +326,7 @@ public void testBasicDeployWithPackagingAsPom()

MavenProject project = (MavenProject) getVariableValueFromObject( mojo, "project" );

setVariableValueToObject( mojo, "pluginContext", new ConcurrentHashMap<>() );
setVariableValueToObject( mojo, "reactorProjects", Collections.singletonList( project ) );

artifact = (DeployArtifactStub) project.getArtifact();
Expand Down Expand Up @@ -381,6 +392,7 @@ public void testDeployIfArtifactFileIsNull()

MavenProject project = (MavenProject) getVariableValueFromObject( mojo, "project" );

setVariableValueToObject( mojo, "pluginContext", new ConcurrentHashMap<>() );
setVariableValueToObject( mojo, "reactorProjects", Collections.singletonList( project ) );

artifact = (DeployArtifactStub) project.getArtifact();
Expand Down Expand Up @@ -422,6 +434,7 @@ public void testDeployWithAttachedArtifacts()

MavenProject project = (MavenProject) getVariableValueFromObject( mojo, "project" );

setVariableValueToObject( mojo, "pluginContext", new ConcurrentHashMap<>() );
setVariableValueToObject( mojo, "reactorProjects", Collections.singletonList( project ) );

artifact = (DeployArtifactStub) project.getArtifact();
Expand Down Expand Up @@ -523,6 +536,7 @@ public void _testBasicDeployWithScpAsProtocol()

MavenProject project = (MavenProject) getVariableValueFromObject( mojo, "project" );

setVariableValueToObject( mojo, "pluginContext", new ConcurrentHashMap<>() );
setVariableValueToObject( mojo, "reactorProjects", Collections.singletonList( project ) );

artifact = (DeployArtifactStub) project.getArtifact();
Expand Down