Skip to content

Commit 3fab816

Browse files
committed
startsWith semantics for support branches
1 parent dab3167 commit 3fab816

File tree

2 files changed

+33
-21
lines changed

2 files changed

+33
-21
lines changed

README.md

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ It does so by:
77
* Enforcing [gitflow](http://nvie.com/posts/a-successful-git-branching-model/) version heuristics in [Maven](http://maven.apache.org/) projects.
88
* Coercing Maven to gracefully support the gitflow workflow without imposing complex CI job configurations or complex Maven setups.
99
* Setting distributionManagement repositories (for things like [maven-deploy-plugin](https://maven.apache.org/plugins/maven-deploy-plugin/)) based upon the current git branch.
10-
* SCM tagging builds for the master branch. 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)
10+
* 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.
1313
* 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).
@@ -19,9 +19,9 @@ This plugin solves a few specific issues common in consolidated Hudson/Jenkins C
1919

2020
1. Ensure the developers are following the (git branching) project version rules, and fail the build if they are not.
2121
2. Enable the maven-deploy-plugin to target a snapshots, test-releases, and releases repository.
22-
3. _Copy_ (rather than rebuild) the tested artifacts from the test-releases repository to the release repository, without doing a full project rebuild from the master branch.
22+
3. _Copy_ (rather than rebuild) the tested artifacts from the test-releases repository to the release repository, without doing a full project rebuild from the master or support branches.
2323
4. Set arbitrary project properties based upon the type of GIT branch being built.
24-
5. Reliably tag deploy builds from the 'master' branch
24+
5. Reliably tag deploy builds from the master and support branches
2525
6. Enable split 'deploy' vs. 'deliver' maven CI job configuration, without rebuilding artifacts for the 'deliver' phase.
2626

2727
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.
@@ -70,6 +70,7 @@ All of the solutions to these issues are implemented independently in different
7070
</goals>
7171
<configuration>
7272
<masterBranchPropertyFile>foo/bar/prod.props</masterBranchPropertyFile>
73+
<supportBranchPropertyFile>foo/bar/support.props</supportBranchPropertyFile>
7374
<hotfixBranchPropertyFile>foo/bar/emer.props</hotfixBranchPropertyFile>
7475
<releaseBranchPropertyFile>foo/bar/test.props</releaseBranchPropertyFile>
7576
<developmentBranchPropertyFile>foo/bar/dev.props</developmentBranchPropertyFile>
@@ -92,7 +93,7 @@ One common stumbling block for teams adjusting to gitflow with Maven projects is
9293
In practice, the Maven versions should:
9394

9495
* Be synchronized with release branch and hotfix branch names.
95-
* Never be -SNAPSHOT in the master branch, release, or hotfix branches.
96+
* Never be -SNAPSHOT in the master, support, release, or hotfix branches.
9697
* Always be -SNAPSHOT in the develop branch.
9798
* Be irrelevant if there's no git branch resolvable from your environment.
9899

@@ -108,6 +109,7 @@ The following properties change the behavior of this goal:
108109
| -------------------- | ------------- | --------------------------- | ----------- |
109110
| gitBranchExpression | current git branch resolved from SCM or ${env.GIT_BRANCH} | n/a | Maven property expression to resolve in order to determine the current git branch |
110111
| masterBranchPattern | (origin/)?master | No | Regex. When matched, signals the master branch is being built. |
112+
| supportBranchPattern | (origin/)?support/(.*) | No | Regex. When matches, signals a support branch (long term master-equivalent for older release) being built. Last subgroup, if present, must be start of the Maven project version. |
111113
| releaseBranchPattern | (origin/)?release/(.*) | No | Regex. When matched, signals a release branch being built. Last subgroup, if present, must match the Maven project version. |
112114
| hotfixBranchPattern | (origin/)?hotfix/(.*) | No | Regex. When matched, signals a hotfix branch is being built. Last subgroup, if present, must match the Maven project version. |
113115
| developmentBranchPattern | (origin/)?develop | Yes | Regex. When matched, signals a development branch is being built. Note the lack of a subgroup. |
@@ -127,9 +129,9 @@ plugins in the build process (deploy, site-deploy, etc.) will use the repositori
127129
| Property | Default Value | Description |
128130
| -------- | ------------- | ----------- |
129131
| gitBranchExpression | current git branch resolved from SCM or ${env.GIT_BRANCH} | Maven property expression to resolve in order to determine the current git branch |
130-
| releaseDeploymentRepository | n/a | The repository to use for releases. (Builds with a GIT_BRANCH matching `masterBranchPattern`) |
131-
| stageDeploymentRepository | n/a | The repository to use for staging. (Builds with a GIT_BRANCH matching `releaseBranchPattern` or `hotfixBranchPattern` |
132-
| snapshotDeploymentRepository | n/a | The repository to use for snapshots. (Builds matching `developmentBranchPattern` |
132+
| releaseDeploymentRepository | n/a | The repository to use for releases. (Builds with a GIT_BRANCH matching `masterBranchPattern` or `supportBranchPattern`) |
133+
| stageDeploymentRepository | n/a | The repository to use for staging. (Builds with a GIT_BRANCH matching `releaseBranchPattern` or `hotfixBranchPattern`) |
134+
| snapshotDeploymentRepository | n/a | The repository to use for snapshots. (Builds matching `developmentBranchPattern`) |
133135

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

@@ -182,9 +184,9 @@ Can be replaced with the following plugin configuration, which also introduces t
182184

183185
In a gitflow environment, a commit to a master branch should trigger a job to build on the master branch, which would result in the release being tagged if successful.
184186

185-
The `tag-master` goal executes the [maven-scm-plugin tag goal](https://maven.apache.org/scm/maven-scm-plugin/tag-mojo.html) when the
186-
`gitBranchExpression` resolves to a value matching the `masterBranchPattern` regular expression. To determine the SCM URL to use, the plugin looks for a
187-
`developerConnection` or `connection` information in an SCM block, and if not found the `gitURLExpression` is evaluated at run-time.
187+
The `tag-master` goal invokes the SCM manager to tag the source repository when `gitBranchExpression` resolves to a value matching the `masterBranchPattern` or
188+
`supportBranchPattern` regular expressions. To determine the SCM URL to use, the plugin looks for a `developerConnection` or `connection` information in an SCM block
189+
and if not found the `gitURLExpression` is evaluated at run-time.
188190
The default expression, `${env.GIT_URL}`, is one that is commonly provided by Jenkins & Hudson.
189191

190192
The following properties can be configured for this goal:
@@ -193,35 +195,37 @@ The following properties can be configured for this goal:
193195
| -------------------- | ------------- | ----------- |
194196
| gitBranchExpression | current git branch resolved from SCM or ${env.GIT_BRANCH} | Maven property expression to resolve in order to determine the current git branch |
195197
| gitURLExpression | current git branch resolved from SCM or ${env.GIT_URL} | Maven property expression to resolve for the GIT URL connection to use. |
196-
| masterBranchPattern | (origin/)?master | Regex. When matched against the resolved value of `gitBranchExpression` this plugin executes the scm:tag goal using the `gitURLExpression` to resolve the git URL to use. |
198+
| masterBranchPattern | (origin/)?master | Regex. When matched against the resolved value of `gitBranchExpression` this plugin tags the SCM using the `gitURLExpression` to resolve the git URL to use. |
199+
| supportBranchPattern | (origin/)?support/(.*) | Regex. When matches against the resolved value of `gitBranchExpression` this plugin tags the SCM using the `gitURLExpression` to resolve the git URL to use. |
197200
| tag | ${project.version} | An expression to use for the SCM tag. |
198201

199202

200203
## Goal: `promote-master` and the Build Extension. (Copy Staged Artifacts to Releases)
201204

202205
With gitflow, a new version of a product is prepared in the `release/.*` and `hotfix/.*` branches of the project.
203-
These artifacts are put through their paces and validated before the merge back into the master branch.
206+
These artifacts are put through their paces and validated before the merge back into the master branch or a support branch.
204207

205208
In a traditional CI approach, the merge to master triggers a build, which gets deployed to a releases repository, and perhaps deployed to an execution
206209
environment. This approach has the consequence of deployed artifacts in the release repository having never been tested in a stage or test environment.
207210
Sure, you've tested the branch, but the actual artifact from the stage repository is what you *really* want to have deployed to the release repository.
208211

209-
If stage artifacts are copied into the releases repository when a master commit occurs (ex: the merge from release/2.3.4.5 into master) then the
212+
If stage artifacts are copied into the releases repository when a master (or support branch) commit occurs (ex: the merge from release/2.3.4.5 into master) then the
210213
artifacts will have the same SHA and MD5 hash, and you'd have full trace-ability for the lifecycle of the artifacts. You'd also have the added benefit
211214
of achieving the ideal situation for gitflow deployment, where releases originate from the branches created for them, and code is **never deployed
212215
directly from master**. Rather, master is really only used for tracking releases and branching to support production issues.
213216

214217
To accomplish this the `promote-master` goal and a Maven build extension work together.
215218

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

220-
The `promote-master` goal executes when the `gitBranchExpression` resolves to a value matching the `masterBranchPattern` regular expression.
224+
The `promote-master` goal executes when the `gitBranchExpression` resolves to a value matching the `masterBranchPattern` or `supportBranchPattern` regular expression.
221225

222226
This goal resolves (and downloads) the artifacts matching the current `${project.version}` from the stage repository, then attaches them to the
223227
current project in the Maven build. This lets later plugins in the lifecycle (like the deploy plugin, which the extension won't remove) make use of
224-
artifacts provided from the stage repository when it uploads to the releases repository. Effectively, this makes a build in master copy the artifacts from
228+
artifacts provided from the stage repository when it uploads to the releases repository. Effectively, this makes a build in master (or support) copy the artifacts from
225229
the stage repository to the releases repository.
226230

227231

@@ -243,6 +247,7 @@ The following table describes the git branch expression -> repository used for r
243247
| Git Branch Expression | Source Repository for re-attachment |
244248
| --------------------- | ---------- |
245249
| masterBranchPattern | release |
250+
| supportBranchPattern | release |
246251
| releaseBranchPattern | stage |
247252
| hotfixBranchPattern | stage |
248253
| developmentBranchPattern | snapshots |

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,18 @@ protected void execute(final GitBranchType type, final String gitBranch, final S
2828
throw new MojoFailureException("The current git branch: [" + gitBranch + "] is defined as a release branch. The maven project version: [" + project.getVersion() + "] is currently a snapshot version.");
2929
}
3030

31-
// Expect the last group on non-master (and non-support) branches to match (exactly) the current projectVersion. (only release / hotfix branches)
32-
if (gitMatcher.groupCount() > 0 && !(GitBranchType.MASTER.equals(type) || GitBranchType.SUPPORT.equals(type))) {
33-
if (!gitMatcher.group(gitMatcher.groupCount()).trim().equals(project.getVersion().trim())) {
31+
// Non-master version branches require a pom version match of some kind to the branch subgroups.
32+
if (gitMatcher.groupCount() > 0) {
33+
// HOTFIX and RELEASE branches require an exact match to the last subgroup.
34+
if ((GitBranchType.RELEASE.equals(type) || GitBranchType.HOTFIX.equals(type)) && !gitMatcher.group(gitMatcher.groupCount()).trim().equals(project.getVersion().trim())) {
3435
throw new MojoFailureException("The current git branch: [" + gitBranch + "] expected the maven project version to be: [" + gitMatcher.group(gitMatcher.groupCount()).trim() + "], but the maven project version is: [" + project.getVersion() + "]");
3536
}
37+
38+
// SUPPORT branches require a 'starts with' match of the maven project version to the subgroup.
39+
// ex: /origin/support/3.1 must have a maven version that starts with "3.1", ala: "3.1.2"
40+
if (GitBranchType.SUPPORT.equals(type) && !project.getVersion().startsWith(gitMatcher.group(gitMatcher.groupCount()).trim())) {
41+
throw new MojoFailureException("The current git branch: [" + gitBranch + "] expected the maven project version to start with: [" + gitMatcher.group(gitMatcher.groupCount()).trim() + "], but the maven project version is: [" + project.getVersion() + "]");
42+
}
3643
}
3744
}
3845
} else if (GitBranchType.DEVELOPMENT.equals(type) && !ArtifactUtils.isSnapshot(project.getVersion())) {

0 commit comments

Comments
 (0)