EDIT: I think I've got this figured out, although ...
# community-support
t
EDIT: I think I've got this figured out, although if anybody wants to confirm my understanding of how a Copy task finds outputs is correct it'd be appreciated. Is anybody able to point me to what changed between Gradle 7.x and Gradle 8.x around shared task outputs? I've been reading the release notes for 8.0 but haven't found anything related to it. I'm getting this error after trying to go from Gradle 7.6.4 to Gradle 8.0 and Spring 3.2.x to Spring 3.3.x:
Copy code
> Task :cyclonedxBuildBom FAILED

FAILURE: Build failed with an exception.

* What went wrong:
A problem was found with the configuration of task ':cyclonedxBuildBom' (type 'CycloneDxTask').
  - Gradle detected a problem with the following location: 'C:\Users\thomasgaskell\git\azure\config-manager-consumer\build\reports'.

    Reason: Task ':processResources' uses this output of task ':cyclonedxBuildBom' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed.

    Possible solutions:
      1. Declare task ':cyclonedxBuildBom' as an input of ':processResources'.
      2. Declare an explicit dependency on ':cyclonedxBuildBom' from ':processResources' using Task#dependsOn.
      3. Declare an explicit dependency on ':cyclonedxBuildBom' from ':processResources' using Task#mustRunAfter.

    Please refer to <https://docs.gradle.org/8.0/userguide/validation_problems.html#implicit_dependency> for more details about this problem.
The full context goes very deep. I've used the cyclonedx-gradle-plugin for a while but Spring 3.3.x recently added a feature to their own Gradle plugin to copy the BOM being produced by
cyclonedxBom
to
build/resources/main
using the
processingResources
task so it's packaged into your JARs/WARs. They wired those two tasks together but I've got another task,
cyclonedxBuildBom
, that produces a second BOM which
processResources
is somehow also seeing. When I look at the inputs for
processResources
however all it's got is
C:\Users\thomasgaskell\git\<my-project>\build\reports\application-bom.json
so I'm a little confused as to why it's also complaining about my
C:\Users\thomasgaskell\git\<my-project>\build\reports\build-bom.json
from
cyclonedxBuildBom
. If I go back to Gradle 7.6.4 it all works fine. I'm somewhat familiar with the whole "mixing inputs/outputs is bad" concept with Gradle but I'm not particularly intimate with it. I don't want to wire
cyclonedxBuildBom
and
processResources
together because they're not actually related. I'm assuming that
processResources
is complaining for a valid reason and the heart of the problem lies in the cyclonedx-gradle-plugin. It defines an
@OutputDirectory
for controlling where it should place the generated BOMs, so maybe that's not best practice? If anybody is able to help me out and put me on the right path I'd appreciate it. I've got some workarounds I can use but I'd like to fix this properly and raise a contribution to CycloneDX if it's to blame.
For reference, this is what I suspect the problem is: https://github.com/CycloneDX/cyclonedx-gradle-plugin/blob/d137d9bdddcd9ea7573fdc2b[…]b774ab10f/src/main/java/org/cyclonedx/gradle/CycloneDxTask.java
CycloneDxTask
defines the
/build/reports
directory as it's only output and that's not how it should be done?
processResources
must be looking at the outputs of all tasks to figure out where my BOM comes from but it could be either
cyclonedxBom
or
cyclonedxBuildBom
(or even both) because the output isn't specific enough. It therefore spits the dummy because one of them hasn't been wired to it? It sounds like I need to raise a change with CycloneDX to tweak how the outputs are defined so it's instead a single
@OutputFile
and not a whole directory? It should presumably instead resemble something like this: https://docs.gradle.org/current/userguide/writing_tasks.html#task_input_and_outputs
v
This error usually happens when tasks are having overlapping outputs, which always was a bad idea and resulted in maybe strange or at least inconsistent and flaky behavior, polluted cache entries and so on. The change in Gradle 8 is "just" that some of these situations are detected and complained about, with solution recommnedations that are most likely just symptom treatment and not fixing the actual problem. It usually is like this: • task A has
build/foo/bar/
as output directory • task B has
build/foo/
as output direcotry • task C has the outputs of A wired as inputs But as the
build/foo/bar/
is also an output of B as the whole
build/foo/
is, Gradle sees that C's inputs are using B's outputs without a dependency or ordering constraint and complains with the non-sense recommendation to add a dependency from C to B. The correct solution is, to make sure A and B do not have overlapping outputs. If for example B is a
Copy
task that copies a file to
layout.buildDirectory
, suddenly the whole build directory is an output of B. Instead you would use an "untyped" task, declare the input file as input file, the actual output file as output file and then use
copy { ... }
in the execution phase of the task to copy over the file.
So yeah, from a cursory look it seems to be a pretty bad default / idea to have the whole
build/reports
as output directory.
❤️ 1