Adding phases to the maven lifecycle?
Asked Answered
P

4

18

I try to add some additional phases to the maven lifecycle. Mainly to add some additional test levels:

<phases>
    <phase>initialize</phase>
    <phase>process-resources</phase>
    <phase>compile</phase>
    <phase>process-test-resources</phase>
    <phase>test-compile</phase>
    <phase>test</phase>
    <phase>prepare-package</phase>
    <phase>package</phase>
    <phase>pre-integration-test</phase>
    <phase>integration-test</phase>
    <phase>post-integration-test</phase>
    <phase>pre-application-test</phase>
    <phase>application-test</phase>
    <phase>post-application-test</phase>
    <phase>pre-system-test</phase>
    <phase>system-test</phase>
    <phase>post-system-test</phase>
    <phase>finalize-tests</phase>
    <phase>install</phase>
    <phase>deploy</phase>
</phases>

Above contains new application-test and system-test phase (including pre- and post-).

I've started a test plugin at: codezoo-lifecycle-maven-plugin The pom I use for testing is in the src/it folder.

It seems the new phases or somewhat picked up but there are some weird things going on:

mvn post-application-test

This works. Also the echo plugin that I added for testing is executed. But there are some warnings (using maven 3.3.9).

mvn install

Executes the default lifecycle skipping the new phases.

If I change the id of the lifecycle fomr "test-levels" to "default" the phases are executed twice.

The warnings issued are:

[WARNING] Duplicated lifecycle phase package. Defined in default but also in test-levels
[WARNING] Duplicated lifecycle phase pre-integration-test. Defined in default but also in test-levels
[WARNING] Duplicated lifecycle phase integration-test. Defined in default but also in test-levels
....

The source code that issues this warning indicates the lifecycle is not properly namespaced. But I cannot figure out how that is done.

I found some hints on the web: create-a-new-phase (Stackoverflow) or in other plugins like the maven-scm-publish-plugin or the docker-maven-plugin. But those are either creating a complete new lifecycle or just change the plugin mapping from the default maven lifecycle.

All other stuff on the web regarding this topic seems to be at least 4 years old...

So:

  • how can I add additional phases to the maven default lifecycle (If I have to repeat the default plugin mappings: I can live with that)
  • how can I namespace the new lifecycle? It seems I create my own packaging (which is referenced as role-hint in the configuration). But still maven has some fallback to the default lifecycle.
  • can the default maven phases not be re-used?

The current state of the test plugin is on github.

Thanks!

Pyriphlegethon answered 14/4, 2016 at 8:35 Comment(0)
S
4

you can take a look at the mvn-finisher plug-in which adds several phases to be called on maven build end (for success, failure and interruption)

Simulacrum answered 10/2, 2020 at 5:30 Comment(0)
U
2

I'm not sure it's possible to modify the default lifecycle for the out-of-the-box packaging types, but there are alternatives. You could take the approach of defining your own plugin (with or without a custom packaging type), or you could simply add some extra test executions to the default lifecycle.

Option 1 - Create a new plugin with a custom lifecycle for standard packaging

With this approach, you define an entirely new lifecycle and specify the phases explicitly.

Pros:

  • Full control over all phases as well as plugin bindings for those phases
  • More DRY than option 3, if you find yourself doing the same thing across multiple unrelated projects

Cons:

  • Requires maintaining the plugin code.
  • IDE integration is a bit more difficult, since it requires the execution of non-standard phases.

Refer to this blog post for a walkthrough. Then, instead of running mvn install, you'd need to run mvn custom_install. You could probably take this a bit further and define your own custom packaging type

Option 2 - Create a new plugin with a custom packaging type, and define the default lifecycle

This one is probably the closest to the approach you've taken. See this blog post for an example.

If you take this approach, your project just needs to declare <packaging>my-custom-packaging</packaging> in addition to adding your plugin with <extensions>true</extensions>.

Pros:

  • Full control over all phases as well as plugin bindings for those phases
  • More DRY than option 3, if you find yourself doing the same thing across multiple unrelated projects
  • Probably easier to integrate with your IDE than option 1

Cons:

  • Requires maintaining the plugin code
  • If you want to support multiple packaging types (jar, war, ear, et cetera), you'll need to define custom versions of each of those packaging types in your plugin.

Option 3 - Add plugin executions to the default lifecycle

If you're willing to lose a bit of control over exactly when in the lifecycle those tests run, you can simply bind new plugin executions to the default lifecycle. I was just looking for how to do this and ran across this blog post describing a solution.

Pros:

  • Easiest to implement
  • No plugin code to maintain

Cons:

  • Can't define custom lifecycle phases
  • Less DRY than options 1 and 2

Essentially, all you have to do is define a new plugin execution, and prefix the execution id with default-. Here's an example I just did with Maven Failsafe Plugin to add the integration-test and verify goals to the default lifecycle of a project with jar packaging:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-failsafe-plugin</artifactId>
  <version>2.22.1</version>
  <executions>
    <execution>
      <id>default-system-test</id>
      <goals>
        <goal>integration-test</goal>
        <goal>verify</goal>
      </goals>
    </execution>
  </executions>
</plugin>

When I run mvn clean install, the execution happens as part of the build process.

Unburden answered 16/10, 2018 at 1:48 Comment(1)
thanks for the reply! I had given up hope. As you say option 2 is closest to what I wanted to achieve. At the time that would have meant to implement one for ear, war, jar. But today extending jar might be enough - so better chances. I'll check out that blog post you linked. Just a second :)Pyriphlegethon
W
1
  • You can add lifecycle and phases if required.
  • But recommended approach is:
    • You already have a well defined build lifecycle with 24 phases
    • Implement your custom plugin if you don't find it on maven repo and bind it to any phase which is most suitable.
    • This way it is easy to maintain because every developer will be already aligned with default phases and if you have added more plugin execution to any specific phase, it is easily understood what you want to do.

Surely you can make your project as complex as you want but generally it is considered bad practice to add lifecycle and phases until you don't have very big thing to manage in the context of build lifecycle.

Welldisposed answered 22/2, 2022 at 3:48 Comment(0)
P
0

Usually in case when you need additional build phases - it's the signal that you need to split your code and move part of it to additional maven module that dedicated to separate functionality.

Add dependency between modules, so in result after start build Maven build graph of modules and build them in expected order, one by one.

Pettish answered 31/7, 2018 at 19:51 Comment(2)
as i mentioned above its mainly to add some additional test levels. To have more structure there. I'm not a fan of moving test sources away from its code and repeating the failsafe plugin in several executions does not bring the level of flexibility I want to achieve for the developers.Pyriphlegethon
Ok, some unit tests should be in the same module as code, some integration test for Spring context for example - too. But some functional tests could be placed in another separate modulePettish

© 2022 - 2024 — McMap. All rights reserved.