khalilou88/jnxplus

Support for plugin dependencies

Closed this issue · 19 comments

In a parent I have a plugin (arch-unit) which has a plugin dependency on a rule set that itself is a module in the pom (so listed in the modules section).

Maven itself recognizes that after the parent, it should first build the module that is used as a plugin-dependency, so that it is available for other modules.

Nx-maven however does not see this dependency. It does not create dependencies in the graph and therefore it sometimes builds/tests a project that has a dependency on another for execution it's plugin, but that project has not been built yet.

Is this a known issue?

@PieterVanEde

I know this case based on jnxplus-examples: https://github.com/khalilou88/jnxplus-examples/blob/main/nx-maven/pom.xml
It's not covered by nx-maven because it will create a circular dependency if the parent project is also the aggregator project.
You can use implicitDependencies to link this project to your parent project.

I will add this feature and in this case we need to separate aggregator project from parent project. Maybe I will add a flag to not break other projects: SkipPluginDependencies!

Would be great indeed to support this. It is indeed possible to create circular dependencies, but that would only happen if a vanilla mvn build would also fail I guess.

Would it also be possible to backport this to the 0.x version range? I'm unfortunately in a project still stuck at NX 18 at the moment, but I would really be happy to use this functionality. Given the number of projects, it would be a chore (and fragile) to depend on developers manually adding the correct implicitDependencies

That's great! Out of curiosity, what is the expected timeline when you expect this functionality to arrive in nx-maven?

I will try to publish a test version today.
I will only look in build tag:

  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>

That's great! Will it also look in the plugin & pluginManagement section of the parent?

For pluginManagement I need an example. I am using jnxplus-examples for cases

No problem, very valid request. I've raised a PR for an example where a dependency is specified in the pluginManagement section: khalilou88/jnxplus-examples#308

@PieterVanEde
You can test the version 1.13.0-next.0

@PieterVanEde
I published also version 0.50.0-next.0 for NX 18.3.5, all features should be present in this release

I will perform a test right away!

This now works almost correctly.

What works correctly:

  • a dependency is created from the parent pom to the project holding the plugin dependency
  • this is created as a circular dependency like you predicted

What I find strange:

Code is perhaps clearer:

<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <!-- Main declaration and configuration of the plugin -->
                <!-- Will be inherited by children -->
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-checkstyle-plugin</artifactId>
                <version>2.9.1</version>
                <executions>
                    <execution>
                        <!--This must be named-->
                        <id>checkstyle</id>
                        <phase>compile</phase>
                        <goals>
                            <goal>check</goal>
                        </goals>
                    </execution>
                </executions>
                <!-- You may also use per-execution configuration block -->
                <configuration...>
            </plugin>
        </plugins>
    </pluginManagement>
    <plugins>
        <plugin>
            <!-- This declaration makes sure children get plugin in their lifecycle -->
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-checkstyle-plugin</artifactId>
            <!-- Configuration won't be propagated to children -->
            <inherited>false</inherited>
            <executions>
                <execution>
                    <!--This matches and thus overrides execution defined above -->
                    <id>checkstyle</id>
                    <!-- Unbind from lifecycle for this POM -->
                    <phase>none</phase>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

This would mean that you have to reason over the effective pom and disregard a plugin if it is not bound to a phase. I don't know how feasible that is.

Alternatively I could seperate my module specification and my plugin/dependency specification in two layered parent poms, but I would rather not do that.

Still so far looks already very nice, but if it is possible it would be great if this is also supported!

nx-maven use a static approach (just reading xml files). Maybe in the future I will try to create a maven plugin if the static approach have more limits.

I think in your case just sperate the aggregator project and the parent project like in this repo : https://github.com/khalilou88/nx-maven-examples

  • The aggregator project at the root of your workspace should be empty just basic info and the modules tag of all your projects.
  • A sub parent project and in this project put all other things, java version, plugins and so on....

If you have a big workspace you can add this option and in this case, adding a new project will not not affect all the projects.

     "graphOptions": {
          "skipAggregatorProjectLinking": true
        }

if you need to share the same version of plugin projects and other projects, you need to create a common parent project for that, then move the plugin to another parent project ...

I added more code to https://github.com/khalilou88/nx-maven-examples.
Run nx graph to understand the architecture

@PieterVanEde I published version 0.50.0 for NX 18.3.5 and 1.13.0 for NX 19 and 20.

Great, thanks a lot!

Sorry to get back to this, I just had some sime to also review the code. I see the current implementation (if I don't misread the code) only looks at plugin dependencies specified in pluginDependencies. However, I think this is a little too narrow approach. I'll try to file a PR that also looks at regular plugin dependencies.

And there I did misread the code, your implementation really is sound.