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

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?

1 Like

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)

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?

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

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?

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

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!

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

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.

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

Nice one…thanks!

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…

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.

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: