kordamp / gm

Gum is a Gradle/Maven/JBang wrapper written in Go
Apache License 2.0
59 stars 2 forks source link

Add mvnd support #50

Closed rmannibucau closed 2 years ago

aalmiray commented 2 years ago

What would be required to support mvnd? Isn't the case that the name of the client command continues to be mvn/mvn.cmd? What would happen with the Maven wrapper?

@ppalaga

rmannibucau commented 2 years ago

@aalmiray mvnd instead of mvn, challenge is how to pick mvn or mvnd, I assume the toml config can solve that but hope it can be done automatically (if in a tty prefer mvnd if there else use mvn - ie in scripts).

aalmiray commented 2 years ago

I guess Gum can check for mvnd/mvnd.cmd before doing the same for mvn/mvn.cmd. But what about the wrapper? Does making use of mvnw will pick up mvnd? Is mvnd compatible with the wrapper or is that still in the works?

rmannibucau commented 2 years ago

No mvnd uses a bundled maven since it is tightly integrated. Not sure it will be in the work (to be honest Im in the camp of finding the wrapper an anti-pattern/bug so will not defend it ;)).

aalmiray commented 2 years ago

Got it. This is how Gum does it job when you issue gm build:

  1. finds the build tool to be invoked based on a pre-configure order, ie. [maven, gradle, ant, jbang, bach]
  2. given each tool in the sequence it'll try to find a suitable build file, if found then the tool is the chosen one, if not it checks the next tool in the sequence.
  3. if a tool is selected then Gum tries to invoke its wrapper if it exists
  4. if no wrapper exists then it tries to invoke the tool using the execution $PATH/%PATH%
  5. if no suitable executable is found the the build fails because nothing can be done.

For mvnd to be hooked in given that there's no wrapper support it'd would happen at step 4.

BUT, if the projects has a wrapper and you wanted to use mvnd then you'd be out of luck, as the wrapper wins. Unless mvnd is elevated to its own category, at same level as the other build tools in the sequence, then you could say [mvnd, maven, ...] so that if mvnd is found in the system it'll be picked up regardless if the maven wrapper is found in the project or not, regardless if the mvn command is available in the path or not.

WDYT?

rmannibucau commented 2 years ago

@aalmiray think it misses the tty (interactive mode) check otherwise it will be impossible to replace mvn and mvnd by gum cause you can't replace mvn by mvnd in scripts in general without loosing the benefit of mvnd (would change the shell env basically due to the way scripts are often written). Alternative is to integrate more deeply with mvnd and check if current daemon cache matches current project and if so use it else let it go (kind of "would it kill the daemon" check) but it is likely harder.

aalmiray commented 2 years ago

I guess I'm lost with the tty argument. If this feature is added the gm will be able to call mvnd ahead of mvn/mvnw. But you have to invoke gm. If you have another script that continues to invoke mvn but you'd like it to be mvnd ... then change said script to use gm.

If you can't change the script but still want mvnd over mvn then ... what else can be done besides stop using that script?

rmannibucau commented 2 years ago

Thinking to dev scripts, not automation scripts to clarify. To make gm an option keeping mvnd usage it must be able to detect mvn and mvnd are elligible for the project and pick the one of both the most appropriated (can still be done in chain, no need to go through 2 passes while mvnd is before mvn and additional checks are added). To do that it must also check that it is a script (if there is a tty then it is not a script so mvnd can be used else mvn should).

ppalaga commented 2 years ago

I am quite ignorant about gm, its purpose and goals, so I'll only add some info about mvnd you might find useful:

  1. mvnd in a non-interactive env: it works, mvnd is designed to detect it ootb, just try mvn install > $TEMP/mvnd.out. mvnd will switch to its non-interactive mode, as if you passed mvnd -Dmvnd.noBuffering. Here is the help entry for mvnd.noBuffering:
-Dmvnd.noBuffering=<boolean>           If true the log messages are displayed continuously like with stock Maven; otherwise buffer the messages and
                                        output at the end of the build, grouped by module. Passing -B or --batch-mode on the command line enables this
                                        too for the given build.
                                        Default: false
  1. Wrapper: We do not have it ATM, but it was asked for several times in the past by the users. Now that we are under Maven umbrella, maybe mvnd could become an option of the existing Maven Wrapper (rather than implementing a separate mvndw).
rmannibucau commented 2 years ago

Well the issue with mvnd in non interactive mode is not that it works or not but often non interactive mode is in scripts and they use a different "env"/context than the main mvnd daemon so at the end if you use mvnd there you kill the daemon benefit so it is not bad to use mvnd for human commands and stick to mvn for scripts (until mvnd will support multiple contexts but it is not the case as of today IIRC.

aalmiray commented 2 years ago

@ppalaga gm is a tool that lets you invoke builds by delegating to a particular build tool. Maven, Gradle, JBang, Ant, and Bach are supported.

In the case of the first 3 gm can launch their respective wrapper if it's found and configured, otherwise it'll launch the build tool if found in the path.

gm relies on finding build files to determine which build tool should be invoked.

gm also lets you invoke the build from anywhere inside the project structure, not just the root.

Now for mvnd support the current option would be to first check if mvnd is in the path before checking for mvn, even if the project has mvnw. A decision must be made (non interactive, via the gm.toml config file) if mvnd wins or if the wrapper must be honored.

aalmiray commented 2 years ago

@rmannibucau it's still not clear to me what you mean by interactive mode. It seems that if you have a dev script that currently calls mvnd with some non-interactive flags you'd want to replace that with gm without the flags, is that the case?

If so then no, I don't think it's within gm's responsibilities to pock certain flags or not.

However a compromise could be adding a new config option for all supported build tools to define in gm.toml a set of flags that should always be used, say for example -S for Gradle, -B for Maven, etc. In this case you could add explicit flags required by mvnd.

rmannibucau commented 2 years ago

@aalmiray the case is the following one:

  1. all human (me ;)) commands use mvnd
  2. all helper scripts (./deploy.sh, ./buildDocker.sh etc...) use currently mvn and they must not use mvnd cause the context key is changed in these scripts

Like that no big deal but, assuming gum manages to handle a bit more (java/mvn version setup) i'd like to move the scripts to gum to avoid to handle this setup in the scripts but it must still delegate to mvn and not mvnd.

aalmiray commented 2 years ago

Got it. OK so here's what could happen then. Set tool preference to be [maven, mvnd, ...] in gm.toml that way mvn (or its wrapper) will always be invoked before mvnd.

If the sequence were to be [mvnd, maven, ...] then we'd face a problem as you expressed in option 2. no matter what mvn should be executed. Here the question is how would gm detect that it was called from within a script? What magic env var exists in both Linux and Windows to get than info? If there's no standard en var then a custom one must be set (say GM_EMBEDDED).

Bear in mind that if the env var is not set then gm will prefer mvnd over mvn given the configuration sequence, that is, there's no 100% fool proof way to they this right, is it?

rmannibucau commented 2 years ago

@aalmiray i was hoping to rely on https://github.com/fusesource/jansi-native/blob/8c923f2b59a7fbf599f3d4922e6fceca645e4610/src/main/native-package/src/jansi_isatty.c to do the detection. More explicit setup is needed, less the tool stays helpful for these cases.

aalmiray commented 2 years ago

Adding the following configuration to .gm.toml will make mvnd the first candidate before mvnw or mvn:

[maven]
mvnd = true
rmannibucau commented 2 years ago

Hi @aalmiray , there is no way to handle the contextual preference right now, it is like adding another build tool, nothing more, right? Would be neat to have some follow up tasks to handle some conditions to select the right tool when it is ambiguous:

  1. tty filtering (exclude mvnd if there is no tty for ex)
  2. custom command (check if mvnd is running for ex, it is easy since the daemon can be detected)
  3. ...?
  4. finally use the order and take the first one
aalmiray commented 2 years ago

Not at the moment, mvnd is just given priority over mvnw and mvn. This feature may be refined later.