When trying to execute cucumber tests from Jenkins pipeline with the invocation looking like this:
sh '''mvn spring-boot:start \
exec:java \
-Dexec.classpathScope=test \
-Dexec.mainClass=io.cucumber.core.cli.Main \
-Dexec.args=\\"src/test-bdd/resources/features/set02 --glue gluepackage\\" \
spring-boot:stop
'''
after that line gets invoked, Jenkins will output the following:
20:39:31 mvn spring-boot:start exec:java -Dexec.classpathScope=test -Dexec.mainClass=io.cucumber.core.cli.Main -Dexec.args="src/test-bdd/resources/features/set02 --glue gluepackage" spring-boot:stop
20:39:31 Unable to parse command line options: Unrecognized option: --glue
20:39:31
20:39:31 usage: mvn [options] [<goal(s)>] [<phase(s)>]
That basically means the shell is not passing the value of the -Dexec.args parameter to the exec plugin as a string but rather interprets that value as arguments to the mvn command. Obviously there's no --glue argument maven recognises, so the shell will print help on how to use maven and exit with a an error.
If I copy-paste the generated command into my terminal in the project directory and hit enter, it will run perfectly fine meaning the contents between quotes will be passed to the exec:java plugin command and the cucumber tests start and run as they should.
I tried quite a few things (single quotes, double quotes, groovy style string interpolation, passing as environment variable etc) except probably writing a simple shell script and invoking the command line inside it with params passed to the script which would probably be the closest to what happens when invoked directly from command line, but from all that I have tried nothing seems to work.
I am running Jenkins 2.375.2. Both controller and nodes run on Mac.
Will appreciate any suggestions.
CodePudding user response:
Too many backslashes, should be:
sh '''mvn spring-boot:start \
exec:java \
-Dexec.classpathScope=test \
-Dexec.mainClass=io.cucumber.core.cli.Main \
-Dexec.args=\"src/test-bdd/resources/features/set02 --glue gluepackage\" \
spring-boot:stop
'''
btw, for this particular case I would recommend to define execution for exec-maven-plugin
:
I. Java
as executable (I prefer this option):
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<id>set02</id>
<phase>none</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>java</executable>
<arguments>
<argument>-classpath</argument>
<classpath />
<argument>io.cucumber.core.cli.Main</argument>
<argument>src/test-bdd/resources/features/set02</argument>
<argument>--glue</argument>
<argument>gluepackage</argument>
</arguments>
<classpathScope>test</classpathScope>
</configuration>
</execution>
</executions>
</plugin>
II. Main class within the same VM as maven
:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<id>set02</id>
<phase>none</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<arguments>
<mainClass>io.cucumber.core.cli.Main</mainClass>
<argument>src/test-bdd/resources/features/set02</argument>
<argument>--glue</argument>
<argument>gluepackage</argument>
</arguments>
<classpathScope>test</classpathScope>
</configuration>
</execution>
</executions>
</plugin>
and run it via exec:java@exection-id
, i.e.:
sh '''mvn spring-boot:start \
exec:java@set02 \
spring-boot:stop
'''
also, it is not clear whether maven
can stop spring-boot
application in case of failure and that is better to split pipeline into separate steps protected by try/finally.