vaadin / hilla

Build better business applications, faster. No more juggling REST endpoints or deciphering GraphQL queries. Hilla seamlessly connects Spring Boot and React to accelerate application development.
https://hilla.dev
Apache License 2.0
896 stars 56 forks source link

Maven plugin uses incorrect repository and causes CI/CD build failure. #2626

Open ggecy opened 1 month ago

ggecy commented 1 month ago

Describe the bug

In Jenkins builds we have explicitly specified maven repository path via -Dmaven.repo.local=../mvnRepository mvn parameter, so each pipeline has its own local maven repo. If vaadin maven plugin determines that hilla is in project, it will run mvn vaadin:configure command in separate child process, but it doesn't pass the path to local maven repository so it will use the default ~/.m2 folder and fail because it will not find the locally built dependencies there which were installed in the local repo by the pipeline build.

To further make this a bigger problem, vaadin plugin calls com.vaadin.hilla.internal.AbstractTaskEndpointGenerator#prepareEngineConfiguration which doesn't even read the error output stream from the child processes it spawns so there is no direct way of knowing why the child process is failing on CI/CD while working fine locally without some time consuming investigation.

Expected-behavior

If vaadin maven plugin runs any child processes with maven commands, it should pass all relevant configuration parameters so they works with same settings as the parent build process and doesn't cause the whole build to fail.

If there is any error in child processes the plugin should read at least the error stream of the child process and write it to build output so the use able to determine what is wrong.

Reproduction

  1. Create a multimodule maven project, where one of the modules will have the vaadin app and vaadin plugin configured in pom xml and it will have a dependency on another module in the project with some dummy class in it.
  2. Make the vaadin plugin think it uses hilla, e.g. move index.tsx outside of src/main/frontend/generated folder - this should be enough to make it think it uses hilla and attempt to run the mvn vaadin:configure during maven build.
  3. Create a mvnRepository folder inside a project dir.
  4. Run a mvn -Dmaven.repo.local=./mvnRepository clean install
  5. The build should fail with error (you can run the build with debug logging but there will be no more relevant info there anyway since the error output of child process is ignored by vaadin plugin):
    [ERROR] Failed to execute goal com.vaadin:vaadin-maven-plugin:24.4.3:build-frontend (default) on project test-vaadin-module: Could not execute build-frontend goal: Failed to configure Hilla engine: no runner succeeded. Set log level to debug to see more details. -> [Help 1]
    org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal com.vaadin:vaadin-maven-plugin:24.4.3:build-frontend (default) on project test-vaadin-module: Could not execute build-frontend goal
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute2 (MojoExecutor.java:333)
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute (MojoExecutor.java:316)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:212)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:174)
    at org.apache.maven.lifecycle.internal.MojoExecutor.access$000 (MojoExecutor.java:75)
    at org.apache.maven.lifecycle.internal.MojoExecutor$1.run (MojoExecutor.java:162)
    at org.apache.maven.plugin.DefaultMojosExecutionStrategy.execute (DefaultMojosExecutionStrategy.java:39)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:159)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:105)
    at org.apache.maven.lifecycle.internal.builder.multithreaded.MultiThreadedBuilder$1.call (MultiThreadedBuilder.java:193)
    at org.apache.maven.lifecycle.internal.builder.multithreaded.MultiThreadedBuilder$1.call (MultiThreadedBuilder.java:180)
    at java.util.concurrent.FutureTask.run (FutureTask.java:317)
    at java.util.concurrent.Executors$RunnableAdapter.call (Executors.java:572)
    at java.util.concurrent.FutureTask.run (FutureTask.java:317)
    at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1144)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:642)
    at java.lang.Thread.run (Thread.java:1583)
    Caused by: org.apache.maven.plugin.MojoFailureException: Could not execute build-frontend goal
    at com.vaadin.flow.plugin.maven.BuildFrontendMojo.execute (BuildFrontendMojo.java:140)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:126)
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute2 (MojoExecutor.java:328)
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute (MojoExecutor.java:316)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:212)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:174)
    at org.apache.maven.lifecycle.internal.MojoExecutor.access$000 (MojoExecutor.java:75)
    at org.apache.maven.lifecycle.internal.MojoExecutor$1.run (MojoExecutor.java:162)
    at org.apache.maven.plugin.DefaultMojosExecutionStrategy.execute (DefaultMojosExecutionStrategy.java:39)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:159)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:105)
    at org.apache.maven.lifecycle.internal.builder.multithreaded.MultiThreadedBuilder$1.call (MultiThreadedBuilder.java:193)
    at org.apache.maven.lifecycle.internal.builder.multithreaded.MultiThreadedBuilder$1.call (MultiThreadedBuilder.java:180)
    at java.util.concurrent.FutureTask.run (FutureTask.java:317)
    at java.util.concurrent.Executors$RunnableAdapter.call (Executors.java:572)
    at java.util.concurrent.FutureTask.run (FutureTask.java:317)
    at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1144)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:642)
    at java.lang.Thread.run (Thread.java:1583)
    Caused by: com.vaadin.flow.server.ExecutionFailedException: Failed to configure Hilla engine: no runner succeeded. Set log level to debug to see more details.
    at com.vaadin.hilla.internal.AbstractTaskEndpointGenerator.prepareEngineConfiguration (AbstractTaskEndpointGenerator.java:122)
    at com.vaadin.hilla.internal.AbstractTaskEndpointGenerator.getEngineConfiguration (AbstractTaskEndpointGenerator.java:72)
    at com.vaadin.hilla.internal.TaskGenerateOpenAPIImpl.execute (TaskGenerateOpenAPIImpl.java:85)
    at com.vaadin.flow.server.frontend.NodeTasks.execute (NodeTasks.java:348)
    at com.vaadin.flow.plugin.base.BuildFrontendUtil.runNodeUpdater (BuildFrontendUtil.java:341)
    at com.vaadin.flow.plugin.maven.BuildFrontendMojo.execute (BuildFrontendMojo.java:138)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:126)
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute2 (MojoExecutor.java:328)
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute (MojoExecutor.java:316)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:212)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:174)
    at org.apache.maven.lifecycle.internal.MojoExecutor.access$000 (MojoExecutor.java:75)
    at org.apache.maven.lifecycle.internal.MojoExecutor$1.run (MojoExecutor.java:162)
    at org.apache.maven.plugin.DefaultMojosExecutionStrategy.execute (DefaultMojosExecutionStrategy.java:39)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:159)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:105)
    at org.apache.maven.lifecycle.internal.builder.multithreaded.MultiThreadedBuilder$1.call (MultiThreadedBuilder.java:193)
    at org.apache.maven.lifecycle.internal.builder.multithreaded.MultiThreadedBuilder$1.call (MultiThreadedBuilder.java:180)
    at java.util.concurrent.FutureTask.run (FutureTask.java:317)
    at java.util.concurrent.Executors$RunnableAdapter.call (Executors.java:572)
    at java.util.concurrent.FutureTask.run (FutureTask.java:317)
    at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1144)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:642)
    at java.lang.Thread.run (Thread.java:1583)

System Info

MacOS 14.5, Vaadin 24.4.3

sahrmann commented 1 month ago

I used to run into the same problem and fixed it putting the command line arguments (-Dmaven.repo.local=../mvnRepository) into the MAVEN_ARGS environment variable in my pipeline.

ggecy commented 1 month ago

I used to run into the same problem and fixed it putting the command line arguments (-Dmaven.repo.local=../mvnRepository) into the MAVEN_ARGS environment variable in my pipeline.

Thanks, that kind of works, but in jenkins pipeline we are using configFileProvider for maven settings.xml, which is stored in temporary file with path to file set to environment variable MAVEN_SETTINGS_XML inside steps in stage. I can setup the MAVEN_ARGS variable in environment block in jenkins pipeline but I cannot use the -s $MAVEN_SETTINGS_XML there since that variable is comming from configFileProvider and it isn't expanded when I put it in MAVEN_ARGS variable. Well, it works when I set the -Dmaven.repo.local=../mvnRepository in MAVEN_ARGS and set the -s $MAVEN_SETTINGS_XML individually for each mvn command, but it means that settings.xml is not passed to child process mvn command, which in our case shouldn't be a problem, however you have an option to specify localRepository also inside settings.xml.

Update: In the end I had to change the configFileProvider to save the settings.xml to jenkins pipeline root folder and added it to MAVEN_ARGS as absolute path (actually all paths in MAVEN_ARGS have to be absolute since mvn vaadin:configure run by vaadin plugin is started in different working directory so the relative paths doesn't work), it wasn't working without it.