Is it possible to check for no SNAPSHOT dependencies only when running a specific task?


(Stig Kleppe-Jørgensen) #1

I’m writing a release plugin that should fail if any of the project’s dependencies is a SNAPSHOT. This is what I have now:

project.allprojects.each { currentProject ->
    currentProject.configurations.all {
        incoming.afterResolve { resolvableDependencies ->
            if (project.gradle.taskGraph.hasTask(TASK_RELEASE_PREPARE)) {
                ensureNoSnapshotDependencies(resolvableDependencies)
            }
        }
    }
}

This must run only when a specific task is used, so that is why the task graph check is used.

The problem is that in some setups the task graph is not completely populated when the closure is called. Anybody know of a way to get around this problem?


(Luke Daley) #2

You have to register a callback for when the task graph is ready.

http://gradle.org/docs/current/javadoc/org/gradle/api/execution/TaskExecutionGraph.html#whenReady(groovy.lang.Closure)


(Stig Kleppe-Jørgensen) #3

Thanks, but how do I get to the resolved dependencies from that callback? Or can I stash them away in the incoming.afterResolve callback somehow and use them from the task graph ready callback?


(Peter Niederwieser) #4

Shouldn’t this check happen while the releasePrepare task runs?


(Luke Daley) #5

Looking again, the fact that when the configuration is resolved before the task graph is ready is usually indicative of a problem in your build script.

If a configuration is resolved before the task graph is ready, your build is going to be slow for every task because you are resolving dependencies during the evaluation phase.

Do you know why the configuration is being resolved during evaluation?


(Stig Kleppe-Jørgensen) #6

We have a classes.doLast {} closure in a configure closure that resolves the default configuration. I guess that would do it?


(Stig Kleppe-Jørgensen) #7

Duh…of course. That was actually where I had that check in the first version, but used resolvedConfiguration instead of simply configuration. So now I’m full circle back where I was a month ago, almost :slight_smile:

Thanks!


(Luke Daley) #8

No, doLast will be firing after the task graph is ready.


(Stig Kleppe-Jørgensen) #9

Ok…I just searched for resolve in the build files and found only this one. Must look into what the plugins we are using are doing then, I guess.


(Luke Daley) #10

One way to do this is to throw an exception from the afterResolve hook and inspect the stack.


(Stig Kleppe-Jørgensen) #11

Nice one…thanks!


(Stig Kleppe-Jørgensen) #12

Not sure I understand this stacktrace completely: https://gist.github.com/1620267

I see another plugin of mine in there (net.nisgits…), but it does not seem the resolving starts on that, rather when building the task graph…


(Peter Niederwieser) #13

Resolving starts when the files of a configuration are first requested. When this happens depends on the particular build - as a plugin author you shouldn’t make any assumptions here. From my understanding of the problem that you are trying to solve, the releasePrepare task should resolve all configurations and then search them for snapshot dependencies. In this case you don’t need to check the task graph.


(Stig Kleppe-Jørgensen) #14

Yes, I have put the snapshot check into the releasePrepare task, but without resolving configurations, only using

project.allProjects.each { currentProject ->
  currentProject.configurations.each { configuration ->
    configuration.allDependencies.each { // snapshot check }
  }
}

as I got the impression that this was the better solution. For my usecase I think it is better to just look at the nearest dependencies anyway and not looking at transitive ones. The reasoning is that it might exist 3rd party libraries having a release that depends on a snapshot build of another library. In that case a user of my plugin would have a bit of a problem :slight_smile:

NB! This plugin is only applied to the root module in a multi-module project.

But these last comments where really only for finding out where my build is resolving configurations too early, as Luke mentioned above :slight_smile: