Reputation:
I have a Java project with some Cucumber tests and some regular JUnit tests, managed by Maven.
I want to run the tests in Jenkins, using Docker, so I wrote this Jenkinsfile
:
pipeline {
agent {
docker {
image 'maven:3.6.1'
}
}
stages {
stage('build') {
steps {
sh 'mvn clean verify -Dmaven.test.failure.ignore=true'
}
post {
success {
junit 'target/surefire-reports/**/*.xml'
}
}
}
}
}
When I run the build, the regular tests pass but the Cucumber tests fail with:
Error Message
URI has a query component
Stacktrace
java.lang.IllegalArgumentException: URI has a query component
It's not until I disable trimStackTrace
for maven-surefire-plugin
that I also get the details:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<trimStackTrace>false</trimStackTrace>
</configuration>
</plugin>
java.lang.IllegalArgumentException: URI has a query component
at java.base/java.io.File.<init>(File.java:427)
at cucumber.runtime.io.ZipResourceIterator.<init>(ZipResourceIterator.java:22)
at cucumber.runtime.io.ZipResourceIteratorFactory.createIterator(ZipResourceIteratorFactory.java:24)
at cucumber.runtime.io.ZipThenFileResourceIteratorFactory.createIterator(ZipThenFileResourceIteratorFactory.java:22)
at cucumber.runtime.io.DelegatingResourceIteratorFactory.createIterator(DelegatingResourceIteratorFactory.java:49)
at cucumber.runtime.io.ClasspathResourceIterable.iterator(ClasspathResourceIterable.java:35)
at cucumber.runtime.io.ResourceLoaderClassFinder.getDescendants(ResourceLoaderClassFinder.java:25)
at cucumber.runtime.Reflections.instantiateSubclasses(Reflections.java:34)
at cucumber.runtime.BackendModuleBackendSupplier.loadBackends(BackendModuleBackendSupplier.java:52)
at cucumber.runtime.BackendModuleBackendSupplier.get(BackendModuleBackendSupplier.java:39)
at cucumber.runner.ThreadLocalRunnerSupplier.createRunner(ThreadLocalRunnerSupplier.java:42)
at cucumber.runner.ThreadLocalRunnerSupplier.access$000(ThreadLocalRunnerSupplier.java:13)
at cucumber.runner.ThreadLocalRunnerSupplier$1.initialValue(ThreadLocalRunnerSupplier.java:22)
at cucumber.runner.ThreadLocalRunnerSupplier$1.initialValue(ThreadLocalRunnerSupplier.java:19)
at java.base/java.lang.ThreadLocal.setInitialValue(ThreadLocal.java:195)
at java.base/java.lang.ThreadLocal.get(ThreadLocal.java:172)
at cucumber.runner.ThreadLocalRunnerSupplier.get(ThreadLocalRunnerSupplier.java:38)
at cucumber.api.junit.Cucumber$RunCucumber.evaluate(Cucumber.java:146)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:365)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:273)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:238)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:159)
at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:384)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:345)
at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:126)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:418)
This is quite puzzling because:
mvn verify
locally, it worksagent any
in the Dockerfile
, instead of the maven Docker image, it worksmaven-surefire-plugin
version 2.22.2
instead of 3.0.0-M3
, it worksI logged in as Jenkins and looked in the workspace:
$ sudo su - jenkins
$ ls /var/lib/jenkins/workspace/question-mark-dir_master
'?' Jenkinsfile LICENSE pom.xml README.md src target
There's a question mark (?
) directory in there, and it contains the .m2
directory, with all the artifacts needed by the project.
I suspect this could be the cause of the exception, because then there are question marks in the classpath, and question marks are the ones who introduce the query component of URIs.
For the moment I can downgrade to maven-surefire-plugin
version 2.22.2
as a workaround.
But what is the actual problem here?
maven-surefire-plugin
? Judging by the stack trace I wouldn't bet on that.If you want to try this out, I have a MVCE. In my local Jenkins installation, I created a new project of type "Multibranch Pipeline" and in "Branch Sources" I added as the git project repository my local git project. No other changes.
Upvotes: 1
Views: 968
Reputation:
By combining TYY's comment to the question and the documentation of the maven docker image, I was able to configure the Jenkinsfile
in a way that avoids creating a question mark directory.
We need to inform Maven of the user's home directory, and map that to a directory outside the container.
pipeline {
agent {
docker {
image 'maven:3.6.1'
args '-v /var/lib/jenkins:/usr/src/mymaven -w /usr/src/mymaven'
}
}
stages {
stage('build') {
steps {
sh 'MAVEN_OPTS="-Duser.home=/usr/src/mymaven" mvn clean verify -Dmaven.test.failure.ignore=true'
}
// ...
}
}
}
-v /var/lib/jenkins:/usr/src/mymaven
maps the /var/lib/jenkins
directory on the host to the /usr/src/mymaven
directory inside the container-w /usr/src/mymaven
sets the working directory inside the containerMAVEN_OPTS="-Duser.home=/usr/src/mymaven"
sets the user.home
Java property for MavenProof that it works, on a branch of the MCVE.
Upvotes: 2