Publish clover coverage in CI: "Invalid input stream" (OD-2579)
pim opened 3 months ago

Hello onedev team, We set up a CI in which phpunit produces unit test coverage data through a clover.xml file. Feeding this into the publish step for clover yields the error "Invalid input stream" in the job log.

Job log:

16:25:24 Generating code coverage report in Clover XML format ... done 16:25:24 Step "Run phpunit in container" is successful (10 seconds) 16:25:24 Running step "Save junit coverage(html) and clover"... 16:25:24 Step "Save junit coverage(html) and clover" is successful (0 seconds) 16:25:24 Running step "Publish unit-test report in junit format"... 16:25:24 Processing JUnit test report 'junit'... 16:25:24 Step "Publish unit-test report in junit format" is successful (0 seconds) 16:25:24 Running step "publish Coverage (Clover)"... 16:25:25 Processing clover report 'clover.xml'... 16:25:25 Invalid input stream 16:25:26 Job finished

The onedev server logs show an error and the "caused by" stacktraces seems to be similar to the stacktrace in a recently fixed issue (OD-2318):

2025-10-16 16:25:37,106 ERROR [qtp1236733963-40769] o.g.j.server.ServerRuntime$Responder An I/O error has occurred while writing a response message entity to the container output stream. org.glassfish.jersey.server.internal.process.MappableException: java.lang.NullPointerException: Cannot invoke "String.length()" because the return value of "io.onedev.server.util.FilenameUtils.getPrefix(String)" is null at org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundWriteTo(MappableExceptionWrapperInterceptor.java:67) at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:139) at org.glassfish.jersey.message.internal.MessageBodyFactory.writeTo(MessageBodyFactory.java:1116) at org.glassfish.jersey.server.ServerRuntime$Responder.writeResponse(ServerRuntime.java:649) at org.glassfish.jersey.server.ServerRuntime$Responder.processResponse(ServerRuntime.java:380) at org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:370) at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:259) at org.glassfish.jersey.internal.Errors$1.call(Errors.java:248) at org.glassfish.jersey.internal.Errors$1.call(Errors.java:244) at org.glassfish.jersey.internal.Errors.process(Errors.java:292) at org.glassfish.jersey.internal.Errors.process(Errors.java:274) at org.glassfish.jersey.internal.Errors.process(Errors.java:244) at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:265) at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:235) at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:684) at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:394) at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:346) at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:358) at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:311) at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:205) at io.onedev.server.rest.DefaultServletContainer.service(DefaultServletContainer.java:27) at io.onedev.server.rest.DefaultServletContainer$$EnhancerByGuice$$204312278.GUICE$TRAMPOLINE() at com.google.inject.internal.InterceptorStackCallback$InterceptedMethodInvocation.proceed(InterceptorStackCallback.java:74) at io.onedev.server.persistence.SessionInterceptor$1.call(SessionInterceptor.java:23) at io.onedev.server.persistence.DefaultSessionManager.call(DefaultSessionManager.java:90) at io.onedev.server.persistence.SessionInterceptor.invoke(SessionInterceptor.java:18) at com.google.inject.internal.InterceptorStackCallback$InterceptedMethodInvocation.proceed(InterceptorStackCallback.java:75) at com.google.inject.internal.InterceptorStackCallback.invoke(InterceptorStackCallback.java:55) at io.onedev.server.rest.DefaultServletContainer$$EnhancerByGuice$$204312278.service() at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:799) at org.eclipse.jetty.servlet.ServletHandler$ChainEnd.doFilter(ServletHandler.java:1656) at com.google.inject.servlet.DefaultFilterPipeline.dispatch(DefaultFilterPipeline.java:47) at com.google.inject.servlet.GuiceFilter.doFilter(GuiceFilter.java:133) at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1626) at io.onedev.server.git.GoGetFilter.doFilter(GoGetFilter.java:90) at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1626) at io.onedev.server.git.GitLfsFilter.doFilter(GitLfsFilter.java:502) at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1626) at io.onedev.server.git.GitFilter.doFilter(GitFilter.java:395) at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1626) at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:61) at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108) at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137) at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:154) at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66) at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108) at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137) at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:154) at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66) at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108) at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137) at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:154) at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66) at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:458) at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:373) at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90) at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83) at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:387) at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:370) at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:154) at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1626) at io.onedev.server.security.CorsFilter.doFilter(CorsFilter.java:47) at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1626) at io.onedev.server.jetty.DisableTraceFilter.doFilter(DisableTraceFilter.java:28) at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193) at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1626) at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:552) at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233) at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1624) at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233) at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1440) at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188) at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:505) at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1594) at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186) at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1355) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) at org.eclipse.jetty.server.handler.gzip.GzipHandler.handle(GzipHandler.java:772) at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127) at org.eclipse.jetty.server.Server.handle(Server.java:516) at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:487) at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:732) at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:479) at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:277) at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311) at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105) at org.eclipse.jetty.io.ChannelEndPoint$1.run(ChannelEndPoint.java:104) at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:338) at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:315) at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:173) at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:131) at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:409) at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:883) at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1034) at java.base/java.lang.Thread.run(Thread.java:1583) Caused by: java.lang.NullPointerException: Cannot invoke "String.length()" because the return value of "io.onedev.server.util.FilenameUtils.getPrefix(String)" is null at io.onedev.server.model.Build.getBlobPath(Build.java:1122) at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) at java.base/java.lang.reflect.Method.invoke(Method.java:580) at org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor.intercept(ByteBuddyInterceptor.java:56) at org.hibernate.proxy.ProxyConfiguration$InterceptorDispatcher.intercept(ProxyConfiguration.java:95) at io.onedev.server.model.Build$HibernateProxy$BVub1Cn3.getBlobPath(Unknown Source) at io.onedev.server.plugin.report.clover.CloverReportParser.parsePackageCoverage(CloverReportParser.java:60) at io.onedev.server.plugin.report.clover.CloverReportParser.parse(CloverReportParser.java:39) at io.onedev.server.plugin.report.clover.PublishCloverReportStep.process(PublishCloverReportStep.java:74) at io.onedev.server.plugin.report.coverage.PublishCoverageReportStep.lambda$run$0(PublishCoverageReportStep.java:41) at io.onedev.commons.utils.LockUtils.write(LockUtils.java:179) at io.onedev.commons.utils.LockUtils.write(LockUtils.java:195) at io.onedev.server.plugin.report.coverage.PublishCoverageReportStep.lambda$run$1(PublishCoverageReportStep.java:36) at io.onedev.server.persistence.DefaultSessionManager.call(DefaultSessionManager.java:90) at io.onedev.server.plugin.report.coverage.PublishCoverageReportStep.run(PublishCoverageReportStep.java:34) at io.onedev.server.job.DefaultJobManager.runServerStep(DefaultJobManager.java:1531) at io.onedev.server.plugin.executor.kubernetes.KubernetesResource.lambda$runServerStep$0(KubernetesResource.java:118) at org.glassfish.jersey.message.internal.StreamingOutputProvider.writeTo(StreamingOutputProvider.java:55) at org.glassfish.jersey.message.internal.StreamingOutputProvider.writeTo(StreamingOutputProvider.java:37) at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.invokeWriteTo(WriterInterceptorExecutor.java:242) at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo(WriterInterceptorExecutor.java:227) at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:139) at org.glassfish.jersey.server.internal.JsonWithPaddingInterceptor.aroundWriteTo(JsonWithPaddingInterceptor.java:85) at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:139) at org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundWriteTo(MappableExceptionWrapperInterceptor.java:61) ... 100 common frames omitted

The CI yaml file:

version: 43
jobs:
- name: PHPCS-testing
  steps:
  - type: CheckoutStep
    name: checkout
    cloneCredential:
      type: DefaultCredential
    withLfs: false
    withSubmodules: false
    condition: SUCCESSFUL
    optional: false
  - type: CommandStep
    name: Run phpcs in container
    runInContainer: true
    image: hostname/ci-cd/php/phpcs-phpunit-phpv:7.2.0
    interpreter:
      type: DefaultInterpreter
      commands: "PR=$(curl -s -u \"Myname\":@secret:access-token@ https://hostname.nl/~api/pulls/@pull_request_number@)\nTARGET=$(echo $PR | jq -r '.targetBranch')\necho $PR\n\ngit fetch --all\n\nif [ -n \"$TARGETBRANCH\" ]; then\n\techo \"ERROR: can't get target branch from ondev api!\"\n    exit 1\nfi\n\n#FILES=$(git diff --name-only --diff-filter=d \"origin/$TARGET\")\n#PHPCS_FILES=$(echo \"$FILES\" | grep '\\.php')\n#echo \"$PHPCS_FILES\"\n\n#if [ -z \"$PHPCS_FILES\" ]; then\n#\techo \"ERROR: No PHP-files found!\"\n#    exit 1\n#fi\n\n#echo \"$PHPCS_FILES\" | xargs php /app/phpcs.phar --standard=build/phpcs.xml --report-file=checkstyle.xml --report=checkstyle\n\n# Get the list of changed files that are not deleted, outputting null-terminated strings\ngit diff --name-only --diff-filter=d \"origin/$TARGET\" -z | \\\n    grep -z '\\.php' | \\\n    xargs -0 php /app/phpcs.phar --standard=build/phpcs.xml --report-file=checkstyle.xml --report=checkstyle\n"
    useTTY: true
    condition: SUCCESSFUL
    optional: false
  - type: PublishCheckstyleReportStep
    name: Phpcs report
    reportName: Phpcs report
    filePatterns: checkstyle.xml
    tabWidth: 8
    failThreshold: HIGH
    condition: ALWAYS
    optional: false
  triggers:
  - type: PullRequestUpdateTrigger
  retryCondition: never
  maxRetries: 3
  retryDelay: 30
  timeout: 14400
- name: PHP-Unit testing
  steps:
  - type: CheckoutStep
    name: checkout code
    cloneCredential:
      type: DefaultCredential
    withLfs: false
    withSubmodules: false
    condition: SUCCESSFUL
    optional: false
  - type: CommandStep
    name: Run phpunit in container
    runInContainer: true
    image: hostname/ci-cd/php/phpcs-phpunit-phpv:7.2.0
    interpreter:
      type: DefaultInterpreter
      commands: |
        php /app/phpunit.phar --whitelist src/lib --log-junit junit --coverage-clover clover.xml tests
    useTTY: true
    condition: SUCCESSFUL
    optional: false
  - type: PublishJUnitReportStep
    name: Publish unit-test report in junit format
    reportName: phpunit results
    filePatterns: junit
    condition: SUCCESSFUL
    optional: false
  - type: PublishArtifactStep
    name: Save junit coverage(html) and clover
    artifacts: junit coverage/* clover.xml
    condition: SUCCESSFUL
    optional: false
  triggers:
  - type: PullRequestUpdateTrigger
  retryCondition: never
  maxRetries: 3
  retryDelay: 30
  timeout: 14400
properties:
- name: php-steps
  value: phpcs
  archived: false
  • Robin Shen commented 3 months ago

    Can you please demonstrate the issue via a test project on this OneDev instance?

  • pim commented 3 months ago

    Can you please demonstrate the issue via a test project on this OneDev instance?

    A demo project with a fake test and some useless php files did not show the problem as the pipeline completes successfully (though without showing a tab with coverage results): https://code.onedev.io/test_project_Issue_OD-2579/~builds/4

    I will do another attempt on monday.

  • Robin Shen commented 3 months ago

    Never mind. Found the issue.

  • OneDev commented 3 months ago

    State changed as code fixing the issue is committed (64e83d99)

  • OneDev changed state to 'Closed' 3 months ago
    Previous Value Current Value
    Open
    Closed
  • OneDev commented 3 months ago

    State changed as build OD-6728 (13.0.9) is successful

  • OneDev changed state to 'Released' 3 months ago
    Previous Value Current Value
    Closed
    Released
  • pim commented 3 months ago

    I can confirm that this fixes the issue. Thank you very much for the quick fix!

issue 1/1
Type
Bug
Priority
Normal
Assignee
Affected Versions
13.0.6
Labels
No labels
Issue Votes (0)
Watchers (3)
Reference
OD-2579
Please wait...
Connection lost or session expired, reload to recover
Page is in error, reload to recover