Skip to content

Commit a7164d2

Browse files
committed
Rather large change, as this more or less solidifies the direction I'd like to take.
1 parent 1d32484 commit a7164d2

File tree

7 files changed

+88
-101
lines changed

7 files changed

+88
-101
lines changed

README.md

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ It does so by:
1010
* SCM tagging builds for master and support branches. You can use the project SCM definition, or if you omit it, you can resolve the CI server's repository connection information. (Zero Maven scm configuration necessary)
1111
* Promoting existing tested (staged) artifacts for release, rather than re-building the artifacts. Eliminates the risk of accidental master merges or commits resulting in untested code being released, and provides digest hash traceability for the history of artifacts.
1212
* Enabling the decoupling of repository deployment and execution environment delivery based on the current git branch.
13+
* Allowing for long-running non-release branches to be deployed to snapshots, automatically reversioning the artifacts based off the branch name.
1314
* Automated deployment, promotion, and delivery of projects without the [maven-release-plugin](http://maven.apache.org/maven-release/maven-release-plugin/) or some other [*almost there* solution](https://axelfontaine.com/blog/final-nail.html).
1415
* Customizing maven project and system properties based upon the current branch being built. This allows test cases to target different execution environments without changing the artifact results.
1516
* Enabling automatic purging and resolving (force update) of 'release' and 'hotfix' release versioned dependencies resolved from the 'stage' repository.
@@ -24,6 +25,7 @@ This plugin solves a few specific issues common in consolidated Hudson/Jenkins C
2425
4. Set arbitrary project properties based upon the type of GIT branch being built.
2526
5. Reliably tag deploy builds from the master and support branches
2627
6. Enable split 'deploy' vs. 'deliver' maven CI job configuration, without rebuilding artifacts for the 'deliver' phase.
28+
7. Allow for deployment of long-running feature branches to repositories without having to mangle the version in the pom.xml.
2729

2830
In addition to supporting these goals for the project, this plugin does it in a manner that tries to be as effortless (yet configurable) as possible.
2931
If you use non-standard gitflow branch names (emer instead of hotfix), this plugin supports that. If you don't want to do version enforcement, this plugin supports that.
@@ -107,14 +109,16 @@ All of the solutions to these issues are implemented independently in different
107109
<releaseDeploymentRepository>localnexus-releases</releaseDeploymentRepository>
108110
<stageDeploymentRepository>localnexus-stage</stageDeploymentRepository>
109111
<snapshotDeploymentRepository>localnexus-snapshots</snapshotDeploymentRepository>
112+
<!-- Allow branches starting with feature/poc to be published as automagically versioned branch-name-SNAPSHOT artifacts -->
113+
<otherDeploymentBranchPattern>(origin/)feature/poc/.*</otherDeploymentBranchPattern>
110114
</configuration>
111115
<executions>
112116
<execution>
113117
<goals>
114118
<goal>enforce-versions</goal>
119+
<goal>set-properties</goal>
115120
<goal>retarget-deploy</goal>
116121
<goal>update-stage-dependencies</goal>
117-
<goal>set-properties</goal>
118122
<goal>tag-master</goal>
119123
<goal>promote-master</goal>
120124
</goals>
@@ -167,6 +171,19 @@ The following properties change the behavior of this goal:
167171
| hotfixBranchPattern | (origin/)?hotfix/(.*) | No | Regex. When matched, signals a hotfix branch is being built. Last subgroup, if present, must match the Maven project version. |
168172
| developmentBranchPattern | (origin/)?develop | Yes | Regex. When matched, signals a development branch is being built. Note the lack of a subgroup. |
169173

174+
## Goal: `set-properties` (Dynamically Set Maven Project / System Properties)
175+
176+
Some situations with automated testing (and integration testing in particular) demand changing configuration properties
177+
based upon the branch type being built. This is a common necessity when configuring automated DB refactorings as part of
178+
a build, or needing to setup / configure datasources for automated tests to run against.
179+
180+
The `set-properties` goal allows for setting project (or system) properties, dynamically based on the detected git
181+
branch being built. Properties can be specified as a Properties collection in plugin configuration, or can be loaded
182+
from a property file during the build. Both property key names and property values will have placeholders resolved.
183+
184+
Multiple executions can be configured, and each execution can target different scopes (system or project), and can load
185+
properties from files with an assigned keyPrefix, letting you name-space properties from execution ids.
186+
170187

171188
## Goal: `retarget-deploy` (Branch Specific Deploy Targets & Staging)
172189

@@ -186,7 +203,7 @@ plugins in the build process (deploy, site-deploy, etc.) will use the repositori
186203
| releaseDeploymentRepository | n/a | The repository to use for releases. (Builds with a GIT_BRANCH matching `masterBranchPattern` or `supportBranchPattern`) |
187204
| stageDeploymentRepository | n/a | The repository to use for staging. (Builds with a GIT_BRANCH matching `releaseBranchPattern` or `hotfixBranchPattern`) |
188205
| snapshotDeploymentRepository | n/a | The repository to use for snapshots. (Builds matching `developmentBranchPattern`) |
189-
206+
| otherDeploymentBranchPattern | false | N/A | Regex. When matched, the branch name is normalized and any artifacts produced by the build will include the normalized branch name and -SNAPSHOT. Deployment will target the snapshot repository|
190207

191208
**The repository properties should follow the following format**, `id::layout::url::uniqueVersion`.
192209

@@ -235,20 +252,15 @@ Can be replaced with the following plugin configuration, which also introduces t
235252
...
236253
</build>
237254

255+
### Deploying non-release (OTHER) type branches as -SNAPSHOT releases.
238256

239-
## Goal: `set-properties` (Dynamically Set Maven Project / System Properties)
240-
241-
Some situations with automated testing (and integration testing in particular) demand changing configuration properties
242-
based upon the branch type being built. This is a common necessity when configuring automated DB refactorings as part of
243-
a build, or needing to setup / configure datasources for automated tests to run against.
244-
245-
The `set-properties` goal allows for setting project (or system) properties, dynamically based on the detected git
246-
branch being built. Properties can be specified as a Properties collection in plugin configuration, or can be loaded
247-
from a property file during the build. Both property key names and property values will have placeholders resolved.
248-
249-
Multiple executions can be configured, and each execution can target different scopes (system or project), and can load
250-
properties from files with an assigned keyPrefix, letting you name-space properties from execution ids.
251-
257+
In addition to setting up repository targets for release branches, the `retarget-depoy` branch can deploy other branches
258+
matching the `otherDeploymentBranchPattern` as -SNAPSHOT artifacts which include the branch name as build metadata.
259+
This is loosely based on the [semVer](https://semver.org) semantic version scheme, in that the plugin will reversion any
260+
artifacts to be produced with `+feature-branch-name-normalized-SNAPSHOT` where any characters not in `[0-9A-Za-z-.]` will
261+
be replaced with `-`. Artifact versions for feature branches will _always_ be -SNAPSHOT, and will _always_ target the
262+
Snapshots repository. The intent for this configuration setting is to provide a way for long-running branches (matching
263+
a naming convention you define) can be published to a SNAPSHOT repo for use by other projects.
252264

253265
## Goal: `update-stage-dependencies` (Force update of dependency staged Releases)
254266

src/main/java/com/e_gineering/maven/gitflowhelper/AbstractGitflowBasedRepositoryMojo.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ private static PrintWriter newPrintWriter(File catalog) throws FileNotFoundExcep
8484
@Parameter(defaultValue = "${repositorySystemSession}", required = true)
8585
RepositorySystemSession session;
8686

87-
@Parameter(property = "gitflow.force.other.deploy", defaultValue = "false", required = true)
88-
String forceOtherDeploy;
87+
@Parameter(property = "otherDeployBranchPattern", required = false)
88+
String otherDeployBranchPattern;
8989

9090
@Component
9191
private EnhancedLocalRepositoryManagerFactory localRepositoryManagerFactory;

src/main/java/com/e_gineering/maven/gitflowhelper/RetargetDeployMojo.java

Lines changed: 19 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -35,37 +35,24 @@ protected void execute(final GitBranchInfo gitBranchInfo) throws MojoExecutionEx
3535
break;
3636
}
3737
case OTHER: {
38+
// If other branches are set to deploy
3839
// Other branches never target release, but may target stage for non-SNAPSHOT artifacts.
3940
// For this reason, "overwrite" is considered _highly_ dangerous.
40-
if (!"false".equalsIgnoreCase(forceOtherDeploy)) {
41-
// Setup the target based on the base project version.
42-
if (ArtifactUtils.isSnapshot(project.getVersion())) {
43-
setTargetSnapshots();
44-
} else {
45-
setTargetStage();
46-
}
47-
48-
// Monkey with things to do our semVer magic.
49-
if ("semVer".equalsIgnoreCase(forceOtherDeploy)) {
50-
if (ArtifactUtils.isSnapshot(project.getVersion())) {
51-
getLog().warn("Maven -SNAPSHOT builds break semVer standards, in that -SNAPSHOT must be the _last_ poriton of a maven version. In semVer, the pre-release status is supposed to come before the build meta-data.");
52-
getLog().info("The gitflow-helper-maven-plugin will inject the build metadata preceding the -SNAPSHOT, allowing for snapshot deployments of this branch.");
53-
}
54-
String branchName = gitBranchInfo.getName();
55-
String semVerAddition = "+" + branchName.replaceAll("[^0-9^A-Z^a-z^-^.]", "-");
41+
getLog().debug("Resolving: " + otherDeployBranchPattern);
42+
String otherBranchesToDeploy = resolveExpression(otherDeployBranchPattern);
43+
getLog().debug("Resolved to: " + otherBranchesToDeploy);
44+
if (!"".equals(otherBranchesToDeploy) && gitBranchInfo.getName().matches(otherBranchesToDeploy)) {
45+
setTargetSnapshots();
5646

57-
updateArtifactVersion(project.getArtifact(), semVerAddition);
58-
for (Artifact a : project.getAttachedArtifacts()) {
59-
updateArtifactVersion(a, semVerAddition);
60-
}
47+
String branchName = gitBranchInfo.getName();
48+
String semVerAddition = "+" + branchName.replaceAll("[^0-9^A-Z^a-z^-^.]", "-") + "-SNAPSHOT";
6149

62-
getLog().info("Artifact versions updated with semVer build metadata: " + semVerAddition);
63-
}
64-
if ("overwrite".equalsIgnoreCase(forceOtherDeploy)) {
65-
getLog().warn("DANGER! DANGER, WILL ROBINSON!");
66-
getLog().warn("Deployment of this build will OVERWRITE Deployment of " + project.getVersion() + " in the targeted repository.");
67-
getLog().warn("THIS IS NOT RECOMMENDED.");
50+
updateArtifactVersion(project.getArtifact(), semVerAddition);
51+
for (Artifact a : project.getAttachedArtifacts()) {
52+
updateArtifactVersion(a, semVerAddition);
6853
}
54+
55+
getLog().info("Artifact versions updated with semVer build metadata: " + semVerAddition);
6956
break;
7057
}
7158
}
@@ -77,20 +64,12 @@ protected void execute(final GitBranchInfo gitBranchInfo) throws MojoExecutionEx
7764
}
7865

7966
private void updateArtifactVersion(final Artifact a, final String semVerAdditon) {
80-
String baseVersion = a.getBaseVersion();
81-
String version = a.getVersion();
82-
83-
String semBaseVersion = baseVersion + semVerAdditon;
84-
String semVersion = version + semVerAdditon;
85-
86-
if (semBaseVersion.contains("-SNAPSHOT")) {
87-
semBaseVersion = semBaseVersion.replace("-SNAPSHOT", "") + "-SNAPSHOT";
88-
}
89-
if (semVersion.contains("-SNAPSHOT")) {
90-
semVersion = semVersion.replace("-SNAPSHOT", "") + "-SNAPSHOT";
91-
}
92-
a.setBaseVersion(semBaseVersion);
93-
a.setVersion(semVersion);
67+
// Handle null-safety. In some cases Projects don't have primary artifacts.
68+
if (a != null) {
69+
// If the version contains -SNAPSHOT, replace it with ""
70+
a.setVersion(a.getVersion().replace("-SNAPSHOT", "") + semVerAdditon);
71+
a.setBaseVersion(a.getBaseVersion().replace("-SNAPSHOT", "") + semVerAdditon);
72+
}
9473
}
9574

9675

src/main/java/com/e_gineering/maven/gitflowhelper/SetPropertiesMojo.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
/**
1616
* Set a project property value based upon the current ${env.GIT_BRANCH} resolution.
1717
*/
18-
@Mojo(name = "set-properties", defaultPhase = LifecyclePhase.INITIALIZE, threadSafe = true)
18+
@Mojo(name = "set-properties", defaultPhase = LifecyclePhase.VALIDATE, threadSafe = true)
1919
public class SetPropertiesMojo extends AbstractGitflowBranchMojo {
2020

2121
/**

src/test/java/com/e_gineering/maven/gitflowhelper/OtherBranchIT.java

Lines changed: 35 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -9,58 +9,53 @@
99
public class OtherBranchIT extends AbstractIntegrationTest {
1010
@Test
1111
public void featureSnapshotSemVer() throws Exception {
12-
Verifier verifier = createVerifier("/project-stub", "origin/feature/my-feature-branch", "5.0.0-SNAPSHOT");
13-
try {
14-
verifier.getCliOptions().add("-Dgitflow.force.other.deploy=semver");
15-
verifier.executeGoal("deploy");
12+
Verifier verifier = createVerifier("/project-stub", "origin/feature/poc/my-feature-branch", "5.0.0-SNAPSHOT");
13+
verifier.executeGoal("deploy");
1614

17-
verifier.verifyTextInLog("Artifact versions updated with semVer build metadata: +origin-feature-my-feature-branch");
18-
verifier.verifyErrorFreeLog();
19-
} finally {
20-
verifier.resetStreams();
21-
}
15+
verifier.verifyTextInLog("Artifact versions updated with semVer build metadata: +origin-feature-poc-my-feature-branch-SNAPSHOT");
16+
verifier.verifyErrorFreeLog();
17+
verifier.resetStreams();
2218
}
2319

2420
@Test
25-
public void featureSnapshotOverwrite() throws Exception {
26-
Verifier verifier = createVerifier("/project-stub", "origin/feature/my-feature-branch", "5.0.0-SNAPSHOT");
27-
try {
28-
verifier.getCliOptions().add("-Dgitflow.force.other.deploy=overwrite");
29-
verifier.executeGoal("deploy");
21+
public void featureSemVer() throws Exception {
22+
Verifier verifier = createVerifier("/project-stub", "origin/feature/poc/my-feature-branch.with.other.identifiers", "5.0.1");
23+
verifier.executeGoal("deploy");
3024

31-
verifier.verifyTextInLog("DANGER! DANGER, WILL ROBINSON!");
32-
verifier.verifyErrorFreeLog();
33-
} finally {
34-
verifier.resetStreams();
35-
}
25+
verifier.verifyTextInLog("Artifact versions updated with semVer build metadata: +origin-feature-poc-my-feature-branch.with.other.identifiers-SNAPSHOT");
26+
verifier.verifyErrorFreeLog();
27+
verifier.resetStreams();
3628
}
3729

3830
@Test
39-
public void featureSemVer() throws Exception {
40-
Verifier verifier = createVerifier("/project-stub", "origin/feature/my-feature-branch.with.other.identifiers", "5.0.1");
41-
try {
42-
verifier.getCliOptions().add("-Dgitflow.force.other.deploy=semver");
43-
verifier.executeGoal("deploy");
31+
public void noOtherDeployMatch() throws Exception {
32+
Verifier verifier = createVerifier("/project-stub", "origin/feature/my-feature-branch", "5.0.1-SNAPSHOT");
33+
verifier.executeGoal("deploy");
4434

45-
verifier.verifyTextInLog("Artifact versions updated with semVer build metadata: +origin-feature-my-feature-branch.with.other.identifiers");
46-
verifier.verifyErrorFreeLog();
47-
} finally {
48-
verifier.resetStreams();
49-
}
35+
verifier.verifyTextInLog("Un-Setting artifact repositories.");
36+
verifier.verifyErrorFreeLog();
37+
verifier.resetStreams();
5038
}
5139

5240
@Test
53-
public void featureOverwrite() throws Exception {
54-
Verifier verifier = createVerifier("/project-stub", "origin/feature/my-feature-branch", "5.0.1");
55-
try {
56-
verifier.getCliOptions().add("-Dgitflow.force.other.deploy=overwrite");
57-
verifier.executeGoal("deploy");
41+
public void automagicVersionDependenciesResolve() throws Exception {
42+
// Create a -SNAPSHOT of the project-stub.
43+
Verifier verifier = createVerifier("/project-stub", "origin/feature/poc/long-running", "2.0.0");
5844

59-
verifier.verifyTextInLog("DANGER! DANGER, WILL ROBINSON!");
60-
verifier.verifyErrorFreeLog();
61-
} finally {
62-
verifier.resetStreams();
63-
}
64-
}
45+
verifier.executeGoal("deploy");
46+
47+
verifier.verifyTextInLog("Artifact versions updated with semVer build metadata: +origin-feature-poc-long-running-SNAPSHOT");
48+
verifier.verifyErrorFreeLog();
49+
verifier.resetStreams();
6550

51+
// Create a -SNAPSHOT of the project-alt1-stub that depends upon the other project's automagic version.
52+
verifier = createVerifier("/project-alt1-stub", "origin/feature/poc/long-running", "2.0.0");
53+
54+
verifier.getCliOptions().add("-Ddependency.stub.version=2.0.0+origin-feature-poc-long-running-SNAPSHOT");
55+
verifier.getCliOptions().add("-Dplugin.stub.version=2.0.0+origin-feature-poc-long-running-SNAPSHOT");
56+
57+
verifier.executeGoal("deploy");
58+
verifier.verifyErrorFreeLog();
59+
verifier.resetStreams();
60+
}
6661
}

src/test/resources/project-alt1-stub/pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,15 @@
5656
<releaseBranchProperties>
5757
<foo>bar</foo>
5858
</releaseBranchProperties>
59-
<scope>system</scope>
59+
<otherDeployBranchPattern>(origin/)feature/poc/.*</otherDeployBranchPattern>
6060
</configuration>
6161
<executions>
6262
<execution>
6363
<goals>
6464
<goal>enforce-versions</goal>
65+
<goal>set-properties</goal>
6566
<goal>retarget-deploy</goal>
6667
<goal>update-stage-dependencies</goal>
67-
<goal>set-properties</goal>
6868
<goal>promote-master</goal>
6969
</goals>
7070
</execution>

src/test/resources/project-stub/pom.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,15 @@
6969
<undefinedBranchProperties>
7070
<build.branch.type>undefined</build.branch.type>
7171
</undefinedBranchProperties>
72+
<otherDeployBranchPattern>(origin/)feature/poc/.*</otherDeployBranchPattern>
7273
</configuration>
7374
<executions>
7475
<execution>
7576
<goals>
7677
<goal>enforce-versions</goal>
78+
<goal>set-properties</goal>
7779
<goal>retarget-deploy</goal>
7880
<goal>update-stage-dependencies</goal>
79-
<goal>set-properties</goal>
8081
</goals>
8182
</execution>
8283
<execution>

0 commit comments

Comments
 (0)