jenkins - Jenkins:Cobertura 插件找不到覆盖率报告
问题描述
这是我的构建日志。我绝对感到困惑,并会感谢任何帮助。我正在使用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
to的值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.access$3400(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$2.run(Request.java:369)
at hudson.remoting.InterceptingExecutorService$1.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$1.lambda$newThread$0(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$0(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
我也尝试使用 pattern **/cobertura-coverage.xml
,但得到了与我最初的帖子相同的错误。
[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
(AKA 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')
}
}
推荐阅读
- jenkins - 更改变量会删除 Jenkins groovy-script 中的其他变量
- pandas - Pandas Dataframe:如何获取单元格而不是值
- android - 如何在 TextInput 中禁用 keyboardAvoidingView 行为
- java - 如何避免 IntelliJ 中可嵌入类的验证错误“无法解析列‘xy’”?
- apify - 从 sitemap.xml 抓取每个链接
- javascript - 在为 React 模块编写单元测试时如何模拟“this”?
- java - 如何使我的 sql 数据可用于我的 Junit 中的所有新事务?
- database - 使用 kubectl 在 DB 中检索与特定 ID 对应的行
- python - 并行异步训练多个神经网络
- python - 在 python 3.7 中替换字符串中的值的问题