Ivy publish task not created when a dependency of a dynamically created task


I am attempting to upgrade some internal plugins from 2.2.1 to 2.8 and am running into a problem. In the past I had a plugin that created an alias task named “publish-local” that depended on publishIvyPublicationToLocalRepsitory. This was done by dynamically adding the ivy publish task as a dependency on the publish-local task by listening to when tasks were added to the project.

Task publishLocalTask ...;

project.tasks.whenTaskAdded { Task task ->
if (‘publishIvyPublicationToLocalRepository’.equals(task.name)) {
task.doLast(new PrintIvyPublishingInformationAction())
} else if (‘build’.equals(task.name)) {
// always publish locally when doing a build
logger.info(“Appending ‘publish-local’ task to ‘build’”);

publish-local depends on "publishIvyPublicationToLocalRepsitory"
build depends on “publish-local”

Running “publish-local” or “build” works in gradle 2.2.1 but not in 2.8. It does not end up having the “publishIvyPublicationToLocalRepsitory” task run. It appears that the publishIvyPublicationToLocalRepsitory task creation code is exectued (IvyPublishPlugin) but somewhere along the line does not make it to the final list of tasks created causing the whenTaskAdded not to pick it up. I have this at the beginning of my build.properties to verify:

project.tasks.whenTaskAdded { task ->
logger.error("TASK ADDED2: " + task + " @ " + task.getClass());

I suspect that this has something to do with the fact that the ivy tasks are created from rules. Any ideas how I can get this to work as I expect?

Update: The IvyPublishPlugin.Rules createTask is indeed run and creates the “publishIvyPublicationToLocalRepository” task and adds it to ModelMap. This task never shows up in the whenTaskAdded hook and does not get added to the execution graph.

Indeed, this is due to the task being “created” by rules. In reality, the task is simply registered and not actually created until it’s required. So in this case whenTaskAdded() will never be called for the publishing task unless you explicitly execute it or another task depends on it. You can accomplish what you want in a much simpler fashion by just using strings to wire task dependencies.

task "publish-local" {
    dependsOn "publishIvyPublicationToLocalRepository"

Referencing the task in this way by name causes the task to be “realized” and therefore added to the task graph and task container.


Thanks for the reply. I used that for a while but it doesn’t work in some situations. I have an additional restriction that my tasks only be dynamically generated if publishing is set up. The only way to know that is to inspect the publishing plugin which isn’t set up until after my plugin is configured.

In the past I would inspect everything with project.tasks.whenTaskAdded but as mentioned above by the time that code is run it is too late to add the ivy tasks created by rules as dependencies. I have come up with a hacky way to get what I need done though.

First I obtain the PublishingExtension via reflection (this is done because obtaining it through the API prematurely causes it to become immutable). From there I added a action to listen to publishingExtension?.getPublications().whenObjectAdded(…). In there I can inspect what was added to determine if my task needs to be created.

With that I can have the following happen regardless of the order plugins are applied:

  • add task publish-local that does work and depends on publishIvyPublicationToLocalRepository. If no ivy publications are setup then publish-local is not added. If ivy publications are set up then publish-local will be created and call the dependency publishIvyPublicationToLocalRepository.
  • make other dynamically created tasks depend on publish-local if it exists