Skip to content

Commit 85506c4

Browse files
authored
Merge pull request #84 from egineering-llc/feature/pr83-integration
Feature/pr83 integration
2 parents a121e30 + 926fb99 commit 85506c4

19 files changed

+734
-166
lines changed

.travis.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ script: mvn verify
44

55
jdk:
66
- openjdk7
7-
- oraclejdk7
87
- oraclejdk8
98

109
cache:

README.md

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ All of the solutions to these issues are implemented independently in different
124124
<hotfixBranchPropertyFile>foo/bar/emer.props</hotfixBranchPropertyFile>
125125
<releaseBranchPropertyFile>foo/bar/test.props</releaseBranchPropertyFile>
126126
<developmentBranchPropertyFile>foo/bar/dev.props</developmentBranchPropertyFile>
127+
<featureOrBugfixBranchPropertyFile>foo/bar/feat.props</featureOrBugfixBranchPropertyFile>
127128
<otherBranchPropertyFile>foo/bar/ci.props</otherBranchPropertyFile>
128129
<undefinedBranchPropertyFile>foo/bar/local.props</undefinedBranchPropertyFile>
129130
</configuration>
@@ -143,8 +144,8 @@ One common stumbling block for teams adjusting to gitflow with Maven projects is
143144
In practice, the Maven versions should:
144145

145146
* Be synchronized with release branch and hotfix branch names.
146-
* Never be -SNAPSHOT in the master, support, release, or hotfix branches.
147-
* Always be -SNAPSHOT in the develop branch.
147+
* Never be -SNAPSHOT in the master, support, release, or hotfix branches. Also, no -SNAPSHOT parent or (plugin) dependencies are allowed. (This condition may be disabled by setting `enforceNonSnapshots` = `false`.)
148+
* Always be -SNAPSHOT in the feature and develop branches.
148149
* Be irrelevant if there's no git branch resolvable from your environment.
149150

150151
The `enforce-versions` goal asserts these semantics when it can resolve the `gitBranchExpression`.
@@ -158,12 +159,17 @@ The following properties change the behavior of this goal:
158159
| Property | Default Value | SNAPSHOT allowed? | Description |
159160
| -------------------- | ------------- | --------------------------- | ----------- |
160161
| 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 |
162+
| deploySnapshotTypeBranches | `false` | n/a | When `true`, the POM version should end with the feature branch name and -SNAPSHOT, e.g. `1.0.0-myfeature-SNAPSHOT`. This prevents a feature branch snapshot from "overwriting" a snapshot from the develop branch. |
163+
| enforceNonSnapshots | `true` | n/a | When `true`, enforce the requirement that none of the following may contain a -SNAPSHOT: the POM version, any parent, or any (plugin) dependencies. |
164+
| releaseBranchMatchType | `equals` | n/a | When `equals`, the POM version should be identical to the branch name for release and hotfix branches (e.g. POM version should be `1.0.0` for branch `release/1.0.0`). When `startsWith`, POM version should start with the name branch (e.g. POM version could be `1.0.1` for branch `release/1.0`. When using the `update-stage-dependencies` mojo, set to `equals`, otherwise set to `startsWith`. |
161165
| masterBranchPattern | (origin/)?master | No | Regex. When matched, signals the master branch is being built. |
162166
| 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. |
163167
| releaseBranchPattern | (origin/)?release/(.*) | No | Regex. When matched, signals a release branch being built. Last subgroup, if present, must match the Maven project version. |
164168
| hotfixBranchPattern | (origin/)?hotfix/(.*) | No | Regex. When matched, signals a hotfix branch is being built. Last subgroup, if present, must match the Maven project version. |
169+
| featureOrBugfixBranchPattern | (origin/)?(?:feature&#124;bugfix)/(.*) | Yes | Regex. When matched, signals a feature or bugfix branch is being built. |
165170
| developmentBranchPattern | (origin/)?develop | Yes | Regex. When matched, signals a development branch is being built. Note the lack of a subgroup. |
166171

172+
167173
## Goal: `retarget-deploy` (Branch Specific Deploy Targets & Staging)
168174

169175
One of the challenges of building a good CI/CD job for Maven environments is the lack of a 'staging' repository baked into Maven.
@@ -179,10 +185,12 @@ plugins in the build process (deploy, site-deploy, etc.) will use the repositori
179185
| Property | Default Value | Description |
180186
| -------- | ------------- | ----------- |
181187
| gitBranchExpression | current git branch resolved from SCM or ${env.GIT_BRANCH} | Maven property expression to resolve in order to determine the current git branch |
188+
| deploySnapshotTypeBranches | `false` | When `true`, feature branches will also be deployed to the snapshots repository. |
182189
| releaseDeploymentRepository | n/a | The repository to use for releases. (Builds with a GIT_BRANCH matching `masterBranchPattern` or `supportBranchPattern`) |
183190
| stageDeploymentRepository | n/a | The repository to use for staging. (Builds with a GIT_BRANCH matching `releaseBranchPattern` or `hotfixBranchPattern`) |
184191
| snapshotDeploymentRepository | n/a | The repository to use for snapshots. (Builds matching `developmentBranchPattern`) |
185192

193+
186194
**The repository properties should follow the following format**, `id::layout::url::uniqueVersion`.
187195

188196
When using this plugin, the `<distributionManagement>` repository definitions can be completely removed from your pom.xml
@@ -250,11 +258,11 @@ properties from files with an assigned keyPrefix, letting you name-space propert
250258
The maven `-U` command line switch does a fine job of updating SNAPSHOT versions from snapshot repositories, there is no
251259
built-in way to force maven to re-resolve non-snapshot release versions. This goal addresses that shortcoming in a fairly
252260
straight-forward manner. Any release version dependency of the project which was provided to the local repository by a
253-
remote repository with the same ID as the `<stageDeploymentRepository>`, will be purged from the local repository and
261+
remote repository with the same ID as the `<stageDeploymentRepository>`, will be purged from the local repository and
254262
re-resolved (so you get the latest version from either the stage repository, or your release repository).
255263

256-
It is **very important** if you're using this goal, that the **`stageDeploymentReposity` have a unique repository/server id**.
257-
If you use the same ID for release, snapshot, and stage, every time you exeucte this goal, every release version
264+
It is **very important** if you're using this goal, that the **`stageDeploymentReposity` have a unique repository/server id**.
265+
If you use the same ID for release, snapshot, and stage, every time you exeucte this goal, every release version
258266
dependency will be purged and re-resolved.
259267

260268
If you have a local build / install of a release version, this goal will currently not update that package, by design.
@@ -299,7 +307,7 @@ To accomplish this the `promote-master` goal and a Maven build extension work to
299307

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

305313
The `promote-master` goal executes when the `gitBranchExpression` resolves to a value matching the `masterBranchPattern` or `supportBranchPattern` regular expression.
@@ -331,6 +339,7 @@ The following table describes the git branch expression -> repository used for r
331339
| supportBranchPattern | release |
332340
| releaseBranchPattern | stage |
333341
| hotfixBranchPattern | stage |
342+
| featureOrBugfixBranchPattern | snapshots |
334343
| developmentBranchPattern | snapshots |
335344
| All Others | local |
336345

@@ -352,3 +361,15 @@ it's building. The attach-deploy will 'clean' the maven project, then download t
352361
that the first build deployed into. Once they're attached to the project, the `jboss-as:deploy-only` goal will deliver
353362
the artifacts built by the first job into a jboss application server.
354363

364+
365+
# Resolving the Git branch name
366+
As stated before, the plugin determines what to do by resolving the Git branch name.
367+
368+
* The first try is a `git symbolic-ref HEAD` to check the local branch name. If it's found, that's the branch name that's used.
369+
* If the `symbolic-ref` fails then it's probably due to a detached HEAD. This typically happens on Jenkins, when it simply checks out the commit hash that was just pushed.
370+
Or, it's because of a developer doing a `git checkout origin/feature/x`, e.g. when doing a code review and no local branch is required.
371+
In such a case:
372+
* The plugin will first resolve the HEAD to a commit using `git rev-parse HEAD`.
373+
* Next, it will do a `git show-ref` to check which (local/remote) branches point to the commit.
374+
* If it can resolve the commit to a single branch type (e.g. develop or master) then that's the branch name that's used.
375+
* If all of the above fails, `${env.GIT_BRANCH}` is tried.

pom.xml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@
128128
<plugin>
129129
<groupId>org.apache.maven.plugins</groupId>
130130
<artifactId>maven-plugin-plugin</artifactId>
131-
<version>3.2</version>
131+
<version>3.5.1</version>
132132
<configuration>
133133
<goalPrefix>gitflow-helper</goalPrefix>
134134
<skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
@@ -151,7 +151,7 @@
151151
<plugin>
152152
<groupId>org.codehaus.plexus</groupId>
153153
<artifactId>plexus-component-metadata</artifactId>
154-
<version>1.6</version>
154+
<version>1.7.1</version>
155155
<executions>
156156
<execution>
157157
<goals>
@@ -164,7 +164,7 @@
164164
<plugin>
165165
<groupId>org.apache.maven.plugins</groupId>
166166
<artifactId>maven-source-plugin</artifactId>
167-
<version>2.4</version>
167+
<version>3.0.1</version>
168168
<executions>
169169
<execution>
170170
<id>attach-sources</id>
@@ -189,7 +189,7 @@
189189
<plugin>
190190
<groupId>org.apache.maven.plugins</groupId>
191191
<artifactId>maven-gpg-plugin</artifactId>
192-
<version>1.5</version>
192+
<version>1.6</version>
193193
<executions>
194194
<execution>
195195
<id>sign-artifacts</id>
@@ -203,7 +203,7 @@
203203
<plugin>
204204
<groupId>org.sonatype.plugins</groupId>
205205
<artifactId>nexus-staging-maven-plugin</artifactId>
206-
<version>1.6.7</version>
206+
<version>1.6.8</version>
207207
<extensions>true</extensions>
208208
<configuration>
209209
<serverId>ossrh</serverId>

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

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,20 @@ abstract class AbstractGitflowBasedRepositoryMojo extends AbstractGitflowBranchM
4545
private static final Pattern ALT_REPO_SYNTAX_PATTERN = Pattern.compile("(.+)::(.+)::(.+)::(.+)");
4646
private static final String CATALOG_HEADER = "[artifacts]";
4747

48+
/**
49+
* Returns the policy or a default policy if {@code policy} is null.
50+
*
51+
* @param policy the policy to check
52+
* @return the {@link org.apache.maven.model.RepositoryPolicy}
53+
*/
54+
private static org.apache.maven.model.RepositoryPolicy ensureRepositoryPolicy(
55+
@Nullable org.apache.maven.model.RepositoryPolicy policy) {
56+
if (policy == null) {
57+
return new org.apache.maven.model.RepositoryPolicy();
58+
}
59+
return policy;
60+
}
61+
4862
private static PrintWriter newPrintWriter(File catalog) throws FileNotFoundException {
4963
checkNotNull(catalog, "catalog must not be null");
5064
return new PrintWriter(new OutputStreamWriter(new FileOutputStream(catalog), UTF_8));
@@ -116,7 +130,8 @@ ArtifactRepository getDeploymentRepository(final String altRepository)
116130

117131
if (candidate == null) {
118132
throw new MojoFailureException(altRepository, "Invalid syntax for repository or repository id not resolved..",
119-
"Invalid syntax for repository. Use \"id::layout::url::unique\" or only specify the \"id\".");
133+
"Invalid syntax for repository. Use \"id::layout::url::unique\" or only specify the \"id\"." +
134+
" For the \"id\", make sure that the corresponding <repository> element has been defined (e.g. in the ~/.m2/settings.xml file)");
120135
}
121136
}
122137

@@ -134,7 +149,12 @@ ArtifactRepository getDeploymentRepository(final String altRepository)
134149

135150
return repositoryFactory.createDeploymentArtifactRepository(id, url, repoLayout, unique);
136151
} else {
137-
return repositoryFactory.createDeploymentArtifactRepository(candidate.getId(), candidate.getUrl(), getLayout(candidate.getLayout()), candidate.getSnapshots().isEnabled());
152+
return repositoryFactory.createDeploymentArtifactRepository(
153+
candidate.getId(),
154+
candidate.getUrl(),
155+
getLayout(candidate.getLayout()),
156+
ensureRepositoryPolicy(candidate.getSnapshots()).isEnabled()
157+
);
138158
}
139159
}
140160

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

Lines changed: 38 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,12 @@ public abstract class AbstractGitflowBranchMojo extends AbstractMojo {
2121

2222
private Properties systemEnvVars = new Properties();
2323

24-
private PropertyResolver resolver = new PropertyResolver();
25-
26-
27-
@Component
28-
protected MavenProject project;
29-
3024
@Component
3125
protected ScmManager scmManager;
3226

27+
@Parameter(defaultValue = "${project}", readonly = true)
28+
protected MavenProject project;
29+
3330
@Parameter(defaultValue = "(origin/)?master", property = "masterBranchPattern", required = true)
3431
private String masterBranchPattern;
3532

@@ -45,68 +42,63 @@ public abstract class AbstractGitflowBranchMojo extends AbstractMojo {
4542
@Parameter(defaultValue = "(origin/)?develop", property = "developmentBranchPattern", required = true)
4643
private String developmentBranchPattern;
4744

48-
// @Parameter tag causes property resolution to fail for patterns containing ${env.}. Default provided in execute();
45+
@Parameter(defaultValue = "(origin/)?(?:feature|bugfix)/(.*)", property = "featureOrBugfixBranchPattern", required = true)
46+
private String featureOrBugfixBranchPattern;
47+
48+
// An expression that resolves to the git branch at run-time.
49+
// @Parameter tag causes property resolution to fail for patterns containing ${env.}.
50+
// The default value _must_ be provided programmaticially at run-time.
4951
@Parameter(property = "gitBranchExpression", required = false)
5052
private String gitBranchExpression;
5153

52-
protected abstract void execute(final GitBranchType type, final String gitBranch, final String branchPattern) throws MojoExecutionException, MojoFailureException;
54+
@Parameter(defaultValue = "false", property = "deploySnapshotTypeBranches")
55+
boolean deploySnapshotTypeBranches;
56+
57+
@Parameter(defaultValue = "equals", property = "releaseBranchMatchType", required = true)
58+
String releaseBranchMatchType;
5359

5460
/**
55-
* Method exposing Property Resolving for subclasses.
61+
* Convenience Method exposing Property Resolving for subclasses.
5662
*
5763
* @param expression
5864
* @return
5965
*/
6066
protected String resolveExpression(final String expression) {
61-
return resolver.resolveValue(expression, project.getProperties(), systemEnvVars);
67+
return PropertyResolver.resolveValue(expression, project.getProperties(), systemEnvVars);
6268
}
6369

64-
private void logExecute(final GitBranchType type, final String gitBranch, final String branchPattern) throws MojoExecutionException, MojoFailureException {
65-
getLog().debug("Building for GitBranchType: " + type.name() + ". gitBranch: '" + gitBranch + "' branchPattern: '" + branchPattern + "'");
66-
execute(type, gitBranch, branchPattern);
67-
}
70+
/**
71+
* Method to be implemented by branch-aware mojos
72+
*
73+
* @param currentBranch
74+
*
75+
* @throws MojoExecutionException
76+
* @throws MojoFailureException
77+
*/
78+
protected abstract void execute(final GitBranchInfo currentBranch) throws MojoExecutionException, MojoFailureException;
6879

6980
public void execute() throws MojoExecutionException, MojoFailureException {
70-
if (gitBranchExpression == null) {
71-
gitBranchExpression = ScmUtils.resolveBranchOrExpression(scmManager, project, getLog());
72-
}
73-
81+
// Weather we resolve a single branch name or not, it won't hurt to run it through property replacement.
7482
try {
7583
systemEnvVars = CommandLineUtils.getSystemEnvVars();
7684
} catch (IOException ioe) {
7785
throw new MojoExecutionException("Unable to read System Envirionment Variables: ", ioe);
7886
}
7987

80-
// Try to resolve the gitBranchExpression to an actual Value...
81-
String gitBranch = resolveExpression(gitBranchExpression);
82-
ExpansionBuffer eb = new ExpansionBuffer(gitBranch);
88+
// Validate the match type.
89+
checkReleaseBranchMatchTypeParam();
8390

84-
if (!gitBranchExpression.equals(gitBranch) || getLog().isDebugEnabled()) { // Resolves Issue #9
85-
getLog().debug("Resolved gitBranchExpression: '" + gitBranchExpression + " to '" + gitBranch + "'");
86-
}
91+
ScmUtils scmUtils = new ScmUtils(systemEnvVars, scmManager, project, getLog(), masterBranchPattern, supportBranchPattern, releaseBranchPattern, hotfixBranchPattern, developmentBranchPattern, featureOrBugfixBranchPattern);
92+
GitBranchInfo branchInfo = scmUtils.resolveBranchInfo(gitBranchExpression);
8793

88-
if (!eb.hasMoreLegalPlaceholders()) {
89-
/*
90-
* (/origin/)?master goes to the maven 'release' repo.
91-
* (/origin/)?release/(.*) , (/origin/)?hotfix/(.*) , and (/origin/)?bugfix/(.*) go to the maven 'stage' repo.
92-
* (/origin/)?develop goes to the 'snapshot' repo.
93-
* All other builds will use the default semantics for 'deploy'.
94-
*/
95-
if (gitBranch.matches(masterBranchPattern)) {
96-
logExecute(GitBranchType.MASTER, gitBranch, masterBranchPattern);
97-
} else if (gitBranch.matches(supportBranchPattern)) {
98-
logExecute(GitBranchType.SUPPORT, gitBranch, supportBranchPattern);
99-
} else if (gitBranch.matches(releaseBranchPattern)) {
100-
logExecute(GitBranchType.RELEASE, gitBranch, releaseBranchPattern);
101-
} else if (gitBranch.matches(hotfixBranchPattern)) {
102-
logExecute(GitBranchType.HOTFIX, gitBranch, hotfixBranchPattern);
103-
} else if (gitBranch.matches(developmentBranchPattern)) {
104-
logExecute(GitBranchType.DEVELOPMENT, gitBranch, developmentBranchPattern);
105-
} else {
106-
logExecute(GitBranchType.OTHER, gitBranch, null);
107-
}
108-
} else {
109-
logExecute(GitBranchType.UNDEFINED, gitBranch, null);
94+
getLog().debug("Building for: " + branchInfo);
95+
execute(branchInfo);
96+
}
97+
98+
private void checkReleaseBranchMatchTypeParam() throws MojoFailureException {
99+
if (!"equals".equals(releaseBranchMatchType) && !"startsWith".equals(releaseBranchMatchType)) {
100+
throw new MojoFailureException("'releaseBranchMatchType' should be either 'equals' or 'startsWith'. Found '" + releaseBranchMatchType + "'.");
110101
}
111102
}
112103
}
104+

0 commit comments

Comments
 (0)