How to conditionally enable launchScript() inside bootJar? - spring

I'm trying to setup a conditional build process.
The following code works, but I need to specify the parameter on the command line, while It should be good to define two separate task to do that.
bootJar {
if (project.hasProperty("exec")) {
launchScript()
}
}
Is there a way to execute the bootJar or another custom task to enable/disable the launchScript()?
For example, how i can define the task bootJarExecutable that acts as the standard bootJar but with the launchScript ?

You can create another task that just configures your bootJar task when executed:
task bootJarExecutable {
finalizedBy bootJar
doFirst {
bootJar.launchScript()
}
}
However, this only works if you need either the one .jar or the other in one invocation, but not both. In this case, you would need to create another BootJar task and configure it on your own.

Related

Passing parameters to dependable task of custom task

There is task which can be executed with parameter like this:
./gradlew taskX -Pkey=value
And plugin with custom task which should execute taskX:
class CustomPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.tasks.register("custom", CustomTask::class.java)
.configure {
it.description = "Description"
it.group = "Group"
val taskX = project.getTasksByName("taskX", true).first()
it.dependsOn(taskX)
}
}
}
I would expect something like this for example:
it.dependsOn(taskX, "key=value")
How to pass parameters to dependsOn?
Simple answer: You can't. Task dependencies only express what needs to be done beforehand, not how it needs to be done.
Let me show you a simple example, why something like this is not possible in the Gradle task system:
First, we need to know that in Gradle, every task will be executed only once in a single invocation (often called build). Now imagine a task that needs to be run before two tasks that are unrelated to each other. A good real world example is the task compileJava from the Java plugin that both the test task and the jar task depend on. If dependsOn would support parameters, it could happen that two tasks depend on a single task with different parameters. What parameters should be used in this case?
As a solution, you may configure the other task directly in your plugin. If you want to pass the parameter only if your custom task is run, you may need to add another task that runs as a setup and applies the required configuration to the actual task:
task setup {
doFirst {
// apply configuration
}
}
taskX.mustRunAfter setup
task custom {
dependsOn setup
dependsOn taskX
}
This example uses Groovy, but it should be possible to translate it to Kotlin and use it in your plugin.
Edit regarding actual parameter
To be honest, I am not that familiar with the Android Gradle plugin, but if I get this documentation right, the project property android.testInstrumentationRunnerArguments.annotation is just an alternative to using the following code in the build script:
android {
defaultConfig {
testInstrumentationRunnerArgument 'annotation', '<some-value>'
}
}
You may try to define the following task and then run it using ./gradlew customTest
task customTest {
doFirst {
android.defaultConfig.testInstrumentationRunnerArgument 'annotation', '<some-value>'
}
finalizedBy 'connectedAndroidTest'
}

How to get the exact copy of original Run task in Gradle?

Does anybody know what the simplest way to register several run tasks that represent exact copy of original one with changed app’s arguments ? Or may be how to supply run task with an optional argument that would represent app’s arguments.
Basically, I want my build to contain some pre-defined options how to run an application and don’t want to declare new JavaExec that requires its manual configuring while I have already had ready-to-go run task supplied by default.
gradle run --args='--mode=middle' ---> gradle run || gradle runDefault || gradle run default
gradle run --args='--mode=greed' ---> gradle runGreed || gradle run greed
gradle run --args='--mode=lavish' ---> gradle runLavish || gradle run lavish
As for now I came up only with the option that suggests implementing my own JavaExec_Custom task class with supplied arguments property. And it seems to be too complex and boilerplating as for my goal.
You can create tasks that modify the configuration of the actual run task in a doFirst or doLast closure:
// Groovy-DSL
task runGreed {
doFirst {
run.args '--mode=greed'
}
finalizedBy run
}
// Kotlin-DSL
register("runGreed") {
doFirst {
run.get().args = listOf("--mode=greed")
}
finalizedBy(run)
}
You can use a property for the args
task run(type: JavaExec) {
args property('run.args').split(' ')
...
}
Usage
gradle run -Prun.args='foo bar baz'

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.

Depend on multiple gradle tasks in multi project build

Currently I have task which starts Google Cloud server, runs tests and stops server. It is defined at root project:
buildscript {...}
allprojects {...}
task startServer (dependsOn: "backend:appengineStart") {}
task testPaid (dependsOn: "app:connectedPaidDebugAndroidTest") {}
task stopServer (dependsOn: "backend:appengineStop") {}
task GCEtesting {
dependsOn = ["startServer",
"testPaid",
"stopServer"]
group = 'custom'
description 'Starts GCE server, runs tests and stops server.'
testPaid.mustRunAfter 'startServer'
stopServer.mustRunAfter 'testPaid'
}
I tried multiple ways to write it something like this, short with only one task. I didn't get how to refer to task from another project and call mustRunAfter on it. This doesn't work (I also tried to refer from Project.tasks.getByPath, root.tasks, etc):
task GCEtesting {
dependsOn = ["backend:appengineStart",
"app:connectedPaidDebugAndroidTest",
"backend:appengineStop"]
group = 'custom'
description 'Starts GCE server, runs tests and stops server.'
"app:connectedPaidDebugAndroidTest".mustRunAfter "backend:appengineStart"
"backend:appengineStop".mustRunAfter "app:connectedPaidDebugAndroidTest"
}
Is it possible? What is correct syntax to make this work?
It looks like your problem is that you're treating dependsOn as meaning "invoke this task". It actually means "ensure the result of the depended on task is available before the dependent task starts". That's why your first solution didn't work: statements like testPaid.mustRunAfter only affect the actions of the testPaid task itself, not its dependencies.
Anyway, you can get the behaviour you want using dependsOn and finalizedBy, but they have to be declared in the build file of the app subproject.
app/build.gradle:
task connectedPaidDebugAndroidTest {
//
//...
//
dependsOn 'backend:appengineStart' // Ensure appengineStart is run at some point before this task
finalizedBy 'backend:appendginStop' // Ensure appengineStop is run at some point after this task
}
Then, you can run your tests simply with gradle app:connectedPaidDebugAndroidTest. If you really want to define a task in the root project to run the tests, then that's easy too:
build.gradle:
task GCEtesting {
dependsOn = "app:connectedPaidDebugAndroidTest"
}

Gradle: Custom task with parameter set programmatically

I have the following scenario where I wish to disable JOOQ Schema generation unless explicitly called for:
gradle.taskGraph.beforeTask {
task ->
if (!rootProject.hasProperty("generate") && task.name.equals("generateSampleJooqSchemaSource")) {
task.enabled = false
}
}
Now I can always manually generate the schema when passing "generate" as a parameter as follows:
$ gradle build -Pgenerate
Whereas a normal
$ gradle build
would not regenerate all my schema classes.
However, I do not like this approach very much. You have to remember the parameter name, and also prepend it with -P which does not look as clean.
I would ideally like to be able to make a custom task as follows:
task generate {
tasks[build].executeWithParameter("generate")
}
So that it would also show up as an actual task.
How can I accomplish this?
You can create a task that dependsOn build task and disable jooq task from it. This requires the task declaration to be put after jooq task declaration.
task generate (dependsOn: build) {
tasks['generateSampleJooqSchemaSource'].enabled = false
}
to set project property from task
task generate (dependsOn: build) {
project.ext.generate = "true"
}

Resources