Closed freshcodemonger closed 5 years ago
I have not seen this one before. It will take some time to investigate.
Here is the stack if that helps
* Exception is:
org.gradle.api.UncheckedIOException: Unable to store input properties for task ':cloverReport'. Property 'additionalColumns' with value '[com.bmuschko.gradle.clover.CloverReportColumn@1d83a008, com.bmuschko.gradle.clover.CloverReportColumn@62d47126, com.bmuschko.gradle.clover.CloverReportColumn@2d13d16d, com.bmuschko.gradle.clover.CloverReportColumn@745fe8a1, com.bmuschko.gradle.clover.CloverReportColumn@450f255f]' cannot be serialized.
at org.gradle.api.internal.changedetection.state.CacheBackedTaskHistoryRepository.snapshotTaskInputProperties(CacheBackedTaskHistoryRepository.java:312)
at org.gradle.api.internal.changedetection.state.CacheBackedTaskHistoryRepository.createExecution(CacheBackedTaskHistoryRepository.java:146)
at org.gradle.api.internal.changedetection.state.CacheBackedTaskHistoryRepository.access$100(CacheBackedTaskHistoryRepository.java:61)
at org.gradle.api.internal.changedetection.state.CacheBackedTaskHistoryRepository$1.getCurrentExecution(CacheBackedTaskHistoryRepository.java:111)
at org.gradle.api.internal.changedetection.changes.DefaultTaskArtifactStateRepository$TaskArtifactStateImpl.getStates(DefaultTaskArtifactStateRepository.java:203)
at org.gradle.api.internal.changedetection.changes.DefaultTaskArtifactStateRepository$TaskArtifactStateImpl.isUpToDate(DefaultTaskArtifactStateRepository.java:89)
at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:50)
at org.gradle.api.internal.tasks.execution.ResolveTaskOutputCachingStateExecuter.execute(ResolveTaskOutputCachingStateExecuter.java:54)
at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:59)
at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:101)
at org.gradle.api.internal.tasks.execution.FinalizeInputFilePropertiesTaskExecuter.execute(FinalizeInputFilePropertiesTaskExecuter.java:44)
at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:88)
at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:62)
at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:54)
at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:34)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker$1.run(DefaultTaskGraphExecuter.java:248)
at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:241)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:230)
at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.processTask(DefaultTaskPlanExecutor.java:123)
at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.access$200(DefaultTaskPlanExecutor.java:79)
at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:104)
at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:98)
at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.execute(DefaultTaskExecutionPlan.java:623)
at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.executeWithTask(DefaultTaskExecutionPlan.java:578)
at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.run(DefaultTaskPlanExecutor.java:98)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
Caused by: org.gradle.api.UncheckedIOException: java.lang.ClassNotFoundException: com.bmuschko.gradle.clover.CloverReportColumn
at org.gradle.api.internal.changedetection.state.SerializedValueSnapshot.populateClass(SerializedValueSnapshot.java:106)
at org.gradle.api.internal.changedetection.state.SerializedValueSnapshot.hasSameSerializedValue(SerializedValueSnapshot.java:70)
at org.gradle.api.internal.changedetection.state.SerializedValueSnapshot.snapshot(SerializedValueSnapshot.java:51)
at org.gradle.api.internal.changedetection.state.ValueSnapshotter.snapshot(ValueSnapshotter.java:209)
at org.gradle.api.internal.changedetection.state.CacheBackedTaskHistoryRepository.snapshotTaskInputProperties(CacheBackedTaskHistoryRepository.java:309)
... 33 more
Caused by: java.lang.ClassNotFoundException: com.bmuschko.gradle.clover.CloverReportColumn
at org.gradle.internal.io.ClassLoaderObjectInputStream.resolveClass(ClassLoaderObjectInputStream.java:40)
at org.gradle.api.internal.changedetection.state.SerializedValueSnapshot.populateClass(SerializedValueSnapshot.java:104)
... 37 more
* Get more help at https://help.gradle.org
Deprecated Gradle features were used in this build, making it incompatible with Gradle 5.0.
See https://docs.gradle.org/4.5.1/userguide/command_line_interface.html#sec:command_line_warnings
This stacktrace helps pinpoint the particular details I need to fix it. I think the newer versions of Gradle try to snapshot the state of input properties deeper than before and cause this issue.
How do you add the Clover plugin in your projects? This seems to be a classpath issue more than a class serialization issue. The classes are properly serializable for the particular ones involved here.
I have them extracted to their own gradle include files but that requires calling out the full package names.
import com.bmuschko.gradle.clover.CloverPlugin import com.bmuschko.gradle.clover.GenerateCoverageReportTask
... dependencies { classpath 'com.bmuschko:gradle-clover-plugin:2.2.2' } ...
apply plugin: com.bmuschko.gradle.clover.CloverPlugin
dependencies {
clover 'org.openclover:clover:4.3.1'
}
That is probably why it fails. Are you adding the clover plugin in the top level build.gradle classpath or are you adding it in a separate included apply from: 'clover.gradle'
?
I know that classpath additions in included gradle scripts are cause for classpath issues of this kind.
I always make my classpath declarations only in the top build.gradle. I add configuration blocks in separate gradle scripts.
FYI, using buildscript classpath dependencies in included gradle modules will be deprecated and removed in a future version of Gradle as far as I know. It is known to be a common cause for classpath issues like the one you are describing here.
I didn't know that. I just hacked the gradle stuff together so open for improvements. I'll try to move the classpath dependency to build.gradle and see if that helps. Thank you !
I worked out the problem. Moving the classpath dependencies wasn't the solution.
Gradle creates a cache directory in your project called .gradle, gradle clean does not clean this.
If you change the columns in the report after running once and rebuild without removing the .gradle directory it will fail. I don't know exactly what output gradle has cached that causes this problem. If you generate a clover report and then change the columns do you not see the same problem? I don't think I have anything other than default gradle caching enabled.
That is how Gradle works. The task inputs for the previous successfully executed tasks are cached in the .gradle directory in the root of your project. When Gradle needs to check your task for up to date conditions it will attempt to deserialize the cached inputs. At that point the classpath is important and will need to have the plugin classes to allow the deserialization to succeed. You should not need to remove this directory except when plugins change in incompatible ways. This particular class in the plugin has not changed since many iterations ago. So, I doubt what you are having issues with it any of my problem. All I can see from the stacktrace is that the class was not found which signals me to suspect your nested script classpath configuration.
I agree with you about how gradle works but independent of if you have the classpath dependencies in the main gradle file - as I tried this - re-running after changing a column will not work unless you wipe that .gradle directory. I can't speak to if this is a bug but it seems odd that I'd have to delete the .gradle directory after changing the column configuration in order for the report to work again. Did you give that a try on your end and see if you can run, change the columns, and re-run a build successfully?
I have to try this myself and find out why it fails. The classnotfound error is a classpath error and there is not much I can do about that. I do not control the classpath Gradle uses for finding the plugin classes. As you see from the stacktrace you provided there is no code stack trace from this plugin in the entire stack so even if I wanted to try I would not have any way to change it.
So, I cannot promise you that I will be able to figure this out easily. It is not within this plugin execution path.
I can certainly reproduce this easily with a simple project. I suspect this never worked well and had such an issue since I added the feature but as it is an obscure kind of feature not many people use it. If I am correct the problem might be that Gradle cannot handle task inputs with custom task types, it prefers simple primitive types and collections of the same or any Gradle provided types. This might mean that I would have to come up with a metadata representation of the columns when I attach them as task inputs and convert them in the task instead. The behavior implemented right now takes the DSL implementation classes which are correctly serializable and uses them as task inputs in a collection.
Ok thanks for looking at it and all the work on the plugin! I can work around the issue by just deleting the .gradle directory if I change the column format. It just took a lot of testing to figure out that was the issue. Probably just add some documentation for now and put it at the back of the pile - at least there is a work around.
You will probably find that this fails if the code is changed and you rebuild the project incrementally. Any time the task cloverGenerateReport or cloverAggregateReports needs to execute the same kind of failure will happen if the task has executed successfully once before. It is standard incremental build issue with Gradle.
I think the solution is actually not hard to implement now that you brought this to my attention. Understanding why this was broken in the first place was the hard part. Now that I can make it happen easily it will not be long before it can be fixed the right way.
Sounds great ! Thank you !
Fixed in release 2.2.3
report { //... columns { //.. ncLineCount format: 'raw' //...
https://confluence.atlassian.com/clover/clover-report-71600095.html#clover-report-Columns