jk1 / Gradle-License-Report

A plugin for generating reports about the licenses of third party software using Gradle
Other
320 stars 97 forks source link

`./gradlew generateLicenseReport --stacktrace` fails with NPE #316

Open bric3 opened 2 months ago

bric3 commented 2 months ago

On multi-module projects, the generation task fails with an NPE

------------------------------------------------------------
Gradle 8.8
------------------------------------------------------------

Build time:   2024-05-31 21:46:56 UTC
Revision:     4bd1b3d3fc3f31db5a26eecb416a165b8cc36082

Kotlin:       1.9.22
Groovy:       3.0.21
Ant:          Apache Ant(TM) version 1.10.13 compiled on January 4 2023
JVM:          21.0.2 (Amazon.com Inc. 21.0.2+13-LTS)
OS:           Mac OS X 14.5 aarch64
Caused by: java.lang.NullPointerException: Cannot get property 'configurations' on null object
    at com.github.jk1.license.reader.ProjectReader.findConfiguredConfigurations(ProjectReader.groovy:96)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
    at com.github.jk1.license.reader.ProjectReader.findConfigurationsToScan(ProjectReader.groovy:71)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
    at com.github.jk1.license.task.ReportTask$_getClasspath_closure1.doCall$original(ReportTask.groovy:51)
    at com.github.jk1.license.task.ReportTask$_getClasspath_closure1.doCall(ReportTask.groovy)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
    at com.github.jk1.license.task.ReportTask.getClasspath(ReportTask.groovy:50)
    at com.github.jk1.license.task.ReportTask_Decorated.getClasspath(Unknown Source)

I don't understand yet the conditions why this is failing, but for sure the project is null

image

this seems to come from the ReportTasks image

But the extension is supposed to have the current project and sub-projects

https://github.com/jk1/Gradle-License-Report/blob/a420142e94307b3817023c6914ae6ed512ce3915/src/main/groovy/com/github/jk1/license/LicenseReportExtension.groovy#L48

The getClasspath method is called on the ReportTask that was configured on my root project.

image
Full stacktrace ```text org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':generateLicenseReport'. at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:38) at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77) at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55) at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52) at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:209) at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204) at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66) at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59) at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166) at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59) at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53) at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52) at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:42) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:331) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:318) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.lambda$execute$0(DefaultTaskExecutionGraph.java:314) at org.gradle.internal.operations.CurrentBuildOperationRef.with(CurrentBuildOperationRef.java:80) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:314) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:303) at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:463) at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:380) at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64) at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:47) Caused by: org.gradle.api.internal.tasks.properties.PropertyEvaluationException: Error while evaluating property 'classpath' of task ':generateLicenseReport'. at org.gradle.api.internal.tasks.properties.InputParameterUtils.prepareInputParameterValue(InputParameterUtils.java:32) at org.gradle.api.internal.tasks.execution.TaskExecution.lambda$visitRegularInputs$1(TaskExecution.java:317) at org.gradle.internal.execution.impl.DefaultInputFingerprinter$InputCollectingVisitor.visitInputProperty(DefaultInputFingerprinter.java:103) at org.gradle.api.internal.tasks.execution.TaskExecution.visitRegularInputs(TaskExecution.java:315) at org.gradle.internal.execution.impl.DefaultInputFingerprinter.fingerprintInputProperties(DefaultInputFingerprinter.java:63) at org.gradle.internal.execution.steps.AbstractCaptureStateBeforeExecutionStep.captureExecutionStateWithOutputs(AbstractCaptureStateBeforeExecutionStep.java:109) at org.gradle.internal.execution.steps.AbstractCaptureStateBeforeExecutionStep.lambda$captureExecutionState$0(AbstractCaptureStateBeforeExecutionStep.java:74) at org.gradle.internal.execution.steps.BuildOperationStep$1.call(BuildOperationStep.java:37) at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:209) at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204) at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66) at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59) at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166) at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59) at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53) at org.gradle.internal.execution.steps.BuildOperationStep.operation(BuildOperationStep.java:34) at org.gradle.internal.execution.steps.AbstractCaptureStateBeforeExecutionStep.captureExecutionState(AbstractCaptureStateBeforeExecutionStep.java:69) at org.gradle.internal.execution.steps.AbstractCaptureStateBeforeExecutionStep.execute(AbstractCaptureStateBeforeExecutionStep.java:62) at org.gradle.internal.execution.steps.AbstractCaptureStateBeforeExecutionStep.execute(AbstractCaptureStateBeforeExecutionStep.java:43) at org.gradle.internal.execution.steps.AbstractSkipEmptyWorkStep.executeWithNonEmptySources(AbstractSkipEmptyWorkStep.java:125) at org.gradle.internal.execution.steps.AbstractSkipEmptyWorkStep.execute(AbstractSkipEmptyWorkStep.java:56) at org.gradle.internal.execution.steps.AbstractSkipEmptyWorkStep.execute(AbstractSkipEmptyWorkStep.java:36) at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsStartedStep.execute(MarkSnapshottingInputsStartedStep.java:38) at org.gradle.internal.execution.steps.LoadPreviousExecutionStateStep.execute(LoadPreviousExecutionStateStep.java:36) at org.gradle.internal.execution.steps.LoadPreviousExecutionStateStep.execute(LoadPreviousExecutionStateStep.java:23) at org.gradle.internal.execution.steps.HandleStaleOutputsStep.execute(HandleStaleOutputsStep.java:75) at org.gradle.internal.execution.steps.HandleStaleOutputsStep.execute(HandleStaleOutputsStep.java:41) at org.gradle.internal.execution.steps.AssignMutableWorkspaceStep.lambda$execute$0(AssignMutableWorkspaceStep.java:35) at org.gradle.api.internal.tasks.execution.TaskExecution$4.withWorkspace(TaskExecution.java:289) at org.gradle.internal.execution.steps.AssignMutableWorkspaceStep.execute(AssignMutableWorkspaceStep.java:31) at org.gradle.internal.execution.steps.AssignMutableWorkspaceStep.execute(AssignMutableWorkspaceStep.java:22) at org.gradle.internal.execution.steps.ChoosePipelineStep.execute(ChoosePipelineStep.java:40) at org.gradle.internal.execution.steps.ChoosePipelineStep.execute(ChoosePipelineStep.java:23) at org.gradle.internal.execution.steps.ExecuteWorkBuildOperationFiringStep.lambda$execute$2(ExecuteWorkBuildOperationFiringStep.java:67) at org.gradle.internal.execution.steps.ExecuteWorkBuildOperationFiringStep.execute(ExecuteWorkBuildOperationFiringStep.java:67) at org.gradle.internal.execution.steps.ExecuteWorkBuildOperationFiringStep.execute(ExecuteWorkBuildOperationFiringStep.java:39) at org.gradle.internal.execution.steps.IdentityCacheStep.execute(IdentityCacheStep.java:46) at org.gradle.internal.execution.steps.IdentityCacheStep.execute(IdentityCacheStep.java:34) at org.gradle.internal.execution.steps.IdentifyStep.execute(IdentifyStep.java:48) at org.gradle.internal.execution.steps.IdentifyStep.execute(IdentifyStep.java:35) at org.gradle.internal.execution.impl.DefaultExecutionEngine$1.execute(DefaultExecutionEngine.java:61) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:127) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:116) at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46) at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:51) at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57) at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:74) at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36) at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77) at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55) at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52) at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:209) at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204) at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66) at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59) at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166) at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59) at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53) at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52) at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:42) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:331) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:318) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.lambda$execute$0(DefaultTaskExecutionGraph.java:314) at org.gradle.internal.operations.CurrentBuildOperationRef.with(CurrentBuildOperationRef.java:80) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:314) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:303) at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:463) at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:380) at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64) at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:47) Caused by: java.lang.NullPointerException: Cannot get property 'configurations' on null object at com.github.jk1.license.reader.ProjectReader.findConfiguredConfigurations(ProjectReader.groovy:96) at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) at com.github.jk1.license.reader.ProjectReader.findConfigurationsToScan(ProjectReader.groovy:71) at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) at com.github.jk1.license.task.ReportTask$_getClasspath_closure1.doCall$original(ReportTask.groovy:51) at com.github.jk1.license.task.ReportTask$_getClasspath_closure1.doCall(ReportTask.groovy) at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) at com.github.jk1.license.task.ReportTask.getClasspath(ReportTask.groovy:50) at com.github.jk1.license.task.ReportTask_Decorated.getClasspath(Unknown Source) at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) at org.gradle.internal.reflect.annotations.impl.DefaultPropertyAnnotationMetadata.getPropertyValue(DefaultPropertyAnnotationMetadata.java:97) at org.gradle.internal.properties.annotations.DefaultTypeMetadataStore$DefaultPropertyMetadata.getPropertyValue(DefaultTypeMetadataStore.java:284) at org.gradle.internal.properties.bean.DefaultPropertyWalker$1.lambda$visitLeaf$0(DefaultPropertyWalker.java:90) at org.gradle.internal.deprecation.DeprecationLogger.whileDisabled(DeprecationLogger.java:253) at org.gradle.internal.properties.bean.DefaultPropertyWalker$CachedPropertyValue.lambda$new$0(DefaultPropertyWalker.java:107) at com.google.common.base.Suppliers$NonSerializableMemoizingSupplier.get(Suppliers.java:181) at org.gradle.internal.properties.bean.DefaultPropertyWalker$CachedPropertyValue.call(DefaultPropertyWalker.java:149) at org.gradle.util.internal.GUtil.uncheckedCall(GUtil.java:437) at org.gradle.util.internal.DeferredUtil.unpackNestableDeferred(DeferredUtil.java:83) at org.gradle.util.internal.DeferredUtil.unpack(DeferredUtil.java:57) at org.gradle.util.internal.DeferredUtil.unpackOrNull(DeferredUtil.java:49) at org.gradle.api.internal.tasks.properties.InputParameterUtils.prepareInputParameterValue(InputParameterUtils.java:38) at org.gradle.api.internal.tasks.properties.InputParameterUtils.prepareInputParameterValue(InputParameterUtils.java:30) ... 69 more ```
bric3 commented 2 months ago

Even explicitly configuring the projects in the parent project doesn't help

extensions.configure<LicenseReportExtension> {
    projects = (subprojects - project(":modules")).toTypedArray()
    // projects = arrayOf(
    //     project(":modules:jvm"),
    //     project(":modules:go"),
    //     project(":modules:js"),
    //     project(":modules:php"),
    //     project(":modules:python"),
    //     project(":modules:ruby"),
    // )
}
Vampire commented 1 month ago

I guess you need to provide an MCVE, because for me it works fine on a multi-module project, so there has to be some edge-case you are hitting.

Vampire commented 2 weeks ago

Also in your last screenshot you are looking at the wrong field. You are looking at project of Task. You have to look at projects in config which for you is a 1-sized array containing only a null entry.

bric3 commented 1 week ago

Sorry I put aside this issue for a couple of months, I'll take a fresher look, there have been quite changes since then in the build file.

bric3 commented 1 week ago

OK I don't know if the message were back then (Gradle 8.8) — I would assume they were — so I feel pretty stupid, the build is failing with these messages now (Gradle 8.10) :

2 problems were found storing the configuration cache.
- Task `:generateLicenseReport` of type `com.github.jk1.license.task.ReportTask`: cannot deserialize object of type 'org.gradle.api.Project' as these are not supported with the configuration cache.
  See https://docs.gradle.org/8.10/userguide/configuration_cache.html#config_cache:requirements:disallowed_types
- Task `:generateLicenseReport` of type `com.github.jk1.license.task.ReportTask`: cannot serialize object of type 'org.gradle.api.internal.project.LifecycleAwareProject', a subtype of 'org.gradle.api.Project', as these are not supported with the configuration cache.
  See https://docs.gradle.org/8.10/userguide/configuration_cache.html#config_cache:requirements:disallowed_types

See the complete report at file:///Users/brice.dutheil/go/src/github.com/DataDog/datadog-intellij-plugin/build/reports/configuration-cache/9npi88kle0xljc5ipkr6p3pr3/5zyu60caq1c85gip0dv3e8wud/configuration-cache-report.html

And indeed I have the gradle configuration cache enabled by default in the gradle properties file:

org.gradle.configuration-cache=true

Turning it off made the task work

 ./gradlew generateLicenseReport -Dorg.gradle.configuration-cache=false
bric3 commented 1 week ago

@Vampire That said I'm not sure this task can be used from an existing build without disabling the configuration cache. E.g. something like this

tasks {
    register("assemble") {
        dependsOn(generateLicenseReport)
    }
}

extensions.configure<LicenseReportExtension> {
    projects = subprojects.toTypedArray()
}

Note I'm using

I've seen some work started since #255, #269.

Vampire commented 1 week ago

Yeah, CC will cause that to be null indeed, so I'd say this is a duplicate of CC incompatible issue. You can probably mark the task as not compatible for the moment to not use CC if the task is executed in the same run

bric3 commented 1 week ago

I don't think notCompatibleWithConfigurationCache("Unsupported") can work entirely (I coudn't) because the build is complaining about the project which is an input to the task especially when the warning mode is enabled in the properties.

org.gradle.configuration-cache.problems=warn
tasks.withType<ReportTask>().configureEach {
    notCompatibleWithConfigurationCache("Unsupported")
}

Seems related to https://github.com/gradle/gradle/issues/20673

Vampire commented 1 week ago

Ah right, the CC state is always serialized and then deserialized and used, even with that option set, it is just not persisted. So yeha, makes senes that it still fails.