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

[MRELEASE-1078] Support version policy to read and use SCM tags and commits #104

Merged
merged 1 commit into from
Mar 12, 2023
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions maven-release-api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@
<groupId>org.apache.maven</groupId>
<artifactId>maven-settings</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven.scm</groupId>
<artifactId>maven-scm-api</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.aether</groupId>
<artifactId>aether-api</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,13 @@ public interface ReleaseDescriptor
*/
String getProjectVersionPolicyId();

/**
* Get the (optional) config for the VersionPolicy implementation used to calculate the project versions.
*
* @return The parsed XML of the provided config (an instance of XmlPlexusConfiguration) or null.
*/
Object getProjectVersionPolicyConfig();

michael-o marked this conversation as resolved.
Show resolved Hide resolved
/**
* Get the role-hint for the release Strategy implementation.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
*/

import org.apache.maven.artifact.repository.metadata.Metadata;
import org.apache.maven.scm.provider.ScmProvider;
import org.apache.maven.scm.repository.ScmRepository;

/**
* <p>VersionPolicyRequest class.</p>
Expand All @@ -33,6 +35,12 @@ public class VersionPolicyRequest

private Metadata metaData;

private ScmRepository scmRepository;
private ScmProvider scmProvider;
private String workingDirectory;

private String config;

/**
* <p>Getter for the field <code>version</code>.</p>
*
Expand Down Expand Up @@ -76,5 +84,93 @@ public VersionPolicyRequest setMetaData( Metadata metaData )
this.metaData = metaData;
return this;
}


/**
* <p>Getter for the field <code>scmRepository</code>.</p>
*
* @return a {@link ScmRepository} object
*/
public ScmRepository getScmRepository()
{
return scmRepository;
}

/**
* <p>Setter for the field <code>scmRepository</code>.</p>
*
* @param scmRepository The {@link ScmRepository} where the history can be retrieved.
* @return a {@link org.apache.maven.shared.release.policy.version.VersionPolicyRequest} object
*/
public VersionPolicyRequest setScmRepository( ScmRepository scmRepository )
{
this.scmRepository = scmRepository;
return this;
}

/**
* <p>Getter for the field <code>scmProvider</code>.</p>
*
* @return a {@link ScmProvider} object
*/
public ScmProvider getScmProvider()
{
return scmProvider;
}

/**
* <p>Setter for the field <code>scmProvider</code>.</p>
*
* @param scmProvider The {@link ScmProvider} where the history can be retrieved.
* @return a {@link org.apache.maven.shared.release.policy.version.VersionPolicyRequest} object
*/
public VersionPolicyRequest setScmProvider( ScmProvider scmProvider )
{
this.scmProvider = scmProvider;
return this;
}

/**
* <p>Getter for the field <code>workingDirectory</code>.</p>
*
* @return the {@link String} that contains the workingDirectory (can be null or empty).
*/
public String getWorkingDirectory()
{
return workingDirectory;
}

/**
* <p>Setter for the field <code>workingDirectory</code>.</p>
*
* @param workingDirectory The {@link String} that contains the workingDirectory (can be null or empty).
* @return a {@link org.apache.maven.shared.release.policy.version.VersionPolicyRequest} object
*/
public VersionPolicyRequest setWorkingDirectory( String workingDirectory )
{
this.workingDirectory = workingDirectory;
return this;
}

/**
* <p>Getter for the field <code>config</code>.</p>
*
* @return the {@link String} that contains the config (can be null or empty).
*/
public String getConfig()
{
return config;
}

/**
* <p>Setter for the field <code>config</code>.</p>
*
* @param config The {@link String} that contains the config (can be null or empty).
* @return a {@link org.apache.maven.shared.release.policy.version.VersionPolicyRequest} object
*/
public VersionPolicyRequest setConfig( String config )
{
this.config = config;
return this;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,14 @@ public VersionParseException( String message )
{
super( message );
}

/**
* <p>Constructor for VersionParseException.</p>
*
* @param message a {@link java.lang.String} object
*/
public VersionParseException( String message, Throwable e )
{
super( message, e );
}
}
1 change: 0 additions & 1 deletion maven-release-manager/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,6 @@
<dependency>
<groupId>org.eclipse.sisu</groupId>
<artifactId>org.eclipse.sisu.plexus</artifactId>
<scope>test</scope>
</dependency>

<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,10 @@ public void write( BuilderReleaseDescriptor config, File file )
{
properties.setProperty( "projectVersionPolicyId", config.getProjectVersionPolicyId() );
}
if ( config.getProjectVersionPolicyConfig() != null )
{
properties.setProperty( "projectVersionPolicyConfig", config.getProjectVersionPolicyConfig().toString() );
Copy link
Member

Choose a reason for hiding this comment

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

Why toString()? I don't understand this reasoning.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I did that as a workaround to the fact that the Properties::setProperty only supports setting a String. Note that this code is used to read/write it to a file.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Also: As a consequence of this (i.e. the config can possibly be written to a file and then read again) I assumed a String config and parse it in the VersionPolicy.

In the more generic usecase I like this because it leaves the format of the config fully to the writer of the VersionPolicy.

Copy link
Member

Choose a reason for hiding this comment

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

How to do you that toString() will give you something reasonable?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This part needs a revisit... This is indeed incorrect code.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I did some more check and currently I think is actually correct code.

What I have now:

  • By setting the type to DOM the generated code makes the class of this thing an Object in Java (i.e. all getters and setters). I checks and the actuall class is an instance of org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration. So the toString() recreates the XML fragment.
  • Some of the code can only handle a String (like for example the parts that reads and writes the release.properties file).

So the code path now is roughly:

  • The ProjectVersionPolicyConfig part in the pom.xml is parsed into a generic XmlPlexusConfiguration by Maven.
  • This XmlPlexusConfiguration is converted into a String so it can be stored and processed by all intermediate components (some of which can only handle String).
  • The actual VersionPolicy has it's own parser to make sense of the provided String.

I did two tests to verify this:

  1. In the integration test I have put this in the pom.xml
<projectVersionPolicyConfig>
  <versionTag>^v([0-9]+(?:\.[0-9]+(?:\.[0-9]+)?)?)$</versionTag>
  <majorRules>
    <majorRule>^[a-zA-Z]+!(?:\([a-zA-Z0-9_-]+\))?: .*$</majorRule>
    <majorRule>^BREAKING CHANGE:.*$</majorRule>
  </majorRules>
  <minorRules>
    <minorRule>^feat(?:\([a-zA-Z0-9_-]+\))?: .*$</minorRule>
  </minorRules>
</projectVersionPolicyConfig>

I see this in the release.properties:

projectVersionPolicyConfig=<projectVersionPolicyConfig><versionTag>^v([0-9]+(?\:\\.[0-9]+(?\:\\.[0-9]+)?)?)$</versionTag>\n<majorRules><majorRule>^[a-zA-Z]+\!(?\:\\([a-zA-Z0-9_-]+\\))?\: .*$</majorRule>\n<majorRule>^BREAKING CHANGE\:.*$</majorRule>\n</majorRules>\n<minorRules><minorRule>^feat(?\:\\([a-zA-Z0-9_-]+\\))?\: .*$</minorRule>\n</minorRules>\n</projectVersionPolicyConfig>\n
  1. To see if any config format is usable I put this in the pom.xml
<projectVersionPolicyConfig>
<![CDATA[
config:
  - something:
      foo:
        - 'foo foo'
      bar:
        - 'bar bar'
]]>
</projectVersionPolicyConfig>

I see this in the release.properties

projectVersionPolicyConfig=<projectVersionPolicyConfig>config\:\n  - something\:\n      foo\:\n        - 'foo foo'\n      bar\:\n        - 'bar bar'</projectVersionPolicyConfig>\n

In both these checks the toString made sure the right config is stored and also by forcing the VersionPolicy to have its own parser it works as I would like it to work.

This way it is up to the VersionPolicy to actually parse the config and verify what it is getting.

}
if ( config.getProjectNamingPolicyId() != null )
{
properties.setProperty( "projectNamingPolicyId", config.getProjectNamingPolicyId() );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,18 @@ public ReleaseDescriptorBuilder setProjectVersionPolicyId( String projectVersion
return this;
}

/**
* <p>setProjectVersionPolicyConfig.</p>
*
* @param setProjectVersionPolicyConfig a {@link java.lang.String} object
* @return a {@link org.apache.maven.shared.release.config.ReleaseDescriptorBuilder} object
*/
public ReleaseDescriptorBuilder setProjectVersionPolicyConfig( String setProjectVersionPolicyConfig )
{
releaseDescriptor.setProjectVersionPolicyConfig( setProjectVersionPolicyConfig );
michael-o marked this conversation as resolved.
Show resolved Hide resolved
return this;
michael-o marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* <p>setPushChanges.</p>
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,10 @@ public static void copyPropertiesToReleaseDescriptor( Properties properties, Rel
{
builder.setProjectVersionPolicyId( properties.getProperty( "projectVersionPolicyId" ) );
}
if ( properties.containsKey( "projectVersionPolicyConfig" ) )
{
builder.setProjectVersionPolicyConfig( properties.getProperty( "projectVersionPolicyConfig" ) );
michael-o marked this conversation as resolved.
Show resolved Hide resolved
}
if ( properties.containsKey( "projectNamingPolicyId" ) )
{
builder.setProjectNamingPolicyId( properties.getProperty( "projectNamingPolicyId" ) );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,24 @@

import org.apache.maven.artifact.ArtifactUtils;
import org.apache.maven.project.MavenProject;
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.ReleaseExecutionException;
import org.apache.maven.shared.release.ReleaseResult;
import org.apache.maven.shared.release.config.ReleaseDescriptor;
import org.apache.maven.shared.release.env.ReleaseEnvironment;
import org.apache.maven.shared.release.policy.PolicyException;
import org.apache.maven.shared.release.policy.version.VersionPolicy;
import org.apache.maven.shared.release.policy.version.VersionPolicyRequest;
import org.apache.maven.shared.release.scm.ScmRepositoryConfigurator;
import org.apache.maven.shared.release.util.ReleaseUtil;
import org.apache.maven.shared.release.versions.VersionParseException;
import org.codehaus.plexus.components.interactivity.Prompter;
import org.codehaus.plexus.components.interactivity.PrompterException;
import org.codehaus.plexus.util.StringUtils;
import org.slf4j.Logger;

import static java.util.Objects.requireNonNull;
import static org.apache.maven.shared.utils.logging.MessageUtils.buffer;
Expand Down Expand Up @@ -70,6 +76,11 @@
public abstract class AbstractMapVersionsPhase
michael-o marked this conversation as resolved.
Show resolved Hide resolved
extends AbstractReleasePhase
{
/**
* Tool that gets a configured SCM repository from release configuration.
*/
private final ScmRepositoryConfigurator scmRepositoryConfigurator;

/**
* Component used to prompt for input.
*/
Expand All @@ -90,9 +101,11 @@ public abstract class AbstractMapVersionsPhase
*/
private final boolean convertToBranch;

public AbstractMapVersionsPhase( Prompter prompter, Map<String, VersionPolicy> versionPolicies,
public AbstractMapVersionsPhase( ScmRepositoryConfigurator scmRepositoryConfigurator,
Prompter prompter, Map<String, VersionPolicy> versionPolicies,
boolean convertToSnapshot, boolean convertToBranch )
{
this.scmRepositoryConfigurator = requireNonNull( scmRepositoryConfigurator );
this.prompter = requireNonNull( prompter );
this.versionPolicies = requireNonNull( versionPolicies );
this.convertToSnapshot = convertToSnapshot;
Expand All @@ -116,7 +129,7 @@ public ReleaseResult execute( ReleaseDescriptor releaseDescriptor, ReleaseEnviro

String projectId = ArtifactUtils.versionlessKey( project.getGroupId(), project.getArtifactId() );

String nextVersion = resolveNextVersion( project, projectId, releaseDescriptor );
String nextVersion = resolveNextVersion( project, projectId, releaseDescriptor, releaseEnvironment );

if ( !convertToSnapshot )
{
Expand Down Expand Up @@ -182,7 +195,7 @@ else if ( ArtifactUtils.isSnapshot( subProject.getVersion() ) )
{
String projectId = ArtifactUtils.versionlessKey( project.getGroupId(), project.getArtifactId() );

String nextVersion = resolveNextVersion( project, projectId, releaseDescriptor );
String nextVersion = resolveNextVersion( project, projectId, releaseDescriptor, releaseEnvironment );

if ( !convertToSnapshot )
{
Expand All @@ -206,7 +219,8 @@ else if ( releaseDescriptor.isBranchCreation() && convertToBranch )

private String resolveNextVersion( MavenProject project,
String projectId,
ReleaseDescriptor releaseDescriptor )
ReleaseDescriptor releaseDescriptor,
ReleaseEnvironment releaseEnvironment )
throws ReleaseExecutionException
{
String defaultVersion;
Expand Down Expand Up @@ -275,14 +289,15 @@ else if ( releaseDescriptor.isBranchCreation() )
{
suggestedVersion =
resolveSuggestedVersion( baseVersion,
releaseDescriptor.getProjectVersionPolicyId() );
releaseDescriptor,
releaseEnvironment );
}
catch ( VersionParseException e )
{
if ( releaseDescriptor.isInteractive() )
{
suggestedVersion =
resolveSuggestedVersion( "1.0", releaseDescriptor.getProjectVersionPolicyId() );
resolveSuggestedVersion( "1.0", releaseDescriptor, releaseEnvironment );
}
else
{
Expand Down Expand Up @@ -347,16 +362,55 @@ private String getContextString( ReleaseDescriptor releaseDescriptor )
return "new development";
}

private String resolveSuggestedVersion( String baseVersion, String policyId )
private String resolveSuggestedVersion( String baseVersion,
ReleaseDescriptor releaseDescriptor,
ReleaseEnvironment releaseEnvironment )
throws PolicyException, VersionParseException
{
String policyId = releaseDescriptor.getProjectVersionPolicyId();
VersionPolicy policy = versionPolicies.get( policyId );
if ( policy == null )
{
throw new PolicyException( "Policy '" + policyId + "' is unknown, available: " + versionPolicies.keySet() );
}

VersionPolicyRequest request = new VersionPolicyRequest().setVersion( baseVersion );

if ( releaseDescriptor.getProjectVersionPolicyConfig() != null )
{
request.setConfig( releaseDescriptor.getProjectVersionPolicyConfig().toString() );
}
request.setWorkingDirectory( releaseDescriptor.getWorkingDirectory() );

if ( scmRepositoryConfigurator != null && releaseDescriptor.getScmSourceUrl() != null )
{
try
{
ScmRepository repository = scmRepositoryConfigurator
.getConfiguredRepository( releaseDescriptor, releaseEnvironment.getSettings() );

ScmProvider provider = scmRepositoryConfigurator
.getRepositoryProvider( repository );

request.setScmRepository( repository );
request.setScmProvider( provider );
}
catch ( ScmRepositoryException | NoSuchScmProviderException e )
{
Logger logger = getLogger();
if ( logger.isWarnEnabled() )
{
logger.warn( "Next Version will NOT be based on the version control: {}", e.getMessage() );
}
else
{
if ( logger.isDebugEnabled() )
{
logger.warn( "Next Version will NOT be based on the version control", e );
}
}
}
}
return convertToSnapshot ? policy.getDevelopmentVersion( request ).getVersion()
: policy.getReleaseVersion( request ).getVersion();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.util.Map;

import org.apache.maven.shared.release.policy.version.VersionPolicy;
import org.apache.maven.shared.release.scm.ScmRepositoryConfigurator;
import org.codehaus.plexus.components.interactivity.Prompter;

/**
Expand Down Expand Up @@ -61,8 +62,9 @@ public class MapBranchVersionsPhase
extends AbstractMapVersionsPhase
{
@Inject
public MapBranchVersionsPhase( Prompter prompter, Map<String, VersionPolicy> versionPolicies )
public MapBranchVersionsPhase( ScmRepositoryConfigurator scmRepositoryConfigurator,
Prompter prompter, Map<String, VersionPolicy> versionPolicies )
{
super( prompter, versionPolicies, true, true );
super( scmRepositoryConfigurator, prompter, versionPolicies, true, true );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.util.Map;

import org.apache.maven.shared.release.policy.version.VersionPolicy;
import org.apache.maven.shared.release.scm.ScmRepositoryConfigurator;
import org.codehaus.plexus.components.interactivity.Prompter;

/**
Expand Down Expand Up @@ -61,8 +62,9 @@ public class MapDevelopmentVersionsPhase
extends AbstractMapVersionsPhase
{
@Inject
public MapDevelopmentVersionsPhase( Prompter prompter, Map<String, VersionPolicy> versionPolicies )
public MapDevelopmentVersionsPhase( ScmRepositoryConfigurator scmRepositoryConfigurator,
Prompter prompter, Map<String, VersionPolicy> versionPolicies )
{
super( prompter, versionPolicies, true, false );
super( scmRepositoryConfigurator, prompter, versionPolicies, true, false );
}
}
Loading