Jenkins:Cobertura 插件找不到覆盖率报告

Jenkins: Cobertura plugin cannot find coverage report

这是我的构建日志。我绝对感到困惑,并希望得到任何帮助。 我正在使用 cobertura 插件版本 1.16

+ ls
Dockerfile
Jenkinsfile
README.md
babel.config.js
coverage
dev-server.sh
jenkins-agent.yaml
jest.config.ts
package-lock.json
package.json
src
tsconfig.json
webpack.config.js
+ ls ./coverage
cobertura-coverage.xml
+ pwd
/home/jenkins/agent/workspace/api_PR-8
+ cat ./coverage/cobertura-coverage.xml
<?xml version="1.0" ?>
<!DOCTYPE coverage SYSTEM "http://cobertura.sourceforge.net/xml/coverage-04.dtd">
<coverage lines-valid="129" lines-covered="46" line-rate="0.3566" branches-valid="1" branches-covered="1" branch-rate="1" timestamp="1609204078913" complexity="0" version="0.1">
  <sources>
    <source>/app</source>
  </sources>
  <packages>
    ...
  </packages>
</coverage>
[Pipeline] cobertura
[Cobertura] Publishing Cobertura coverage report...

[Cobertura] No coverage results were found using the pattern './coverage/cobertura-coverage.xml' relative to '/home/jenkins/agent/workspace/api_PR-8'.  Did you enter a pattern relative to the correct directory?  Did you generate the XML report(s) for Cobertura?

我也试过使用模式'coverage/cobertura-coverage.xml',但我得到了同样的错误。

这是我Jenkinsfile的相关部分:

        stage('Test') {
            steps {
                sh '''
                    docker build . --target test
                    DOCKER_BUILDKIT=1 docker build . -o ./coverage --target coverage
                    ls
                    ls ./coverage
                    pwd
                    cat ./coverage/cobertura-coverage.xml
                '''
                cobertura(coberturaReportFile: './coverage/cobertura-coverage.xml')
            }
        }

更新 1

这很有趣...我尝试将 coberturaReportFile 的值更改为 coverage/*.xml,并且构建产生了以下错误:

[Pipeline] cobertura
[Cobertura] Publishing Cobertura coverage report...

FATAL: Unable to find coverage results
java.io.IOException: IO error scanning directory '/home/jenkins/agent/workspace/api_PR-8/coverage'
    at hudson.FilePath.glob(FilePath.java:1975)
    at hudson.FilePath.access00(FilePath.java:212)
    at hudson.FilePath$ListGlob.invoke(FilePath.java:1949)
    at hudson.FilePath$ListGlob.invoke(FilePath.java:1937)
    at hudson.FilePath.act(FilePath.java:1076)
    at hudson.FilePath.act(FilePath.java:1059)
    at hudson.FilePath.list(FilePath.java:1935)
    at hudson.FilePath.list(FilePath.java:1919)
    at hudson.FilePath.list(FilePath.java:1904)
    at hudson.plugins.cobertura.CoberturaPublisher$ParseReportCallable.invoke(CoberturaPublisher.java:896)
    at hudson.plugins.cobertura.CoberturaPublisher$ParseReportCallable.invoke(CoberturaPublisher.java:885)
    at hudson.FilePath$FileCallableWrapper.call(FilePath.java:3122)
    at hudson.remoting.UserRequest.perform(UserRequest.java:211)
    at hudson.remoting.UserRequest.perform(UserRequest.java:54)
    at hudson.remoting.Request.run(Request.java:369)
    at hudson.remoting.InterceptingExecutorService.call(InterceptingExecutorService.java:72)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at hudson.remoting.Engine.lambda$newThread[=12=](Engine.java:117)
    at java.lang.Thread.run(Thread.java:748)
    Suppressed: hudson.remoting.Channel$CallSiteStackTrace: Remote call to JNLP4-connect connection from 10.0.4.46/10.0.4.46:49386
        at hudson.remoting.Channel.attachCallSiteStackTrace(Channel.java:1800)
        at hudson.remoting.UserRequest$ExceptionResponse.retrieve(UserRequest.java:357)
        at hudson.remoting.Channel.call(Channel.java:1001)
        at hudson.FilePath.act(FilePath.java:1070)
        at hudson.FilePath.act(FilePath.java:1059)
        at hudson.plugins.cobertura.CoberturaPublisher.perform(CoberturaPublisher.java:548)
        at jenkins.tasks.SimpleBuildStep.perform(SimpleBuildStep.java:123)
        at org.jenkinsci.plugins.workflow.steps.CoreStep$Execution.run(CoreStep.java:99)
        at org.jenkinsci.plugins.workflow.steps.CoreStep$Execution.run(CoreStep.java:69)
        at org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution.lambda$start[=12=](SynchronousNonBlockingStepExecution.java:47)
        at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
        at java.base/java.lang.Thread.run(Thread.java:834)

所以可能在 Cobertura 插件代码中有一个 try-catch 阻止了这个 IO 错误。

我不清楚为什么会出现此 IO 错误或它的含义。每次构建都会重新创建工作区。

更新 2

我也尝试使用模式 **/cobertura-coverage.xml,但出现了与我最初 post 相同的错误。

[Cobertura] Publishing Cobertura coverage report...

[Cobertura] No coverage results were found using the pattern '**/cobertura-coverage.xml' relative to '/home/jenkins/agent/workspace/api_PR-8'.  Did you enter a pattern relative to the correct directory?  Did you generate the XML report(s) for Cobertura?

这是一个文件所有权问题。将 ls -l 放入我的管道脚本中显示 coverage/ 目录和 coverage/cobertura-coverage.xml 是在 root:root 所有权下生成的,而不是 1000:1000(又名 jenkins:jenkins) .这就是为什么 cobertura 跳过目录或未能从中读取的原因。

+ ls -alh
total 500K   
drwxr-xr-x    5 1000     1000        4.0K Dec 29 02:59 .
drwxr-xr-x    4 1000     1000        4.0K Dec 29 02:58 ..
-rw-r--r--    1 1000     1000          77 Dec 29 02:58 .dockerignore
drwxr-xr-x    8 1000     1000        4.0K Dec 29 02:59 .git
-rw-r--r--    1 1000     1000          47 Dec 29 02:58 .gitignore
-rw-r--r--    1 1000     1000         353 Dec 29 02:58 Dockerfile
-rw-r--r--    1 1000     1000        1.5K Dec 29 02:58 Jenkinsfile
-rw-r--r--    1 1000     1000         877 Dec 29 02:58 README.md
-rw-r--r--    1 1000     1000         145 Dec 29 02:58 babel.config.js
drwx------    2 root     root        4.0K Dec 29 02:59 coverage
-rwxr-xr-x    1 1000     1000         316 Dec 29 02:58 dev-server.sh
-rw-r--r--    1 1000     1000         289 Dec 29 02:58 jenkins-agent.yaml
-rw-r--r--    1 1000     1000        6.5K Dec 29 02:58 jest.config.ts
-rw-r--r--    1 1000     1000      420.5K Dec 29 02:58 package-lock.json
-rw-r--r--    1 1000     1000        1.0K Dec 29 02:58 package.json
drwxr-xr-x    9 1000     1000        4.0K Dec 29 02:58 src
-rw-r--r--    1 1000     1000        5.4K Dec 29 02:58 tsconfig.json
-rw-r--r--    1 1000     1000         472 Dec 29 02:58 webpack.config.js

为了修复它,我在 运行 cobertura 之前更改了目录的所有权。这是我的最终解决方案:

        stage('Test') {
            steps {
                sh '''
                    docker build . --target test
                    DOCKER_BUILDKIT=1 docker build . -o ./coverage --target coverage
                    chown -R 1000:1000 ./coverage
                '''
                cobertura(coberturaReportFile: 'coverage/cobertura-coverage.xml')
            }
        }