How to split my build.gradle and make it less imperative

I used gradle-js-plugin to lint and minify my Javascript, and wrote some tasks to automate uploading the scripts via FTP. Any feedback is welcome, but specifically I am concerned that

  • The tasks I wrote myself like viewJshintResults are all imperative and not declarative
  • The section after the /********/ feels like it should all be in its own file or class somehow, but I don’t know how Gradle does that.

Here’s my build.gradle:

plugins {
  id "base"
  id "com.eriwen.gradle.js" version "1.12.1"
}
            
repositories {
    mavenCentral()
}

dependencies {
    rhino 'com.google.javascript:closure-compiler:v20150920'
}

javascript.source { // source sets
    dev {
        js {
            srcDir "/scripts"
            include "*.js"
            exclude "*.min.js"
        }
    }
    prod {
        js {
            srcDir "/scripts"
            include "*.min.js"
        }
    }
}


/*
 * To see the errors for this task easily, run it as 
 * gradle clean check 2>info.txt 1>&2 & info.txt 
 * (you have to redirect stdout to catch warnings, stderr to catch errors)
 */ 
check {
    dependsOn 'viewJshintResults'
    dependsOn 'minifyJs'
}

combineJs {
    source = javascript.source.dev.js.files
    dest = file("${buildDir}/all.js")
}

minifyJs {
    source = javascript.source.dev.js.files
    dest = file("${buildDir}/all-min.js")
    sourceMap = file("${buildDir}/all.sourcemap.json")
    closure {
        warningLevel 'VERBOSE'
        // jQuery-1.9.js externs downloaded from https://raw.githubusercontent.com/google/closure-compiler/master/contrib/externs/jquery-1.9.js
        externs = files("resources/jQueryExterns.js", "resources/externs.js")
    }
}

jshint {
    tasks.jshint.source = javascript.source.dev.js.files
    tasks.jshint.dest = file("${buildDir}/jshint.out.xml")
    tasks.jshint.reporter = 'checkstyle'
    jshint.options = [expr: "true", browser: "true", jquery: "true"]
    jshint.options << [wsh: "true"] //for Jon's ActiveXObjects
    if (false) {jshint.options << [devel: "true"]}
}

task viewJshintResults (dependsOn:tasks.jshint, type:Exec) {
    onlyIf {
        tasks.jshint.state.failure != null
    }
    def firefoxPath = /C:\Program Files (x86)\Mozilla Firefox\firefox.exe/
    executable firefoxPath
    args tasks.jshint.dest
    ignoreExitValue = true
}
/************************************************************************/    
// FTP section
configurations {
    ftpAntTask
}

dependencies {
    ftpAntTask("org.apache.ant:ant-commons-net:1.9.4") {
        module("commons-net:commons-net:1.4.1") {
            dependencies "oro:oro:2.0.8:jar"
        }
    }
}

task ftp {
    description "Uploads all files that have changed to the server"
    dependsOn minifyJs
    def identity = file("resources/ftpid.txt").readLines()
    ext.remotedir = "/k/"
    doLast {
        ant {
            taskdef(name: 'ftp',
                    classname: 'org.apache.tools.ant.taskdefs.optional.net.FTP',
                    classpath: configurations.ftpAntTask.asPath)
            ftp(server: "ftp.mankatopedia.com", userid: "${identity[0]}", password: "${identity[1]}", remotedir: "${remotedir}", verbose: "yes", depends: "yes", serverTimeZoneConfig: "America/Los_Angeles", newer: "yes") {
                fileset(dir: ".") {
                    exclude(name: ".gradle/")
                    exclude(name: "build.gradle")
                    include(name: "**/*.php")
                    include(name: "**/*.css")
                    include(name: "scripts/**/*")
                    include(name: "gfx/**/*")
                }
            }
        }
    }
}

task alertWhenServerUpdates (dependsOn: 'ftp', type:Exec){
    description "Launches an external script to poll the server until new file is live"
    inputs.files(fileTree(dir: 'scripts', include: '*.js'))
    outputs.file 'always up-to-date without this fake file.txt'
    workingDir "resources/"
    commandLine "cmd", "/k", 
        "start /d \"resources\" checkforupdatedjs-Shortcut"
    doLast {
        println 'Launched server polling script'
    }
}

task release (dependsOn: ['build', 'alertWhenServerUpdates']) {
    //changes behavior when present in task graph
    description "Produces build version"
}

gradle.taskGraph.whenReady {
    if (gradle.taskGraph.hasTask(release)) {
        minifyJs.source = combineJs  // don't need files and line numbers for release
    }
}

This is an x-post of this codereview.stackexchange question in case you want karma for answering it.