我有一个 Jenkins 项目来对我的 NodeJS 项目进行 SonarQube 分析。我添加了istanbul
作为对我的项目的依赖package.json
。在 Jenkins 构建配置中,首先我运行一个 shell 脚本:
cd ./project-name
npm install
node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha path-to-unit-tests
node_modules/.bin/istanbul report cobertura
cd ..
这将安装依赖项、运行测试并生成代码覆盖率报告并生成 cobertura-coverage.xml 文件。
shell脚本之后,我运行Invoke Standalone SonarQube Analysis
具有以下代码覆盖率属性:
sonar.java.coveragePlugin=cobertura
sonar.dynamicAnalysis=reuseReports
sonar.cobertura.reportPath=./project-name/coverage/cobertura-coverage.xml
Jenkins 作业通过 SonarQube 仪表板成功运行,该仪表板描述了项目的各种内容,例如代码行、技术债务、问题等。但单元测试的代码覆盖率不会显示在 SonarQube 仪表板上。我确保仪表板具有单元测试小部件。
Version of SonarQube server: 5.2
Version of JavaScript plguin used on SonarQube: 2.9
Version of Cobertura plugin used on SonarQube: 1.6.3
Version of Cobertura plugin used on Jenkins: 1.9.7
Version of NodeJS plugin used on Jenkins: 0.2.1
我验证工作区确实有cobertura-coverage.xml
文件。还检查了构建控制台日志,没有发现错误。我之前也尝试过使用 LCOV 格式推送代码覆盖率:
sonar.dynamicAnalysis=reuseReports
sonar.javascript.lcov.reportPath=./project-name/coverage/lcov.info
即使覆盖率报告确实在 Jenkins 工作区中生成,该报告也不会发布到 SonarQube。我查看了工作区内容并进行了验证。控制台日志显示正在生成的覆盖率报告。也尝试过
sonar.dynamicAnalysis=reuseReports
sonar.javascript.lcov.reportPath=project-name/coverage/lcov.info
and
sonar.dynamicAnalysis=reuseReports
sonar.cobertura.reportPath=project-name/coverage/cobertura-coverage.xml
无济于事。我还分别重新启动了 Jenkins 和 SonarQube 服务器 2 次。在 StackOverflow 和其他地方查看了许多类似的问题,但没有找到任何有效的方法。
如果我添加构建后操作Publish Cobetura Coverage Report
并指定 cobetura-coverage.xml 文件的路径Cobertura xml report pattern
领域,代码覆盖率报告确实发布在 Jenkins 中。
查看 SonarQube 中的后台任务日志,发现异常。
java.lang.IllegalStateException: Cannot persist sources of project-key:project-name/node_modules/jscs/jscs-browser.js
at org.sonar.server.computation.step.PersistFileSourcesStep$FileSourceVisitor.visitFile(PersistFileSourcesStep.java:132) ~[sonar-server-5.2.jar:na]
at org.sonar.server.computation.component.DepthTraversalTypeAwareCrawler.visitNode(DepthTraversalTypeAwareCrawler.java:72) ~[sonar-server-5.2.jar:na]
at org.sonar.server.computation.component.DepthTraversalTypeAwareCrawler.visit(DepthTraversalTypeAwareCrawler.java:44) ~[sonar-server-5.2.jar:na]
at org.sonar.server.computation.component.DepthTraversalTypeAwareCrawler.visitChildren(DepthTraversalTypeAwareCrawler.java:91) ~[sonar-server-5.2.jar:na]
at org.sonar.server.computation.component.DepthTraversalTypeAwareCrawler.visit(DepthTraversalTypeAwareCrawler.java:47) ~[sonar-server-5.2.jar:na]
at org.sonar.server.computation.component.DepthTraversalTypeAwareCrawler.visitChildren(DepthTraversalTypeAwareCrawler.java:91) ~[sonar-server-5.2.jar:na]
at org.sonar.server.computation.component.DepthTraversalTypeAwareCrawler.visit(DepthTraversalTypeAwareCrawler.java:47) ~[sonar-server-5.2.jar:na]
at org.sonar.server.computation.step.PersistFileSourcesStep.execute(PersistFileSourcesStep.java:89) ~[sonar-server-5.2.jar:na]
at org.sonar.server.computation.step.ComputationStepExecutor.execute(ComputationStepExecutor.java:39) ~[sonar-server-5.2.jar:na]
at org.sonar.server.computation.taskprocessor.report.ReportTaskProcessor.process(ReportTaskProcessor.java:53) ~[sonar-server-5.2.jar:na]
at org.sonar.server.computation.taskprocessor.CeWorkerRunnableImpl.executeTask(CeWorkerRunnableImpl.java:78) [sonar-server-5.2.jar:na]
at org.sonar.server.computation.taskprocessor.CeWorkerRunnableImpl.run(CeWorkerRunnableImpl.java:55) [sonar-server-5.2.jar:na]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_45-internal]
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) [na:1.8.0_45-internal]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_45-internal]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) [na:1.8.0_45-internal]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_45-internal]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_45-internal]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_45-internal]
Caused by: org.apache.ibatis.exceptions.PersistenceException:
### Error updating database. Cause: com.mysql.jdbc.PacketTooBigException: Packet for query is too large (7989143 > 4194304). You can change this value on the server by setting the max_allowed_packet' variable.
### The error may involve org.sonar.db.source.FileSourceMapper.insert-Inline
### The error occurred while setting parameters
### SQL: INSERT INTO file_sources (project_uuid, file_uuid, created_at, updated_at, binary_data, line_hashes, data_hash, src_hash, data_type, revision) VALUES (?, ?, ?, ?, ?, ?, ?, ?,?, ?)
### Cause: com.mysql.jdbc.PacketTooBigException: Packet for query is too large (7989143 > 4194304). You can change this value on the server by setting the max_allowed_packet' variable.
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:26) ~[mybatis-3.2.7.jar:3.2.7]
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:154) ~[mybatis-3.2.7.jar:3.2.7]
at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:141) ~[mybatis-3.2.7.jar:3.2.7]
at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:51) ~[mybatis-3.2.7.jar:3.2.7]
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:52) ~[mybatis-3.2.7.jar:3.2.7]
at com.sun.proxy.$Proxy84.insert(Unknown Source) ~[na:na]
at org.sonar.db.source.FileSourceDao.insert(FileSourceDao.java:117) ~[sonar-db-5.2.jar:na]
at org.sonar.server.computation.step.PersistFileSourcesStep$FileSourceVisitor.persistSource(PersistFileSourcesStep.java:160) ~[sonar-server-5.2.jar:na]
at org.sonar.server.computation.step.PersistFileSourcesStep$FileSourceVisitor.visitFile(PersistFileSourcesStep.java:130) ~[sonar-server-5.2.jar:na]
... 18 common frames omitted
Caused by: com.mysql.jdbc.PacketTooBigException: Packet for query is too large (7989143 > 4194304). You can change this value on the server by setting the max_allowed_packet' variable.
at com.mysql.jdbc.MysqlIO.send(MysqlIO.java:3540) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2417) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2582) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2535) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1911) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:1203) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at org.apache.commons.dbcp.DelegatingPreparedStatement.execute(DelegatingPreparedStatement.java:172) ~[commons-dbcp-1.4.jar:1.4]
at org.apache.commons.dbcp.DelegatingPreparedStatement.execute(DelegatingPreparedStatement.java:172) ~[commons-dbcp-1.4.jar:1.4]
at org.apache.ibatis.executor.statement.PreparedStatementHandler.update(PreparedStatementHandler.java:44) ~[mybatis-3.2.7.jar:3.2.7]
at org.apache.ibatis.executor.statement.RoutingStatementHandler.update(RoutingStatementHandler.java:69) ~[mybatis-3.2.7.jar:3.2.7]
at org.apache.ibatis.executor.ReuseExecutor.doUpdate(ReuseExecutor.java:50) ~[mybatis-3.2.7.jar:3.2.7]
at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:105) ~[mybatis-3.2.7.jar:3.2.7]
at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:71) ~[mybatis-3.2.7.jar:3.2.7]
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:152) ~[mybatis-3.2.7.jar:3.2.7]
... 25 common frames omitted
所以现在我已经将 shell 脚本代码覆盖率生成行更新为
node_modules/.bin/istanbul cover -x node_modules ./node_modules/.bin/_mocha path-to-unit-tests
仍然遇到异常。基于max_allowed_packet,我没有MySQL,我需要提高MAX_ALLOWED_PACKET
在数据库设置中。刚刚完成此操作并重新触发 Jenkins 作业以进行 SonarQube 分析。异常消失了。 SonarQube 中的后台任务成功。但我仍然没有在仪表板中看到单元测试代码覆盖率。没有其他例外。当我单击“配置小部件”按钮时,单元测试小部件上有“无数据”标签。当我返回仪表板时,单元测试小部件消失了。
知道我缺少什么吗?