Search code examples
gradleartifactorypublishivy

Is there a way to read command line parameters from within a gradle task?


I'm looking for a way to disable most of my sub project processing stack if I know it's already built and published. I'm managing a project with 400 sub projects, and I can shave tones of time by checking if I really need to build a sub project or not.

My attempt to do this end I have a block inside a task that calls

task disablePublish{
  if (the resultant product is already published.)
  {
    project.tasks.all {
      task -> task.enabled = false
    }
  }
}
...
publish.dependsOn += [disablePublish]

When I call publish, this seems to work great, if the rpm is already published, it doesn't publish, and builds it and publishes if it's not.

However it seems to break building if I don't call publish, if the rpm is published.

Skipping task 'mytask' as task onlyIf is false.

And no rpm gets built.

if I comment out the

project.tasks.all {
  task -> task.enabled = false
}

build works great.

So I'm not sure if others have a great solution to this design or ideas to try.

Thank you for your time and consideration.


Solution

  • I'm looking for a way to disable most of my sub project processing stack if I know it's already built [and published].

    Take a look at incremental builds. Gradle can determine whether a task needs to be run or not, if the inputs and outputs of the task are properly defined. This should work without a problem for tasks that build the project. Checking whether a project was already published (and thus a build is not required) may be difficult, as it would be hard to define a task output.

    if I really need to build a sub project or not

    This actually indicates that you should not solve your problem on the task level, but rather on the project level. Are there any dependencies between the projects or are they just part of the same multi-project build because it is handy to run a single command for all projects? Take a look at the difference between multi-project builds and composite builds.

    My attempt to do this end I have a block inside a task that calls

    This is not completely true. There is a task and there is a code block, but they are not connected in the way you think they are. Actually, your code would work in the same way if it would look like this:

    if (the resultant product is already published.)
    {
      project.tasks.all {
        task -> task.enabled = false
      }
    }
    
    task disablePublish {
    }
    

    Why is this the case? Well, whatever code is put inside the closure when a task is created does not define what happens when the task is executed. Instead, the code is run directly to configure the task. Only (internal) task actions, doFirst and doLast closures are run when the task gets executed (either because it was mentioned on the command line or because of dependsOn):

    println 'Before creating the task'
    
    task myTask {
        println 'Task is configured'
        doLast {
            println 'Task is executed'
        }
    }
    
    println 'After creating the task'
    

    Just put the code above in a build.gradle file and run gradle myTask from the same directory. The statement 'Task is executed' will be printed last. Now just call gradle without any task defined on the command line. Gradle will print all statements beside 'Task is executed', showing that each task is configured on every invocation of gradle.

    This shows that your 'task' logic gets applied every time Gradle is run. The task disablePublish however remains empty and does nothing at all.

    When I call publish, this seems to work great, if the rpm is already published, it doesn't publish, and builds it and publishes if it's not.

    Well, that depends on the condition of the if block, as this condition basically enables or disables your whole project. Of course, if the condition is false, the project will work completely normal, if the condition is true, no task will be executed at all.

    However it seems to break building if I don't call publish, if the rpm is published.

    If it is published (and your if condition confirms this), your whole project won't do anything, as every task is disabled. Since this logic gets applied regardless of any task, this has nothing to do with the publish task.