[rule based model] Select a rule-created tarTask as publication artifact

The maven-publish plugin has rules like

public void realizePublishingTasks(ModelMap<Task> tasks, PublishingExtension extension, ...)

Let’s say I create a task using the new model

    void createPublicationTasks(ModelMap<Task> tasks){

and that I want to use this task as a publication artifact

    void createPublication(PublishingExtension publishing, ModelMap<Task> tasks){
        PublicationContainer publications = publishing.getPublications()
        publications.create('myPub', MavenPublication) {MavenPublication pub ->

I’m screwed, because of a cycle in my rules
ModelMap<Task> is the subject of a rule where PublishingExtension is an input (so already realized)
and vice versa

Is there a way to achieve this behaviour right now, using the new model ?

I guess the correct way of declaring things would be

    void createPublicationTasks(ModelMap<Task> tasks){
    tasks.create('fooTask', **FooTaskType**)


    void createPublication(PublishingExtension publishing, ModelMap<**FooTaskType**> fooTask){

This would express that for executing the createPublication Rule, only the rules whose subject is the tasks of type FooTaskType are needed.
This implies changing all rules with ModelMap<Task> to target only the minimal subset of tasks these rules are affecting.

Is the rule based model going to this direction ? Does it make sense to even try to create a rule like the createPublication rule I’m trying above ?

I briefly tried to find some insights in the design-docs, and found in this one:

Story: DSL rule configures elements of ModelMap

Allow configuration of an element to take the configuration of a sibling as input.

Now that 2.10 is almost out, you can declare a dependency to a sibling, using the model DSL.
Is it possible using RuleSource classes (ie in a plug-in)?

Have you tried using @Path?

void createPublication(PublishingExtension publishing, @Path("tasks.foo") fooTask) {

Hi Mark,

Yes, By-Path binding works, but something bothers me with it: you have to manually enter the name of the model element you want to reach, so you have to know its name, and also probably duplicate its name at several places in your build script / plugin.

e.g. I always define constants for my task names
private static final String FOO_TASK_NAME = 'fooTask'
and I use this constant everywhere:
tasks.withType(BarTask).dependsOn FOO_TASK_NAME

I don’t think you can use it in a by-path binding (i.e. @Path(FOO_TASK_NAME) does not work()), so you have to use @Path('fooTask'), which I’m not fond of.
) you get the error 'Groovy:Expected ‘FOO_TASK_NAME’ to be an inline constant of type java.lang.String not a field expression in @org.gradle.model.Path

And what if I want to use several tasks of a given type as rule inputs for another task (possibly not knowing their names or how many they are)
will it be possible to declare something like the following ?
@Mutate void createBarTaskDependingOnAllFooTasks(ModelMap<Task> tasks, ModelMap<FooTask> fooTasks){ // this rule would need all [FooTask tasks] to be realized in the model, but not the whole [ModelMap<Task> tasks] element (since this rule will create a new task of type BarTask in the tasks element, tasks still needs to be mutable) tasks.create('aBarTask', BarTask){ dependsOn fooTasks } }

That is a reasonable concern. Matching a collection of inputs based on type I believe is a use case we want to support but don’t currently.

Hi François, did you get any further with this please? I’ve got a similar situation, where I have a dynamic number of Zip tasks (whose name starts with a known prefix), each of which creates an artifact. I want to add these artifacts to a single MavenPublication. I don’t know how to bind these Zip tasks as an input to a rule that will add them to the PublishingExtension, without triggering the circular dependency.

The problem I’m having is also listed here: Gradle: how to create maven publication from inside rule block