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

Allow explicit configured plugins to execute on master as well #129

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: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -332,8 +332,8 @@ directly from master**. Rather, master is really only used for tracking releases
To accomplish this the `promote-master` goal and a Maven build extension work together.

With the build extension added to your project, any build where the `gitBranchExpression` matches the `masterBranchPattern` or `supportBranchPattern` will have it's
build lifecycle (plugins, goals, etc) altered. Any plugin other than the gitflow-helper-maven-plugin, the maven-deploy-plugin, or plugins with goals
explicitly referenced on the command line will be ignored (removed from the project reactor).
build lifecycle (plugins, goals, etc) altered. Any plugin other than the gitflow-helper-maven-plugin, the maven-deploy-plugin, plugins with goals
explicitly referenced on the command line or those configured explicitly in the `retainPlugins` list, will be ignored (removed from the project reactor).
This allows us to enforce the ideal that code should never be built in the master branch.

The `promote-master` goal executes when the `gitBranchExpression` resolves to a value matching the `masterBranchPattern` or `supportBranchPattern` regular expression.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import org.codehaus.plexus.util.xml.Xpp3Dom;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

public abstract class AbstractBranchDetectingExtension extends AbstractMavenLifecycleParticipant {
Expand All @@ -34,6 +36,7 @@ public abstract class AbstractBranchDetectingExtension extends AbstractMavenLife
String featureOrBugfixBranchPattern;
String otherDeployBranchPattern;
String otherBranchVersionDelimiter;
List<String> retainPlugins;
GitBranchInfo branchInfo;
Properties systemEnvVars;

Expand Down Expand Up @@ -93,6 +96,10 @@ public void afterProjectsRead(MavenSession session) throws MavenExecutionExcepti
if (gitBranchExpression == null) {
gitBranchExpression = extractPluginConfigValue("gitBranchExpression", plugin);
}

if (retainPlugins == null) {
retainPlugins = extractPluginConfigList("retainPlugins", plugin);
}
}
}
}
Expand Down Expand Up @@ -145,6 +152,10 @@ public void afterProjectsRead(MavenSession session) throws MavenExecutionExcepti
logger.debug("Using default otherBranchVersionDelimiter.");
otherBranchVersionDelimiter = "+";
}

if (retainPlugins == null) {
logger.debug("No additional plugin executions will be retained on master");
}

ScmUtils scmUtils = new ScmUtils(systemEnvVars, scmManager, session.getTopLevelProject(), new PlexusLoggerToMavenLog(logger), masterBranchPattern, supportBranchPattern, releaseBranchPattern, hotfixBranchPattern, developmentBranchPattern);
branchInfo = scmUtils.resolveBranchInfo(gitBranchExpression);
Expand All @@ -168,4 +179,25 @@ private String extractConfigValue(String parameter, Object configuration) {
}
return null;
}

private List<String> extractPluginConfigList(String parameter, Plugin plugin) {
List<String> value = extractConfigList(parameter, plugin.getConfiguration());
for (int i = 0; i < plugin.getExecutions().size() && value == null; i++) {
value = extractConfigList(parameter, plugin.getExecutions().get(i).getConfiguration());
}
return value;
}

private List<String> extractConfigList(String parameter, Object configuration) {
try {
List<String> result = new ArrayList<>();
Xpp3Dom parameterNode = ((Xpp3Dom) configuration).getChild(parameter);
for (int i = 0; i < parameterNode.getChildCount(); i++) {
result.add(parameterNode.getChild(i).getValue());
}
return result;
} catch (Exception ignored) {
}
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,14 @@
import org.codehaus.plexus.component.annotations.Component;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
* Maven extension which removes (skips) undesired plugins from the build reactor when running on a master branch.
Expand All @@ -19,6 +25,15 @@
*/
@Component(role = AbstractMavenLifecycleParticipant.class, hint = "promote-master")
public class MasterPromoteExtension extends AbstractBranchDetectingExtension {

private static final Set<String> PLUGIN_WHITELIST = Collections.unmodifiableSet(
new HashSet<>(
Arrays.asList(
"org.apache.maven.plugins:maven-deploy-plugin",
"com.e-gineering:gitflow-helper-maven-plugin"
)
)
);

@Override
public void afterProjectsRead(final MavenSession session) throws MavenExecutionException {
Expand All @@ -41,26 +56,25 @@ public void afterProjectsRead(final MavenSession session) throws MavenExecutionE
}

// Build up a map of plugins to remove from projects, if we're on the master branch.
HashMap<MavenProject, List<Plugin>> pluginsToDrop = new HashMap<>();
Map<MavenProject, List<Plugin>> pluginsToDrop = new HashMap<>();

final List<String> configuredPluginsToRetain;
if (this.retainPlugins != null) {
configuredPluginsToRetain = this.retainPlugins;
} else {
configuredPluginsToRetain = Collections.emptyList();
}

for (MavenProject project : session.getProjects()) {
List<Plugin> dropPlugins = new ArrayList<>();

for (Plugin plugin : project.getModel().getBuild().getPlugins()) {
// Don't drop our plugin.
if (plugin.getKey().equals("com.e-gineering:gitflow-helper-maven-plugin")) {
continue;
// Don't drop things we declare goals for.
} else if (pluginsToRetain.contains(plugin)) {
logger.debug("gitflow-helper-maven-plugin retaining plugin: " + plugin + " from project: " + project.getName());
// Don't drop the maven-deploy-plugin
} else if (plugin.getKey().equals("org.apache.maven.plugins:maven-deploy-plugin")) {
logger.debug("gitflow-helper-maven-plugin retaining plugin: " + plugin + " from project: " + project.getName());
} else {
logger.debug("gitflow-helper-maven-plugin removing plugin: " + plugin + " from project: " + project.getName());
dropPlugins.add(plugin);
}
}
// Create a list of all plugins that are not in the whitelist, not explicitly invoked from the commandline,
// and not configured to be allowed on master/support.
List<Plugin> dropPlugins = project.getModel().getBuild().getPlugins()
.stream()
.filter(plugin -> !PLUGIN_WHITELIST.contains(plugin.getKey()))
.filter(plugin -> !pluginsToRetain.contains(plugin))
.filter(plugin -> !configuredPluginsToRetain.contains(plugin.getKey()))
.collect(Collectors.toList());

pluginsToDrop.put(project, dropPlugins);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;

import java.util.List;

/**
* If the build is being executed from a DEVELOPMENT, HOTFIX or RELEASE branch, attach an artifact containing a list of
Expand All @@ -17,6 +20,15 @@
@Mojo(name = "promote-master", defaultPhase = LifecyclePhase.INSTALL)
public class PromoteMasterMojo extends AbstractGitflowBasedRepositoryMojo {

/**
* List of groupId:artifactId strings that refer to plugins that should be retained while building on master.
*
* Note that this property is listed here for documentation purposes, but it is handled within
* {@link MasterPromoteExtension}.
*/
@Parameter(property = "retainPlugins")
private List<String> retainPlugins;

@Override
protected void execute(final GitBranchInfo gitBranchInfo) throws MojoExecutionException, MojoFailureException {
switch (gitBranchInfo.getType()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,16 @@ public void promotionOfRelease() throws Exception {
// Otherwise, it's the VerificationException from looking for "Compiling", and that's expected to fail.
}

try {
// The flatten-maven-plugin should not activate, fail if it does.
verifier.verifyTextInLog("Generating flattened POM of project");
throw new VerificationException(PROMOTION_FAILED_MESSAGE);
} catch (VerificationException ve) {
if (ve.getMessage().equals(PROMOTION_FAILED_MESSAGE)) {
throw ve;
}
}

verifier.verifyTextInLog(
"gitflow-helper-maven-plugin: Enabling MasterPromoteExtension. GIT_BRANCH: [origin/master] matches masterBranchPattern");
verifier.verifyTextInLog("[INFO] Setting release artifact repository to: [releases]");
Expand Down Expand Up @@ -121,4 +131,46 @@ public void dontPruneExplicitlyInvokedPlugins() throws Exception {
verifier.resetStreams();
}
}

@Test
public void dontPruneExplicitlyConfiguredPlugins() throws Exception {
// Create a release version and get it deployed.
Verifier verifier = createVerifier("/project-stub", "origin/release/1.2.0", "1.2.0");

try {
verifier.executeGoal("deploy");

verifier.verifyErrorFreeLog();
} finally {
verifier.resetStreams();
}

// Promote (deploy) from /origin/master
verifier = createVerifier("/project-stub", "origin/master", "1.2.0");
// Activate a profile to enable the retainPlugins configuration
verifier.addCliOption("-Pretain-configuration");
try {
verifier.executeGoal("deploy");

try {
verifier.verifyTextInLog("Compiling");
throw new VerificationException(PROMOTION_FAILED_MESSAGE);
} catch (VerificationException ve) {
if (ve.getMessage().equals(PROMOTION_FAILED_MESSAGE)) {
throw ve;
}
// Otherwise, it's the VerificationException from looking for "Compiling", and that's expected to fail.
}

verifier.verifyTextInLog("Generating flattened POM of project"); // This should still be there.
verifier.verifyTextInLog(
"gitflow-helper-maven-plugin: Enabling MasterPromoteExtension. GIT_BRANCH: [origin/master] matches masterBranchPattern");
verifier.verifyTextInLog("[INFO] Setting release artifact repository to: [releases]");
verifier.verifyTextInLog(
"[INFO] Resolving & Reattaching existing artifacts from stageDeploymentRepository [test-releases");
verifier.verifyErrorFreeLog();
} finally {
verifier.resetStreams();
}
}
}
35 changes: 35 additions & 0 deletions src/test/resources/project-stub/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,42 @@
<version>4.2.0</version>
<extensions>true</extensions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>flatten-maven-plugin</artifactId>
<version>1.2.2</version>
<executions>
<execution>
<goals>
<goal>flatten</goal>
</goals>
<phase>process-resources</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>

<profiles>
<profile>
<id>retain-configuration</id>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>com.e-gineering</groupId>
<artifactId>gitflow-helper-maven-plugin</artifactId>
<version>${version.gitflow.plugin}</version>
<configuration>
<retainPlugins>
<retainPlugin>org.codehaus.mojo:flatten-maven-plugin</retainPlugin>
</retainPlugins>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</profile>
</profiles>

</project>