eirslett / frontend-maven-plugin

"Maven-node-grunt-gulp-npm-node-plugin to end all maven-node-grunt-gulp-npm-plugins." A Maven plugin that downloads/installs Node and NPM locally, runs NPM install, Grunt, Gulp and/or Karma.
Apache License 2.0
4.23k stars 867 forks source link

Property not loaded from activated profile in multi module project #905

Closed imtiazShakil closed 4 years ago

imtiazShakil commented 4 years ago

Do you want to request a feature or report a bug? --> Bug

What is the current behavior?

I have a multi module project. For simplicity let's assume following project structure:

.
├── pom.xml                         # parent pom
├── child-project                   # Child Project Directory
│   ├── child-project              #  Angular Project
│   └── pom.xml                    # child pom

I've defined some profile specific property in my child pom which should be picked up by frontend maven plugin for respective active profile. but frontend maven plugin uses properties correctly only when I explicitly set current profile like this: mvn clean install -Pdev # works on both parent and child project

Even though when I've defined default profile frontend maven plugin doesn't seem to set property when I don't explicitly set it.

What is the expected behavior? When I don't explicitly set default profile frontend maven plugin still should be able to load properties

Please mention your frontend-maven-plugin and operating system version. frontend-maven-plugin: 1.10.0 OS: Windows 10

Here is My parent Pom:

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>com.mypackage.demo</groupId>
    <artifactId>MavenTest</artifactId>
    <version>1.0.0</version>
    <packaging>pom</packaging>

    <name>Maven Sample Parent</name>

    <modules>
        <module>child-project</module>
    </modules>

    <profiles>
        <profile>
            <id>dev</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
        </profile>
        <profile>
            <id>stage</id>
        </profile>
    </profiles>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <junit.version>3.8.1</junit.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

And this is my child pom:

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

    <parent>
        <groupId>com.mypackage.demo</groupId>
        <artifactId>MavenTest</artifactId>
        <version>1.0.0</version>
    </parent>

    <modelVersion>4.0.0</modelVersion>
    <artifactId>child-project</artifactId>
    <name>child-project demo</name>
    <packaging>jar</packaging>

    <properties>
        <npm-install-id>npm install</npm-install-id>
        <npm-build-id>npm run build</npm-build-id>
        <eirslett.version>1.10.0</eirslett.version>
        <node.version>v8.12.0</node.version>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>com.github.eirslett</groupId>
                <artifactId>frontend-maven-plugin</artifactId>
                <version>${eirslett.version}</version>
                <configuration>
                    <workingDirectory>child-project</workingDirectory>
                </configuration>

                <executions>

                    <execution>
                        <id>install node and npm</id>
                        <goals>
                            <goal>install-node-and-npm</goal>
                        </goals>
                        <configuration>
                            <nodeVersion>${node.version}</nodeVersion>
                        </configuration>
                    </execution>

                    <execution>
                        <id>npm install</id>
                        <goals>
                            <goal>npm</goal>
                        </goals>

                        <configuration>
                            <arguments>install</arguments>
                        </configuration>
                    </execution>

                    <execution>
                        <id>${npm.build.id}</id>
                        <goals>
                            <goal>npm</goal>
                        </goals>
                        <configuration>
                            <arguments>${angular.build}</arguments>
                        </configuration>
                    </execution>

                </executions>
            </plugin>
        </plugins>
    </build>

    <profiles>
        <profile>
            <id>dev</id>
            <properties>
                <angular.build>run build</angular.build>
            </properties>
        </profile>
        <profile>
            <id>stage</id>
            <properties>
                <angular.build>run build -- --configuration=stage</angular.build>
            </properties>
        </profile>
    </profiles>

</project>

Now when inside parent pom directory if I run: mvn clean install -Pdev everything works fine but if I run
mvn clean install frontend maven plugin won't set angular.build property.

neoxpert commented 4 years ago

If I didn't miss something, this has nothing to do with the frontend plugin but Maven.

The property angular.build is only defined within the dev and stage profile of the child but not within the parent ones. Afaik the inheritence order in Maven projects is top down. So the child poms would inherit properties from the parent but the parent won't take properties from the childs. Also parent profiles do not activate child profiles, even if they have the same id. The autoactivation of the dev profile in the parent does not activate the dev profile in the child.

Also, if the angular.build property is only defined within those profiles, there simply is no default value for Maven to use in order to parametrize the frontend plugin.

So you can either move the property up into the parents profiles, enabled auto activation for the childs dev profile too, or define a default property value in case none of the profiles are active.

imtiazShakil commented 4 years ago

Also parent profiles do not activate child profiles, even if they have the same id. The autoactivation of the dev profile in the parent does not activate the dev profile in the child.

This is not true. please check below stackoverflow link. https://stackoverflow.com/questions/3695394/inheriting-maven-profiles/17730471

neoxpert commented 4 years ago

Okay while this seems be to true (at least mvn help:all-profiles lists it as active):

Listing Profiles for Project: com.mypackage.demo:MavenTest:pom:1.0.0
  Profile Id: dev (Active: true , Source: pom)
  Profile Id: stage (Active: false , Source: pom)
Listing Profiles for Project: com.mypackage.demo:child-project:jar:1.0.0
  Profile Id: dev (Active: true , Source: pom)
  Profile Id: stage (Active: false , Source: pom)

But it's not a plugins job to evaluate and resolve variables within a pom. This is done before the actual Maven process starts. Just have a look at the generated effective poms ( mvn help:effective-pom ).

Using Maven 3.6.3 calling mvn help:effective-pom yields the following properties for the child-project:

<properties>
      <eirslett.version>1.10.0</eirslett.version>
      <junit.version>3.8.1</junit.version>
      <node.version>v8.12.0</node.version>
      <npm-build-id>npm run build</npm-build-id>
      <npm-install-id>npm install</npm-install-id>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

While calling mvn -P dev help:effective-pom yields this result:

<properties>
      <angular.build>run build</angular.build>
      <eirslett.version>1.10.0</eirslett.version>
      <junit.version>3.8.1</junit.version>
      <node.version>v8.12.0</node.version>
      <npm-build-id>npm run build</npm-build-id>
      <npm-install-id>npm install</npm-install-id>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

If I add the auto activation flag to the childs dev profile the angular.build property is set without explicitly calling Maven with the dev profile.

imtiazShakil commented 4 years ago

If I add the auto activation flag to the childs dev profile the angular.build property is set without explicitly calling Maven with the dev profile.

Yes, I also use this approach as a work around for this problem.

So what you are implying is that, it's not the plugin who is responsible for this, right?

neoxpert commented 4 years ago

Yes, that's what I wanted to imply. You can also remove the plugin from the pom. The behaviour observed with the variable stays the same.

I would also expect that if the profile get's listed as active using the help plugin should also set the variable, but so far I did not find any clues about if this behaviour is correct or not in terms of Maven :-/.

imtiazShakil commented 4 years ago

okay, should I close this issue then as it's not related to eirslett plugin ?

eirslett commented 4 years ago

Looks like it's not related. Thanks @neoxpert for helping!