开源软件名称(OpenSource Name):egineering-llc/gitflow-helper-maven-plugin开源软件地址(OpenSource Url):https://github.com/egineering-llc/gitflow-helper-maven-plugin开源编程语言(OpenSource Language):Java 100.0%开源软件介绍(OpenSource Introduction):gitflow-helper-maven-pluginA build extension and plugin that helps Maven play nicely with gitflow projects, CI servers and local development. It does so by:
Why would I want to use this?This plugin solves a few specific issues common in consolidated Hudson/Jenkins Continuous Integration (CI) and Continuous Delivery (CD) jobs for projects following the gitflow workflow.
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. 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. If you want to use scm tagging with a custom tag format, we support that. If you want to use scm tagging without having to add the section to your pom.xml or adding arcane -Dproperty arguments to your Maven command, this plugin supports that. If you want to do three-tier deployments (snapshot, stage, production) without 'professional' artifact repository tools, and without having to define a section to your pom.xml, yep, this plugin supports that too. All of the solutions to these issues are implemented independently in different plugin goals, so you can pick and choose what parts you'd like to leverage. I want all of that. (Usage)
Goal: |
Property | Default Value | SNAPSHOT allowed? | Description |
---|---|---|---|
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 |
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. |
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. |
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 . |
masterBranchPattern | (origin/)?master | No | Regex. When matched, signals the master branch is being built. |
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. |
releaseBranchPattern | (origin/)?release/(.*) | No | Regex. When matched, signals a release branch being built. Last subgroup, if present, must match the Maven project version. |
hotfixBranchPattern | (origin/)?hotfix/(.*) | No | Regex. When matched, signals a hotfix branch is being built. Last subgroup, if present, must match the Maven project version. |
developmentBranchPattern | (origin/)?develop | Yes | Regex. When matched, signals a development branch is being built. Note the lack of a subgroup. |
set-properties
(Dynamically Set Maven Project / System Properties)Some situations with automated testing (and integration testing in particular) demand changing configuration properties based upon the branch type being built. This is a common necessity when configuring automated DB refactorings as part of a build, or needing to setup / configure datasources for automated tests to run against.
The set-properties
goal allows for setting project (or system) properties, dynamically based on the detected git
branch being built. Properties can be specified as a Properties collection in plugin configuration, or can be loaded
from a property file during the build. Both property key names and property values will have placeholders resolved.
Multiple executions can be configured, and each execution can target different scopes (system or project), and can load properties from files with an assigned keyPrefix, letting you name-space properties from execution ids.
retarget-deploy
(Branch Specific Deploy Targets & Staging)One of the challenges of building a good CI/CD job for Maven environments is the lack of a 'staging' repository baked into Maven. The maven-release-plugin does introduce a concept of a staging repository, but the imposed workflow from the release plugin is incompatible with CI jobs and the gitflow model.
For projects being managed with the gitflow workflow model, release and hotfix branches should be deployed to a stage repository, where artifacts can be tested and validated prior to being deployed to the release repository.
The retarget-deploy
goal sets the snapshot and release repository based upon the resolved value of the gitBranchExpression
. Subsequent
plugins in the build process (deploy, site-deploy, etc.) will use the repositories set by the retarget-deploy
goal.
Property | Default Value | Description |
---|---|---|
gitBranchExpression | current git branch resolved from SCM or ${env.GIT_BRANCH} | Maven property expression to resolve in order to determine the current git branch |
releaseDeploymentRepository | n/a | The repository to use for releases. (Builds with a GIT_BRANCH matching masterBranchPattern or supportBranchPattern ) |
stageDeploymentRepository | n/a | The repository to use for staging. (Builds with a GIT_BRANCH matching releaseBranchPattern or hotfixBranchPattern ) |
snapshotDeploymentRepository | n/a | The repository to use for snapshots. (Builds matching developmentBranchPattern ) |
otherDeployBranchPattern | 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 |
The repository properties should follow the following format, id::layout::url::uniqueVersion
.
When using this plugin, the <distributionManagement>
repository definitions should be removed from your pom.xml
This block, is replaced by defining 'normal' repositories which are then referenced by the <id>
and used by the gitflow-helper-maven-plugin to retarget artifact repository deployment and resolution.
<distributionManagement>
<snapshotRepository>
<id>snapshots</id>
<layout>default</layout>
<url>https://some.server.path/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>releases</id>
<layout>default</layout>
<url>https://some.server.path/content/repositories/releases</url>
</repository>
</distributionManagement>
Keep in mind repositories can be defined in a user settings.xml as part of your development profiles to keep from repeating yourself in project files. Below is an example configuration for the gitflow-helper-maven-plugin.
<project...>
...
<repositories>
<repository>
<id>snapshots</id>
<url>https://some.server.path/content/repositories/snapshots</url>
<snapshots><enabled>true</enabled></snapshots>
<releases><enabled>false</enabled></releases>
</repository>
<repository>
<id>test-releases</id>
<url>https://some.server.path/content/repositories/test-releases</url>
<snapshots><enabled>false</enabled></snapshots>
<releases><enabled>true</enabled></releases>
</repository>
<repository>
<id>releases</id>
<url>https://some.server.path/content/repositories/releases</url>
<snapshots><enabled>false</enabled></snapshots>
<releases><enabled>true</enabled></releases>
</repository>
</repositories>
...
<build>
<plugins>
<plugin>
<groupId>com.e-gineering</groupId>
<artifactId>gitflow-helper-maven-plugin</artifactId>
<version>${gitflow.helper.plugin.version}</version>
<configuration>
<releaseDeploymentRepository>releases</releaseDeploymentRepository>
<stageDeploymentRepository>stage</stageDeploymentRepository>
<snapshotDeploymentRepository>snapshots</snapshotDeploymentRepository>
</configuration>
<executions>
<execution>
<goals>
<goal>retarget-deploy</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
...
</build>
In addition to setting up repository targets for release branches, the retarget-depoy
branch can deploy other branches
matching the otherDeployBranchPattern
as -SNAPSHOT artifacts which include the branch name as build metadata.
By default this is loosely based on the semVer semantic version scheme, in that the plugin will
reversion any artifacts to be produced with +feature-branch-name-normalized-SNAPSHOT
where any characters not in
[0-9A-Za-z-.]
will be replaced with -
. In cases where the +
delimiter is problematic, you can override that default
by specifying <otherBranchVersionDelimiter>
in your configuration block.
Using this feature, artifact versions for feature branches will always be -SNAPSHOT, and will always target the Snapshots repository. The intent for this configuration setting is to provide a way for long-running branches (matching a naming convention you define) can be published to a SNAPSHOT repo for use by other projects, and to prevent feature branches forked from release branches from mangling the test release in an artifact repository.
update-stage-dependencies
(Force update of dependency staged Releases)The maven -U
command line switch does a fine job of updating SNAPSHOT versions from snapshot repositories, there is no
built-in way to force maven to re-resolve non-snapshot release versions. This goal addresses that shortcoming in a fairly
straight-forward manner. Any release version dependency of the project which was provided to the local repository by a
remote repository with the same ID as the <stageDeploymentRepository>
, will be purged from the local repository and
re-resolved (so you get the latest version from either the stage repository, or your release repository).
It is very important if you're using this goal, that the stageDeploymentReposity
have a unique repository/server id.
If you use the same ID for release, snapshot, and stage, every time you exeucte this goal, every release version
dependency will be purged and re-resolved.
If you have a local build / install of a release version, this goal will currently not update that package, by design. You will need to manually remove your local build (or have a newer version resolve from a remote) before this goal will purge it.
tag-master
("Automagic" Tagging for Master Branch Releases)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.
The tag-master
goal invokes the SCM manager to tag the source repository when gitBranchExpression
resolves to a value matching the masterBranchPattern
or
supportBranchPattern
regular expressions. To determine the SCM URL to use, the plugin looks for a developerConnection
or connection
information in an SCM block
and if not found the gitURLExpression
is evaluated at run-time.
The default expression, ${env.GIT_URL}
, is one that is commonly provided by Jenkins & Hudson.
The following properties can be configured for this goal:
Property | Default Value | Description |
---|---|---|
gitBranchExpression | current git branch resolved from SCM or ${env.GIT_BRANCH} | Maven property expression to resolve in order to determine the current git branch |
gitURLExpression | current git branch resolved from SCM or ${env.GIT_URL} | Maven property expression to resolve for the GIT URL connection to use. |
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. |
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. |
tag | ${project.version} | An expression to use for the SCM tag. |
promote-master
and the Build Extension. (Copy Staged Artifacts to Releases)With gitflow, a new version of a product is prepared in the release/.*
and hotfix/.*
branches of the project.
These artifacts are put through their paces and validated before the merge back into the master branch or a support branch.
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 environment. This approach has the consequence of deployed artifacts in the release repository having never been tested in a stage or test environment. 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.
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
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
of achieving the ideal situation for gitflow deployment, where releases originate from the branches created for them, and code is never deployed
directly from master. Rather, master is really only used for tracking releases and branching to support production issues.
To accomplish this the promote-master
goal and a Maven build extension work together.
With the build extension added to your project, any build where the gitBranchExpression
matches the masterBranchPattern
or supportBranchPattern
will have it's
build lifecycle (plugins, goals, etc) altered. Any plugin other than the gitflow-helper-maven-plugin, the maven-deploy-plugin, or plugins with goals
explicitly referenced on the command line will be ignored (removed from the project reactor).
This allows us to enforce the ideal that code should never be built in the master branch.
The promote-master
goal executes when the gitBranchExpression
resolves to a value matching the masterBranchPattern
or supportBranchPattern
regular expression.
This goal resolves (and downloads) the artifacts matching the current ${project.version}
from the stage repository, then attaches them to the
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
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
the stage repository to the releases repository.
attach-deployed
(Deliver already Deployed artifacts)In some cases it is not advantageous to have instantaneous delivery of deployed artifacts into execution environments. The Maven lifecycle has no concept of this. The manner in which traditional 'deploy' (really, delivery) plugins deliver new artifacts to execution environments overlaps with the 'deploy' to a binary artifact repository. The overlap of these two operations into a single Maven lifecycle phase represents a conflict of interest when attempting to deliver already deployed artifacts without re-building the artifacts at the time of delivery. Within the context of auditing deployed artifact provenance, this is a 'bad thing'.
The attach-deployed
goal will execute a clean, resolve previously built artifacts appropriate for the git branch
being built, attach the artifacts to the project, and place them in the /target
directory as part of the Maven
package phase.
The following table describes the git branch expression -> repository used for resolving prebuilt artifact mapping.
Git Branch Expression | Source Repository for re-attachment |
---|---|
masterBranchPattern | release |
supportBranchPattern | release |
releaseBranchPattern | stage |
hotfixBranchPattern | stage |
developmentBranchPattern | snapshots |
otherBranchesToDeploy | snapshots |
All Others | local |
As an example, assume you have two CI jobs.
The first job would likely run the following maven goals:
mvn clean deploy
The second job could then run these maven goals:
mvn gitflow-helper:attach-deploy jboss-as:deploy-only
The effect would be that the first job builds, and pushes binaries to the proper artifact repository.
The second job would have a clean workspace, with the proper version of the project defined by the pom.xml in the branch
it's building. The attach-deploy will 'clean' the maven project, then download the binary artifacts from the repository
that the first build deployed into. Once they're attached to the project, the jboss-as:deploy-only
goal will deliver
the artifacts built by the first job into a jboss application server.
If the <scm>
sections of the pom points to a git repository, git symbolic-ref HEAD
to is used to check the local branch name.
If the symbolic-ref
fails then it's likely due to a detached HEAD.
This is typical of CI servers like Jenkins, where the commit hash that was just pushed is pulled.
This can also be done as a consequene of attempting to rebuild from a tag, without branching, or in some
workflows where code reviews are done without branches.
In the case of a detached HEAD the plugin will:
git rev-parse HEAD
.git show-ref
to resolve which (local/remote) branches point to the commit.If the first two methods fail, the plugin attempts to resolve ${env.GIT_BRANCH}
.
You can 'bootstrap' the plugin into your local repository and get the test project stubbed by running:
mvn -Dmaven.test.skip=true install
Then, change directories:
cd target/test-classes/project-stub
From there, you'll need to supply the required environment variables or commandline arguments to mvnDebug
:
export GIT_BRANCH=origin/feature/mybranch-foo-bar
mvnDebug -Dstub.project.version=5.0.0-SNAPSHOT -DotherBranchDeploy=semver -DallowGitflowPluginSnapshot=true deploy
You can then connect a remote debugger and step through the plugin code.
Configure the Maven commandline to include
-DforkCount=0
Add (Insert)
, and browse to target/jacoco.exec
.
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论