如何在自定义任务中定义默认dependsOn

时间:2012-12-29 00:30:07

标签: gradle

我比较陌生。 为了在集群上创建自动部署脚本,我创建了一堆彼此依赖的自定义任务。例如:

class StartSchedulerTask extends SchedulerTask {
    @TaskAction
    void start() {
        dependsOn env.nodes.name.collect {"startTomcat_$it"}
        println "Starting quartz on node: ${node}"
    }
}
在build.gradle中,我已经动态创建了任务:

project.extensions.environment.nodes.each { TomcatNode n ->
    String name = n.name
    task "nodeInit_$name"(type: DeployToNodeInitTask) {
                node(n)
    }
    task "stopWorker_$name"(type: StopWorkerTask) {
        node(n)
    }
    task "stopTomcat_$name"(type: StopTomcatTask){
        node(n)
    }
    task "updateAppConfigs_$name"(type: UpdateAppConfigsTask){
        node(n)
        apps(V3Application.ALL_APPS)
        buildName('develop')
    }
    task "deployWars_$name"(type: DeployWarsTask){
        node(n)
        apps(V3Application.ALL_APPS)
        buildName('develop')
    }
    task "startTomcat_$name"(type: StartTomcatTask){
        node(n)
    }
    task "startWorker_$name"(type: StartWorkerTask){
        node(n)
    }
    task "terminateNode_$name"(type: DeployToNodeTerminationTask){
        node(n)
    }
}
task stopScheduler(type: StopSchedulerTask) {
    environment(environment)
}
task startScheduler(type: StartSchedulerTask) {
    environment(environment)
}

默认任务配置为startScheduler,这是部署过程的最后一步,其构思是任务图一旦构建,将处理我的任务的正确执行顺序。

但是,当我打印出任务图时,列出的唯一任务是startScheduler。我错过了什么吗?

3 个答案:

答案 0 :(得分:3)

任务依赖性必须在配置时声明,而不是在执行时声明。从理论上讲,您可以在任务的构造函数中执行此操作,但更好的方法是在构建脚本或插件中执行此操作。

答案 1 :(得分:2)

这是因为你在@TaskAction方法中声明了依赖关系。 @TaskAction仅在形成依赖图时运行。

您可以滥用@TaskActions方法中的DoFirst()来调用所有依赖项,但这不会出现在依赖关系图上。

答案 2 :(得分:2)

感谢Peter Niederwieser和Jeffrey的评论,我能够提出我想要的完整解决方案。我没有将彼得的标记作为答案,因为完整的答案如下,但这是对正确解决方案的必要暗示:

我创建了一个接口DependencyAware:

public interface DependencyAware {
    void declareDependencies()
}

每个知道如何声明其依赖关系的任务都会实现此接口。例如:

class StartSchedulerTask extends SchedulerTask {

    @TaskAction
    void start() {
        println "Starting quartz on node: ${node}"
    }

    void declareDependencies() {
        dependsOn env.nodes.name.collect {"startTomcat_$it"}
    }
}

在我的构建脚本中:

tasks.each { Task t ->
    if (t instanceof DependencyAware) {
        t.declareDependencies()
    }
}

就是这样!

感谢指点Peter和Jeffrey

更新1

task deploy(dependsOn: ['backupWars', 'startScheduler'])

task stopScheduler(type: StopSchedulerTask)

task backupWars(type: BackupWarsTask)

project.extensions.targetEnvironment.nodes.each { TomcatNode n ->
    String name = n.name
    [
        ("nodeInit_$name"): DeployToNodeInitTask,
        ("stopWorker_$name"): StopWorkerTask,
        ("stopTomcat_$name"): StopTomcatTask,
        ("updateAppConfigs_$name"): UpdateAppConfigsTask,
        ("deployWars_$name"): DeployWarsTask,
        ("startTomcat_$name"): StartTomcatTask,
        ("startWorker_$name"): StartWorkerTask,
        ("terminateNode_$name"): DeployToNodeTerminationTask,
    ].each { String taskName, Class taskType ->
        task "$taskName"(type: taskType) {
            node(n)
        }
    }
}

task startScheduler(type: StartSchedulerTask) {
    dryRun(testMode)
}

不同部署步骤之间的内部依赖关系位于任务本身,例如:

class StartWorkerTask extends WorkerTask {

    @TaskAction
    void start() {
        println "Starting worker ${node}"
    }

    void declareDependencies() {
        dependsOn tomcatOnThisNodeHasBeenStarted()
    }

    String tomcatOnThisNodeHasBeenStarted() {
        "startTomcat_${node.name}"
    }
}

拓扑的声明如下:

environments {
    prod {
        nodes {
            (1..2).each { int i ->
                "w${i}_prod" {
                    host = "prod-n$i"
                    userName = "xxxxx"
                    password = "xxxxx"
                    loadBalancer = 'lb_prod'
                    frontendJkManagerUrl = 'http://web01/jkmanager'
                }
            }

            scheduler {
                name = "w1_prod"
            }
        }
    }
    rc {
    //rc topology here
    }
}