Skip to content

Commit abd6890

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

11 files changed

+291
-29
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: 240 additions & 4 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,13 @@ public abstract class AbstractGitFlowMojo extends AbstractMojo {
124126
@Parameter(property = "argLine")
125127
private String argLine;
126128

129+
/**
130+
* Stores the original argLine.
131+
* If branch based properties are needed, this will be used as reference
132+
* for the argLine manipulation.
133+
*/
134+
private String argLineOrig;
135+
127136
/**
128137
* Whether to make a GPG-signed commit.
129138
*
@@ -149,6 +158,70 @@ public abstract class AbstractGitFlowMojo extends AbstractMojo {
149158
@Parameter(property = "versionProperty")
150159
private String versionProperty;
151160

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

192266
@Component
193267
protected ProjectBuilder projectBuilder;
194-
268+
195269
/** Default prompter. */
196270
@Component
197271
protected Prompter prompter;
@@ -611,7 +685,7 @@ protected boolean gitCheckTagExists(final String tagName) throws MojoFailureExce
611685
* @throws MojoFailureException
612686
* @throws CommandLineException
613687
*/
614-
protected void gitCheckout(final String branchName)
688+
private void gitCheckout(final String branchName)
615689
throws MojoFailureException, CommandLineException {
616690
getLog().info("Checking out '" + branchName + "' branch.");
617691

@@ -628,7 +702,7 @@ protected void gitCheckout(final String branchName)
628702
* @throws MojoFailureException
629703
* @throws CommandLineException
630704
*/
631-
protected void gitCreateAndCheckout(final String newBranchName,
705+
private void gitCreateAndCheckout(final String newBranchName,
632706
final String fromBranchName) throws MojoFailureException,
633707
CommandLineException {
634708
getLog().info(
@@ -1288,5 +1362,167 @@ public String getError() {
12881362

12891363
public void setArgLine(String argLine) {
12901364
this.argLine = argLine;
1365+
this.argLineOrig = argLine;
1366+
}
1367+
1368+
/**
1369+
* Executes git checkout and sets Maven CI friendly settings per branch.
1370+
*
1371+
* @param branchType
1372+
* Branch type to set config for.
1373+
* @param branchName
1374+
* Branch name to checkout.
1375+
* @throws MojoExecutionException
1376+
* @throws MojoFailureException
1377+
* @throws CommandLineException
1378+
*/
1379+
protected void checkoutAndSetConfigForBranch(final BranchType branchType, final String branchName)
1380+
throws MojoExecutionException, MojoFailureException, CommandLineException {
1381+
if (branchType == null) {
1382+
throw new MojoExecutionException("INTERNAL: given BranchType is null");
1383+
}
1384+
1385+
gitCheckout(branchName);
1386+
setConfigForBranchType(branchType);
1387+
}
1388+
1389+
/**
1390+
* Executes git checkout -b and sets Maven CI friendly settings per branch.
1391+
*
1392+
* @param branchType
1393+
* Branch type to set config for.
1394+
* @param newBranchName
1395+
* Create branch with this name.
1396+
* @param fromBranchName
1397+
* Create branch from this branch.
1398+
* @throws MojoExecutionException
1399+
* @throws MojoFailureException
1400+
* @throws CommandLineException
1401+
*/
1402+
protected void createAndCheckoutAndSetConfigForBranch(final BranchType branchType, final String newBranchName,
1403+
final String fromBranchName) throws MojoExecutionException, MojoFailureException, CommandLineException {
1404+
if (branchType == null) {
1405+
throw new MojoExecutionException("INTERNAL: given BranchType is null");
1406+
}
1407+
1408+
gitCreateAndCheckout(newBranchName, fromBranchName);
1409+
setConfigForBranchType(branchType);
1410+
}
1411+
1412+
/**
1413+
* Sets Maven CI friendly settings dependent of the type of branch.
1414+
* This includes re-configuring the <code>argLine</code> which is passed to the maven commands in
1415+
* <code>executeMvnCommand</code> and manipulates the user properties inside of the <code>MavenSession</code>,
1416+
* to guarantee that internal mvn commands via eg <code>ProjectBuilder.build</code> also uses the correct properties.
1417+
*
1418+
* @param branchType
1419+
* Branch type to set config for.
1420+
* @throws MojoExecutionException
1421+
*/
1422+
protected void setConfigForBranchType(final BranchType branchType) throws MojoExecutionException {
1423+
if (branchType == null) {
1424+
throw new MojoExecutionException("INTERNAL: given BranchType is null");
1425+
}
1426+
1427+
final boolean noChangelistValueToBeModified = productionChangelistValue == null
1428+
&& hotfixChangelistValue == null && releaseChangelistValue == null
1429+
&& developmentChangelistValue == null && featureChangelistValue == null
1430+
&& supportChangelistValue == null;
1431+
1432+
if (StringUtils.isBlank(changelistProperty) || noChangelistValueToBeModified) {
1433+
return;
1434+
}
1435+
1436+
final String changelistValue;
1437+
1438+
switch (branchType) {
1439+
case PRODUCTION:
1440+
changelistValue = productionChangelistValue;
1441+
break;
1442+
case HOTFIX:
1443+
changelistValue = hotfixChangelistValue;
1444+
break;
1445+
case RELEASE:
1446+
changelistValue = releaseChangelistValue;
1447+
break;
1448+
case DEVELOPMENT:
1449+
changelistValue = developmentChangelistValue;
1450+
break;
1451+
case FEATURE:
1452+
changelistValue = featureChangelistValue;
1453+
break;
1454+
case SUPPORT:
1455+
changelistValue = supportChangelistValue;
1456+
break;
1457+
default:
1458+
throw new MojoExecutionException("INTERNAL: unhandled case for branchType value: " + branchType);
1459+
}
1460+
1461+
setPropertyInProperties(changelistProperty, changelistValue, mavenSession.getProjectBuildingRequest().getUserProperties());
1462+
argLine = replacePropertyInArgline(changelistProperty, changelistValue, argLineOrig);
1463+
}
1464+
1465+
/**
1466+
* Sets a property in the given <code>Properties</code>.
1467+
* Updates the <code>Properties</code> and manipulates the <code>argLine</code> inside
1468+
* of the <code>Properties</code> as well.
1469+
*
1470+
* @param key
1471+
* The key of the property to set.
1472+
* @param value
1473+
* The value of the property to set, if null, the property gets removed.
1474+
* @param properties
1475+
* The properties where to replace the entry.
1476+
*/
1477+
private void setPropertyInProperties(final String key, final String value, final Properties properties) {
1478+
if (StringUtils.isBlank(key) || properties == null) {
1479+
return;
1480+
}
1481+
1482+
final String argLineFromProperty = properties.getProperty("argLine");
1483+
final String replaced = replacePropertyInArgline(key, value, argLineFromProperty);
1484+
1485+
if (replaced == null) {
1486+
properties.remove("argLine");
1487+
} else {
1488+
properties.put("argLine", replaced);
1489+
}
1490+
1491+
if (value == null) {
1492+
properties.remove(key);
1493+
} else {
1494+
properties.put(key, value);
1495+
}
1496+
}
1497+
1498+
/**
1499+
* Replaces/sets a property in a argLine-String.
1500+
*
1501+
* @param key
1502+
* The key of the property to set.
1503+
* @param value
1504+
* The value of the property to set, if null, the property gets removed.
1505+
* @param argLine
1506+
* A argLine-representation used to replace the key.
1507+
* @return a new argLine where the property is replaced/set.
1508+
*/
1509+
private String replacePropertyInArgline(final String key, final String value, final String argLine) {
1510+
final String javaProperty = "-D" + key + "=";
1511+
final String argLinePropertyRegex = javaProperty + "\\S*";
1512+
final String argLinePropertyReplacement = (value == null) ? "" : javaProperty + value;
1513+
1514+
if (StringUtils.isBlank(argLine) || !argLine.contains(javaProperty)) {
1515+
// noop: old argLine is empty or does not contain the property and no property to set
1516+
if (StringUtils.isBlank(argLinePropertyReplacement)) {
1517+
return argLine;
1518+
// append: old argLine is empty or does not contain the property and property to set
1519+
} else {
1520+
final String argLineReadyToAppend = StringUtils.isBlank(argLine) ? "" : argLine + " ";
1521+
return argLineReadyToAppend + argLinePropertyReplacement;
1522+
}
1523+
// replace or remove: old argLine contains property, replacement: new or empty
1524+
} else {
1525+
return argLine.replaceAll(argLinePropertyRegex, argLinePropertyReplacement);
1526+
}
12911527
}
12921528
}
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)