How to conditionally download and unzip artifacts from repo during initialization?

Using the script below, I was able to download a set of java script libraries needed for compile/testing
of java script for a multi-project build. The download happens once and when updates are detected by a version change. This is somewhat similar to the wrapper. This is currently working by the compileJavaScript and testJavaScript tasks depending on the gruntWrapper task (referring to below).

Is it possible to execute the operations encapsulated in the gruntWrapper task (below) using an init script. My initial attempt failed because of: Could not find method configurations(). I would like to perform the operations encapsulated in the gruntWrapper task once each time a build is executed - similar to the wrapper (and the install of gradle).

ext.gruntVersion = '0.1.3' 
ext.gruntHome = 'grunt' 
ext.gruntManifest = "$gruntHome/manifest.json" 
ext.nodeJsDirectory = "$gruntHome/nodejs" 
ext.gruntPluginsDirectory = "$gruntHome/node_modules"

configurations { 
    grunt 
    nodejs 
}

dependencies { 
    grunt libraries.gruntcli, libraries.gruntplugins, libraries.nodejsplugins 
    nodejs libraries.nodejs 
}

def isLatestGruntVersionInstalled() { 
    def isLatestGruntVersionInstalled = false 
    def manifest = file(gruntManifest) 
    if (manifest.exists()) { 
        def parser = new groovy.json.JsonSlurper() 
        def properties = parser.parseText(manifest.text) 
        if (properties.gruntVersion == gruntVersion) { 
            isLatestGruntVersionInstalled = true 
        } 
   } 
    return isLatestGruntVersionInstalled 
}

def installManifest() { 
    def builder = new groovy.json.JsonBuilder() 
    def root = builder { gruntVersion gruntVersion } 
    file(gruntManifest).text = builder.toString() 
}

def installPackages() { 
    copy { 
        from { 
            configurations.nodejs.collect { zipTree(it) } 
        } 
        into gruntHome 
    }   
    copy { 
        from { 
            configurations.grunt.collect { zipTree(it) } 
        } 
        into gruntPluginsDirectory 
    } 
}

def cleanGrunt() { 
    delete gruntManifest, gruntPluginsDirectory, nodeJsDirectory 
}

task gruntWrapper () { 
    onlyIf { !isLatestGruntVersionInstalled() }
    doFirst {  
       cleanGrunt()  
       installPackages()  
   }  
   doLast { installManifest() }  
}

I’d highly suggest refactoring this logic into tasks with dependencies between them. The problem with defining methods with calls to copy() is that you get no incremental build support. If you need Grunt “initialized” in order to perform some other task then that task should simply depend on another task that performs that initialization.

I do not think I explained my question well. I am able to get the desired behavior with task dependencies; also, I am getting incremental build support from ‘onlyIf { !isLatestGruntVersionInstalled() }’ of the gruntWrapper task (not typical).

Is there a way to perform the operations of gruntWrapper from with an init script (in init.d)? My initial attempt failed because of: Could not find method configurations().

I’m just trying to understand exactly what it is you want to do. I’m not sure an init script is necessarily what you want based on what you are describing. If you want some operation to happen prior to every build an init script isn’t required. Init scripts are just configuration that is added to your project at an earlier stage of the Gradle lifecycle. You can certainly do what you want in an init script, however.

The error you are getting is due to the fact that an init script delegates to an instance of Gradle rather than Project. If you want to configure the project then you’ll want to put that configuration in an allprojects { } or afterProject { } block.

I was trying to use the init script to download a set of zips from Artifactory and unzip into a shared directory (a java script runtime). I thought I could try using an init script to accomplish that (versus tasks dependencies). It is something I wanted downloaded once for a multi-project build - versus even checking if the task was up-to-date… kind-of like how gradle is installed via the wrapper.

I almost want to install this runtime as part of the wrapper (when is detects a new gradle version available) - but not bundled with it - I want to pull the artifacts from Artifactory.

I have this working via task dependencies… .i.e. every project that has a compileJavaScript task depends on the gruntWrapper task. If the latest version is installed the task is skipped. I was just reviewing the init scripts and it seemed like an alternative - if the latest version was not installed could I download / unzip these archives into a directory during initialization.

Thanks

The Gradle wrapper isn’t extensible in a way to provide custom bootstrapping mechanisms. The method you are using with task dependencies is the recommended way to do this.

Thanks… When I use the --parallel option, my gruntInstall task does not work. I need a critical section around the isLatestGruntVersionInstalled() operation. Can you provide some guidance - my initial attempts where not successful?

My guess is it’s a concurrency issue with your projects all fighting for that file. In reality though, this task should only be run once per build, therefore, it shouldn’t be executed by every subproject. Perhaps define the task just once, in the root project, and have subproject depend on that single task.