Generate a dependency build number using a task - gradle

I am attempting to generate a build number for an artifact using a task and then plug that into my dependency. My task looks something like this:
task getCurrentBuild() {
doFirst{
if(! file('/folder/dailyBuildNumber.txt').exists()) {
assert false,'Cannot find latest runtime build at /folder/dailyBuildNumber.txt'
}
else {
ext.set("myVersion", file('folder/dailyBuildNumber.txt').getText('UTF-8'))
}
}
}
while my dependencies look something like this:
latestArtifactCompile "com.example.1.0-${project.ext.get("myVersion")}"
I am getting errors that it cannot find the extra or get the property myVersion

doFirst closures are executed during execution phase, but the dependencies closure is executed before, during the configuration phase.
Why do you want to generate your dependency in a task? This seems to me like a regular and mandatory configuration required for each build, not depeding on the tasks you execute.

Related

How to define gradle task dependencies - inputs outputs OR dependsOn?

To get the incremental build support running correctly in gradle it is required to define the "inputs" and "outputs" in each (custom-) tasks.
That's a very neat way of gradle to check if a task can be skipped cause it is up-to-date or not. Sample:
task myTaskA {
def someOutputDir = file("$buildDir/gen")
// define task outputs (input not required here)
outputs.dir someOutputDir
doLast{
// generate something into the defined output directory
new File(someOutputDir, "dummy.txt").text = "Gradle sample"
}
}
task myTaskB {
// Input of this task is dependent on the output of myTaskA
inputs.files myTaskA
doLast{
// do something
}
}
Yes, that is pretty nice and additionally the good thing is, we do not need to declare a explicit dependency instruction (dependsOn) in task "myTaskB".
dependsOn myTaskA
This directive is not necessary cause we have a implicit dependency defined by the inputs-declaration.
I think it is a good style to provide always a inputs/outputs definition in custom tasks to support incremental builds.
BUT: This also means we can completely ignore the dependsOn.
SO: When should we prefer dependsOn over inputs/outputs?
Maybe if there is no inputs or outputs. Yes, but are there other use cases conceivable? I was always working with dependsOn, and this seams to me as obsolete now. What do you think?
Bye have a great day, Tony

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'
}

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.

How to return gradle build status

I have a multi-module gradle project setup.when I do gradle build in each module I need to check gradle build is success/failure
If it is success execute the task.
Any idea how we can achieve this.
Thanks in Advance!
Ideally you could just call the last task in the task graph and if any task in the graph fails before the last task, it just doesn't get called.
However if you want some code to be explicitly executed on any task failure in the build, then you could write something like following in your build file:
gradle.buildFinished { buildResult ->
if (buildResult.failure) {
println "Do something specific on failure!"
}
}

Resources