srs / gradle-grunt-plugin

Gradle plugin for running Grunt tasks
106 stars 16 forks source link

Manipulate the path on grunt tasks to include downloaded node directory #12

Open ljohnston opened 10 years ago

ljohnston commented 10 years ago

Currently, using the grunt plugin seems to require that I already have node in my path before kicking off gradle. It looks like the node plugin is calling node using the absolute path to it as configured by the plugin (based on node version, etc.), which makes sense. Within the node infrastructure, however, node is again being referenced. If node is not already in the path, things will fail.

For example (with node NOT in the path):

<snip>
12:56:36.334 [INFO] [org.gradle.process.internal.DefaultExecHandle] Starting process 'command '/Users/my.user/.gradle/nodejs/node-v0.11.10-darwin-x64/bin/node''. Working directory: /Users/my.user/dev/audience-management_node-build-changes Command: /Users/my.user/.gradle/nodejs/node-v0.11.10-darwin-x64/bin/node /Users/my.user/dev/audience-management_node-build-changes/node_modules/grunt-cli/bin/grunt protractorQuickStart

<snip>

12:56:36.378 [INFO] [org.gradle.process.internal.DefaultExecHandle] Successfully started process 'command '/Users/my.user/.gradle/nodejs/node-v0.11.10-darwin-x64/bin/node''
12:56:37.649 [QUIET] [system.out] Running "protractor:run_quickStartPageTest" (protractor) task
12:56:37.659 [QUIET] [system.out] >> Error: not found: node
12:56:37.660 [QUIET] [system.out] Fatal error: protractor exited with code: 127
<snip>

If I do the following before kicking off gradle, however, everything works:

export PATH=/Users/my.user/.gradle/nodejs/node-v0.11.10-darwin-x64/bin:$PATH

Is there any way to modify the environment to include the path to the node executable being used by the plugin? I tried modifying the node task's 'environment' attribute, but was unable to get things working.

Thanks, Lance

srs commented 10 years ago

Can cut'n'paste your buildscript here so I can see. And which versions of gradle and gradle-grunt-plugin are you using?

ljohnston commented 10 years ago

gradle version 1.11 (via gradlew) gradle-grunt-plugin 0.5

From the main build script:

<snip>
apply from: 'gradle/node.gradle'

grunt_protractorQuickStart {
    dependsOn webdriverManagerStart
    finalizedBy webdriverManagerStop
    ignoreExitValue = true
}
<snip>

... and from gradle/node.gradle:

buildscript {
    repositories {
        jcenter()
    }

    dependencies {
        classpath 'com.moowork.gradle:gradle-grunt-plugin:0.5'
    }
}

apply plugin: com.moowork.gradle.grunt.GruntPlugin

node {
    version = '0.11.10'
    download = true
}

task gruntSetup() {
    dependsOn installGrunt, npmInstall
}

task webdriverManagerUpdate(type: NodeTask) {
    dependsOn gruntSetup
    script = file('./node_modules/protractor/bin/webdriver-manager')
    args = ['update', '--standalone']
}

task webdriverManagerStop() {
    dependsOn gruntSetup

    doLast {
        def url = new URL("http://127.0.0.1:4444/selenium-server/driver/?cmd=shutDownSeleniumServer")
        url.openConnection().content
    }
}

task webdriverManagerStart(type: ThreadedNodeTask) {
    dependsOn webdriverManagerUpdate

    script = file('./node_modules/protractor/bin/webdriver-manager')
    args = ['start']

    doFirst {
        ServerSocket socket = null
        try { 
            socket = new ServerSocket(4444); 
        }
        catch( IOException e ) {
            throw new GradleException("port 4444 already in use")
        }
        finally {
            if (socket != null) socket.close()
        }
    }

    doLast {
        def url = 'http://127.0.0.1:4444/wd/hub'
        if (! waitForHttpUrl(url, 20000, 2000)) {
            throw new GradleException("timeout waiting for url '${url}' to become available")
        }
    }
}

class ThreadedNodeTask extends com.moowork.gradle.node.task.NodeTask {

    @Override
    void exec() {
        Thread.start {
            super.exec() 
        }
    }
}

private boolean waitForHttpUrl(String url, int timeout, int interval = 1000) {

    int beenWaiting = 0

    while (beenWaiting < timeout) {
        try {
            HttpURLConnection connection = 
                (HttpURLConnection) new URL(url).openConnection();
            connection.connect()

            int responseCode = connection.getResponseCode();

            if (200 <= responseCode && responseCode <= 399) {
                return true
            }
            else {
                throw new IOException(
                    "response code '${responseCode}' while waiting for url '${url}'")
            }
        }
        catch (IOException e) {
            // Just keep waiting.
        }

        sleep(interval)
        beenWaiting += interval
    }
}
dankelleher commented 9 years ago

Bump. I have exactly the same problem on my Bamboo CI with protractor 0.23.1, node v. 0.10.28, gradle-grunt-plugin 0.6, gradle 2.1. Is this a protractor problem?

dougborg commented 9 years ago

Hey @dankelleher and @ljohnston, this should be fixed in the gradle-node-plugin v0.8. Try explicitly declaring a dependency on that version of the gradle-node-plugin, and let me know if that helps.

buildscript {
    repositories {
        jcenter()
    }

    dependencies {
        classpath 'com.moowork.gradle:gradle-grunt-plugin:0.6'
        classpath 'com.moowork.gradle:gradle-node-plugin:0.8'
    }
}

@srs - have you considered consolidating these plugins (gradle-node-plugin, gradle-grunt-plugin, and gradle-gulp-pluing) into one repository and releasing them as a unit? They are all pretty small plugins, and users could still apply them independently. It seems like the grunt and gulp plugins (and any other future node-y plugins) would have a pretty tight dependency on the node plugin and it would be nice to have them released together. It would also cut down on the release overhead and some build code duplication.

srs commented 9 years ago

Yes, was meaning to release new grunt (and gulp) plugins using the newest node-plugin version but have not come to that yet. Sorry.

@dougborg - Have tought about that and the grunt and gulp plugins are fairly simple and could either be a part of node-plugin or in the same project. What do you think, is it better to be seperate plugins or one bigger one?

dougborg commented 9 years ago

I think having them in the same project makes a lot of sense and possibly even the same artifact (if that is supported with the new plugins {} configuration in Gradle 2.1+). I think it may still make sense to be able to apply them separately though - so we would probably need to have separate plugin descriptor files.