Skip to content

Commit cf63898

Browse files
committed
Add support for changelist property per branch for maven ci friendly versioning - closes aleksandr-m#314
1 parent 54d31d9 commit cf63898

11 files changed

+289
-30
lines changed

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,18 @@ The `skipUpdateVersion` parameter can be used to skip updating `<version>` in th
215215

216216
To support [CI friendly versioning](https://maven.apache.org/maven-ci-friendly.html) in projects which use `<version>${revision}</version>` set `versionProperty` to `revision` and `skipUpdateVersion` to `true`.
217217

218+
### CI friendly in dependencies/multi module
219+
220+
Projects which additionally use the `changelist` property in the version (`<version>${revision}${changelist}</version>`) and refer to it via `<version>${project.version}</version>` in dependencies are supported as well.
221+
222+
As the different steps of the plugin running on different branches, different values for `changelist` may be needed to successfully resolve the dependencies.
223+
224+
To set different values to `changelist` per branch the properties `productionChangelistValue`, `hotfixChangelistValue`, `releaseChangelistValue`, `developmentChangelistValue`, `featureChangelistValue`, `supportChangelistValue` are used.
225+
226+
As example for the `gitflow:hotfix-finish` the following properties may be used (setting `developmentChangelistValue` done explicit for better understanding):
227+
228+
mvn gitflow:hotfix-finish -DhotfixVersion=x.y.z -DproductionChangelistValue='' -DhotfixChangelistValue='' -DdevelopmentChangelistValue='-SNAPSHOT'
229+
218230
## Additional goal parameters
219231

220232
The `gitflow:release-finish`, `gitflow:release` and `gitflow:hotfix-finish` goals have `skipTag` parameter. This parameter controls whether the release/hotfix will be tagged in Git.

src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java

Lines changed: 238 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.util.List;
2323
import java.util.Map;
2424
import java.util.Map.Entry;
25+
import java.util.Properties;
2526
import java.util.TimeZone;
2627
import java.util.regex.Pattern;
2728

@@ -30,6 +31,7 @@
3031
import org.apache.maven.execution.MavenSession;
3132
import org.apache.maven.model.Dependency;
3233
import org.apache.maven.plugin.AbstractMojo;
34+
import org.apache.maven.plugin.MojoExecutionException;
3335
import org.apache.maven.plugin.MojoFailureException;
3436
import org.apache.maven.plugins.annotations.Component;
3537
import org.apache.maven.plugins.annotations.Parameter;
@@ -91,7 +93,7 @@ public abstract class AbstractGitFlowMojo extends AbstractMojo {
9193
*/
9294
@Parameter(defaultValue = "false")
9395
protected boolean tychoBuild;
94-
96+
9597
/**
9698
* Whether to call Maven install goal during the mojo execution.
9799
*
@@ -124,6 +126,12 @@ public abstract class AbstractGitFlowMojo extends AbstractMojo {
124126
@Parameter(property = "argLine")
125127
private String argLine;
126128

129+
/**
130+
* Stores the branch specific maven arguments.
131+
* Gets set if branch based properties are requested and appended to the maven commands.
132+
*/
133+
private String mvnArgsBranchSpecific = "";
134+
127135
/**
128136
* Whether to make a GPG-signed commit.
129137
*
@@ -149,6 +157,70 @@ public abstract class AbstractGitFlowMojo extends AbstractMojo {
149157
@Parameter(property = "versionProperty")
150158
private String versionProperty;
151159

160+
/**
161+
* Property to treat as <code>changelist</code> property.
162+
* Used for Maven CI friendly versioning handling. Only relevant in conjunction
163+
* with the <code>xxxChangelistValue</code>'s.
164+
*
165+
* @since 1.17.0
166+
*/
167+
@Parameter(property = "changelistProperty", defaultValue = "changelist")
168+
private String changelistProperty;
169+
170+
/**
171+
* The value to pass as <code>changelist</code> value when running on the
172+
* production branch.
173+
*
174+
* @since 1.17.0
175+
*/
176+
@Parameter(property = "productionChangelistValue")
177+
private String productionChangelistValue;
178+
179+
/**
180+
* The value to pass as <code>changelist</code> value when running on the
181+
* hotfix branch.
182+
*
183+
* @since 1.17.0
184+
*/
185+
@Parameter(property = "hotfixChangelistValue")
186+
private String hotfixChangelistValue;
187+
188+
/**
189+
* The value to pass as <code>changelist</code> value when running on the
190+
* release branch.
191+
*
192+
* @since 1.17.0
193+
*/
194+
@Parameter(property = "releaseChangelistValue")
195+
private String releaseChangelistValue;
196+
197+
/**
198+
* The value to pass as <code>changelist</code> value when running on the
199+
* development branch.
200+
*
201+
* @since 1.17.0
202+
*/
203+
@Parameter(property = "developmentChangelistValue")
204+
private String developmentChangelistValue;
205+
206+
/**
207+
* The value to pass as <code>changelist</code> value when running on the
208+
* feature branch.
209+
*
210+
* @since 1.17.0
211+
*/
212+
@Parameter(property = "featureChangelistValue")
213+
private String featureChangelistValue;
214+
215+
/**
216+
* The value to pass as <code>changelist</code> value when running on the
217+
* support branch.
218+
*
219+
* @since 1.17.0
220+
*/
221+
@Parameter(property = "supportChangelistValue")
222+
private String supportChangelistValue;
223+
152224
/**
153225
* Whether to skip updating version. Useful with {@link #versionProperty} to be
154226
* able to update <code>revision</code> property without modifying version tag.
@@ -171,6 +243,7 @@ public abstract class AbstractGitFlowMojo extends AbstractMojo {
171243
*/
172244
@Parameter(property = "mvnExecutable")
173245
private String mvnExecutable;
246+
174247
/**
175248
* The path to the Git executable. Defaults to "git".
176249
*/
@@ -191,7 +264,7 @@ public abstract class AbstractGitFlowMojo extends AbstractMojo {
191264

192265
@Component
193266
protected ProjectBuilder projectBuilder;
194-
267+
195268
/** Default prompter. */
196269
@Component
197270
protected Prompter prompter;
@@ -611,7 +684,7 @@ protected boolean gitCheckTagExists(final String tagName) throws MojoFailureExce
611684
* @throws MojoFailureException
612685
* @throws CommandLineException
613686
*/
614-
protected void gitCheckout(final String branchName)
687+
private void gitCheckout(final String branchName)
615688
throws MojoFailureException, CommandLineException {
616689
getLog().info("Checking out '" + branchName + "' branch.");
617690

@@ -628,7 +701,7 @@ protected void gitCheckout(final String branchName)
628701
* @throws MojoFailureException
629702
* @throws CommandLineException
630703
*/
631-
protected void gitCreateAndCheckout(final String newBranchName,
704+
private void gitCreateAndCheckout(final String newBranchName,
632705
final String fromBranchName) throws MojoFailureException,
633706
CommandLineException {
634707
getLog().info(
@@ -1188,7 +1261,8 @@ private void executeGitCommand(final String... args)
11881261
*/
11891262
private void executeMvnCommand(final String... args)
11901263
throws CommandLineException, MojoFailureException {
1191-
executeCommand(cmdMvn, true, argLine, args);
1264+
final String argLineWithBranchSpecifics = joinStrings(argLine, mvnArgsBranchSpecific);
1265+
executeCommand(cmdMvn, true, argLineWithBranchSpecifics, args);
11921266
}
11931267

11941268
/**
@@ -1289,4 +1363,163 @@ public String getError() {
12891363
public void setArgLine(String argLine) {
12901364
this.argLine = argLine;
12911365
}
1366+
1367+
/**
1368+
* Executes git checkout and sets Maven CI friendly settings per branch.
1369+
*
1370+
* @param branchType
1371+
* Type of branch to set config for.
1372+
* @param branchName
1373+
* Branch name to checkout.
1374+
* @throws MojoExecutionException an internal error occurred
1375+
* @throws MojoFailureException an error with the underlying commands occurred
1376+
* @throws CommandLineException an error with the underlying commands occurred
1377+
*/
1378+
protected void checkoutAndSetConfigForBranch(final BranchType branchType, final String branchName)
1379+
throws MojoExecutionException, MojoFailureException, CommandLineException {
1380+
if (branchType == null) {
1381+
throw new MojoExecutionException("INTERNAL: given BranchType is null");
1382+
}
1383+
1384+
gitCheckout(branchName);
1385+
setConfigForBranchType(branchType);
1386+
}
1387+
1388+
/**
1389+
* Executes git checkout -b and sets Maven CI friendly settings per branch.
1390+
*
1391+
* @param branchType
1392+
* Type of branch to set config for.
1393+
* @param newBranchName
1394+
* Create branch with this name.
1395+
* @param fromBranchName
1396+
* Create branch from this branch.
1397+
* @throws MojoExecutionException an internal error occurred
1398+
* @throws MojoFailureException an error with the underlying commands occurred
1399+
* @throws CommandLineException an error with the underlying commands occurred
1400+
*/
1401+
protected void createAndCheckoutAndSetConfigForBranch(final BranchType branchType, final String newBranchName,
1402+
final String fromBranchName) throws MojoExecutionException, MojoFailureException, CommandLineException {
1403+
if (branchType == null) {
1404+
throw new MojoExecutionException("INTERNAL: given BranchType is null");
1405+
}
1406+
1407+
gitCreateAndCheckout(newBranchName, fromBranchName);
1408+
setConfigForBranchType(branchType);
1409+
}
1410+
1411+
/**
1412+
* Sets Maven CI friendly settings dependent of the type of branch.
1413+
* This includes settings passed to the maven commands in <code>executeMvnCommand</code> and manipulates
1414+
* the user properties inside the <code>MavenSession</code>, to guarantee that internal mvn commands
1415+
* via e.g. <code>ProjectBuilder.build</code> also uses the correct properties.
1416+
*
1417+
* @param branchType
1418+
* Type of branch to set config for.
1419+
* @throws MojoExecutionException an internal error occurred
1420+
*/
1421+
protected void setConfigForBranchType(final BranchType branchType) throws MojoExecutionException {
1422+
if (branchType == null) {
1423+
throw new MojoExecutionException("INTERNAL: given BranchType is null");
1424+
}
1425+
1426+
final boolean noChangelistValueToBeModified = productionChangelistValue == null
1427+
&& hotfixChangelistValue == null && releaseChangelistValue == null
1428+
&& developmentChangelistValue == null && featureChangelistValue == null
1429+
&& supportChangelistValue == null;
1430+
1431+
if (StringUtils.isBlank(changelistProperty) || noChangelistValueToBeModified) {
1432+
return;
1433+
}
1434+
1435+
final String changelistValue;
1436+
1437+
switch (branchType) {
1438+
case PRODUCTION:
1439+
changelistValue = productionChangelistValue;
1440+
break;
1441+
case HOTFIX:
1442+
changelistValue = hotfixChangelistValue;
1443+
break;
1444+
case RELEASE:
1445+
changelistValue = releaseChangelistValue;
1446+
break;
1447+
case DEVELOPMENT:
1448+
changelistValue = developmentChangelistValue;
1449+
break;
1450+
case FEATURE:
1451+
changelistValue = featureChangelistValue;
1452+
break;
1453+
case SUPPORT:
1454+
changelistValue = supportChangelistValue;
1455+
break;
1456+
default:
1457+
throw new MojoExecutionException("INTERNAL: unhandled case for branchType value: " + branchType);
1458+
}
1459+
1460+
setPropertyInProperties(changelistProperty, changelistValue, mavenSession.getProjectBuildingRequest().getUserProperties());
1461+
mvnArgsBranchSpecific = getJavaPropertyAsArgLineString(changelistProperty, changelistValue);
1462+
}
1463+
1464+
/**
1465+
* Sets a property in the given <code>Properties</code>.
1466+
*
1467+
* @param key
1468+
* The key of the property to set.
1469+
* @param value
1470+
* The value of the property to set, if null, the property gets removed.
1471+
* @param properties
1472+
* The properties where to replace the entry.
1473+
*/
1474+
private void setPropertyInProperties(final String key, final String value, final Properties properties) {
1475+
if (StringUtils.isBlank(key) || properties == null) {
1476+
return;
1477+
}
1478+
1479+
if (value == null) {
1480+
properties.remove(key);
1481+
} else {
1482+
properties.put(key, value);
1483+
}
1484+
}
1485+
1486+
/**
1487+
* Retrieve a string representation of a java property defined by key/value.
1488+
*
1489+
* @param key
1490+
* The key of the property to set.
1491+
* @param value
1492+
* The value of the property to set, if null, an empty string is returned.
1493+
* @return
1494+
* A string representation to be used as java argument.
1495+
* Empty if key is null or empty, or the value is null.
1496+
*/
1497+
private String getJavaPropertyAsArgLineString(final String key, final String value) {
1498+
if (StringUtils.isBlank(key) || value == null) {
1499+
return "";
1500+
} else {
1501+
return "-D" + key + "=" + value;
1502+
}
1503+
}
1504+
1505+
/**
1506+
* Join two <code>String</code>'s with a space.
1507+
* Both <code>String</code>'s can be null. And always a non-null value is returned.
1508+
*
1509+
* @param a
1510+
* The first string, where the second gets appended to. null is treated as empty.
1511+
* @param b
1512+
* The second string, which gets appended to the first one. null is treated as empty.
1513+
* @return
1514+
* The combined string, if both strings are null or empty, an empty String is returned.
1515+
*/
1516+
private String joinStrings(final String a, final String b) {
1517+
if (StringUtils.isBlank(a)) {
1518+
return StringUtils.clean(b);
1519+
} else if (StringUtils.isBlank(b)) {
1520+
return StringUtils.clean(a);
1521+
} else {
1522+
return a + " " + b;
1523+
}
1524+
}
12921525
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package com.amashchenko.maven.plugin.gitflow;
2+
3+
public enum BranchType {
4+
PRODUCTION, DEVELOPMENT, FEATURE, RELEASE, HOTFIX, SUPPORT;
5+
}

src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowFeatureFinishMojo.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ public void execute() throws MojoExecutionException, MojoFailureException {
149149

150150
if (!skipTestProject) {
151151
// git checkout feature/...
152-
gitCheckout(featureBranchName);
152+
checkoutAndSetConfigForBranch(BranchType.FEATURE, featureBranchName);
153153

154154
// mvn clean test
155155
mvnCleanTest();
@@ -196,7 +196,7 @@ public void execute() throws MojoExecutionException, MojoFailureException {
196196
}
197197

198198
// git checkout develop
199-
gitCheckout(gitFlowConfig.getDevelopmentBranch());
199+
checkoutAndSetConfigForBranch(BranchType.DEVELOPMENT, gitFlowConfig.getDevelopmentBranch());
200200

201201
if (featureSquash) {
202202
// git merge --squash feature/...
@@ -222,7 +222,7 @@ public void execute() throws MojoExecutionException, MojoFailureException {
222222
}
223223

224224
if (keepBranch) {
225-
gitCheckout(featureBranchName);
225+
checkoutAndSetConfigForBranch(BranchType.FEATURE, featureBranchName);
226226

227227
mvnSetVersions(keptFeatureVersion);
228228

src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowFeatureStartMojo.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,8 @@ public void execute() throws MojoExecutionException, MojoFailureException {
120120
}
121121

122122
// git checkout -b ... develop
123-
gitCreateAndCheckout(
123+
createAndCheckoutAndSetConfigForBranch(
124+
BranchType.FEATURE,
124125
gitFlowConfig.getFeatureBranchPrefix() + featureBranchName,
125126
gitFlowConfig.getDevelopmentBranch());
126127

0 commit comments

Comments
 (0)