1

I want to add an extra task to Gradle "build", specifically to copy a file to resources.

So I do this:

task copySettingsGradle(type: Copy) {
    from file("settings.gradle")
    into file("src/main/resources")
}
build.dependsOn copySettingsGradle

But if settings.gradle is not there it currently seems to fail silently: the build proceeds as normal.

I want to prevent the build from happening if this required task fails. For that, it seems to me that I need two things: a means of determining that from.file(...) couldn't find the file, and then a way of setting "failed" flag on the task... or something.

Trying to work this one out led me to AbstractCopyTask and then CopySourceSpec.from... but I'm none the wiser.

Of course I could use non-DSL Groovy to copy and perform checks of success. But it's the question of marking the required task as failed which puzzles me.

There's a question here, from 8 years ago, about "way to stop a Gradle build". In his answer, Peter Niederwieser says "there have been discussions to add [a way of stopping]".

Furthermore, on this page of the official Gradle documentation, I see that the following expression is used: "The task will be marked as failed" (if a timer runs out). "Marked as failed"... and that means???

I find it pretty amazing that I haven't been able to find any info on this! The concept of "dependency" involves being dependent on the existence or success of something else. Not only can I not find out whether such a mechanism (other than throwing a GradleException) has now been introduced into Gradle, I can't even find any talk about it. Baffled!

mike rodent
  • 14,126
  • 11
  • 103
  • 157

1 Answers1

1

You could use the ANT copy task to do that. Gradle allows to delegate calls to an underlying ANT runtime.

The ANT copy task provides an option called failonerror, which gets you the failure-if-file-not-found behavior.

It'd look something like this:

task copySettingsGradle {
    doLast {
        ant.copy(file: 'settings.gradle',
            todir: 'src/main/resources',
            overwrite: true,
            failonerror: true)
    }
}

For all options available see tha ANT docs: https://ant.apache.org/manual/Tasks/copy.html

Roland Kreuzer
  • 912
  • 4
  • 11
  • Thanks very much. In fact I've now modified the question slightly: the main question for me is how to mark a task as "failed". Your answer is great, and crucially gives a nice message: "Warning: Could not find file ...". Just wonder whether there's a more "pure Gradle" way to signal that a task has failed (and for that matter to check on success of the copy operation). NB I know next to nothing about Ant or Maven: I have only ever used Gradle as my build tool. – mike rodent Mar 22 '20 at 09:50
  • As far as I know making the build fail is always communicated via exception in Gradle. It doesn't necessary need to be of type GradleException (especially when coding your own Gradle plugins) basically any exception will do. But I'm not aware of any dedicated Gradle DSL to do this. I think your options are using plain Groovy to throw an exception `throw new GradleException('msg')` or again use the ANT DSL via `ant.fail("msg")` to halt the script manually – Roland Kreuzer Mar 22 '20 at 10:08
  • But the underlying problem in your example is not the `dependsOn` declaration. The `dependsOn` works as you would expect. If the dependent task fails, also the main task fails. The reason you don't get the behavior you want is located in the way the copy task in Gradle always assumes to work on file sets and wildcard conditions and therefore doesn't really bother if the one file you wanted to copy is not present. In other words: For Gradle the tasks does not fail, so your build does not fail – Roland Kreuzer Mar 22 '20 at 10:14
  • Yes, sure, I get that now. And failure, it appears, is signalled solely and exclusively through the throwing of an `Exception`. Except your Ant solution somehow uses another mechanism, which is (probably) not (yet) available in "pure Gradle". – mike rodent Mar 22 '20 at 10:23
  • 1
    The mechanism is basically the same. If you look at the source code of ant.copy it is also just `if (failonerror) { throw Exception() }` https://github.com/apache/ant/blob/master/src/main/org/apache/tools/ant/taskdefs/Copy.java The only difference is that ANT allows you to set that behavior as an option, which Gradle does currently not. – Roland Kreuzer Mar 22 '20 at 10:31