0

我对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。我错过了什么吗?

4

3 回答 3

3

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

于 2012-12-29T06:40:38.207 回答
3

感谢 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()
    }
}

就是这样!

感谢彼得和杰弗里的指点

更新 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
    }
}
于 2012-12-29T11:53:09.730 回答
2

这是因为您从 @TaskAction 方法内部声明了依赖项。@TaskAction 仅在依赖关系图形成后运行。

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

于 2012-12-29T01:21:11.293 回答