Gradle task is broken - cannot execute - gradle

import org.apache.tools.ant.filters.ReplaceTokens
task genScript(type:Copy){
copy{
from "../../scripts/script.txt"
into projectDir
filter ReplaceTokens, tokens: [baseName: jar.baseName, version: jar.version, prefix: 'x']
}
}
jar.doLast{
tasks.genScript.execute()
}
genScript executes fine if I just click on it and run. But when I do ..\gradlew clean jar, it gives me the following error:
Could not find method execute() for arguments [] on task ':myModule:genScript' of type org.gradle.api.tasks.Copy.
How to fix it?
I am using Gradle 6.0.1.

You can't programatically execute tasks from other tasks in newer versions of Gradle. Instead, you are supposed to declare task dependencies and Gradle will ensure they get executed in the correct order.
The quick fix is just to make jar depend on your task like this:
jar.dependsOn('genScript')
Alternatively, you could move your logic into the doLast block in the jar task.

Related

I can't find the declaration of a Gradle task

My build.gradle looks like this:
println 'First top level script element'
task first {
println 'First task: Configuration'
doLast {
println 'First task: Action'
}
}
task second(dependsOn: first) {
println 'Second task: Configuration'
doLast {
println 'Second task: Action'
}
}
println 'Second top level script element'
Following my tutorial, I got the following exercises:
Execute the help task and observe the output.
Execute the first task and observe the output.
Execute the second task and observe the output.
Now, I executed:
$ gradle help
And it works. But how can it be if the task help is not declared anywhere?
Am I looking at the correct file at all?
Gradle provides a set of tasks out of the box, including a help task. You may use gradle tasks --all to get a list of all tasks available to your project. This will be particularly useful once you apply plugins to your build script, because those plugins may create tasks implicitly. For a lot of use cases, is it not even necessary at all to manually create tasks. As an example, the following minimal build script provides all you need to build Java projects:
plugins {
id 'java'
}
You may even run gradle tasks in an empty folder (without an build.gradle file) and Gradle will still offer you its default tasks, as it will automatically create a project based on an empty build.gradle file.

skip a task in gradle, but only if the task exists

I have a complex multi sub-project gradle project with a little kotlin multiplatform inside and a fex custom gradle plugin.
My issue is , when I want to run the build by skipping some tasks(mostly test), not all the project have the same test task name : for some it's call jsTest, for other nodeJsTest, for other jvmTest.
So when I call gradle build -x jsTest -x nodeJsTest I have error because sometime some of the tasks to skip don't exist.
How can I skip the task, and ignore-it if it don't exist?
You can modify your Gradle file to do something like (Kotlin DSL):
tasks.named("build") {
dependsOn.removeIf { it.toString().contains("flakyTest") }
}
Otherwise you will need to aggregate your tasks to what you want specifically either by doing ./gradlew myTask anotherTask anotherOne andAnotherOne or create a task that dependsOn all the tasks you want.
Instead of making your test tasks to depend on build directly, you can create generic test task task testType in the middle- build triggers task testType and then it triggers jsTest or whatever relevant test task you create in that module.
Now you can safely run gradle build -x testType.
For example (in your .gradle file):
task jsTest { ... }
task testType { dependsOn jsTest }
build.finalizedBy(testType)
Do the same for the rest of your test tasks files, you can also create task testType globaly if you want the solution to be cleaner.

Create task for dependency lock in Gradle >5.0

I want to create a task which to execute
dependencies --update-locks ':'
I had a configuration:
dependencyLocking {
lockAllConfigurations()
}
I try with
task lockDependencies {
dependsOn = ['dependencies','--update-locks *:*']
}
But have:
What went wrong: Could not determine the dependencies of task ':lockDependencies'.
Task with path '--update-locks :' not found in root project
You cannot pass Gradle command line parameters as a task dependency, that's what your error above is about.
The state of writing locks, either with --write-locks or --update-locks, is something that happens really early in the build lifecycle.
You can somewhat control it from a task with the following:
* Create a placeholder task in your build script
* In the settings.gradle(.kts) query the requested tasks from the command line, and if it is there, mutate the start parameters:
if (startParameter.taskNames.contains('placeHolder')) {
startParameter.setWriteDependencyLocks(true)
}
Note that this is not an option if you are trying to lock the classpath of the build itself, which is one of the motivations behind using a command line flag.
Note also that this just allows replacing a flag, like --update-locks *:* with a task invocation like updateLocks but will not work if that task is wired as a dependency of other tasks, as it needs to be requested explicitly. And doing the start parameter mutation after the task graph is computed is too late in the lifecycle.
The best way to do this in my opinion is to add inside the build.gradle file the following code:
dependencyLocking {
lockAllConfigurations()
}
task commitLockDependencies {
'git add /gradle/dependency-locks '.execute()
}
init {
dependsOn('commitLockDependencies')
}
And then inside the settings.gradle the following line:
startParameter.setWriteDependencyLocks(true)
Working with gradle 7.1.

Gradle multi project, scope task

I have a multi project in the following way:
rootProject
Subproject1
Subproject2
task whatever << {
println "WHATEVER"
}
I want to be able to configure task 'whatever' once and execute it from any scope (root or subproject) and be executed only once!
This means:
If I run /gradle whatever, I should get: "WHATEVER"
If I run /subproject1/gradle whatever, I should get: "WHATEVER"
In summary, I don't what to execute the same task several tasks according to the number of projects.
I haven't been able to get such a simple result. Please let me know if you can offer any help! Thanks!
gradle whatever searches for whatever in the current subproject and below. Instead, use gradle :whatever and declare the task in the root project.

Creating a post build copy task with Gradle

I am struggling with the Gradle build lifecycle; specifically with the split between the configuration and execution phases. I have read a number of sections in the Gradle manual and have seen a number of ideas online, but have not found a solution to the following problem:
I want to run a specific task to produce an artifact at the end of my java-library-distribution build that is a flattened version of the runtime configuration jars. That is, I only want to produce the artifact when I run the specific task to create the artifact.
I have created the following task:
task packageSamplerTask(type: Tar, dependsOn: distTar) {
description "Packages the build jars including dependencies as a flattened tar file. Artifact: ${distsDir}/${archivesBaseName}-${version}.tar"
from tarTree("${distsDir}/${archivesBaseName}-${version}.tar").files
classifier = 'dist'
into "${distsDir}/${archivesBaseName}-dist-${version}.tar"
}
Although this task does produce the required artifact, the task runs during gradle's configuration phase. This behavior has the following consequences:
Irrespective of which task I run from the command line, this packageSamplerTask task is always run, often unnecessarily; and
If I clean the project, then the build fails on the next run because $distsDir doesn't exist during the configuration phase (obviously).
It appears that if I extend the Copy task in this manner I'm always going to get this kind of premature behavior.
Is there a way to use the << closure / doLast declarations to get what I want? Or is there something else I'm missing / should be doing?
Update
After further work I have clarified my requirements, and resolved my question as follows (specifically):
"I want to package my code and my code's dependencies as a flat archive of jars that can be deployed as a jMeter plugin. The package can then be installed by unpacking into the jMeter lib/ext directory, as is. The package, therefore, must not include the jMeter jars (and their dependencies) which are used for building and testing"
Because Gradle doesn't appear to support the Maven-like provided dependency management, I created a new configuration for my package which excludes the jMeter jars.
configurations {
jmpackage {
extendsFrom runtime
exclude group: 'org.apache.jmeter', name: 'ApacheJMeter_core', version: '2.11'
exclude group: 'org.apache.jmeter', name: 'ApacheJMeter_java', version: '2.11'
}
}
And then created the following task (using the closure recommendation from Peter Niederwieser):
task packageSamplerTask(type: Tar, dependsOn: assemble) {
from { libsDir }
from { configurations.jmpackage.getAsFileTree() }
classifier = 'dist'
}
This solution appears to work, and it allows me to use just theGradle java plugin, too.
The task declaration is fine, but the flattening needs to be deferred too:
...
from { tarTree("${distsDir}/${archivesBaseName}-${version}.tar").files }
Also, the Tar file should be referred to in a more abstract way. For example:
from { tarTree(distTar.archivePath).files }
First your task isn't executed in the configuration phase but like EVERY task it is configured in that phase. And your closure is just a configuration of your task (a Configuration closure, not an Action closure). That is why your code is "executed" in the configuration phase".
If you want your code to be executed in the execution phase have to write it in a doLastclosure or doFirst. But in your case it is better to keep it in a configuration closure, because you are configuring your task.
To make sure your build doesn't fail because of the missing folder, you can create it with distsDir.mkdirs().

Resources