I am working on an Android project which uses a Gradle task with command line parameters. The task should be called from command line like that:
gradlew myTask -Parg1=aaa
Instead of calling it from command line I want to call this task from a Gradle file where I have all the arguments in a list. I need to create another task which runs myTask in a loop with all the arguments. By following this example I created the following code:
def data=['1', '2', '3']
project.task('runAll') {
data.collect { count ->
project.task('run_' + count, type: GradleBuild) {
startParameter.projectProperties = ['arg1': count]
tasks = ['myTask']
}.name
}.forEach { name ->
dependsOn name
}
}
When running individual tasks run_1, run_2, and run_3 everything works fine. If I run runAll, run_1 finishes successfully, but run_2 and run_3 crashes with the following error:
Included build C:\Projects\MyAwesomeApp\app has build path :app which is the same as included build C:\Projects\MyAwesomeApp\app
Can you help me solve this error?
Related
I have to create a gradle custom task in KOTLIN with different args as input.
So based on the args, the custom task should run other tasks.
e.g: I want to run:
./gradlew ci type=release distribution=true version=1.2.2
OR
./gradlew ci type=debug distribution=true version=1.2.2
This command should run tasks: clean, assembleRelease OR assembleDebug (based on type param) and also another task to distribute the artifact (already have this one) if the distribute param is true.
Question 1: Is there any way to create a custom task that runs other tasks based on external params?
Question 2: Is there any way to inject the args? (the above commands are not valid I think)
You can pass properties with -P command and here is an example.
task passP() {
if (customProp.equals("myProp")) {
println customProp
}
}
this will only print if you execute the following command Gradle -PcustomProp=myProp passP
Now that you can pass parameters, You can clean, assembleRelease OR assembleDebug according to the passed parameters.
There Are two ways you can achieve that.
First way :
Make a gradle custome task to execute another gradle command which do not look neat. but the code will look like this
task passP(type: Exec) {
commandLine("cmd", "/c")
if (customProp.equals("clean")) {
args "gradle clean"
}
}
This will execute a normal clean if you passed clean as a parameter.
The second way :
You would be using finializeBy keyword
You can call the 3 tasks according to the passed parameters.
The code will be something like this (not tested) :
task passP() {
if (customProp.equals("clean")) {
tasks.named("clean") { finalizedBy("passP") }
if (customProp.equals("debug")) {
tasks.named("assembleDebug ") { finalizedBy("passP") }
}
}
The first way work 100%, But am not sure about the second one, As am only used to use finalizedBy out side of the custom task scope.
I can refer to connectedCheck task (which came from android plugin) from my build script:
connectedCheck.finalizedBy AndroidShowTestResults
But trying to use connectedDebugAndroidTest (which came from android plugin too)
connectedDebugAndroidTest.finalizedBy AndroidShowTestResults
gives me
Error:(48, 0) Could not find property 'connectedDebugAndroidTest' on project ':app'.
And if I try
task connectedDebugAndroidTest << {print '123'}
it curses me with
Error:Cannot add task ':app:connectedDebugAndroidTest' as a task with that name already exists.
I don't undestand why I cannot refer to connectedDebugAndroidTest?
Available gradle tasks are shown below:
The android plugin defers the addition of several tasks especially those that have buildType or flavor names in them till a very late stage of the configuration phase. Which in turn means if you try to refer to these yet-to-be-added-tasks by name, you're likely to see a "does not exist" type error messages. If you want to add dependencies around deferred-created tasks, you should wait until configuration is complete:
gradle.projectsEvaluated {
connectedDebugAndroidTest.finalizedBy AndroidShowTestResults
}
Alternatively, you can add a listener to task-graph events, so you can do stuff as soon as a certain task is added to task-graph:
tasks.whenTaskAdded { task ->
if (task.name == 'connectedDebugAndroidTest') {
task.finalizedBy AndroidShowTestResults
}
}
Try
task connectedTest(dependsOn: ["connectedDebugAndroidTest"]){
}
connectedTest.finalizedBy "AndroidShowTestResults"
I think you should try to open test and rebuild.
UPDATE
I could get hold of the task at the runtime. But I am not able to finalize another task. The code I used for is:
gradle.taskGraph.whenReady {taskGraph ->
if (taskGraph.hasTask(spoonFreeDebugAndroidTest)) {
for(Task task : project.gradle.taskGraph.allTasks.iterator())
{
if(task.name.startsWith("spoonFreeDebugAndroidTest")) {
println "spoonFreeDebugAndroidTest task found"
ciIntegrationTests.mustRunAfter task.name
task.finalizedBy "ciIntegrationTests"
}
}
}
}
But, still the task "ciIntegrationTests" does not get executed when "spoonFreeDebugAndroidTest" fails. (The println line gets printed though.)
ORIGINAL QUESTION
I have a spoon task which is built at the runtime (when the task graph is generated) depending on my app flavours. e.g. A task "spoonFreeAndroidDebugTest" is generated at run time and is not accessible to me in build.gradle.
I want to add a dependancy on this task so that this task executes even if some other task fails. I tried these approaches:
spoon.finalizedBy "ciIntegrationTests"
which gives me this error
Could not find method finalizedBy() for arguments [ciIntegrationTests] on com.stanfy.spoon.gradle.SpoonExtension_Decorated#147456b6.
and
spoonFreeAndroidDebugTest.finalizedBy "ciIntegrationTests"
which gives me an error
Could not find property 'spoonDeltaAndroidDebugTest'
and
"spoonDeltaAndroidDebugTest".finalizedBy "ciIntegrationTests"
which results in
No signature of method: java.lang.String.finalizedBy() is applicable for argument types: (java.lang.String) values: [ciIntegrationTests]
Is there a way we can access a task in build.gradle which is generated at runtime.
Wrap your task string with tasks["taskName"]
tasks["spoonDeltaAndroidDebugTest"].finalizedBy tasks["ciIntegrationTests"]
Reference:
More About Tasks
I wanted to remove the project makefile and write some nice gradle tasks.
I need to execute the following tasks, in this order:
Clean
Increment version
Build
Upload
#1, #3 and #4 are tasks from android and plugin (bintray) while #2 is a custom task. Here is what I have so far:
task releaseMajor {
doLast {
clean.execute()
build.execute()
incrementVersion.execute()
bintrayUpload.execute()
}
}
The run order was not so great as I think clean was run after build. And binrayUpload was running without flavor (release). I've also tried to use dependsOn without success (order not working).
I couldn't find in Gradle doc how to do this properly. When execute in the right order, from CLI, everything works perfectly.
Use mustRunAfter, or finalizedBy for finer order control:
task releaseMajor (dependsOn: ['clean', 'build', 'incrementVersion', 'bintrayUpload'])
build.mustRunAfter clean
incrementVersion.mustRunAfter build
bintrayUpload.mustRunAfter incrementVersion
Tried this
task clean {
println 'clean task executing'
}
task incrementVersion (dependsOn:"clean"){
println 'incrementVersion task executing'
}
task building (dependsOn:"incrementVersion"){
println 'build task executing'
}
task bintrayUpload (dependsOn:"building") {
println 'bintrayUpload task executing'
}
The output was
clean task executing
incrementVersion task executing
build task executing
bintrayUpload task executing
and executed ./gradlew bintryUpload
I want to edit gradle task named installDebug. Where is the task (or script) located? Maybe this script is located in binary code and I'm not change that?
Really, I want run edit something option for adb.
Example: My task must contain:
Run adb like "adb connect 192.168.1.2:5555"
Run "debugInstall" gradles task, directly.
Do something, like - adb then open apk on my adb server..
What I should do:
Edit debugTask if possible?
Or edit build.grade and make own task script?
All the tasks are located in build.gradle script itself or in the plugin that is applied at the beginning of the script.
installDebug task is provided by as far as I remember android plugin. Every single task consists of actions that are executed sequentially. Here's the place to start.
You can extend a task adding action to the beginning of at the end of internal actions list.
So:
//this piece of code will run *adb connect* in the background
installDebug.doFirst {
def processBuilder = new ProcessBuilder(['adb', 'connnect', '192.168.1.2:5555'])
processBuilder.start()
}
installDebug.doLast {
//Do something, like - adb then open apk on my adb server..
}
Here, two actions were added to installDebug task. If you run gradle installDebug, first action will be run, then the task itself and finally the second action that is defined. That's all in general.
You can add a task to your build.gradle, and call it in command line.
This is what I have done :
task adbConnect(type: Exec) {
commandLine 'adb', 'connect', '192.168.200.92'
}
then I call gradle adbConnect connectedCheck, but you can use gradle adbConnect debugInstall