Skip to content

Commit

Permalink
[MRELEASE-229] implementation of RemoveScmTagPhase, with unit test
Browse files Browse the repository at this point in the history
this closes #29
  • Loading branch information
cquoss authored and hboutemy committed Dec 1, 2019
1 parent cfcc8ca commit 13ccc54
Show file tree
Hide file tree
Showing 3 changed files with 352 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
* under the License.
*/

import java.io.File;
import org.apache.maven.project.MavenProject;
import org.apache.maven.shared.release.ReleaseExecutionException;
import org.apache.maven.shared.release.ReleaseFailureException;
Expand All @@ -28,33 +29,131 @@
import org.codehaus.plexus.component.annotations.Component;

import java.util.List;
import org.apache.maven.scm.CommandParameter;
import org.apache.maven.scm.CommandParameters;
import org.apache.maven.scm.ScmException;
import org.apache.maven.scm.ScmFileSet;
import org.apache.maven.scm.command.untag.UntagScmResult;
import org.apache.maven.scm.manager.NoSuchScmProviderException;
import org.apache.maven.scm.provider.ScmProvider;
import org.apache.maven.scm.repository.ScmRepository;
import org.apache.maven.scm.repository.ScmRepositoryException;
import org.apache.maven.shared.release.scm.ReleaseScmCommandException;
import org.apache.maven.shared.release.scm.ReleaseScmRepositoryException;
import org.apache.maven.shared.release.scm.ScmRepositoryConfigurator;
import org.apache.maven.shared.release.util.ReleaseUtil;
import org.codehaus.plexus.component.annotations.Requirement;

/**
* @author Edwin Punzalan
* Remove tag from SCM repository during rollback
*/
@Component( role = ReleasePhase.class, hint = "remove-scm-tag" )
public class RemoveScmTagPhase
extends AbstractReleasePhase
{
/**
* Tool that gets a configured SCM repository from release configuration.
*/
@Requirement
private ScmRepositoryConfigurator scmRepositoryConfigurator;

@Override
public ReleaseResult execute( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
List<MavenProject> reactorProjects )
throws ReleaseExecutionException, ReleaseFailureException
{
ReleaseResult result = new ReleaseResult();
ReleaseResult releaseResult = new ReleaseResult();

validateConfiguration( releaseDescriptor );

logInfo( releaseResult, "Removing tag with the label " + releaseDescriptor.getScmReleaseLabel() + " ..." );

ReleaseDescriptor basedirAlignedReleaseDescriptor =
ReleaseUtil.createBasedirAlignedReleaseDescriptor( releaseDescriptor, reactorProjects );

ScmRepository repository;
ScmProvider provider;
try
{
repository =
scmRepositoryConfigurator.getConfiguredRepository( basedirAlignedReleaseDescriptor.getScmSourceUrl(),
releaseDescriptor,
releaseEnvironment.getSettings() );

repository.getProviderRepository().setPushChanges( releaseDescriptor.isPushChanges() );

repository.getProviderRepository().setWorkItem( releaseDescriptor.getWorkItem() );

provider = scmRepositoryConfigurator.getRepositoryProvider( repository );
}
catch ( ScmRepositoryException e )
{
throw new ReleaseScmRepositoryException( e.getMessage(), e.getValidationMessages() );
}
catch ( NoSuchScmProviderException e )
{
throw new ReleaseExecutionException( "Unable to configure SCM repository: " + e.getMessage(), e );
}

UntagScmResult untagScmResult;
try
{
ScmFileSet fileSet = new ScmFileSet( new File( basedirAlignedReleaseDescriptor.getWorkingDirectory() ) );
String tagName = releaseDescriptor.getScmReleaseLabel();
String message = releaseDescriptor.getScmCommentPrefix() + "remove tag " + tagName;
CommandParameters commandParameters = new CommandParameters();
commandParameters.setString( CommandParameter.TAG_NAME, tagName );
commandParameters.setString( CommandParameter.MESSAGE, message );
if ( getLogger().isDebugEnabled() )
{
getLogger().debug(
"RemoveScmTagPhase :: scmUntagParameters tagName " + tagName );
getLogger().debug(
"RemoveScmTagPhase :: scmUntagParameters message " + message );
getLogger().debug( "ScmTagPhase :: fileSet " + fileSet );
}
untagScmResult = provider.untag( repository, fileSet, commandParameters );
}
catch ( ScmException e )
{
throw new ReleaseExecutionException( "An error is occurred in the remove tag process: "
+ e.getMessage(), e );
}

// TODO [!]: implement
if ( !untagScmResult.isSuccess() )
{
throw new ReleaseScmCommandException( "Unable to remove tag ", untagScmResult );
}

result.setResultCode( ReleaseResult.SUCCESS );
releaseResult.setResultCode( ReleaseResult.SUCCESS );

return result;
return releaseResult;
}

@Override
public ReleaseResult simulate( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
List<MavenProject> reactorProjects )
throws ReleaseExecutionException, ReleaseFailureException
{
return execute( releaseDescriptor, releaseEnvironment, reactorProjects );
ReleaseResult releaseResult = new ReleaseResult();

validateConfiguration( releaseDescriptor );

logInfo( releaseResult, "Full run would remove tag with label: '" + releaseDescriptor.getScmReleaseLabel()
+ "'" );

releaseResult.setResultCode( ReleaseResult.SUCCESS );

return releaseResult;
}

private void validateConfiguration( ReleaseDescriptor releaseDescriptor )
throws ReleaseFailureException
{
if ( releaseDescriptor.getScmReleaseLabel() == null )
{
throw new ReleaseFailureException( "A release label is required for removal" );
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
package org.apache.maven.shared.release.phase;

/*
* 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.
*/

import java.util.List;

import org.apache.maven.project.MavenProject;
import org.apache.maven.scm.CommandParameters;
import org.apache.maven.scm.ScmFileSet;
import org.apache.maven.scm.command.untag.UntagScmResult;
import org.apache.maven.scm.manager.ScmManager;
import org.apache.maven.scm.provider.ScmProvider;
import org.apache.maven.scm.repository.ScmRepository;
import org.apache.maven.shared.release.ReleaseResult;
import org.apache.maven.shared.release.config.ReleaseDescriptorBuilder;
import org.apache.maven.shared.release.config.ReleaseUtils;
import org.apache.maven.shared.release.env.DefaultReleaseEnvironment;
import org.apache.maven.shared.release.scm.ReleaseScmCommandException;
import org.apache.maven.shared.release.stubs.ScmManagerStub;
import org.apache.maven.shared.release.util.ReleaseUtil;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.Matchers;
import org.mockito.Mockito;

/**
* Test the remove SCM tag phase.
*/
public class RemoveScmTagPhaseTest extends AbstractReleaseTestCase
{

@Override
public void setUp() throws Exception
{

super.setUp();

phase = ( ReleasePhase ) lookup( ReleasePhase.class, "remove-scm-tag" );

}

@Test
public void testExecuteOutput() throws Exception
{

// prepare
ReleaseDescriptorBuilder builder = new ReleaseDescriptorBuilder();
builder.setScmReleaseLabel( "release-label" );
builder.setScmSourceUrl( "scm-url" );
List<MavenProject> reactorProjects = createReactorProjects();
MavenProject rootProject = ReleaseUtil.getRootProject( reactorProjects );
builder.setWorkingDirectory( getPath( rootProject.getFile().getParentFile() ) );
builder.setPomFileName( rootProject.getFile().getName() );
ScmFileSet fileSet = new ScmFileSet( rootProject.getFile().getParentFile() );

// mock, only real mather is the file set
ScmProvider scmProviderMock = Mockito.mock( ScmProvider.class );
Mockito.when( scmProviderMock.untag( Matchers.isA( ScmRepository.class ),
Matchers.argThat( new IsScmFileSetEquals( fileSet ) ),
Matchers.isA( CommandParameters.class ) ) )
.thenReturn( new UntagScmResult( "...", "...", "...", true ) );
ScmManagerStub stub = ( ScmManagerStub ) lookup( ScmManager.class );
stub.setScmProvider( scmProviderMock );

// execute
ReleaseResult actual = phase.execute( ReleaseUtils.buildReleaseDescriptor( builder ),
new DefaultReleaseEnvironment(), reactorProjects );

// verify, actual contains trailing newline
Assert.assertEquals( "[INFO] Removing tag with the label release-label ...", actual.getOutput().trim() );

}

@Test
public void testExecuteResultCode() throws Exception
{

// prepare
ReleaseDescriptorBuilder builder = new ReleaseDescriptorBuilder();
builder.setScmReleaseLabel( "release-label" );
builder.setScmSourceUrl( "scm-url" );
List<MavenProject> reactorProjects = createReactorProjects();
MavenProject rootProject = ReleaseUtil.getRootProject( reactorProjects );
builder.setWorkingDirectory( getPath( rootProject.getFile().getParentFile() ) );
builder.setPomFileName( rootProject.getFile().getName() );
ScmFileSet fileSet = new ScmFileSet( rootProject.getFile().getParentFile() );

// mock, only real mather is the file set
ScmProvider scmProviderMock = Mockito.mock( ScmProvider.class );
Mockito.when( scmProviderMock.untag( Matchers.isA( ScmRepository.class ),
Matchers.argThat( new IsScmFileSetEquals( fileSet ) ),
Matchers.isA( CommandParameters.class ) ) )
.thenReturn( new UntagScmResult( "...", "...", "...", true ) );
ScmManagerStub stub = ( ScmManagerStub ) lookup( ScmManager.class );
stub.setScmProvider( scmProviderMock );

// execute
ReleaseResult actual = phase.execute( ReleaseUtils.buildReleaseDescriptor( builder ),
new DefaultReleaseEnvironment(), reactorProjects );

// verify
Assert.assertEquals( 0, actual.getResultCode() );

}

@Rule
public ExpectedException exceptionRule = ExpectedException.none();

@Test
public void testExecuteError() throws Exception
{

// prepare
ReleaseDescriptorBuilder builder = new ReleaseDescriptorBuilder();
builder.setScmReleaseLabel( "release-label" );
builder.setScmSourceUrl( "scm-url" );
List<MavenProject> reactorProjects = createReactorProjects();
MavenProject rootProject = ReleaseUtil.getRootProject( reactorProjects );
builder.setWorkingDirectory( getPath( rootProject.getFile().getParentFile() ) );
builder.setPomFileName( rootProject.getFile().getName() );
ScmFileSet fileSet = new ScmFileSet( rootProject.getFile().getParentFile() );

// mock, only real mather is the file set
ScmProvider scmProviderMock = Mockito.mock( ScmProvider.class );
Mockito.when( scmProviderMock.untag( Matchers.isA( ScmRepository.class ),
Matchers.argThat( new IsScmFileSetEquals( fileSet ) ),
Matchers.isA( CommandParameters.class ) ) )
.thenReturn( new UntagScmResult( "command-line", "provider-message", "command-output", false ) );
ScmManagerStub stub = ( ScmManagerStub ) lookup( ScmManager.class );
stub.setScmProvider( scmProviderMock );

// set up exception rule
exceptionRule.expect( ReleaseScmCommandException.class );
exceptionRule.expectMessage(
"Unable to remove tag \nProvider message:\nprovider-message\nCommand output:\ncommand-output" );

// execute
phase.execute( ReleaseUtils.buildReleaseDescriptor( builder ),
new DefaultReleaseEnvironment(), reactorProjects );

}

@Test
public void testSimulateOutput() throws Exception
{

// prepare
ReleaseDescriptorBuilder builder = new ReleaseDescriptorBuilder();
builder.setScmReleaseLabel( "release-label" );
builder.setScmSourceUrl( "scm-url" );
List<MavenProject> reactorProjects = createReactorProjects();
MavenProject rootProject = ReleaseUtil.getRootProject( reactorProjects );
builder.setWorkingDirectory( getPath( rootProject.getFile().getParentFile() ) );
builder.setPomFileName( rootProject.getFile().getName() );

// execute
ReleaseResult actual = phase.simulate(ReleaseUtils.buildReleaseDescriptor( builder ),
new DefaultReleaseEnvironment(), reactorProjects );

// verify, actual contains newline
Assert.assertEquals( "[INFO] Full run would remove tag with label: 'release-label'",
actual.getOutput().trim() );

}

@Test
public void testSimulateResultCode() throws Exception
{

// prepare
ReleaseDescriptorBuilder builder = new ReleaseDescriptorBuilder();
builder.setScmReleaseLabel( "release-label" );
builder.setScmSourceUrl( "scm-url" );
List<MavenProject> reactorProjects = createReactorProjects();
MavenProject rootProject = ReleaseUtil.getRootProject( reactorProjects );
builder.setWorkingDirectory( getPath( rootProject.getFile().getParentFile() ) );
builder.setPomFileName( rootProject.getFile().getName() );

// execute
ReleaseResult actual = phase.simulate( ReleaseUtils.buildReleaseDescriptor( builder ),
new DefaultReleaseEnvironment(), reactorProjects );

Assert.assertEquals( 0, actual.getResultCode() );

}

private List<MavenProject> createReactorProjects() throws Exception
{
return createReactorProjects( "scm-commit/single-pom", "" );
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<!--
~ 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.
-->

<component-set>
<components>
<component>
<role>org.apache.maven.scm.manager.ScmManager</role>
<implementation>org.apache.maven.shared.release.stubs.ScmManagerStub</implementation>
</component>
<!-- Turn off info messages -->
<component>
<role>org.codehaus.plexus.logging.LoggerManager</role>
<implementation>org.codehaus.plexus.logging.console.ConsoleLoggerManager</implementation>
<lifecycle-handler>basic</lifecycle-handler>
<configuration>
<threshold>ERROR</threshold>
</configuration>
</component>
</components>
</component-set>

0 comments on commit 13ccc54

Please sign in to comment.