Skip to content

Commit 5476358

Browse files
committed
Add support for changelist property per branch for maven ci friendly versioning - closes #305 #314
1 parent cb93c2f commit 5476358

11 files changed

+307
-30
lines changed

README.md

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

220220
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`.
221221

222+
### CI friendly in dependencies/multi module
223+
224+
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.
225+
226+
As the different steps of the plugin running on different branches, different values for `changelist` may be needed to successfully resolve the dependencies.
227+
228+
To set different values to `changelist` per branch the properties `productionChangelistValue`, `hotfixChangelistValue`, `releaseChangelistValue`, `developmentChangelistValue`, `featureChangelistValue`, `supportChangelistValue` are used.
229+
230+
As example for the `gitflow:hotfix-finish` the following properties may be used (setting `developmentChangelistValue` done explicit for better understanding):
231+
232+
mvn gitflow:hotfix-finish -DhotfixVersion=x.y.z -DproductionChangelistValue='' -DhotfixChangelistValue='' -DdevelopmentChangelistValue='-SNAPSHOT'
233+
222234
## Additional goal parameters
223235

224236
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.
@@ -189,6 +261,7 @@ public abstract class AbstractGitFlowMojo extends AbstractMojo {
189261
*/
190262
@Parameter(property = "mvnExecutable")
191263
private String mvnExecutable;
264+
192265
/**
193266
* The path to the Git executable. Defaults to "git".
194267
*/
@@ -201,7 +274,7 @@ public abstract class AbstractGitFlowMojo extends AbstractMojo {
201274

202275
@Component
203276
protected ProjectBuilder projectBuilder;
204-
277+
205278
/** Default prompter. */
206279
@Component
207280
protected Prompter prompter;
@@ -646,7 +719,7 @@ protected boolean gitCheckTagExists(final String tagName) throws MojoFailureExce
646719
* @throws CommandLineException
647720
* If command line execution fails.
648721
*/
649-
protected void gitCheckout(final String branchName)
722+
private void gitCheckout(final String branchName)
650723
throws MojoFailureException, CommandLineException {
651724
getLog().info("Checking out '" + branchName + "' branch.");
652725

@@ -665,7 +738,7 @@ protected void gitCheckout(final String branchName)
665738
* @throws CommandLineException
666739
* If command line execution fails.
667740
*/
668-
protected void gitCreateAndCheckout(final String newBranchName,
741+
private void gitCreateAndCheckout(final String newBranchName,
669742
final String fromBranchName) throws MojoFailureException,
670743
CommandLineException {
671744
getLog().info(
@@ -1278,7 +1351,8 @@ private void executeGitCommand(final String... args)
12781351
*/
12791352
private void executeMvnCommand(final String... args)
12801353
throws CommandLineException, MojoFailureException {
1281-
executeCommand(cmdMvn, true, argLine, args);
1354+
final String argLineWithBranchSpecifics = joinStrings(argLine, mvnArgsBranchSpecific);
1355+
executeCommand(cmdMvn, true, argLineWithBranchSpecifics, args);
12821356
}
12831357

12841358
/**
@@ -1380,4 +1454,163 @@ public String getError() {
13801454
public void setArgLine(String argLine) {
13811455
this.argLine = argLine;
13821456
}
1457+
1458+
/**
1459+
* Executes git checkout and sets Maven CI friendly settings per branch.
1460+
*
1461+
* @param branchType
1462+
* Type of branch to set config for.
1463+
* @param branchName
1464+
* Branch name to checkout.
1465+
* @throws MojoExecutionException an internal error occurred
1466+
* @throws MojoFailureException an error with the underlying commands occurred
1467+
* @throws CommandLineException an error with the underlying commands occurred
1468+
*/
1469+
protected void checkoutAndSetConfigForBranch(final BranchType branchType, final String branchName)
1470+
throws MojoExecutionException, MojoFailureException, CommandLineException {
1471+
if (branchType == null) {
1472+
throw new MojoExecutionException("INTERNAL: given BranchType is null");
1473+
}
1474+
1475+
gitCheckout(branchName);
1476+
setConfigForBranchType(branchType);
1477+
}
1478+
1479+
/**
1480+
* Executes git checkout -b and sets Maven CI friendly settings per branch.
1481+
*
1482+
* @param branchType
1483+
* Type of branch to set config for.
1484+
* @param newBranchName
1485+
* Create branch with this name.
1486+
* @param fromBranchName
1487+
* Create branch from this branch.
1488+
* @throws MojoExecutionException an internal error occurred
1489+
* @throws MojoFailureException an error with the underlying commands occurred
1490+
* @throws CommandLineException an error with the underlying commands occurred
1491+
*/
1492+
protected void createAndCheckoutAndSetConfigForBranch(final BranchType branchType, final String newBranchName,
1493+
final String fromBranchName) throws MojoExecutionException, MojoFailureException, CommandLineException {
1494+
if (branchType == null) {
1495+
throw new MojoExecutionException("INTERNAL: given BranchType is null");
1496+
}
1497+
1498+
gitCreateAndCheckout(newBranchName, fromBranchName);
1499+
setConfigForBranchType(branchType);
1500+
}
1501+
1502+
/**
1503+
* Sets Maven CI friendly settings dependent of the type of branch.
1504+
* This includes settings passed to the maven commands in <code>executeMvnCommand</code> and manipulates
1505+
* the user properties inside the <code>MavenSession</code>, to guarantee that internal mvn commands
1506+
* via e.g. <code>ProjectBuilder.build</code> also uses the correct properties.
1507+
*
1508+
* @param branchType
1509+
* Type of branch to set config for.
1510+
* @throws MojoExecutionException an internal error occurred
1511+
*/
1512+
protected void setConfigForBranchType(final BranchType branchType) throws MojoExecutionException {
1513+
if (branchType == null) {
1514+
throw new MojoExecutionException("INTERNAL: given BranchType is null");
1515+
}
1516+
1517+
final boolean noChangelistValueToBeModified = productionChangelistValue == null
1518+
&& hotfixChangelistValue == null && releaseChangelistValue == null
1519+
&& developmentChangelistValue == null && featureChangelistValue == null
1520+
&& supportChangelistValue == null;
1521+
1522+
if (StringUtils.isBlank(changelistProperty) || noChangelistValueToBeModified) {
1523+
return;
1524+
}
1525+
1526+
final String changelistValue;
1527+
1528+
switch (branchType) {
1529+
case PRODUCTION:
1530+
changelistValue = productionChangelistValue;
1531+
break;
1532+
case HOTFIX:
1533+
changelistValue = hotfixChangelistValue;
1534+
break;
1535+
case RELEASE:
1536+
changelistValue = releaseChangelistValue;
1537+
break;
1538+
case DEVELOPMENT:
1539+
changelistValue = developmentChangelistValue;
1540+
break;
1541+
case FEATURE:
1542+
changelistValue = featureChangelistValue;
1543+
break;
1544+
case SUPPORT:
1545+
changelistValue = supportChangelistValue;
1546+
break;
1547+
default:
1548+
throw new MojoExecutionException("INTERNAL: unhandled case for branchType value: " + branchType);
1549+
}
1550+
1551+
setPropertyInProperties(changelistProperty, changelistValue, mavenSession.getProjectBuildingRequest().getUserProperties());
1552+
mvnArgsBranchSpecific = getJavaPropertyAsArgLineString(changelistProperty, changelistValue);
1553+
}
1554+
1555+
/**
1556+
* Sets a property in the given <code>Properties</code>.
1557+
*
1558+
* @param key
1559+
* The key of the property to set.
1560+
* @param value
1561+
* The value of the property to set, if null, the property gets removed.
1562+
* @param properties
1563+
* The properties where to replace the entry.
1564+
*/
1565+
private void setPropertyInProperties(final String key, final String value, final Properties properties) {
1566+
if (StringUtils.isBlank(key) || properties == null) {
1567+
return;
1568+
}
1569+
1570+
if (value == null) {
1571+
properties.remove(key);
1572+
} else {
1573+
properties.put(key, value);
1574+
}
1575+
}
1576+
1577+
/**
1578+
* Retrieve a string representation of a java property defined by key/value.
1579+
*
1580+
* @param key
1581+
* The key of the property to set.
1582+
* @param value
1583+
* The value of the property to set, if null, an empty string is returned.
1584+
* @return
1585+
* A string representation to be used as java argument.
1586+
* Empty if key is null or empty, or the value is null.
1587+
*/
1588+
private String getJavaPropertyAsArgLineString(final String key, final String value) {
1589+
if (StringUtils.isBlank(key) || value == null) {
1590+
return "";
1591+
} else {
1592+
return "-D" + key + "=" + value;
1593+
}
1594+
}
1595+
1596+
/**
1597+
* Join two <code>String</code>'s with a space.
1598+
* Both <code>String</code>'s can be null. And always a non-null value is returned.
1599+
*
1600+
* @param a
1601+
* The first string, where the second gets appended to. null is treated as empty.
1602+
* @param b
1603+
* The second string, which gets appended to the first one. null is treated as empty.
1604+
* @return
1605+
* The combined string, if both strings are null or empty, an empty String is returned.
1606+
*/
1607+
private String joinStrings(final String a, final String b) {
1608+
if (StringUtils.isBlank(a)) {
1609+
return StringUtils.clean(b);
1610+
} else if (StringUtils.isBlank(b)) {
1611+
return StringUtils.clean(a);
1612+
} else {
1613+
return a + " " + b;
1614+
}
1615+
}
13831616
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Copyright 2014-2021 Aleksandr Mashchenko.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.amashchenko.maven.plugin.gitflow;
17+
18+
/**
19+
* The possible types of the different used branches.
20+
*/
21+
public enum BranchType {
22+
PRODUCTION, DEVELOPMENT, FEATURE, RELEASE, HOTFIX, SUPPORT;
23+
}

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)