Only run task if another isn't UP-TO-DATE in g

2019-06-17 02:20发布

I want to automatically add a serverRun task when doing functional tests in Gradle, so I add a dependency :

funcTestTask.dependsOn(serverRun)

Which results in the task running whether or not the funcTestTask even runs

:compile
:serverRun
:funcTestTask (and associate compile tasks... etc)
:serverStop

OR

:compile UP-TO-DATE
:serverRun <-- unnecessary 
:funcTestTask UP-TO-DATE
:serverStop

The cost of starting the server is pretty high and I only want it to start if the functionalTest isn't UP-TO-DATE, I'd like to do or something :

if(!funcTestTask.isUpToDate) {
    funcTestTask.dependsOn(serverRun)
}

So I know I can't know the up-to-date status of funcTestTask until all it's inputs/outputs are decided BUT can I inherit it's uptoDate checker?

serverRun.outputs.upToDateWhen(funcTestTask.upToDate)

The alternative is to "doFirst" the ServerRun in the FuncTest, which I believe is generally frowned upon?

funcTestTask.doFirst { serverRun.execute() }

Is there a way to conditionally run a task before another?

UPDATE 1
Tried settings inputs/outputs the same

serverRun.inputs.files(funcTestTask.inputs.files)
serverRun.outputs.files(funcTestTask.outputs.files)

and this seems to rerun the server on recompiles (good), skips reruns after successful unchanged functional tests (also good), but wont rerun tests after a failed test like the following

:compile
:serverRun
:funcTestTask FAILED

then

:compile UP-TO-DATE
:serverRun UP-TO-DATE <-- wrong!
:funcTestTask FAILED

标签: gradle task
4条回答
Rolldiameter
2楼-- · 2019-06-17 02:29

I had the same problem but the solution I came up is much simpler. This starts up the server only if testing is necessary

test {
    doFirst {
        exec {
            executable = 'docker/_ci/run.sh'
            args = ['--start']
        }
    }

    doLast {
        exec {
            executable = 'docker/_ci/run.sh'
            args = ['--stop']
        }
    }
}
查看更多
相关推荐>>
3楼-- · 2019-06-17 02:37

Having faced the same problem I found a very clean solution. In my case I want an eclipse project setup to be generated when the build is run, but only at the times when a new jar is generated. No project setup should be executed when the jar is up to date. Here is how one can accomplish that:

tasks.eclipse {
  onlyIf {
    !jar.state.upToDate
  }
}

build {
  dependsOn tasks.eclipse
}
查看更多
欢心
4楼-- · 2019-06-17 02:39

I ended up writing to a 'failure file' and making that an input on the serverRun task

File serverTrigger = project.file("${buildDir}/trigger") 

project.gradle.taskGraph.whenReady { TaskExectuionGraph taskGraph ->
  // make the serverRun task have the same inputs/outputs + extra trigger
  serverRun.inputs.files(funcTestTask.inputs.files, serverTrigger)
  serverRun.outputs.files(funcTestTask.outputs.files)
}

project.gradle.taskGraph.afterTask { Task task, TaskState state ->
  if (task.name == "funcTestTask" && state.failure) {
    serverRun.trigger << new Date()
  }
}

with info from an answer to my question on the gradle forums : http://forums.gradle.org/gradle/topics/how-can-i-start-a-server-conditionally-before-a-functionaltestrun

查看更多
forever°为你锁心
5楼-- · 2019-06-17 02:45

Since the task is a dependent tasks of the one you are trying to control then you can try:

tasks {
    onlyIf {
        dependsOnTaskDidWork()
    }
}
查看更多
登录 后发表回答