Resolving non-Ivy artifacts via Ivy (in the context of Node.js)

We are using the gradle-node-plugin version 0.5 and we are experiencing intermittent connectivity issues to nodejs.org. While investigating these, some dependency resolution questions came up.

The plugin declares a repository pointing to http://nodejs.org/dist by default, and a dependency on node.

In our build script, we set the node version to 0.12.0:

node {
    version = '0.12.0'
    download = true
    workDir = file("${project.buildDir}/nodejs")
}

The plugin is declaring an Ivy respository, even though Node is not published with ivy.xml (as far as I can see).

And here are the log messages of a failed attempt to connect to nodejs.org:

04:37:19.175 [DEBUG] [org.gradle.api.internal.artifacts.ivyservice.ivyresolve.CachingModuleComponentRepository] Cached meta-data for module must be refreshed: will perform fresh resolve of 'org.nodejs:node:0.12.0' in 'ivy'
04:37:19.176 [DEBUG] [org.gradle.api.internal.artifacts.repositories.resolver.DefaultExternalResourceArtifactResolver] Loading http://nodejs.org/dist/v0.12.0/ivy.xml
04:37:19.176 [DEBUG] [org.gradle.internal.resource.transfer.DefaultCacheAwareExternalResourceAccessor] Constructing external resource: http://nodejs.org/dist/v0.12.0/ivy.xml
04:37:19.178 [DEBUG] [org.gradle.internal.resource.transport.http.HttpResourceAccessor] Constructing external resource: http://nodejs.org/dist/v0.12.0/ivy.xml
04:37:19.178 [DEBUG] [org.gradle.internal.resource.transport.http.HttpClientHelper] Performing HTTP GET: http://nodejs.org/dist/v0.12.0/ivy.xml
04:37:19.187 [DEBUG] [org.apache.http.impl.conn.PoolingClientConnectionManager] Connection request: [route: {}->http://nodejs.org][total kept alive: 0; route allocated: 0 of 5; total allocated: 0 of 10]
04:37:19.188 [DEBUG] [org.apache.http.impl.conn.PoolingClientConnectionManager] Connection leased: [id: 8][route: {}->http://nodejs.org][total kept alive: 0; route allocated: 1 of 5; total allocated: 1 of 10]
04:37:19.216 [DEBUG] [org.apache.http.impl.conn.DefaultClientConnectionOperator] Connecting to nodejs.org:80
04:37:40.218 [DEBUG] [org.apache.http.impl.conn.DefaultClientConnection] Connection org.apache.http.impl.conn.DefaultClientConnection@b1b856f closed
04:37:40.219 [DEBUG] [org.apache.http.impl.conn.DefaultClientConnection] Connection org.apache.http.impl.conn.DefaultClientConnection@b1b856f shut down
04:37:40.219 [DEBUG] [org.apache.http.impl.conn.DefaultClientConnection] Connection org.apache.http.impl.conn.DefaultClientConnection@b1b856f closed
04:37:40.219 [DEBUG] [org.apache.http.impl.conn.PoolingClientConnectionManager] Connection released: [id: 8][route: {}->http://nodejs.org][total kept alive: 0; route allocated: 0 of 5; total allocated: 0 of 10]

My questions are

  1. Could you explain more about dependency resolution in the case where an Ivy repository is used to download a non-Ivy artifact? In particular, why does this ever work? Apparently a default ivy.xml is generated on the fly?

  2. The first log message quote above states that the cached meta-data must be refreshed. This is presumably the generated ivy.xml. Is that correct? Is the generated ivy.xml always going to be considered out of date, such that it must be refreshed? This leaves us more exposed to connectivity issues than we otherwise would be.

  3. Digging around, I found ResolutionControl#useCachedResult(). Is this something I can use to tell Gradle to consider the artifact and metadata in the cache to be valid without need for refresh? (I can’t figure out how to access this via the DSL.) Is there some other approach you would recommend?

We could probably put node itself into our local Artifactory instance, even with a bogus ivy.xml, to get around this particular issue. But I expect that we’d simply be deferring the connectivity issues to the resolution of npm packages themselves, and thus wouldn’t be any better off. So for now I want to at least have a better understanding of what is going on.

Our long term approach will be to upgrade our Artifactory install to 3.2 or higher such that we can proxy npm packages.

Thanks for any insight.

Yep, when there is no metadata file (ivy.xml or pom), gradle will look for a default artifact. If it finds one, it proceeds as if there was an empty metadata file (no dependencies).

I wouldn’t expect this to be the case. I would think you’d only see that if using the --refresh-dependencies flag.
You can investigate further by following the code from here.

Yes, you may be able to use the never released cache control DSL to change this behaviour. First I’d try using --offline and see if that helps.

I would think you’d only see that if using the --refresh-dependencies flag.

Bingo. We are indeed using that flag. Our use of --refresh-dependencies dates from 2012. Partially due to the forum discussions here and here, and partially for other reasons such as subpar project structure and incomplete understanding of “changing” modules.

I removed the flag from one of the projects, and of course, now I see

21:15:00.753 [DEBUG] [org.gradle.api.internal.artifacts.ivyservice.ivyresolve.CachingModuleComponentRepository] Using cached module metadata for module 'org.nodejs:node:0.12.0' in 'ivy'

I think between removing this flag and appropriate application of ExternalModule#setChanging(), we should be able to find a workaround for our current problem and even improve build times. Thanks for the reply.