27

Note regarding the accepted answer: I accepted the answer because of strong circumstantial evidence. Nonetheless, this is circumstantial evidence, so take it with a grain of salt.


How can I have a plugin be triggered when the user runs a plugin goal, not a lifecycle phase? (This has been asked before, but the answer was to use a lifecycle phase.)

Case in point: I need release:branch to invoke regex-plugin to generate a branch with the current version as its name, minus the -SNAPSHOT suffix. This is what I have, which requires the developer to activate a profile and invoke the verify phase. I need the developer to simply invoke release:branch, which in turn should cause regex-plugin to run. In a bit of a marriage to Gitflow.

<profile>
    <id>Release Branch</id>
    <build>
        <plugins>
            <!-- On validate, compute the current version without -SNAPSHOT. -->
            <!-- Put the result in a property. -->
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>build-helper-maven-plugin</artifactId>
                <version>1.7</version>
                <executions>
                    <execution>
                        <phase>validate</phase>
                        <goals>
                            <goal>regex-property</goal>
                        </goals>
                        <configuration>
                            <value>${project.version}</value>
                            <regex>^(.*)-SNAPSHOT$</regex>
                            <replacement>$1</replacement>
                            <name>project.unqualifiedVersion</name>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <!-- Also on validate, run the branch plugin, and use -->
            <!-- the non-SNAPSHOT version thus computed in the branch name. -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-release-plugin</artifactId>
                <version>2.3.2</version>
                <executions>
                    <execution>
                        <phase>validate</phase>
                        <goals>
                            <goal>branch</goal>
                        </goals>
                        <configuration>
                            <branchName>release/${project.unqualifiedVersion}</branchName>
                            <updateWorkingCopyVersions>true</updateWorkingCopyVersions>
                            <updateBranchVersions>false</updateBranchVersions>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</profile>

The intent is for release:branch to move the current snapshot version (say, 1.0.5-SNAPSHOT) into a new branch, which should be named after the version but without the superfluous -SNAPSHOT suffix (1.0.5). The current branch should then take on a new snapshot version (1.1.0-SNAPSHOT, not 1.0.6-SNAPSHOT, because we want release 1.0.x to have room for hotfixes, so we reserve it for the branch) (I don't have the automatic computation of the next snapshot version figured out yet, so, if you run the Maven configuration above with validate, you will have to enter it at a prompt).

Community
  • 1
  • 1
Mihai Danila
  • 2,229
  • 1
  • 23
  • 28
  • I second your remark that it cannot be done, but I'm waiting to be surprised :) – Sander Verhagen Apr 29 '13 at 00:18
  • Yeah, it doesn't look good. Here's another answer claiming that it's not doable: http://stackoverflow.com/a/15185774/1569108. Sounds like a job for a custom lifecycle, or maybe I should take this away from Maven entirely and use something like Ant instead, since Maven is so unfriendly with this scenario. If they had a dummy phase that always runs, even when we only run a plugin goal, that would have been enough to solve this problem without headaches. – Mihai Danila Apr 29 '13 at 02:21
  • The entire Maven release plugin may even be goals that you'd normally not bind to lifecycle phases. As such they may've been designed exclusively with passing parameters on the command-line along in mind. Oddly enough, the `prepare` goal supports `preparationGoals`, that sounds like what you'd want for the `branch` goal. – Sander Verhagen Apr 29 '13 at 02:42
  • That would do the job, though I don't like `preparationGoals`, as it lacks structure in an otherwise highly structured file format. – Mihai Danila Apr 29 '13 at 13:58
  • I think it wouldn't do the job in this case, as it does not pertain to the `branch` goal (rather to the `prepare` goal). – Sander Verhagen Apr 30 '13 at 15:19
  • Agreed. I mean, if `preparationGoals` were available to `branch`, it would be enough to solve my problem, albeit a shortsighted solution. `completionGoals` should also be included with it, to allow post-processing. In any case, it seems like Maven is meant to expose only highly controlled entry points (barring writing your custom Mojos), so it may not be the most adapted tool for managing Gitflow activities. – Mihai Danila Apr 30 '13 at 16:05
  • A lot of things let themselves be overridden, but I don't see how that'd work for this one. I was thinking, though, that you'd typically want to branch off of a tag, in which case you have the `SNAPSHOT` stripped to begin with, assuming it's a branch for a release that was done with `prepare`. – Sander Verhagen May 01 '13 at 15:07
  • In Gitflow, you would frequently branch off of `develop`, which is always on a `-SNAPSHOT` version. – Mihai Danila May 01 '13 at 15:57
  • I have posted this question on the Maven developer list, but no answer yet. – Mihai Danila May 07 '13 at 16:26
  • Mihai... Would combining multiple maven goals with [Exec Maven Plugin](http://mojo.codehaus.org/exec-maven-plugin/) help you? See [maba](http://stackoverflow.com/users/1350762/maba) answer [here](http://stackoverflow.com/a/12835976/664577). You could run `regex-plugin` and `release:branch` with `exec:exec`, no profiles or binding to custom phases required. – Anthony Accioly Jul 07 '13 at 19:35
  • Anthony: an interesting proposition, that I will have to think about. Nonetheless, my first preference would be not to touch the entry point, but rather just adjust its behavior. In other words, I prefer `release:branch` over `exec:exec`. Moreover, there will be other operations that will need to be overloaded in order to marry Maven's branching model with Gitflow, and I only have one `exec:exec` to use. – Mihai Danila Jul 07 '13 at 19:41
  • @MihaiDanila - I'm facing a similar situation, however I have the issue where I want to run another plugin prior to the execution of the release:prepare goal but within the same context. Specifically, run the `properties-maven-plugin` to load properties from a file to be available to the release plugin. What did you end up deciding/doing in the end? – Eric B. Jun 23 '15 at 14:29
  • @EricB. I haven't used Maven in over a year now, and the details are foggy. I would ask a question. I suspect your problem has to do specifically with how parts of the release stage are executed in a separate process. – Mihai Danila Jun 24 '15 at 16:59
  • @MihaiDanila Acutally - no. It's b/c I want to call the `properties-maven-plugin` during the context of my release:prepare/perform goals, but given that the release plugin is called directly (specifying the plugin:goal), there is no way to call the other plugin in the same context, short of specifying the specific goal in the properties plugin within the same mvn cmd. Basically, looking for a custom lifecycle in which I can map the different plugins and goals myself but without having to create a custom lifecycle.... – Eric B. Jun 25 '15 at 00:20
  • You might be hitting on the same problem as me. It may just not be possible without that custom lifecycle. There were, nonetheless, some interesting ideas put forth in this thread and in others, if you're willing to do away with some purity. Sorry that I can't be of more help. If you insist that I partake in the brainstorming, I will have to read up on Maven again :), because I'm not in a Java shop anymore, as of over a year ago. – Mihai Danila Jul 06 '15 at 15:31

2 Answers2

9

The evidence presented so far is rather circumstantial. I've done some research of my own, so it's best I share it here. The below are either more of the same "it's not possible", or the building blocks for alternatives.

jetspeed:mvn plugin --- run a specified sequence of plugins; the configuration to run can be varied via a system property; IDE integration concerns


Executing goals before plugin runs (StackOverflow) --- same question answered in the context of a custom Mojo


Make Mojo run other goals (StackOverflow) --- again, from the context of a custom Mojo


Configuring default Mojo executions --- Maven page describing how Mojos run - more circumstantial evidence


Triggering phases before goal execution (StackOverflow) --- roundabout solution to my problem, unfortunately answered in the negative


INTERESTING: Guide to Ant plugin development --- appealing to me, because, while it requires writing a custom plugin, it's all Ant + Maven configuration, no code to compile; presumably a lower barrier to entry


Creating a parallel lifecycle --- appealing approach, because I could fully control the contents of the lifecycle to where it would use Gitflow verbs; unclear how IDEs would integrate this; learning curve and adoption barrier concerns exist

Community
  • 1
  • 1
Mihai Danila
  • 2,229
  • 1
  • 23
  • 28
8

No, you can't bind to a plugin to another plugin. Only to a phase.

In Maven-internal terms, a "Mojo" is the thing that does work. A "plugin" is a collection of mojos wrapped up so you can reference them from the POM. Mojos bind to phases only.

From the plugin development documentation:

Each Mojo specified inside a plugin descriptor must provide the following

...

phase ... Defines a default phase to bind a mojo execution to if the user does not explicitly set a phase in the POM. Note: This annotation will not automagically make a mojo run when the plugin declaration is added to the POM. It merely enables the user to omit the <phase> element from the surrounding <execution> element.

For further confirmation, see the source of MojoExecution (the JavaDoc for this class isn't helpful) and notice that there are two possible sources of execution enumerated:

An execution that originates from the direct invocation of a goal from the CLI

and

An execution that originates from a goal bound to a lifecycle phase

No other way to kick off an execution means you're out of luck (barring extraordinary measures like rolling your own plugin that combines the effects of the two plugins you want to link and then using your custom plugin).

Nathaniel Waisbrot
  • 23,261
  • 7
  • 71
  • 99
  • You seem to be correct that there is no standard straightforward way to do achieve what I need without writing a plugin, but how about a pre-existing "aggregator" plugin like `jetspeed:mvn`? The site also does a good job of explaining the standard ways to chain. http://portals.apache.org/jetspeed-2/buildguide/the-need-for-a-custom-lifecycle.html – Mihai Danila May 08 '13 at 04:04
  • There is strong circumstantial evidence that you are right, but your answer still does not prove it. Firstly, the default phase pertains only to phase bound executions, not CLI executions. The requirement does not preclude the execution of multiple goals from a CLI invocation any more than it precludes the execution of a single goal from a CLI invocation. Second, the source code mentions the direct invocation of *a* goal, not of the goal in question. Who is to say multiple goals triggered by the CLI are not represented by the same `Source`? – Mihai Danila May 08 '13 at 04:38
  • 1
    @MihaiDanila True, which is why I hedged a little at the end. My assumption is that you want to be *using* plugins and not developing them. You could write new plugins, or get a plugin that would call some external script which would then run another Maven instance, etc. But when you get to this point, you probably really should be using Ant or something else, rather than building a pile of kludges on top of Maven. – Nathaniel Waisbrot May 08 '13 at 14:38